2016-07-13 11 views
1

私はPortAudioのコールバックAPIを使ってシグナル処理ループバックライブラリを設計しています。PortAudioのコールバックと他の場所で変数を変更する

私はそう

do_something_flagが定期的に別の場所で私のプログラムで設定されている
int pa_callback(const void *inputuffer, 
       void *outputBuffer, 
       unsigned long frameCount, 
       const PaStreamCallbackTimeInfo *timeInfo, 
       PaStreamCallbackFlags statusFlags, 
       void *userData) 
{ 
    if (do_something_flag) { 
    do_something(inputBuffer, outputBuffer, frameCount); 
    } else { 
    do_something_else(inputBuffer, outputBuffer, frameCount); 
    } 

    return paContinue; 
} 

のように、コールバック内のフラグに依存枝を追加したいと思います。

PortAudioコールバックのドキュメントの状態:

始める前に、それはコールバックが 繊細な場所であることを認識することが重要です。これは、一部のシステムで 特殊スレッドまたは割り込みハンドラでコールバックを実行するため、残りのコードと同じように扱われることはほとんどありません。最新のシステムでは、 はコールバックで許可されていない呼び出しを行うことでクラッシュする可能性がありますが、 では、コードにグリッチフリーのオーディオを生成したい場合は、 実行に無制限の量の をとります。これらはお使いのプラットフォームによって異なりますが、 には次のものが含まれていることがほとんどです。メモリ 割り当て/割り当て解除、I/O(ファイルI/Oおよびprintf()などのコンソール I/Oを含む) exec()やyield())、 mutex操作、またはOSに依存する可能性のあるその他のものが含まれます。 の場合、短いクリティカルセクションが安全であると考える場合は、優先度 の逆転についてお読みください。

do_something_flagのアトミック性については気にしません。つまり、正しい値(理由の範囲内)を得るために必要なサイクル数は気にしません。 ドキュメントによると、私はmutexを使ってその変数を設定/読み込むことはできないようです。

1)私のオプションは何ですか?

2)グローバル化してプログラムの別の部分(別のスレッド)に設定した場合、どうなるのでしょうか?ここでもまた、プログラムの失敗点などのデータを破壊するという意味です。

これを行う正しい方法はありますか?

答えて

1

私はあなたがしていることを完全には確信していませんが、私はあなたのタイトルが尋ねていることを推測しています - 「変数を別の場所に変更する」。

この例を考えてみましょう:時間の経過と共に変化する変数frequencyがあります。どのようにこれにアクセスしますか?コールバックにuserDataという汎用ポインタがあります。これは何かを指すことができます - データ構造、配列など私はコールバック関数が呼び出される頻度を覚えていません(それはかなり頻繁に...私はスピードについて心配しませんが)userDataは変数それはあなたのメインスレッドで変更することができますが、オーディオスレッドのポインタは、メモリに直接アクセスすることができます...スレッドの安全性に関する私の知識は最高ではなく、申し訳ありません。少なくともコードを使ってそれを行う方法を示します(下記参照)。

これは私が通常行う方法ですが、自分で行う必要はありません。 dataのタイプがある(

明らか
typedef struct { 
    float freq; 
    float vol; 
}paData; 

あなたは(おそらくあなたのmain関数呼び出しに)あなたのコードでは、このどこかを初期化するだろうとのようなオーディオストリームを開く:私はそうのような私のファイルの先頭に構造を設定しますpaData):あなたはこのようなあなたのコールバックを持つことができ、それを開いた後

/* Open audio stream */ 
err = Pa_OpenStream(&(*stream), 
     &inputParameters, 
     &outputParameters, 
     SAMPLE_RATE, bufSize, paNoFlag, 
     paCallback, &data); 

static int pa_callback(const void *inputBffer, 
      void *outputBuffer, 
      unsigned long frameCount, 
      const PaStreamCallbackTimeInfo *timeInfo, 
      PaStreamCallbackFlags statusFlags, 
      void *userData) 
{ 
    // cast data so we can use it 
    paData *data = (paData *)userData; 

    // what's our frequency? 
    printf("%f\n", data->freq); 

    /* Do something with your code here */ 

    return paContinue; 
} 

お役に立てば幸いです。

+0

ええ、それは完璧です。私はスレッドの安全性、アトミシティ、グローバル変数に関心を持っていましたが、私は単純な答えは見ませんでした。 – justynnuff

+0

あなた自身で新しいAPIを学ぶのは難しいですね... PortAudioを学んだときに幸運にも偉大な先生がいました。あなたがやっていることで幸運! –

+0

HI @ yun.cloud、私は最近、音声の取得とportaudioを使用した処理を開始しました。私はそれを実装する際に少し問題に直面しています。私はここでstackoverflow(https://stackoverflow.com/questions/44645466/portaudio-real-time-audio-processing-for-continuous-input-stream)に質問を掲載しました。どんな種類の助けも大歓迎です。 –

関連する問題