2012-06-26 11 views
9

Sto scrivendo un programma c per generare un'onda sinusoidale che aumenta lentamente la frequenza da f1 a f2 per un intervallo di tempo di consegna.onda sinusoidale che aumenta lentamente la frequenza da f1 a f2 per un dato tempo

Ho scritto questo programma c per aumentare la frequenza da 0 a 10 Hz, ma il problema è che la frequenza cambia dopo il completamento di 360 gradi. Se provo a cambiare la frequenza tra 0 e 360 ​​gradi, la transizione non è fluida ed è brusca.

Questa è l'equazione il peccato che ho usato y = Ampiezza * sin (freq * fase)

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. Come posso cambiare la frequenza senza problemi per un dato periodo di tempo?
  2. devo esaminare le trasformazioni di Fourier?
+0

Per generare una frequenza di onda sin "reale" di Hz desiderati utilizzare contatori e timer. Usando la formula sin la frequenza generata dipende dalla velocità con cui il programma viene eseguito. – katta

risposta

14

se si desidera la frequenza angolare (w = 2 pi f) per variare linearmente con il tempo, quindi dw/dt = a e w = w0 + (wn-w0)*t/tn (dove t passa da 0 a tn, w passa da w0 a wn). fase è l'integrale di questo, così phase = w0 t + (wn-w0)*t^2/(2tn) (come oli dice):

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)); 
    } 
} 

(dove intervallo è tn e delta t/tn).

ecco l'output per il codice python equivalente (1-10Hz più di 5 secondi):

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 per inciso, se si sta ascoltando in questo (o guardarla - nulla che coinvolge la percezione umana) sospetto che tu non voglia un aumento lineare, ma esponenziale. ma questo è a different question ...

+0

fantastico !! Ha funzionato alla grande. quando n_step è molto grande la fase - = 2 * PI è quasi zero quindi sin (0) è 0. fase - = 2 * PI causa l'inizio dell'onda sin con valori negativi. Il grafico sopra è corretto quando il ciclo while è commentato. Potete indicarmi la fonte dove avete letto di questo. Mi sono sciolto i capelli per un paio di giorni e tu mi hai salvato. Grazie mille. Ho letto di un aumento esponenziale, ma non ho potuto capire potrebbe chiedere di spiegare in modo intuitivo. – katta

+0

+1 perché sono semplicemente stupito dalla tua abilità ^^ – Offirmo

+0

risolto il problema (float) nel codice c, grazie. non capisco il commento sulla fase, ma è solo lì nel caso in cui si desidera che sia sempre nel range 0-2PI. non l'ho letto da nessuna parte - l'ho appena elaborato - ma per quanto ne so, è lo stesso della voce wikipedia (che ho collegato a e ho controllato in seguito). –

9

Come si modifica la frequenza in modo uniforme per un determinato periodo di tempo?

Una sinusoide liscia richiede una fase continua. La fase è l'integrale della frequenza, quindi se si ha una funzione lineare per la frequenza (cioè un aumento di velocità costante da f1 a f2), allora la fase sarà una funzione quadratica del tempo.

È possibile calcolare la matematica con carta e penna oppure posso dire che la forma d'onda risultante è denominata linear chirp.

Devo esaminare le trasformazioni di Fourier?

La trasformata di Fourier di un chirp lineare è di per sé un chirp lineare, quindi probabilmente no.

+0

Downvoter: cura di commentare? –

+0

Grazie per avermi indicato nella direzione corretta – katta

2

Dovrebbe essere abbastanza semplice. Piuttosto che pensare di variare la frequenza, pensa di far girare un oggetto sempre più velocemente. La distanza angolare che ha percorso potrebbe essere X dopo N secondi, ma sarà più che 2X (forse 4X) dopo 2N secondi. Quindi trovare una formula per la distanza angolare (es. Alpha = k1 * T + k2 * T ** 2) e prendere il seno di quella distanza angolare per trovare il valore della forma d'onda in qualsiasi momento 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

Non proprio. Anche se questo è regolare e "sembra buono" su una calcolatrice grafica, una dimostrazione rapida è sufficiente per illustrare l'errore. L'uso di questo codice per generare un suono circondato dai suoni di frequenza di inizio e fine mostra che non finisce nel posto giusto. Sine (startFreq, 1 secondo), sweep (startFreq, endFreq, 1 secondo), Sine (endFreq, 1 secondo), quindi, se lo si desidera, eseguire alcune analisi spettrali. La mia analisi spettrale (Cool Edit Pro 2) mostra che arriva fino a 650 hertz circa. –

+0

Quali erano i tuoi input quando la tua analisi spettrale mostrava 650 Hertz? La mia funzione potrebbe non essere accurata, ma sono abbastanza sicuro che il suo output dipenda dal suo input. Questo metodo proviene dal mio sintetizzatore software, a proposito, e suona bene e sembra buono. – MusiGenesis

+0

@MusicGenesis Mi dispiace, ho dimenticato di dirti i parametri! Ho fatto una scansione sinusoidale da 220 a 440 hz. Come ho detto, lo sweep finisce intorno a 650 hz prima che i 440 suoni vengano riprodotti. –