BirchJD / PicoRecPlayAudio

Record and play audio on a Raspberry Pi Pico. View video on YouTube: https://youtu.be/05PH0kyxEnQ

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Raspberry Pi Pico Audio Record/Play/WAV File [PicoRecPlayAudio]
===============================================================

By Jason Birch 2022-10-21

This project, software/hardware/documents, are distributed under the:
GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007

YouTube Video: https://youtu.be/05PH0kyxEnQ

GitHub: https://github.com/BirchJD/PicoRecPlayAudio


OVERVIEW
========

This project has been designed to be a very simple and easy to understand, audio
recording and playback system. Using a Raspberry Pi Pico and C programming
language. It has the added facility to also save WAV formatted files, which can
be played directly on Linux, Windows & Mac OS. The code in this project can be
used in larger projects to provide audio recording and playback features.


OPERATION
=========

The project has three switches, each with a dedicated operation. The first
starts an audio capture operation. Press the button, the onboard Pico LED
lights for the period that audio is being captured from the microphone into
the RAM of the Pico. Pressing the second button will play what ever audio is
currently in the Pico RAM, also lighting the onboard Pico LED during the
operation. And the final button will output the audio data from RAM to the Pico
debug terminal as ASCII HEX values. The Pico LED will be lit during the
transfer. If logged to a file, the file can then be processed with the
HexDumpToWav program (source code also provided in the project). This will
create a binary WAV file from the data, which can then be played from the host
operating system.


USE CASES
=========

The Pico has ~260KB of RAM, which will store stereo audio, sampled at a
rate of 22050 Samples per second for about three seconds. Which provides enough
for this project to demonstrate the capabilities of the process. But a 
process of capturing more audio is required for decent application. The
simplest solution would be to either stream to a local storage medium 
such as an SD card, or stream the audio over wires or wirelessly via Wi-Fi.

Examples of local storage applications:
   Dictaphone.
   Seismology monitor (seismograph).

Examples of wireless storage applications:
   Intercom, walkie talkie, baby monitor.
   Lapel wireless microphone.


HARDWARE
========

The hardware for the project consists of three parts:

A pre-amplifier for the microphone. The microphone used in this example has the
letters "SG" marked on the side. It varies resistance as it reacts to audio.
When used in series with VR1 between the 3V3 supply for the Pico and 0V, it
forms a potential divider to produce a voltage which varies with the resistance
of the microphone when in use. This voltage is millivolts in amplitude, the 
Pico A/D converter requires a voltage which varies between 0V and 3V3 for best
results. So the signal is amplified via a couple of op-amps. A single op-amp
could be used, but as an LM324 is used two op-amps are available for each
channel, left and right. It is probably better to use two per channel as each
op-amp will not have to work as hard and may reduce unwanted noise. The pre
amplifiers are configured as inverting amplifiers, each stage can be adjusted
for best results with the type of microphone being used. Ultimately the POT
resistors could be replaced with their fixed values. The resistors R3 and R4
form a voltage divider which sets the output voltage of the amplifier for when
the input is 0V. This needs to be half of the power supply of the op-amp, with
one caveat. The LM324 can output all the way down to 0V, but can't operate up to
the supply voltage. So when supplied with 3V3, reduced to about 3V after the
1N5819 diode used to prevent noise from the power supply to the op-amp, the
values of the resistors I have selected, bias the potential divider lower to
account for this. Capacitors C3 & C5 remove any DC voltage from the audio
signal, however the output of the op-amp U1B does not have the DC voltage
removed as it is sent to the A/D converter on the Pico, which requires a
positive voltage only. If the DC voltage was removed the audio signal would
swing from positive to negative voltage.

The second part of the hardware is the LM386 power amplifier which amplifies the
output of the Pico PWM pin to a current that can drive a speaker. A pair of
these amplifiers are required for a stereo system. The power amplifier is
supplied directly from the 5V USB supply to prevent too much load on the Pico
3V3 regulator. This amplifier comes in several variants capable of different
power outputs, the 1W version is used here, however any can be used as long as
the one chosen is capable of enough power to drive the speaker chosen. Resistor
R1 reduces the current available to the volume control, as the volume control
can pull the signal to 0V. It prevents the GPIO pin output being shorted to 0V
when outputting a logic 1. C1 removes DC voltage from the PWM output. It may seem
strange as the PWM output is digital, this is a standard configuration for an
amplifier input and is desirable as it will make the PWM voltage swing positive
to negative, which is required to drive the speaker cone in and out. C2 and C6
set the gain of the amplifier. C4 and R3 filter high frequency noise from the
output. And C5 removes DC voltage from the output.

The remaining components are the supplementary components to complete the
project. The Pico, switches, microphone and speaker.


Hardware for a stereo configuration:
   1x Raspberry Pi Pico [A/D Input, PWM Output].
   2x Microphone.
   2x >=1W Speaker.
   3x 6mm Switches.

   1x Pre-amplifier:
      1x LM324
      4x 4K7
      8x 10K
      6x 100K POT
      1x 10nF
      5x 10uF
      5x 2 pin Polarised header.

   2x 1W Power amplifier:
      1x LM386 (1W Version)
      1x 10K
      1x 100R
      1x 100K POT
      2x 10nF
      2x 10uF
      2x 100uF
      3x 2 pin Polarised header.



SOFTWARE
========

There are two software applications. The main application running on the Pico,
which will record audio, playback the recorded audio and output WAV file
formatted data, to the debug console. The second application converts the data
captured on the debug console to a binary WAV file which can be played on the
host system.


Capturing An Audio Sample
-------------------------

Recording audio with the Pico is a very simple process, extracted below are
the few lines of code which perform the operation. The size of the audio data
is stored in the first four bytes of the audio data. After that repeatedly
two bytes are stored for a left channel sample, followed by two bytes for the
right channel audio. A period is waited between each pair of samples in order
to throttle the process to 22KHz, the period required is 1/Sample Rate 
seconds. The RAM of the Pico is large enough to store about three seconds of
stereo audio sampled at 22KHz. After this the audio needs to be moved to a
storage device or over a wired or wireless network before the next three
seconds can be sampled.

SampleCount = 0;
AudioBuffer[SampleCount++] = (AUDIO_BUFF_SIZE & 0xFFFF);
AudioBuffer[SampleCount++] = (AUDIO_BUFF_SIZE >> 16);
SamplePeriod = time_us_64() + (1000000 / WAV_SAMPLE_RATE);
while (SampleCount < AUDIO_BUFF_SIZE)
{
   while(time_us_64() < SamplePeriod);
   SamplePeriod = time_us_64() + (1000000 / WAV_SAMPLE_RATE);
   adc_select_input(ADC_PORT_AUDIO_IN_LEFT);
   AudioBuffer[SampleCount++] = WAV_PWM_COUNT * adc_read() / 4096;
   adc_select_input(ADC_PORT_AUDIO_IN_RIGHT);
   AudioBuffer[SampleCount++] = WAV_PWM_COUNT * adc_read() / 4096;
};



Playing An Audio Sample
-----------------------

Play back of the audio is just as simple as recording. The Pico has the
hardware required to play sampled audio using only the DMA and PWM features.
The software just needs to kick off the process. So the code below sets up
a DMA transfer to transfer 32 bits at a time, which is equivalent to the two
byte of left and two bytes of a right sample. The DMA transfers the data
directly to the PWM hardware. When a PWM GPIO is configured, it is configured
as pairs of GPIO pins, so two channels are automatically configured. In this
example PWM channel 0 is being used for the audio playback, so the DMA just
needs to send the sample data to PWM_BASE + PWM_CH0_CC_OFFSET. Now the program
can do other things while the audio plays to completion. The playback API
provided also offers features such as stop playing and query if audio is
currently playing.

WavPwmDmaChConfig = dma_channel_get_default_config(WavPwmDmaCh);
channel_config_set_irq_quiet(&WavPwmDmaChConfig, true);
channel_config_set_read_increment(&WavPwmDmaChConfig, true);
channel_config_set_write_increment(&WavPwmDmaChConfig, false);
channel_config_set_transfer_data_size(&WavPwmDmaChConfig, DMA_SIZE_32);
channel_config_set_dreq(&WavPwmDmaChConfig, pwm_get_dreq(PwmSliceNum));
dma_channel_configure(WavPwmDmaCh, &WavPwmDmaChConfig, (void*)(PWM_BASE + PWM_CH0_CC_OFFSET), &(WavPwmData[2]), (WavPwmData[0] + (65536 * WavPwmData[1])) / 2, false);
dma_hw->ints0 = (1 << WavPwmDmaCh);
dma_start_channel_mask(1 << WavPwmDmaCh);



Downloading Audio Data
----------------------

To download the recorded data to a host computer over USB, use the minicom
terminal application. Start it in a command line window on Linux as follows:

minicom -b 115200 -o -D /dev/ttyACM0

Then log the output to a file, ensure the file does not exist first as the
data will be concatenated to the end of an existing file. Press CTRL+A then
press L to start logging. Then press the third key switch on the Pico project.
The data for the audio will be sent to the terminal. After the complete data
has been received, press CTRL+A then then press L to close the log file.
The data downloaded is an ASCII HEX dump of the captured audio. An example of
the start and end of data can be seen below. Pass this file into the
HexDumpToWav application to produce a binary WAV file.

./HexDumpToWav [FILENAME]

The result will be a file named [FILENAME].WAV


----- WAV DUMP START -----
52494646B809040057415645666D742010000000010002002256000044AC00
00020010006461746194090400
A9DFAE3172E4F53011E7B12FDEE997317EEBF431ABEC0E3079EE
6C2F76F0552F74F1B52D8AF2FF2A11F5162B6EF52F2A55F68F289EF490276EF5
1E269BF61E26F7F6BD283CF77C256BF7B61E52F8EB1AAEF85E1B6CF6751B6CF6
8E1AB2F6301BDEF7191B52F8B81D97F8FA1FAEF8CA207FF9B61E50F93F2009FA
552196F9552138FA9F1EF4F86C217DFA55217DFA9C2069F8591E39F9FD1D97F8

...

53147FF93B1469F83B14AEF83A150BF91C19AEF8DF1350F9AD15ADF94F167DFA
F315F1FA6A140DF8381697F8961550F91E18ADF91E18F2F94F167DFAAD15ABFA
0C1569F8951697F84E177FF9F61350F94F16DBF9AC1669F80A1696F9F01750F9
7E16F4F86B13F4F80A1639F91F17ADF93A1509FA9814F2F9AD1599F79D1197F8
3D1309FADD143BF81F1769F87E1697F8961552F80D140DF8B113
------ WAV DUMP END ------



Software:
   PicoRecPlayAudio.uf2
      CMakeLists.txt
      pico_sdk_import.cmake
      PicoRecPlayAudio.c
      PicoRecPlayAudio.h
      WavPwmAudio.c
      WavPwmAudio.h

   HexDumpToWav
      HexDumpToWav.c

About

Record and play audio on a Raspberry Pi Pico. View video on YouTube: https://youtu.be/05PH0kyxEnQ


Languages

Language:C 83.6%Language:CMake 16.1%Language:Shell 0.2%