Find start point (time) of each cycle in a sine wa

2019-02-28 23:14发布

问题:

I am tying to achieve sine wave gradually changing from 8Hz to 2Hz over 5 seconds:

This waveform was produced in Cool Edit. I gave it a start frequency of 8Hz, an end frequency of 2Hz and a duration of 5 seconds. The sine wave gradually changes from one frequency to the other over the given time.

My question is, how can I accurately find the start time of each cycle (highlighted with a red dot), using a FOR loop?

Pseudo code:

time   = 5 //Duration
freq1  = 8 //Start frequency
freq2  = 2 //End frequency

cycles = ( (freq1 + freq2) / 2 ) * time //Total number of cycles

for(i = 0; i < cycles; i++) {
    /* Formula to find start time of each cycle */
}

回答1:

That is backward thinking for this problem which leads to madness in the program. Not to mention the individual waves will not be a sin wave because the frequency is changing (they will be slightly distorted) which you will not achieve with your generator and also there is very slight chance the ending signal will stop on zero after 5sec. Instead do a continuous sin wave with variable frequency:

  1. First compute actual frequency

    linear interpolation will suffice (unless you need different change)

    f=f0+(f1-f0)*t/T
    

    where:

    f0=8 [Hz] start frequency
    f1=2 [Hz] stop frequency
    T =5 [s]  change time
    t =<0,T> is actual time in [s]
    
  2. compute the sin wave data

    for (t=0.0,angle=0.0;t<=T;t+=dt)
     {
     f=f0+((f1-f0)*t/T); // actual frequency
     signal=Amplitude*sin(angle); // your signal put it in a array or output somewhere ...
     angle+=6.283185307179586476925286766559*dt*f; // update phase
     while (angle>6.283185307179586476925286766559) // cut just to avoid floating rounding problems
      angle-=6.283185307179586476925286766559;
     }
    

    Where dt [s] is a time step you want to sample your signal with. If you are generating this in Real Time and outputting to real HW you can use a timer or measure the time directly (with performance counters on Windows or by RDTSC or whatever you have at disposal)

    If you got predefined number of samples n for this then

    dt=T/double(n-1);
    

    Here sample output (n=image width):

    If you also need the number of periods then add counter increment inside the angle cut while loop And also there is your zero point too (but if samplerate is too small or you need high precision you need to interpolate the real zero position).