在给定时间内从f1到f2缓慢上升频率的正弦波

我正在编写交流程序,以产生一个正弦波,在给定的时间间隔内,从f1到f2的频率缓慢上升。

我已经编写了这个c程序来将频率从0增加到10 Hz,但问题是频率在完成360度后会发生变化。 如果我试图改变0到360度之间的频率,那么转换不平滑且突然。

这是我用过的罪的等式y =幅度* sin(频率*相位)

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. 如何在给定时间段内平滑地改变频率?
  2. 我应该研究傅立叶变换吗?

如果你想要角频率(w = 2 pi f)随时间线性变化那么dw/dt = aw = w0 + (wn-w0)*t/tn (其中t从0到tnww0 to wn )。 phase是其中的积分,因此phase = w0 t + (wn-w0)*t^2/(2tn) (正如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)); } } 

(其中interval是tn,delta是t / tn)。

这是等效python代码的输出(1-10Hz超过5秒):

1-10 Hz超过5秒

 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) 

顺便说一句,如果你正在听这个(或者看着它 – 任何涉及人类感知的东西),我怀疑你不想要线性增加,而是指数增长。 但这是一个不同的问题 ……

如何在给定时间段内平滑地改变频率?

平滑的正弦曲线需要连续相位。 相位是频率的积分,因此如果您具有频率的线性函数(即从f1到f2的恒定速率增加),则相位将是时间的二次函数。

你可以用笔和纸来计算数学,或者我可以告诉你结果波形被称为线性啁啾

我应该研究傅立叶变换吗?

线性啁啾的傅里叶变换本身就是线性啁啾,所以可能没有。

它应该相当简单。 不要考虑改变频率,而是考虑让物体旋转越来越快。 它经过的角距离在N秒后可能是X,但在2N秒后将超过2倍(可能是4X)。 因此,想出一个角距离的公式(例如,alpha = k1 * T + k2 * T ** 2)并取该角距离的正弦值以在任何时间T找到波形的值。

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