3

同様のことをする必要があるため、iOS でのサウンド生成に関するこの例を見ていますが、理解できない部分がいくつかあり、誰かがそれを手伝ってくれることを望んでいました。

コードのこの部分では:

    double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;
    // Generate the samples
    for (UInt32 frame = 0; frame < inNumberFrames; frame++) 
    {
        buffer[frame] = sin(theta) * amplitude;

        theta += theta_increment;
        if (theta > 2.0 * M_PI)
        {
            theta -= 2.0 * M_PI;
        }
    }

何のための部品なのかよくわかりませんtheta += theta_increment;。私にとっては、for ループ内で次のようなことを行う方が理にかなっています。

buffer[frame] = sin(theta_increment * frame);

なぜそれがうまくいかないのですか?また、コードのこの部分が何のためにあるのかわからないif (theta > 2.0 * M_PI)ので、それについての説明も大歓迎です。

4

2 に答える 2

0

私はそれがあなたのやり方でうまくいくと想像します(しかし、振幅を掛けることを忘れないでください):

buffer[frame] = sin(theta_increment * frame) * amplitude;

同じ数学を表現する2つの異なる方法。元のコードを書いた人が0<=theta <2piを維持したかったように見えますが、これはおそらく必要ありません(sin()呼び出しが私が知らない方法で奇妙でない限り)。また、同じスニペットが他の場所のループに表示される場合に備えて、「数学」の部分をフレーム変数から独立させたいと考えていたかもしれませんが、それは単なる推測です。

于 2012-03-06T02:47:23.737 に答える
0

あなたのアプローチを使用して、同じ結果を別の方法で作成することができます。ただし、theta += theta_increment;提案するものよりも (計算する) 単純な式になります。

フェーズのドメインは、sin'論理パラメーター ドメインにラップされます。この手順は、短いサンプルでは必要ありません。float浮動小数点ストレージの制限により、値がラップされていない場合、生成するサンプルの数とまたはを使用するかどうかによって、周波数は最終的に変化し、最終的には増加しませんdouble。次のように考えてみてください:巨大な正の浮動小数点数 (位相アキュムレータの値) があり、加算しようとするとどうなるでしょうか。0.000004それに?浮動小数点エラーは、float または double に収まるように丸められ、エラーによって位相が不安定になり、最終的にはピッチが不安定になります。短いサンプル (たとえば、いくつかのサイクル) の場合、ラップは必要ありませんが、多くのサイクルでは、時間の経過とともにピッチと位相のアキュムレータを安定させる役割を果たします。

最後に、theta を使用してフェーズ ランプの最後の値を格納し、次のレンダリング呼び出しで中断したところから生成を再開します。これがないと、レンダリング呼び出しの境界で出力が 0 から再開され、非常に不快なノイズと間違った周波数が生成されます。

すべてのことを考慮すると、それは単純なデモであり、そのコンテキストで正弦波を生成するための高速な方法だった可能性があります. あなたのアプローチにはいくつかの「コストのかかる」変換がありますが、それはブランチレスです。特に、より高い周波数では、元の方法よりも高速になる可能性があります。

于 2012-03-06T03:02:06.947 に答える