3

pcm.c と speaker-test.c のサイン ジェネレーターが、ループ内で新しいサイン バッファーを生成することに気付きました。そのため、常に同じバッファーを再作成します。CPU時間を節約するために、毎回バッファを再作成せずにバッファを再生したかったのです。ただし、最初にバッファーを構築してから同じバッファーを snd_pcm_writei に送信してコードを実行しようとすると、各バッファーの最後で少しクリック音がします。ただし、毎回再構築されてから snd_pcm_writei に送信されると、バッファの最後に小さなクリックはありません。クリックノイズが発生しないように、再生する前に毎回サインバッファを再構築する必要があるのはなぜですか?

何か助けていただければ幸いです。

pcm.c から:

while (1) {
    generate_sine(areas, 0, period_size, &phase);
    ptr = samples;
    cptr = period_size;
4

1 に答える 1

4

毎回同じ正弦波が生成されると仮定していますが、phase変数が使用されており、正弦波が常にバッファに正確に収まるとは限らないため、反復ごとに異なる正弦波が生成され、少しシフトされます。

毎回正弦波を生成しないと、正弦波の「ブレーク」につながります。

正弦波の代わりにノコギリ波で視覚化してみます。バッファー サイズが 16 で、波の値が A から H までの範囲であるとします。

// Old way
  phase = 0        phase = 2        phase = 4
ABCDEFGHGFEDCBAB|CDEFGHGFEDCBABCD|EFGHGFEDCBABCDEF....

// New way
  phase = 0        phase = 0        phase = 0
ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB....

サウンドが「不正な形式」であるバッファ エッジの周囲には小さな断片しかないことに注意してください (たとえば、AB|ABの代わりにAB|CD)。これが、その間にいくつかの不穏な短い「クリック」が発生しても、ほとんどの場合正しく聞こえる理由です。

まれに、バッファー長が波長の倍数である場合、またはphaseが前の反復と同じ値である場合、実際にはバッファーの生成をスキップする可能性がありますが、毎回実行することはできません。

編集: generate_sine関数を見て、どのようphaseに変更されたかを確認します。

static void generate_sine(const snd_pcm_channel_area_t *areas, 
                          snd_pcm_uframes_t offset,
                          int count, double *_phase)
{
    static double max_phase = 2. * M_PI;
    double phase = *_phase;
    double step = max_phase*freq/(double)rate;

    [...]

             phase += step;
             if (phase >= max_phase)
                    phase -= max_phase;
     }
     *_phase = phase;
}

EDIT2:この画像は、より良い/より明確な視覚化になる可能性があります:

ここに画像の説明を入力

于 2011-05-07T11:08:38.353 に答える