9.2 KiB
Capturar áudio - Raspberry Pi
Nesta parte da lição, vais escrever código para capturar áudio no teu Raspberry Pi. A captura de áudio será controlada por um botão.
Hardware
O Raspberry Pi precisa de um botão para controlar a captura de áudio.
O botão que vais usar é um botão Grove. Este é um sensor digital que liga ou desliga um sinal. Estes botões podem ser configurados para enviar um sinal alto quando o botão é pressionado, e baixo quando não é, ou baixo quando pressionado e alto quando não é.
Se estiveres a usar um ReSpeaker 2-Mics Pi HAT como microfone, não é necessário conectar um botão, pois este HAT já tem um botão integrado. Podes passar para a próxima secção.
Conectar o botão
O botão pode ser conectado ao Grove Base Hat.
Tarefa - conectar o botão
-
Insere uma extremidade de um cabo Grove na entrada do módulo do botão. Só encaixará de uma forma.
-
Com o Raspberry Pi desligado, conecta a outra extremidade do cabo Grove à entrada digital marcada como D5 no Grove Base Hat conectado ao Pi. Esta entrada é a segunda da esquerda, na fila de entradas ao lado dos pinos GPIO.
Capturar áudio
Podes capturar áudio do microfone usando código em Python.
Tarefa - capturar áudio
-
Liga o Pi e espera que ele inicie.
-
Abre o VS Code, diretamente no Pi ou conecta-te através da extensão Remote SSH.
-
O pacote PyAudio Pip tem funções para gravar e reproduzir áudio. Este pacote depende de algumas bibliotecas de áudio que precisam de ser instaladas primeiro. Executa os seguintes comandos no terminal para instalá-las:
sudo apt update sudo apt install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev libasound2-plugins --yes
-
Instala o pacote PyAudio Pip.
pip3 install pyaudio
-
Cria uma nova pasta chamada
smart-timer
e adiciona um ficheiro chamadoapp.py
a esta pasta. -
Adiciona as seguintes importações ao topo deste ficheiro:
import io import pyaudio import time import wave from grove.factory import Factory
Isto importa o módulo
pyaudio
, alguns módulos padrão do Python para lidar com ficheiros WAV, e o módulogrove.factory
para importar umaFactory
que cria uma classe de botão. -
Abaixo disso, adiciona código para criar um botão Grove.
Se estiveres a usar o ReSpeaker 2-Mics Pi HAT, usa o seguinte código:
# The button on the ReSpeaker 2-Mics Pi HAT button = Factory.getButton("GPIO-LOW", 17)
Isto cria um botão na porta D17, a porta à qual o botão no ReSpeaker 2-Mics Pi HAT está conectado. Este botão está configurado para enviar um sinal baixo quando pressionado.
Se não estiveres a usar o ReSpeaker 2-Mics Pi HAT e estiveres a usar um botão Grove conectado ao Base Hat, usa este código:
button = Factory.getButton("GPIO-HIGH", 5)
Isto cria um botão na porta D5, configurado para enviar um sinal alto quando pressionado.
-
Abaixo disso, cria uma instância da classe PyAudio para lidar com áudio:
audio = pyaudio.PyAudio()
-
Declara o número da placa de hardware para o microfone e altifalante. Este será o número da placa que encontraste ao executar
arecord -l
eaplay -l
anteriormente nesta lição.microphone_card_number = <microphone card number> speaker_card_number = <speaker card number>
Substitui
<microphone card number>
pelo número da placa do teu microfone.Substitui
<speaker card number>
pelo número da placa do teu altifalante, o mesmo número que configuraste no ficheiroalsa.conf
. -
Abaixo disso, declara a taxa de amostragem a usar para a captura e reprodução de áudio. Poderás precisar de alterar isto dependendo do hardware que estás a usar.
rate = 48000 #48KHz
Se obtiveres erros de taxa de amostragem ao executar este código mais tarde, altera este valor para
44100
ou16000
. Quanto maior o valor, melhor a qualidade do som. -
Abaixo disso, cria uma nova função chamada
capture_audio
. Esta será chamada para capturar áudio do microfone:def capture_audio():
-
Dentro desta função, adiciona o seguinte para capturar o áudio:
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()
Este código abre um fluxo de entrada de áudio usando o objeto PyAudio. Este fluxo capturará áudio do microfone a 16KHz, capturando-o em buffers de 4096 bytes.
O código então entra num loop enquanto o botão Grove está pressionado, lendo estes buffers de 4096 bytes para um array a cada vez.
💁 Podes ler mais sobre as opções passadas ao método
open
na documentação do PyAudio.Quando o botão é solto, o fluxo é parado e fechado.
-
Adiciona o seguinte ao final desta função:
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
Este código cria um buffer binário e escreve todo o áudio capturado nele como um ficheiro WAV. Este é um formato padrão para escrever áudio não comprimido num ficheiro. Este buffer é então retornado.
-
Adiciona a seguinte função
play_audio
para reproduzir o buffer de áudio: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()
Esta função abre outro fluxo de áudio, desta vez para saída - para reproduzir o áudio. Usa as mesmas configurações do fluxo de entrada. O buffer é então aberto como um ficheiro WAV e escrito no fluxo de saída em blocos de 4096 bytes, reproduzindo o áudio. O fluxo é então fechado.
-
Adiciona o seguinte código abaixo da função
capture_audio
para entrar num loop até que o botão seja pressionado. Quando o botão é pressionado, o áudio é capturado e depois reproduzido.while True: while not button.is_pressed(): time.sleep(.1) buffer = capture_audio() play_audio(buffer)
-
Executa o código. Pressiona o botão e fala no microfone. Solta o botão quando terminares e ouvirás a gravação.
Poderás ver alguns erros ALSA quando a instância PyAudio é criada. Isto deve-se à configuração no Pi para dispositivos de áudio que não tens. Podes ignorar estes erros.
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
Se obtiveres o seguinte erro:
OSError: [Errno -9997] Invalid sample rate
então altera o
rate
para 44100 ou 16000.
💁 Podes encontrar este código na pasta code-record/pi.
😀 O teu programa de gravação de áudio foi um sucesso!
Aviso Legal:
Este documento foi traduzido utilizando o serviço de tradução por IA Co-op Translator. Embora nos esforcemos para garantir a precisão, é importante notar que traduções automáticas podem conter erros ou imprecisões. O documento original na sua língua nativa deve ser considerado a fonte autoritária. Para informações críticas, recomenda-se a tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas decorrentes da utilização desta tradução.