2012-06-26 19 views
9

Piszę program c, aby wygenerować falę sinusoidalną, która powoli zwiększa częstotliwość od f1 do f2 przez pewien przedział czasu.Fala sinusoidalna, która powoli zwiększa częstotliwość od f1 do f2 dla danego czasu

Napisałem ten program c, aby zwiększyć częstotliwość od 0 do 10 Hz, ale problem polega na tym, że częstotliwość zmienia się po ukończeniu 360 stopni. Jeśli spróbuję zmienić częstotliwość między 0 a 360 stopni, to przejście nie jest płynne i jest nagłe.

Jest to równanie sin że użyłem y = Amplituda * sin (freq * faza)

int main(int argc, char *argv[]) { 

double y, freq,phase; 
int count; // for convenience of plotting in matlab so all the waves are spread on x axis. 
    for (freq = 0; freq < 10; freq+=1) { 
     for (phase = 0; phase < 360; phase++) { // phase is 360 degrees 
     y = 3 * sin((count*6.283185)+(freq*(phase*(3.14159/180)))); 
    printf("%f %f %f \n", freq, phase, y); 
    } 
    count++; 
    } 
return EXIT_SUCCESS; 
} 
  1. Jak płynnie zmieniać częstotliwość dla danego okresu?
  2. Czy powinienem zaglądać w transformacje Fouriera?
+0

Aby wygenerować "prawdziwą" częstotliwość fali grzechu żądanego Hz, należy użyć liczników i timerów. Używając wzoru sin, wygenerowana częstotliwość zależy od prędkości, z jaką program wykonuje. – katta

Odpowiedz

14

jeśli chcesz, aby częstotliwość kątowa (w = 2 pi f) zmieniała się liniowo z czasem, to dw/dt = a i w = w0 + (wn-w0)*t/tn (gdzie t przechodzi od 0 do tn, w przechodzi od w0 do wn). faza jest integralny z tym, tak phase = w0 t + (wn-w0)*t^2/(2tn) (jak mówi OLI)

void sweep(double f_start, double f_end, double interval, int n_steps) { 
    for (int i = 0; i < n_steps; ++i) { 
     double delta = i/(float)n_steps; 
     double t = interval * delta; 
     double phase = 2 * PI * t * (f_start + (f_end - f_start) * delta/2); 
     while (phase > 2 * PI) phase -= 2 * PI; // optional 
     printf("%f %f %f", t, phase * 180/PI, 3 * sin(phase)); 
    } 
} 

(gdzie odstęp jest tn delta T/TN).

oto wyjście dla równoważnego kodu Pythona (1-10Hz ponad 5 sekund):

1-10 Hz over 5 seconds

from math import pi, sin 

def sweep(f_start, f_end, interval, n_steps): 
    for i in range(n_steps): 
     delta = i/float(n_steps) 
     t = interval * delta 
     phase = 2 * pi * t * (f_start + (f_end - f_start) * delta/2) 
     print t, phase * 180/pi, 3 * sin(phase) 

sweep(1, 10, 5, 1000) 

ps nawiasem mówiąc, jeśli słuchasz tego (lub patrząc na niego - coś to wymaga ludzkiej percepcji) podejrzewam, że nie chcesz liniowego wzrostu, ale wykładniczego. ale to jest a different question ...

+0

fantastyczne !! To działało świetnie. gdy n_step jest bardzo duża faza - = 2 * PI jest prawie zerowa, zatem sin (0) wynosi 0. faza - = 2 * PI powoduje rozpoczęcie fali sinusoidalnej z ujemnymi wartościami. Powyższy wykres jest poprawny, gdy pętla while jest skomentowana. Możesz wskazać mi źródło, z którego czytałeś o tym. Przez kilka dni gubiłem sobie włosy i mnie uratowałeś. Dziękuję bardzo. Czytałem o wykładniczym wzroście, ale nie mogłem zrozumieć, może poprosić o wyjaśnienie intuicyjnie. – katta

+0

+1, ponieważ jestem zaskoczony twoją umiejętnością ^^ – Offirmo

+0

naprawiono problem (pływak) w kodzie c, dzięki. nie rozumiem komentarza na temat fazy, ale jest ona dostępna tylko wtedy, gdy chcesz, aby zawsze była w zakresie 0-2PI. nigdzie tego nie czytałem - po prostu to wymyśliłem - ale o ile wiem, jest to to samo, co wpis wikipedia (do którego i oli dołączyłem i sprawdziłem później). –

9

Jak mogę płynnie zmieniać częstotliwość przez zadany czas?

Gładka sinusoida wymaga ciągłej fazy. Faza jest całką częstotliwości, więc jeśli masz liniową funkcję częstotliwości (tj. Wzrost stałej szybkości od f1 do f2), to faza będzie kwadratową funkcją czasu.

Możesz obliczyć matematykę za pomocą pióra i papieru lub mogę powiedzieć, że powstały kształt fali nazywa się linear chirp.

Czy powinienem zaglądać w transformacje Fouriera?

Transformacja Fouriera liniowego ćwierkania jest liniowym ćwierkaniem, więc prawdopodobnie nie.

+0

Downvoter: czy chcesz skomentować? –

+0

Dzięki za wskazanie mnie we właściwym kierunku – katta

2

To powinno być dość proste. Zamiast myśleć o zmianie częstotliwości, pomyśl o tym, aby obiekt obracał się coraz szybciej. Odległość kątowa, którą przebył, może wynosić X po N sekundach, ale będzie większa niż 2X (może 4X) po 2N sekundach. Tak więc wymyśl wzór na odległość kątową (np. Alfa = k1 * T + k2 * T ** 2) i weź sinus tej odległości kątowej, aby znaleźć wartość kształtu fali w dowolnym momencie T.

0
+ (void) appendChirp:(int[])sampleData size:(int)len 
    withStartFrequency:(double)startFreq withEndFrequency:(double)endFreq 
    withGain:(double)gain { 

double sampleRate = 44100.0; 

for (int i = 0; i < len; i++) { 

    double progress = (double)i/(double)len; 
    double frequency = startFreq + (progress * (endFreq - startFreq)); 
    double waveLength = 1.0/frequency; 

    double timePos = (double)i/sampleRate; 
    double pos = timePos/waveLength; 
    double val = sin(pos * 2.0 * M_PI); // -1 to +1 

    sampleData[i] += (int)(val * 32767.0 * gain); 
} 

} 
+0

Niezupełnie. Chociaż jest to gładkie i "dobrze wyglądało" na kalkulatorze graficznym, wystarczy krótka demonstracja, aby zilustrować błąd. Używanie tego kodu do generowania dźwięku otoczonego dźwiękiem częstotliwości początkowej i końcowej pokazuje, że nie kończy się ono we właściwym miejscu. Sinus (startFreq, 1 sekunda), sweep (startFreq, endFreq, 1 sekunda), sinus (endFreq, 1 sekunda), następnie, jeśli chcesz, przeprowadź analizę spektralną. Moja analiza spektralna (Cool Edit Pro 2) pokazuje, że wzrasta do 650 herców. –

+0

Jakie były twoje dane wejściowe, gdy twoja analiza spektralna pokazała 650 herców? Moja funkcja może nie być dokładna, ale jestem prawie pewien, że jej wydajność zależy od jej wejścia. Ta metoda przyszła z mojego syntezatora oprogramowania, nawiasem mówiąc, i brzmi dobrze i dobrze wygląda. – MusiGenesis

+0

@MusicGenesis Przepraszam, zapomniałem podać parametry! Zrobiłem sinusoida z 220 na 440 Hz. Jak już powiedziałem, zamiatanie kończy się na około 650 Hz przed odtwarzaniem sinusa 440. –