0

ボタンが押されたときに生成された信号を再生するために単一のオーディオユニットを使用する iOS/Objective-C プログラムがあります。次のような機能を追加したいと思います。

a) ボタンが最初に押されると、ある種の数値配列で信号が生成されます。

b) オーディオが開始され、レンダリング コールバックがその生成された信号にアクセス (および再生) します。

私の現在のコードを考えると、これらの追加はほんの数行になると思いますが、構文、使用する変数の型、現在のサンプルを追跡する方法などに問題があります。関連するコードをそのまま含めました。


ボタンを押す:

- (IBAction)startPressed:(id)sender {
        [self setupAudioPlayer];
        [self createSignal];
        [self playAudio];
}

setupAudioPlayer からの行:

input.inputProcRefCon=&mySignal; // mySignal is an instance var

オーディオの作成:

-(void)createSignal{
    int beepLength=0.020*Fs; // Fs is sampling frequency
    float beepFrequency=440; // Hz

    // Declare some kind of numeric array "mySignal", which is an instance var.
    mySignal=...?

    // Generate audio signal (pure tone)
    for (int i=1; i<=beepLength; i++) {
        float t=i/Fs;
        mySignal[i]=sinf(2*M_PI*beepFrequency*t);
    }
}

レンダリング コールバック:

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

{
    const int channel1 = 0;
    Float32 *buffer = (Float32 *)ioData->mBuffers[channel1].mData;

    // This is where things get hazy
    Float32 *mySignal=(Float32 *)inRefCon;
    for (UInt32 frame = 0; frame < inNumberFrames; frame++)
    {
            buffer[frame]=mySignal[?]; 
    }

    return noErr;
}

私の質問を要約すると、mySignal はどのように定義する必要がありますか? RenderTone からこのインスタンス変数にアクセスするにはどうすればよいですか (上記の「漠然とした」コードは単なる推測です)。RenderTone で現在のサンプルを追跡するにはどうすればよいですか? このアプローチで欠けている/不安定なものは他にありますか?

読んでくれてありがとう、そして助けてくれて本当にありがとう!

(ビュー コントローラーのインスタンスへの参照をレンダー コールバックに渡し、その方法でインスタンス変数にアクセスするサンプル コードを見てきました。このような厳密なタイミング要件を持つコールバックの計算オーバーヘッド。)

4

1 に答える 1

1

代数関数からフレームを生成しているので、単純にMatt Gallagher の例に従ってみませんか? 簡単に言うと、render コールバック内に関数を移動し、vc インスタンスを介してパラメーターを転送するだけです。

一般的に言えば、事前定義されたフォームを持つコールバックにデータを渡すための選択肢は限られています。Objective C の適切な形式について助言するのはおそらく私が最後ですが、数少ないオプションの 1 つはグローバルを使用することです。

mySignal配列 (または頻度) をグローバルとして渡すことができます。最も「エレガントな」オブジェクト指向ソリューションではありませんが、機能し、オブジェクト指向のすべてのオーバーヘッドを回避するものです。render コールバックは基本的に C 関数であるため、C ベースのソリューションを使用するのにのみ適しているようです。

「追跡」に関しては、あなたが何を意味するのかよくわかりませんが、トーンを生成する私自身の作業ではremainingCycles、トーンの長さでグローバルを初期化しました(フレームサイクルで=秒の長さ*FsまたはsampleRateあなたがそれを呼びたいものは何でも)frameループを通過するたびにデクリメントします。数字がゼロになると、トーンが終了します。(もちろん、グローバルの代わりにインスタンス変数を使用することもできます。)

これはオブジェクト指向コーディングの規範に違反している可能性がありますが、結局のところ、仕事を終わらせる必要があるだけです。

于 2013-05-16T16:32:40.357 に答える