2

トーン ジェネレーター アプリでオシレーターの波形タイプを生成するコードを少し作成したいと考えています。この例の 1 つは正弦波です。コードがどのように機能するか教えてください。将来的にカスタムの波形タイプと正方形、のこぎり歯、および三角形のタイプを作成したいと考えています。

OSStatus RenderTone(
    void *inRefCon, 
    AudioUnitRenderActionFlags  *ioActionFlags, 
    const AudioTimeStamp        *inTimeStamp, 
    UInt32                      inBusNumber, 
    UInt32                      inNumberFrames, 
    AudioBufferList             *ioData)

{
    // Fixed amplitude is good enough for our purposes
    const double amplitude = 0.25;

    // Get the tone parameters out of the view controller
    ToneGeneratorViewController *viewController =
        (ToneGeneratorViewController *)inRefCon;
    double theta = viewController->theta;
    double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

    // This is a mono tone generator so we only need the first buffer
    const int channel = 0;
    Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;

     // 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;
        } 
    }

    // Store the theta back in the view controller
    viewController->theta = theta;

    return noErr;

}
4

2 に答える 2

1

目的の波形を生成するには、sin()関数を目的の波形を生成する関数に置き換える必要があります。

この関数は、グラフィカルな例を含む関数の表で見つけることができる場合があります。または、関数を作成する必要がある場合があります。関数近似を作成する方法はたくさんあります。たとえば、多項式、フーリエ級数、補間の有無にかかわらずテーブルルックアップ、再帰などがあります。しかし、それ自体が大きなテーマです(多くの教科書など)。

于 2012-02-08T22:21:55.710 に答える
1

以下のスニペットでは、実際の正弦波サンプルが生成され、バッファに入力されています。

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;
    } 
}

が割り当てられている行でbuffer[frame]は、 を呼び出しており、ループsin(theta) * amplitudeの反復ごとに、周波数とサンプルレートに基づいて有限のステップ サイズをインクリメントしています。fortheta

double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

2.0 * PI * frequencyこれは基本的にサンプルレートで割っています。

thetaループをループしながら変数をインクリメントするforことは、基本的に、バッファがいっぱいになるまで (つまり、) タイム ステップを一度に 1 サンプルずつ進めることframe == iNumberFramesです。

正弦波以外のものを生成したい場合は、次の行を他の関数に置き換えるだけです。

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

たとえば、三角波に収束する無限フーリエ級数の最初の 3 つの項が必要だとします。代わりに次のようにすることができます...

buffer[frame] = (8 / pow(M_PI,2)) * (sin(theta) - sin(3*theta)/9 + sin(5*theta)/25);
于 2012-02-08T17:37:58.583 に答える