Help producing sine wave

This is a discussion on Help producing sine wave within the C++ Programming forums, part of the General Programming Boards category; I'm trying to produce a sine wave with a period chosen by the user. I'm sure this should be quite ...

  1. #1
    Registered User
    Join Date
    Oct 2003
    Posts
    7

    Question Help producing sine wave

    I'm trying to produce a sine wave with a period chosen by the user. I'm sure this should be quite simple to do but I can't work out how to produce a sine wave with a set period (in secodns as opposed to pixels).

    Thanks in advance for your help

    Rich

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    Just determine a scale to use - X pixels = N seconds

    If this doesn't help at all, then post a more specific question.

    gg

  3. #3
    Registered User
    Join Date
    Oct 2003
    Posts
    7
    Umm maybe I've missed something obvious here but how do I define time in C++? I want to send a sine wave (and other waveforms hopefuly) to a pci card and I have a dll which allows me to set the value on the card but only at that instant, so I need a way of sending values to give a sine wave of a chosen period/frequency.

    Thanks again,

    Rich

  4. #4
    Hardware Engineer
    Join Date
    Sep 2001
    Posts
    1,398

    Unhappy This is going to be tricky....

    A DLL implies Windows, and precise timing is impossible in "user mode". With a multitasking OS, you have to get into "kernel mode" to get full control of the processor. Kernel mode and driver programming is still beyond my abilities, so I can't help with how to do it, other than that it's advanced stuff, and you have to use the DDK (Driver Development Kit).

    [EDIT]
    Actually, it would be a bad idea to do this in software with a multitasking OS. The right way is to do it in hardware. for example, sound cards have their own clock, and they have (at least) three modes.

    Wave files work somewhat like your approach, except that the samples are buffered and sent to the sound card in quick-bursts... not at the rate they are reproduced. Even with the built-in buffering, you can get clitches & dropouts when playing a wave file and heavy multitasking.

    The 2nd mode is MIDI, where the waveform is stored the soundcard's RAM, and the program just sends it a "Play-it" command.

    The 3rd mode is direct audio from the CD player. The CD drive has it's own DAC, and sends audio directly to the sound card, bypassing the computer's data bus.
    Last edited by DougDbug; 10-31-2003 at 12:46 PM.

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    What type of card is it? I have developed software that interfaces with several different types of data acquisition cards (that support output as well).

    What kind of period are we talking about for the sine wave? And how smooth does the curve need to be? What is this sine wave output going to be use for?

    gg

  6. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Create the sine wave and then use linear interpolation, bi linear interpolation, or cubic interpolation to smooth it out. This will get you past the exact timing problem.

    Just create it via a Windows timer with a set period and then smooth it.


    Linear interpolation: f1 is smoothing coefficient

    As a function
    Code:
    double LI(double v1,double v2,double f1)
    {
      return (v1+f1*(v2-v1));
    }
    As a #define
    Code:
    #define LI(v1,v2,f1)  (v1+f1*(v2-v1))
    As a pure 16-bit TASM assembly function
    32-bit only differs in stack and ebp esp.
    Code:
    _LI  proc
    ARG v1:QWORD,v2:QWORD,f1:QWORD
    
    push   bp
    mov    bp,sp
    
    fld      [v2]
    fsub   [v1]
    fmul   [f1]
    fadd  [v1]
    
    pop   bp
    ret
    _LI     endp
    As an inline assembly function
    Code:
    void LI(double v1,double v2,double f1,double result)
    {
      asm {
        fld     [v2]
        fsub  [v1]
        fmul  [f1]
        fadd  [v1]
        fstp   [result]
      }
    }
    Bi linear interpolation:

    Code:
    double BI(double v1,double v2,double v3,double v4,double f1,double f2)
    {
      double val1=(v1+f1*(v2-v1));
      double val2=(v3+f1*(v4-v3));
      return (val1+f2*(val2-val1));
    }
    or

    Code:
    #define LI(v1,v2,f1)  (v1+f1*(v2-v1));
    
    double BI(double v1,double v2,double v3,double v4,double f1,double f2)
    {
      double val1=LI(v1,v2,f1);
      double val2=LI(v3,v4,f1);
      return LI(val1,val2,f2);
    }
    Pure 16-bit TASM assembly function
    Code:
    _BI   proc
    ARG v1:QWORD,v2:QWORD,v3:QWORD,v4:QWORD,f1:QWORD,f2:DWORD
    LOCAL val1:WORD,val2:QWORD
    
      push   bp
      mov    bp,sp
      
      fld       [v2]
      fsub    [v1]
      fmul    [f1]
      fadd    [v1]
      fstp     [val1]
    
      fld       [v4]
      fsub    [v3]
      fmul    [f1]
      fadd   [v3]
      fstp    [val2]
    
      fld      [val2]
      fsub   [val1]
      fmul   [f2]
      fadd   [val1]
    
      pop    bp
      ret
    _BI  endp

    Anyways, you get the idea. There are other smoothing functions out there - look on www.google.com

    SoundBlaster Live Series cards can do linear interpolation on waves to make the sound better and crisper - they also do loads of other things.
    Last edited by VirtualAce; 10-31-2003 at 04:16 PM.

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    Assembly language showoff indeed!!! Numerical computing showoff too!

    Don't think it's gonna help though. What we have here is an external pin on a special PCI card which can output a particular voltage via a DLL call.
    So by continually adjusting the voltage you can produce a sine wave.
    That's why the period and smoothness of the wave are important for determining the "real-time'ness" of the requirements.

    gg

  8. #8
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Create the wave using a set period for changing the voltage via the DLL call. It must take an argument or something to manipulate the voltage.

    Or you can pre-compute the sine wave - not actual values but voltages that correspond to values. During pre-compute you can then smooth the wave and send the smoothed data to the DLL function which in turn will send it to the card. Linear interpolation will work whether its on the voltages or on the values in the sine wave.

    Code:
    double voltage=0.0;
    double angle=.001;
    double Wave[length_of_wave];
    
    for (int i=0;i<length_of_wave;i++)
    {
      voltage=sin(angle)*(voltage_to_value_coef);
      Wave[i]=voltage;
      angle=angle+(360/length_of_wave);   //one period
    }
    
    //Smooth it
    for (int i=0;i<length_of_wave-1;i++)
    {
       double v1=Wave[i];
       double v2=Wave[i+1];
       Wave[i]=LI(v1,v2,.5);
    }
    
    for (int i=0;i<length_of_wave;i++)
    {
      DLLFunc(Wave[i]);
    }


    Not the most elegant as it calls too much....but it should work based on the info you've given.
    Last edited by VirtualAce; 10-31-2003 at 08:15 PM.

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    Ooops, that didn't read right

    Yes! Interpolation can certainly be used to dertermine the voltage values beforehand. The problem is how quickly (and by how much) do the values need to change to produce a sine wave that meets the requirements of whatever he's trying to do.

    gg

  10. #10
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Well that can be achieved mathematically or you can experiment with the various coefs.

    In sound programming you must create an interrupt handler and the DMA signals when the current buffer is done. Then the sound card generates an interrupt which your code handles and then you load the correct portion of the circular buffer with new sound data.

    The only way to do this in Windows would be to create a timer and put it into a thread or do this via a callback function. Create a timer callback function and set the period via Windows. You should be able to get some accurate times. Also the pre-computed data can still be streamed and smoothed as well.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compression/Decompression Wave File and MP3
    By cindy_16051988 in forum Projects and Job Recruitment
    Replies: 51
    Last Post: 04-29-2006, 06:25 AM
  2. Sine Wave Program
    By Stiks in forum C Programming
    Replies: 10
    Last Post: 10-15-2005, 12:35 AM
  3. Processing a sine wave file
    By subdene in forum C++ Programming
    Replies: 2
    Last Post: 07-12-2004, 03:04 PM
  4. ...simple sine wave?
    By Sebastiani in forum C++ Programming
    Replies: 27
    Last Post: 12-15-2002, 01:12 PM
  5. Sine Wave Program Help
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 10-19-2001, 12:33 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21