9

特定の時間間隔で周波数を f1 から f2 にゆっくりと上昇させる正弦波を生成する ac プログラムを作成しています。

周波数を 0 から 10 Hz にランプするこの C プログラムを作成しましたが、問題は、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/tn( t0 から までtnwからw0までwn) になります。位相はその積分であるため、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 コードの出力は次のとおりです (5 秒間で 1 ~ 10Hz)。

5 秒間で 1 ~ 10 Hz

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 ちなみに、これを聞いている (または見ている - 人間の知覚に関係するものなら何でも) 場合は、直線的な増加ではなく、指数関数的な増加を望んでいると思います。しかし、それは別の質問です...

于 2012-06-26T01:58:15.887 に答える
9

特定の期間の頻度をスムーズに変更するにはどうすればよいですか?

滑らかな正弦波には連続位相が必要です。位相は周波数の積分であるため、周波数の線形関数 (つまり、f1 から f2 への一定率の増加) がある場合、位相は時間の二次関数になります。

ペンと紙で数学を理解するか、結果の波形が線形チャープと呼ばれることをお伝えできます。

フーリエ変換を調べる必要がありますか?

線形チャープのフーリエ変換自体は線形チャープであるため、おそらく違います。

于 2012-06-26T01:08:22.383 に答える
2

それはかなり単純なはずです。周波数を変えることを考えるのではなく、オブジェクトをどんどん速く回転させることを考えてください。移動した角度距離は、N 秒後に X になる可能性がありますが、2N 秒後には 2X (おそらく 4X) 以上になります。したがって、角度距離の式 (たとえば、アルファ = 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 に答える