【问题标题】:Channels and Sample rates using python and pyaudio使用 python 和 pyaudio 的通道和采样率
【发布时间】:2015-12-10 12:01:47
【问题描述】:

我正在尝试使用 python 和 pyaudio 录制和播放一些音频。 我正在使用连接到树莓派的麦克风,并将 C-Media Electronics, Inc. CM108 音频控制器设置为默认设备。

此设备仅录制单声道。

    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()

我收到的音频以错误的采样率播放,所以我听起来像是来自(Alvin 和花栗鼠)的声音,并且有很多嗡嗡声/嗡嗡声。 我认为这是因为 C-media USB 声卡无法原生播放单声道流。

使用 aplay 时,plughw:0,0 可以解决此问题。 我已将 .asoundrc 设置如下,因此在使用 aplay 时不必再指定。

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

但这在使用 python 播放音频文件时没有帮助。 请有人指出我正确的方向。

【问题讨论】:

    标签: python audio raspberry-pi pyaudio


    【解决方案1】:

    我不知道它是否适用于 Pi,但您可以尝试 python-sounddevice

    【讨论】:

    • 谢谢,我可以使用这种方法播放单声道和立体声流,但是在树莓派上开始播放流大约需要 7 秒。
    • 我刚刚有个主意……是每次都需要这么长时间还是第一次?可能加载 NumPy 需要那么长时间?如果是这种情况,你可以试试sounddevice.RawStream,不需要 Numpy。
    【解决方案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 的样本.

    【讨论】:

      猜你喜欢
      • 2022-01-01
      • 2013-08-22
      • 1970-01-01
      • 2023-03-24
      • 2012-06-18
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      相关资源
      最近更新 更多