2017-09-05 61 views
0

私はpyaudioを使用して、チャンクで処理したいオーディオを記録します(たとえば、5秒ごと)。私は、記録されたオーディオの1500サンプルごとに呼び出され、その関数内でそれらのサンプルがキューに追加されるコールバック関数でコールバックモードでpyaudioを使用しています。また、サンプルが期待どおりであることを確認するために記録されているので、サンプルをwavファイルに保存しています。コールバックモードでpyaudioを使用したPythonを使用したスレッディング問題

q = Queue.Queue() 
flag = False 
waveFile = wave.open('recording.wav', 'wb') 
waveFile.setnchannels(1) 
waveFile.setsampwidth(2) 
waveFile.setframerate(RATE) 


def callback(in_data, frame_count, time_info, status): 
    silent = is_silent(in_data) 
    if silent == False: 
     numpydata = np.fromstring(in_data, dtype=np.int16) 
     waveFile.writeframes(in_data) 
     q.put(numpydata) 
     callback_flag = pyaudio.paContinue 

    elif silent == True and flag == True: 
     numpydata = np.fromstring(in_data, dtype=np.int16) 
     if len(numpydata) != 0: 
      waveFile.writeframes(in_data) 
      q.put(numpydata) 
     waveFile.close() 
     callback_flag = pyaudio.paComplete 
    else: 
     callback_flag = pyaudio.paContinue 

    return (in_data, callback_flag) 

p=pyaudio.PyAudio() # start the PyAudio class 
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,frames_per_buffer=1500, stream_callback = callback) #uses default input device 

キューがもはや空になると、私は別々のバッファにキューからデータを追加し、オーディオの5秒が追加されていたときに、そのバッファ内のデータを処理whileループを入力します。

while q.empty() == True: 
if q.empty() == False: 
    break 

buf = [] 

while 1: 
    flag = True 
    try: 
     snd_data = q.get(True,timeout = 4) 
     buf.extend(snd_data) 
     if len(buf) >= 220500: 

      process audio... 


    except Queue.Empty: 

私の問題は、プログラムが簡単にいくつかのサンプルのための記録を停止し、再び起動しているかのよう私は、オーディオ信号に奇妙な予期せぬ不具合に気付いていますということです。 Audacityで録音したwavファイルを開き、信号を拡大することでこれを見ることができます。私はpyaudioが1500サンプルごとに別々のスレッドでコールバック関数を呼び出すため、コールバック関数を呼び出そうとするが、前のコールバック関数のスレッドがまだ開いていて、このコールバック関数がまだ終了していないために起こっていると思うまだキューなどに追加されています(これは矛盾した説明である場合は謝罪しますが、私はどの用語を使用するかについてはあまりよく分かりません)。

この問題を解決する方法を知っている人はいますか?以前のコールバック関数が処理を完了した後にのみ各コールバック関数が呼び出されるように同期させる方法はありますか?

答えて

0

あなたがコールバック関数で行うことについては非常に注意する必要があります。特に、そこにあるファイルを読み書きしないでください。 あなたは、デバッグのためだけにファイルを書き込んでいると述べましたが、実際にはこの問題が発生する可能性があります。

また、コールバック関数の引数は常にstatusであることを確認する必要があります。これは、オーバーランまたはアンダーランがあるかどうかを示します。 オーバーランやアンダーランが発生している場合は、ブロックサイズ(およびレイテンシ)が消えるまで増やしてください。

ここでは、そのレコードをサウンドファイルに作成したスクリプトの例を示します:rec_unlimited.py。 次に、入力信号をプロットする例を示します。plot_input.py。これをプロットするのではなく、他の処理を行うように変更することができます。

以前のコールバック関数が処理を完了した後にのみ各コールバック関数が呼び出されるように、同期化の方法はありますか?

これは実際には既にありますが、コールバック関数の呼び出しは重複しません。しかし、コールバック関数の1回の呼び出しに時間がかかりすぎると、生成された出力データをサウンドカードに送信するのが遅すぎ、このオーディオデータを破棄しなければならなくなり、可聴ドロップアウトになります。これは「出力アンダーラン」と呼ばれます。 コールバック関数の前回の呼び出しに時間がかかりすぎると、利用可能なオーディオ入力データが多すぎます。そのうちいくつかは破棄する必要があり、再度ドロップアウトになります。これは「入力オーバーラン」と呼ばれます。

+0

あなたの有益な返答をお寄せいただきありがとうございます。私はコールバック関数内からオーディオを処理することで問題を取り除いたようですが(私はとにかくそう考えていますが)、あなたのスクリプトを見て、それらを自分の目的に合わせて試してみます。 – CJF

関連する問題