2015-09-14 86 views
3

我想使用python和pyaudio來記錄和回放一些音頻。 我正在使用連接到C-Media Electronics,Inc. CM108音頻控制器作爲默認設備的覆盆子pi的麥克風。使用python和pyaudio的通道和採樣率

此設備僅記錄單聲道。

0 - USB PnP Sound Device: USB Audio (hw:0,0) 
    {'defaultSampleRate': 44100.0, 'defaultLowOutputLatency': 0.011609977324263039, 'defaultLowInputLatency': 0.011609977324263039, 'maxInputChannels': 1L, 'structVersion': 2L, 'hostApi': 0L, 'index': 0, 'defaultHighOutputLatency': 0.046439909297052155, 'maxOutputChannels': 2L, 'name': u'USB PnP Sound Device: USB Audio (hw:0,0)', 'defaultHighInputLatency': 0.046439909297052155} 

記錄碼

import pyaudio, wave, sys 
    CHUNK = 8192 
    FORMAT = pyaudio.paInt16 
    CHANNELS = 1 
    RATE = 44100 
    RECORD_SECONDS = 10 
    WAVE_OUTPUT_FILENAME = 'Audio_.wav' 
    p = pyaudio.PyAudio() 
    stream = p.open(format=FORMAT, 
      channels = CHANNELS, 
      rate = RATE, 
      input = True, 
      input_device_index = 0, 
      frames_per_buffer = CHUNK) 
    print("* recording") 
    frames = [] 
    for i in range(0, int(RATE/CHUNK * RECORD_SECONDS)): 
     data = stream.read(CHUNK) 
     frames.append(data) 
    print("* done recording") 
    stream.stop_stream() # "Stop Audio Recording 
    stream.close()   # "Close Audio Recording 
    p.terminate()   # "Audio System Close 

    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') 
    wf.setnchannels(CHANNELS) 
    wf.setsampwidth(p.get_sample_size(FORMAT)) 
    wf.setframerate(RATE) 
    wf.writeframes(b''.join(frames)) 
    wf.close() 

而且我可以發揮使用aplay這種精細,它顯示了以下

Playing WAVE 'Audio_.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Mono 

但是當我試圖打它使用python/pyaudio使用此代碼我問題開始了。

播放代碼

import pyaudio 
    import wave 
    import sys 
    import time 
    output_device_index = 0 
    CHUNK = 1024 
    if len(sys.argv) < 2: 
     print("Plays a wave file.\n\nUsage: %s filename.wav" 
     % sys.argv[0]) 
     sys.exit(-1) 

    wf = wave.open(sys.argv[1], 'rb') 

    # instantiate PyAudio (1) 
    p = pyaudio.PyAudio() 
    def callback(in_data, frame_count, time_info, status): 
     data = wf.readframes(frame_count) 
     return (data, pyaudio.paContinue) 

    stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 
      channels=wf.getnchannels(), 
      rate=wf.getframerate(), 
      output=True, 
      output_device_index=output_device_index, 
      stream_callback=callback) 

    data = wf.readframes(CHUNK) 
    while stream.is_active(): 
     time.sleep(0.1) 

    stream.stop_stream() 
    stream.close() 
    wf.close() 
    p.terminate() 

我得到的音頻在錯誤的採樣率播放,所以我聽起來像來自(艾爾文與花栗鼠),並有大量的嗡嗡聲/嗡嗡的財產以後。 我認爲這是因爲C-media USB聲卡不能播放單聲道流。

當使用aplay時,plughw:0,0修復了這個問題。 我已經設置了我的.asoundrc,因此我不必在使用aplay時再指定。

pcm.plug0 { 
     type plug 
     slave { 
      pcm "hw:0,0" 
     } 
    } 

但是,當使用python來播放音頻文件時,這個dosn't沒有幫助。 請有人指出我在正確的方向。

回答

1

我不知道它是否適用於Pi,但您可以嘗試python-sounddevice

+0

謝謝,我可以使用這種方法播放單聲道和立體聲流,但開始播放樹莓流大約需要7秒。 – Richard

+0

好吧,那很不好... – Matthias

+0

我剛剛有一個主意......每次或只有第一次需要那麼長時間?可能加載NumPy需要那麼長時間?如果是這種情況,你可以嘗試[sounddevice.RawStream](http://python-sounddevice.rtfd.org/#sounddevice.RawStream),而不需要Numpy。 – Matthias

2

您可以嘗試將輸出流中的通道數設置爲2。您將不得不每2個字節複製一次。

假設您的寬度是2(16位音頻),你從你的wavfile(以字節的字符串)獲得流將是這樣的:

B1a B1b B2a B2b B3a B3b ... etc 

需要流下來,這是什麼(只要你想在兩個通道輸出:

B1a B1b B1a B1b B2a B2b B2a B2b B3a B3b B3a B3b 

如果您嘗試第一個流流至立體聲設備會發出聲音兩倍的間距中的偶數樣本去左邊通道和奇通道往右走,都渠道只獲得1/2的樣本。