2016-03-29 5 views
0

私は現在、Pythonを使って再生と記録の機能を同期させるアルゴリズムを実装しています。このアルゴリズムは、マイクロホンとスピーカーの間のタイムラグや遅延を測定するために使用されるため、内部レイテンシとソフトウェア実行時間の観点から、タイミングは非常に正確でなければなりません。 私は、スレッド化モジュールを使って、これらの関数をPythonで同期させることができました。しかし、これが最良のオプションであるかどうかは不明ですが、マルチスレッドなどの他のモジュールがそこにあることを示しています。私の専門知識と経験に欠けているのは、Pythonでマルチスレッド(非同期/同期)モジュールを使用しているため、以下のスクリプトに示すように、スレッドモジュールの基本を実装しただけです。また、私はそれにロック機能があることを知っているが、それは私のアプリケーションを与えることに役立つだろうか?関数のタイムスタンプ実行とPythonのスレッド化

私が前に述べたように、私のアプリケーションでは正確なタイミングが重要です。私は記録と再生の両方の関数が実行されているインスタンスをタイムスタンプしようとしていますが、これまでデータ/サンプルが各バッファに供給される前に単にtime.time()を呼び出しています。しかし、私はそのtime.clock()とtime.process_time()が私により正確なタイムスタンプを与えるかもしれません。しかし、そこにはもっと良い解決策があるかもしれないと私は確信しています。追加するには

#!/usr/bin/env python3 
import pyaudio 
import numpy as np 
import time 
import glob 
import wave 
import threading 

rec_start=0.0 
play_start=0.0 
rec_signal = np.array([],dtype=np.float64) 

def record(): 
    RATE = 16000 
    DURATION = 0.5 
    CHUNKSIZE_REC = 2**12 

    global rec_signal 
    global rec_start 

    #initialize portaudio 
    p_rec = pyaudio.PyAudio() 
    stream = p_rec.open(format=pyaudio.paInt16, 
        channels=1,rate=RATE, 
        input=True,frames_per_buffer=CHUNKSIZE_REC) 

    frames = [] 
    rec_start = time.time() 
    for _ in range(0,int(RATE/CHUNKSIZE_REC*DURATION)): 
     data = stream.read(CHUNKSIZE_REC) 
     frames.append(np.fromstring(data,dtype=np.int16)) 

    #convert the list of numpy-arrays into a 1D array (column-wise) 
    numpydata = np.hstack(frames) 

    #close stream 
    stream.stop_stream() 
    stream.close() 
    p_rec.terminate() 

    rec_signal = numpydata 
#end def 

#----------------------------------------------------------------------------- 
def playback(): 
    CHUNKSIZE_PLAY = 2**12 
    global play_start 

    wf =wave.open('AC_PRN_Signal.wav','rb') 
    p_play = pyaudio.PyAudio() 
    stream = p_play.open(format=p_play.get_format_from_width(wf.getsampwidth()), 
         channels=wf.getnchannels(), 
         rate=wf.getframerate(), 
         output=True) 
    playData = wf.readframes(CHUNKSIZE_PLAY) 
    time.sleep(0.005) 
    play_start =time.time() 
    while playData !='': 
     stream.write(playData) 
     playData = wf.readframes(CHUNKSIZE_PLAY) 

    stream.stop_stream() 
    stream.close() 
    p_play.terminate() 
#end def 

#----------------------------------------------------------------------- 
def play_while_recording(): 
    rec_thread = threading.Thread(target=record) 
    play_thread = threading.Thread(target=playback) 

    '''start recording while playing back signal''' 
    rec_thread.start() 
    play_thread.start() 

    '''stop both threads before exiting func.''' 
    play_thread.join() 
    rec_thread.join() 

#end def 
#--------------------------------------------------------------------- 
if __name__ == "__main__": 
    play_while_recording() 
    global rec_signal 
    global rec_start 
    global play_start 

    print("rec start @ "+str(rec_start)) 
    print("play start @ "+str(play_start)) 
    print("time_delta: "+str((play_start-rec_start)*1000.0)+"ms") 

、私はまた、以下に示すように、LinuxのALSAのはaplayとarecordを呼び出し、その後、scipy.io.wavefileを使用して、それらの波ファイルを読み込み、ポストを実行するためにpythonでsubprocesモジュールに実装され、テストされています処理。しかし、私はそれが実際に実行の時間インスタンスを取得するか、またはタイムスタンプを取得することは本当に難しいと思っています。

def playback(): 
    global play_start 
    time.sleep(0.005) 
    play_start =time.time() 
    subprocess.Popen(["/usr/bin/aplay","test_audio.wav"]) 
#end def 

答えて

1

タイムスタンプの実行に関する議論が多すぎることがあります。 私はすぐに私の2セントを共有することができます

  • 時間() - LINUX/UNIX上で、より良い使用すると
  • クロック() - より良いprocess_time
  • Windows上を使用するためには、() - のみのシステムとユーザーを算出し、 CPU時間ですが、スリープ時間は除外されます
  • クロスプラットフォームソリューションが必要な場合は、「timeit」モジュールを使用する必要があります。コードから直接呼び出すだけでなく、コマンドラインから呼び出すこともできます。これは大きな利点です。

あなたは

ウォールクロック時間や処理時間、あなたはまた、使用するクロックを選択することができますcProfileを使用することができ、あなたのコードをプロファイリングする場合
関連する問題