2012-06-26 17 views
9

Estoy escribiendo un programa c para generar una onda sinusoidal que aumenta lentamente la frecuencia de f1 a f2 durante un intervalo de tiempo determinado.onda sinusoidal que ralentiza lentamente la frecuencia de f1 a f2 durante un tiempo determinado

He escrito este programa c para aumentar la frecuencia de 0 a 10 Hz pero el problema es que la frecuencia cambia después de completar 360 grados. Si trato de cambiar la frecuencia entre 0 y 360 grados, la transición no es suave y es abrupta.

Ésta es la ecuación del pecado que he utilizado y = Amplitud * sen (* frec 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. ¿Cómo cambio de frecuencia sin problemas durante un período de tiempo determinado?
  2. ¿Debería investigar las transformaciones de Fourier?
+0

Para generar una frecuencia de onda de pecado "real" de los contadores y temporizadores de uso de Hz deseado. Usando la fórmula sin, la frecuencia generada depende de la velocidad a la que se ejecuta el programa. – katta

Respuesta

14

si desea que la frecuencia angular (w = 2 pi f) varíe linealmente con el tiempo, entonces dw/dt = a y w = w0 + (wn-w0)*t/tn (donde t va de 0 a tn, w va de w0 a wn). fase es la integral de que, por lo phase = w0 t + (wn-w0)*t^2/(2tn) (como dice 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)); 
    } 
} 

(donde se tn intervalo y delta es t/tn).

Aquí está la salida para el código Python equivalente (1-10Hz más de 5 segundos):

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 dicho sea de paso, si estás escuchando a esta (o mirarlo - nada que involucra la percepción humana) sospecho que no quieres un aumento lineal, sino uno exponencial. pero eso es a different question ...

+0

¡¡fantástico !! Funcionó muy bien. cuando n_step es muy grande la fase - = 2 * PI es casi cero, por lo tanto sen (0) es 0. phase - = 2 * PI hace que la onda sinusoidal comience con valores negativos. El gráfico anterior es correcto cuando while loop está comentado. ¿Puede indicarme la fuente en la que leyó sobre esto? Me estaba soltando el pelo durante un par de días y me salvaste. Muchas gracias. Leí acerca de un aumento exponencial pero no pude entenderlo, puede pedirte que expliques de forma intuitiva. – katta

+0

+1 porque estoy sorprendido por tu habilidad ^^ – Offirmo

+0

corrigió el problema (flotante) en el código c, gracias. No entiendo el comentario sobre la fase, pero solo está allí en caso de que quiera que siempre esté en el rango 0-2PI. No lo leí en ninguna parte, lo resolví, pero hasta donde sé, es lo mismo que la entrada de la wikipedia (a la que me he vinculado y he comprobado más adelante). –

9

¿Cómo cambio la frecuencia sin problemas durante un período de tiempo determinado?

Una sinusoide lisa requiere una fase continua. La fase es la integral de la frecuencia, por lo que si tiene una función lineal para la frecuencia (es decir, un aumento de la tasa constante de f1 a f2), entonces la fase será una función cuadrática del tiempo.

Puede calcular las matemáticas con lápiz y papel, o puedo decirle que la forma de onda resultante se llama linear chirp.

¿Debería estar investigando las transformaciones de Fourier?

La transformada de Fourier de un chirrido lineal es en sí misma un chirrido lineal, por lo que probablemente no.

+0

Downvoter: ¿me gustaría comentar? –

+0

Gracias por señalarme en la dirección correcta – katta

2

Debe ser bastante simple. En lugar de pensar en variar la frecuencia, piense en hacer que un objeto gire más y más rápido. La distancia angular que ha recorrido podría ser X después de N segundos, pero será más de 2X (tal vez 4 veces) después de 2 segundos. Así que proponga una fórmula para la distancia angular (por ejemplo, alfa = k1 * T + k2 * T ** 2) y tome el seno de esa distancia angular para encontrar el valor de la forma de onda en cualquier 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

No del todo. Aunque esto es sencillo y se vería "bien" en una calculadora gráfica, una demostración rápida es suficiente para ilustrar el error. El uso de este código para generar un sonido rodeado por los sonidos de frecuencia de inicio y final muestra que no termina en el lugar correcto. Sine (startFreq, 1 segundo), sweep (startFreq, endFreq, 1 segundo), Sine (endFreq, 1 segundo), luego, si lo desea, realice un análisis espectral. Mi análisis espectral (Cool Edit Pro 2) muestra que va hasta 650 hertz más o menos. –

+0

¿Cuáles fueron sus entradas cuando su análisis espectral mostró 650 hertzios? Mi función puede no ser precisa, pero estoy bastante seguro de que su salida depende de su entrada. Este método vino de mi sintetizador de software, por cierto, y suena bien y se ve bien. – MusiGenesis

+0

@MusicGenesis Lo siento, ¡olvidé decirte los parámetros! Hice un barrido sinusoidal de 220 a 440 hz. Como dije, el barrido termina alrededor de las 650 hz antes de que suene el seno de 440. –

Cuestiones relacionadas