You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/zh/6-consumer/lessons/1-speech-recognition/pi-audio.md

8.4 KiB

捕捉音频 - 树莓派

在本节课程中,您将编写代码在树莓派上捕捉音频。音频捕捉将通过一个按钮来控制。

硬件

树莓派需要一个按钮来控制音频捕捉。

您将使用的是一个 Grove 按钮。这是一个数字传感器,可以打开或关闭信号。这些按钮可以配置为在按下时发送高信号,未按下时发送低信号,或者按下时发送低信号,未按下时发送高信号。

如果您使用的是 ReSpeaker 2-Mics Pi HAT 作为麦克风,那么无需连接按钮,因为这个 HAT 已经自带一个按钮。直接跳到下一节。

连接按钮

按钮可以连接到 Grove 基座 HAT。

任务 - 连接按钮

一个 Grove 按钮

  1. 将 Grove 电缆的一端插入按钮模块上的插座。它只能以一种方式插入。

  2. 在树莓派断电的情况下,将 Grove 电缆的另一端连接到 Grove 基座 HAT 上标记为 D5 的数字插座。这个插座位于 GPIO 引脚旁边的一排插座中,从左数第二个。

Grove 按钮连接到 D5 插座

捕捉音频

您可以使用 Python 代码从麦克风捕捉音频。

任务 - 捕捉音频

  1. 启动树莓派并等待其启动完成。

  2. 启动 VS Code可以直接在树莓派上运行也可以通过 Remote SSH 扩展连接。

  3. PyAudio Pip 包提供了录制和回放音频的功能。此包依赖于一些需要先安装的音频库。在终端中运行以下命令来安装这些库:

    sudo apt update
    sudo apt install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev libasound2-plugins --yes 
    
  4. 安装 PyAudio Pip 包。

    pip3 install pyaudio
    
  5. 创建一个名为 smart-timer 的新文件夹,并在此文件夹中添加一个名为 app.py 的文件。

  6. 在文件顶部添加以下导入:

    import io
    import pyaudio
    import time
    import wave
    
    from grove.factory import Factory
    

    这将导入 pyaudio 模块、一些用于处理 WAV 文件的标准 Python 模块,以及 grove.factory 模块以导入用于创建按钮类的 Factory

  7. 在此之后,添加代码以创建一个 Grove 按钮。

    如果您使用的是 ReSpeaker 2-Mics Pi HAT请使用以下代码

    # The button on the ReSpeaker 2-Mics Pi HAT
    button = Factory.getButton("GPIO-LOW", 17)
    

    这将在端口 D17 上创建一个按钮,该端口连接到 ReSpeaker 2-Mics Pi HAT 上的按钮。此按钮设置为在按下时发送低信号。

    如果您未使用 ReSpeaker 2-Mics Pi HAT而是使用连接到基座 HAT 的 Grove 按钮,请使用以下代码:

    button = Factory.getButton("GPIO-HIGH", 5)
    

    这将在端口 D5 上创建一个按钮,该按钮设置为在按下时发送高信号。

  8. 在此之后,创建一个 PyAudio 类的实例来处理音频:

    audio = pyaudio.PyAudio()
    
  9. 声明麦克风和扬声器的硬件卡号。这将是您在本课程前面通过运行 arecord -laplay -l 找到的卡号。

    microphone_card_number = <microphone card number>
    speaker_card_number = <speaker card number>
    

    <microphone card number> 替换为您的麦克风卡号。

    <speaker card number> 替换为您的扬声器卡号,与您在 alsa.conf 文件中设置的卡号相同。

  10. 在此之后,声明用于音频捕捉和回放的采样率。根据您使用的硬件,可能需要更改此值。

    rate = 48000 #48KHz
    

    如果稍后运行代码时出现采样率错误,请将此值更改为 4410016000。值越高,音质越好。

  11. 在此之后,创建一个名为 capture_audio 的新函数。此函数将用于从麦克风捕捉音频:

    def capture_audio():
    
  12. 在此函数中,添加以下代码以捕捉音频:

    stream = audio.open(format = pyaudio.paInt16,
                        rate = rate,
                        channels = 1, 
                        input_device_index = microphone_card_number,
                        input = True,
                        frames_per_buffer = 4096)
    
    frames = []
    
    while button.is_pressed():
        frames.append(stream.read(4096))
    
    stream.stop_stream()
    stream.close()
    

    此代码使用 PyAudio 对象打开一个音频输入流。该流将以 16KHz 的采样率从麦克风捕捉音频,并以 4096 字节大小的缓冲区捕捉。

    然后代码在 Grove 按钮被按下时循环运行,每次将这些 4096 字节的缓冲区读取到一个数组中。

    💁 您可以在 PyAudio 文档 中了解更多关于传递给 open 方法的选项。

    一旦按钮被释放,流将停止并关闭。

  13. 在此函数的末尾添加以下代码:

    wav_buffer = io.BytesIO()
    with wave.open(wav_buffer, 'wb') as wavefile:
        wavefile.setnchannels(1)
        wavefile.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
        wavefile.setframerate(rate)
        wavefile.writeframes(b''.join(frames))
        wav_buffer.seek(0)
    
    return wav_buffer
    

    此代码创建一个二进制缓冲区,并将所有捕捉到的音频以 WAV 文件 的形式写入其中。这是一种将未压缩音频写入文件的标准方式。然后返回此缓冲区。

  14. 添加以下 play_audio 函数以回放音频缓冲区:

    def play_audio(buffer):
        stream = audio.open(format = pyaudio.paInt16,
                            rate = rate,
                            channels = 1,
                            output_device_index = speaker_card_number,
                            output = True)
    
        with wave.open(buffer, 'rb') as wf:
            data = wf.readframes(4096)
    
            while len(data) > 0:
                stream.write(data)
                data = wf.readframes(4096)
    
            stream.close()
    

    此函数打开另一个音频流,这次是用于输出 - 播放音频。它使用与输入流相同的设置。缓冲区被作为 WAV 文件打开,并以 4096 字节块的形式写入输出流,从而播放音频。然后关闭流。

  15. capture_audio 函数下方添加以下代码,以循环检测按钮是否被按下。一旦按钮被按下,音频将被捕捉并播放。

    while True:
        while not button.is_pressed():
            time.sleep(.1)
    
        buffer = capture_audio()
        play_audio(buffer)
    
  16. 运行代码。按下按钮并对着麦克风说话。完成后释放按钮,您将听到录音。

    在创建 PyAudio 实例时,您可能会看到一些 ALSA 错误。这是由于树莓派上为您未使用的音频设备配置所致。可以忽略这些错误。

    pi@raspberrypi:~/smart-timer $ python3 app.py 
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.front
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
    

    如果您收到以下错误:

    OSError: [Errno -9997] Invalid sample rate
    

    请将 rate 更改为 44100 或 16000。

💁 您可以在 code-record/pi 文件夹中找到此代码。

😀 您的音频录制程序成功了!

免责声明
本文档使用AI翻译服务Co-op Translator进行翻译。尽管我们努力确保准确性,但请注意,自动翻译可能包含错误或不准确之处。应以原始语言的文档作为权威来源。对于关键信息,建议使用专业人工翻译。对于因使用本翻译而引起的任何误解或误读,我们概不负责。