9

我正在编写 ac 程序来生成一个正弦波,该正弦波在给定的时间间隔内将频率从 f1 缓慢上升到 f2。

我已经编写了这个 c 程序来将频率从 0 提升到 10 Hz,但问题是完成 360 度后频率会发生变化。如果我尝试在 0 到 360 度之间更改频率,则过渡不平滑且突然。

这是我使用的等式 y = Amplitude*sin(freq*phase)

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. 我应该研究傅立叶变换吗?
4

4 回答 4

14

如果您希望角频率(w = 2 pi f)随时间线性变化,那么dw/dt = aw = w0 + (wn-w0)*t/tnt0 到tnww0wn)。相位是它的积分,所以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));
    }
}

(其中间隔为 tn,增量为 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)

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

于 2012-06-26T01:58:15.887 回答
9

如何在给定的时间段内平稳地更改频率?

平滑的正弦曲线需要连续相位。相位是频率的积分,所以如果你有一个频率的线性函数(即从 f1 到 f2 的恒定速率增加),那么相位将是时间的二次函数。

你可以用笔和纸算出数学,或者我可以告诉你,得到的波形称为线性啁啾

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

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

于 2012-06-26T01:08:22.383 回答
2

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

于 2012-06-26T01:15:33.633 回答
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);
}

}
于 2012-06-26T02:02:11.257 回答