This recipe demonstrates how to play audio clips downloaded from the Internet globally. When you search for digital audio, you will encounter two common digital audio formats: Waveform Audio
File Format (WAVE or WAV) and MPEG-1, MPEG-2 Audio Layer III Format (MP3). This recipe focuses on playing WAV-encoded audio clips. The STM3241G-EVAL and STM32F4-DISCOVERY evaluation boards both include an MP3 player demo that can be ported to other systems. This recipe illustrates a skeleton that could form the basis for a similar application on the MCBSTM32F400 evaluation board. We'll call this recipe codecDemo_c7v1
.
The easiest way to import WAV audio samples into our program is to convert them into C source code (in the same way that images were imported in Chapter 6, Multimedia Support). A number of programs to manipulate WAV files and write samples to a C source file are available. This recipe uses a free converter by Colin Seymour called WAVtoCode that supports a number of WAV file formats. The following screenshot shows the conversion program being used (note that this program also includes a mixing desk):
The program exports samples in 8/16 mono/stereo formats, as follows:
BYTE data[NUM_ELEMENTS] = { -23417, -21874, -20238, -18517, -16716, -14844, -12909, -10920, -8885, -6811, -4709, -2586, -452, 1683, 3812, 5923, 8010, 10063, 12073, 14033, 15931, 17763, 19519, 21193, 22775, 24261, 25645, 26919, 28078, 29119, 30037, 30825, 31483, 32008, 32397, 32648, 32760, 32733, 32567, 32262, 31821, 31244, 30535, 29696, 28730, 27642, 26438, 25121, 23696, 22171, 20553, 18847, 17060, 15201, 13279, 11299,...
More exciting audio clips are available!
Follow the outlined steps to play prerecorded audio:
codecDemo_c7v0
from the Configuring the audio codec recipe that we described earlier in this chapter.int16_t data [] = { -23417, -23417, -21874, -21874, -20238, -20238, -18517, -18517, -16716, -16716, -14844, -14844, -12909, -12909, -10920, -10920, etc... };
I2S_audio.c
and change the sample frequency defined in the I2S_Audio_Initialize()
function to match that of the WAV file:hi2s.Init.AudioFreq = I2S_AUDIOFREQ_96K;
I2S_Audio_Initialize()
to enable interrupts:NVIC_EnableIRQ(SPI2_IRQn);
codecDemo.c
file:void SPI2_IRQHandler(void) { HAL_I2S_IRQHandler(&hi2s); }
codecDemo.c
file (that is, overriding this in stm32f4xx_hal_i2s.c
):void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) { HAL_I2S_Transmit_IT(hi2s, (uint16_t *) dacLUT, ARR_SZ(dacLUT)); }
main()
function so that it calls the HAL_I2S_Transmit_IT()
function before entering the super loop (note that there is nothing left to do in the super loop as the interrupt service routine takes care of everything):HAL_I2S_Transmit_IT(&hi2s, (uint16_t *) dacLUT, ARR_SZ(dacLUT)); while (1) { if (mode == AUDIO_BEEP) { Beep(note); /* Play the note */ wait_delay(500); /* pause */ } } /* WHILE */
The HAL_I2S_Transmit()
function that we deployed in codecDemo_c7v0
from the Configuring the audio codec recipe sends a block of audio samples to the codec. This function operates in polling mode to establish when the I2S transmit data register is empty, and it spins (busy waiting) on the codec's status register to determine when successive samples are needed. Unfortunately, while the processor is doing this, it can't perform much useful work. To address this problem, this recipe uses the HAL_I2S_Transmit_IT()
library function to set the I2S interface to generate an interrupt when the I2S transmit data register is empty. It also keeps count of the number of samples that are transmitted and calls a function named HAL_I2S_TxCpltCallback()
when the last audio sample in the block has been sent.
Prior to calling HAL_I2S_TxCpltCallback()
, we need to enable interrupts (step 4), provide an interrupt service routine (step 5), and override the HAL_I2S_TxCpltCallback()
function (step 6).
As the audio channel is essentially managed by the ISR, there isn't anything for the main()
function to do!
18.218.151.44