2014-04-05 26 views
2

我目前使用PyAudio對適合的應用我計劃的具體需要一個輕量級的記錄工具工作同步播放和錄製。我正在使用ASIO音頻接口。我正在編寫的程序是通過界面播放一個wav文件,同時記錄界面的輸出。該接口正在實時處理板載信號並更改音頻。因爲我打算導入此渲染輸出到DAW,我需要的輸出與輸入的音頻完美同步。使用DAW我可以同時播放音頻到我的界面並記錄輸出。當我這樣做時,它在DAW中完全同步。我的實用程序的目的是能夠從一個python腳本中觸發。PyAudio -

通過蠻力的方法,我提出了一個可行的解決方案,但我現在堅持使用一個幻數,我不確定這是某種常數還是我可以計算的東西。如果這是一個數字,我可以計算出這將是理想的,但我仍然想知道它從哪裏來。

我的回調如下:

def testCallback(in_data, frame_count, time_info, status): 
    #read data from wave file 
    data = wave_file.readframes(frame_count) 
    #calculate number of latency frames for playback and recording 
    #1060 is my magic number 
    latencyCalc = math.ceil((stream.get_output_latency() + stream.get_input_latency()) * wave_file.getframerate()) + 1060 

    #no more data in playback file 
    if data == "": 
     #this is the number of times we must keep the loop alive to capture all playback 
     recordEndBuffer = latencyCalc/frame_count 
     if lastCt < recordEndBuffer: 
      #return 0-byte data to keep callback alive 
      data = b"0"*wave_file.getsampwidth()*frame_count 
      lastCt += 1 
    #we start recording before playback, so this accounts for the initial "pre-playback" data in the output file 
    if firstCt > (latencyCalc/frame_count): 
     wave_out.writeframes(in_data) 
    else: 
     firstCt += 1 
    return (data, pyaudio.paContinue) 

我擔心的是在功能:

latencyCalc = math.ceil((stream.get_output_latency() + stream.get_input_latency()) * wave_file.getframerate()) + 1060 

我把這個計算起來通過觀察相較於原始播放我的輸出文件的偏移文件。發生了兩件事,我的輸出文件在同時播放時比原始文件開始時間晚,並且也會提前結束。通過試驗和錯誤,我確定它在開始時是額外的特定數量的幀,並在最後丟失。這將計算這些幀數。我明白的第一塊,它是輸入/輸出延遲(在第二/一秒精度提供)轉換爲使用採樣速率幀。但我不太清楚如何填寫1060的價值,因爲我不確定它來自哪裏。

我發現,通過播放ASIO驅動程序上的延遲設置,我的應用程序可以繼續正確地同步錄製的文件,即使上述輸出/輸入延遲由於調整而改變(輸入/輸出延遲始終是相同的值),所以1060在我的機器上看起來是一致的。但是,我根本不知道這是否是可以計算的值。或者,如果它是一個特定的常數,我不確定它代表了什麼。

更好地理解這些值任何幫助,將不勝感激。我很高興我的實用程序現在能夠正常工作,但是想要完全理解這裏發生的事情,因爲我懷疑可能使用不同的界面可能不再正常工作(我想通過幾個原因支持這一點)。

EDIT 2014年4月8日響應於羅伯特: 我接收對所述值 latencyCalc = math.ceil((stream.get_output_latency()+ stream.get_input_latency())* wave_file.getframerate()) + 1060 是8576,與額外1060使總延遲到9636幀。你假設我爲什麼添加了1060幀是正確的。我打通過外部接口ASIO的文件,我希望在我的記錄文件中捕捉處理是界面(不是我有編碼)上發生的處理結果。爲了比較輸出,我只是簡單地播放了測試文件並記錄了界面的輸出,而沒有對界面進行任何處理。然後我審查了Audacity中的兩條曲目,通過反覆試驗確定1060是最接近的,我可以讓這兩條曲線對齊。之後我意識到它仍然不完美,但當它同時播放時(這在1060偏移被移除時,這是一個明顯的延遲)是非常接近和聽不到的。與1060相比,添加/刪除額外的框架也會產生過多的補償。

我相信你是正確的,額外的延遲來自外部接口。我最初想知道這是否可以用我手邊的數字信息來計算,但我得出結論,它只是界面中的一個常數。我覺得這是真的,因爲我確定如果我刪除了1060,文件的偏移量與執行相同的測試完全相同,但是在收割者中手動執行(這正是我自動執行的過程)。我得到的延遲比我在新的暴力抵消方面的收益要好得多,所以我打算稱之爲贏。在我的應用程序中,目標是用新處理的文件完全替換原始文件,因此希望兩者之間的絕對最小延遲。

回答您在PyAudio中關於ASIO的問題時,答案是幸運的。您必須使用用於PortAudio的ASIO SDK編譯PortAudio才能使用ASIO,然後更新PyAudio設置以便以此方式進行編譯。幸運的是,我正在開發windows,http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio,它內置了ASIO支持,然後可以通過ASIO訪問這些設備。

回答

1

由於我不能發表評論,我會在這裏問你:stream.get_output_latency() + stream.get_input_latency()) * wave_file.getframerate()的價值是多少?你是如何得到這個數字1060在第一位?
使用您標記的代碼行:
latencyCalc = math.ceil((stream.get_output_latency() + stream.get_input_latency()) * wave_file.getframerate()) + 1060,您只需爲總延遲添加額外的1060幀即可。從描述中我不清楚,爲什麼要這麼做,但是我假設您已經測量了生成文件中的總延遲,除輸入延遲+輸出延遲總和外,總是有額外的幀數。那麼,你認爲這種額外的延遲可能是由於處理?你說你對輸入音頻信號做了一些處理;並且處理當然需要一些時間。嘗試對未改變的輸入信號進行同樣的處理,並查看是否減少/移除了額外的延遲。即使您的應用程序的其他部分,例如如果應用程序具有GUI,那麼所有這些都會降低錄製速度。你沒有完全描述你的應用程序,但我猜測額外的延遲是由你的代碼和代碼的操作引起的。爲什麼'魔術數字'總是一樣的?因爲你的代碼總是一樣的。

簡歷:
'幻數'代表什麼?
顯然,除了總的往返延遲外,它還會帶來一些額外的延遲。
什麼是造成這種額外的延遲?
原因很可能是在您的代碼中的某處。你的應用程序正在做某些事情需要一些額外的時間,因此會造成一些額外的延遲。我想到的唯一可能的事情是,您已在您的設置中添加了一些額外的「沉默期」,因此您也可以查看此內容。

+0

對於正確的迴應,評論太有限,所以我編輯了我的原始問題以解決您的問題。 – user3500739

+0

您是否使用MinGW/MSYS工具鏈編譯portaudio? – roberto

+0

不,我在我提供的鏈接中使用了預編譯的安裝程序。 – user3500739