How to play audio files using STM32 Part 3
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Email to a Friend
- Printer Friendly Page
- Report Inappropriate Content
on 2022-06-22 6:46 AM
How to play audio files using STM32?
Welcome back!
In this last part we'll cover the interrupt implementation and the final results, so stay tuned
In the interrupt service routine, more specifically in the TIM3 periodic interrupt, we must execute a few actions as well:
- Include the adpcm header
- Check if the audio file to be played has changed or not
- Clear the interrupt flag
- Decode the audio file
- Repeat the same position of the audio file 8 times
- Output the decoded value in the PWM or DAC
- Once the 8 repetitions are made, move to the next decoded position in the vector
- If the audio file was fully played, stop the TIM3 interrupt to stop the audio output
/* USER CODE BEGIN Includes */ #include "adpcm.h" #ifdef USE_DAC #include "dac.h" #endif /* USER CODE END Includes */ /* USER CODE BEGIN PV */ tTwoByte newSample; extern AudioElement AudioFile; extern uint8_t AudioFileToPlay; /* USER CODE END PV */ /** * @brief This function handles TIM3 global interrupt. */ void TIM3_IRQHandler(void) { /* USER CODE BEGIN TIM3_IRQn 0 */ uint8_t adpcmSample; static uint16_t pcmSample; static uint8_t nibble = 1; static uint8_t repetition = 0; static uint16_t sample_position = 0; static unsigned char *RawAudio; static uint8_t PrevAudioFileToPlay = 0xFF; if(PrevAudioFileToPlay != AudioFileToPlay) { PrevAudioFileToPlay = AudioFileToPlay; nibble = 1; repetition = 0; sample_position = 0; RawAudio = (unsigned char *)AudioFile.AudioFiles[AudioFileToPlay]; } if (LL_TIM_IsActiveFlag_UPDATE(TIM3)) { LL_TIM_ClearFlag_UPDATE(TIM3); if ((repetition==0) & (sample_position < AudioFile.AudioSize[AudioFileToPlay])) { // new sample is generated repetition = 7; // reinitialize repetition down counter if (nibble) { // first 4 bits of the ADPCM byte decoded adpcmSample = (uint8_t)(RawAudio[sample_position] >> 4); } else { // last 4 bits of the ADPCM byte decoded adpcmSample = (uint8_t)(RawAudio[sample_position] & 0x0F); sample_position++ ; } nibble = (uint8_t)(!nibble);/* indicator inverted mean next interrupt will handle the second part of the byte. */ pcmSample = ADPCM_Decode(adpcmSample); // update sample newSample.uShort = (uint16_t)32768 + pcmSample; TIM3->CCR2 = newSample.uBytes[0]; //LSB TIM3->CCR1 = newSample.uBytes[1]; //MSB #ifdef USE_DAC HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, (newSample.uShort)>>4); #endif } else if (sample_position < AudioFile.AudioSize[AudioFileToPlay]) { // repetition 7 more times of the PWM period before new sample, total of times the same value is repeated = 8 repetition--; // reload Timer with the actual sample value newSample.uShort = (uint16_t)32768 + pcmSample; TIM3->CCR2 = newSample.uBytes[0]; //LSB TIM3->CCR1 = newSample.uBytes[1]; //MSB #ifdef USE_DAC HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, (newSample.uShort)>>4); #endif } else { // end of the audio clip /* Disable the TIM3 Interrupt */ NVIC_DisableIRQ(TIM3_IRQn); // stop the timer LL_TIM_DisableCounter(TIM3); } } return; /* USER CODE END TIM3_IRQn 0 */ /* USER CODE BEGIN TIM3_IRQn 1 */ /* USER CODE END TIM3_IRQn 1 */ }Now you have all the steps prepared and you can build your application by pressing “Ctrl+B”. You should see 0 errors and 0 warnings and in the memory details you should have the .myAudioFiles with the size of your audio file:
Assuming you have your hardware ready and properly connected, you can load the program in the STM32 and play with your audio file! You can add as many audio files your memory can withstand by repeating the process shown in this article
Conclusion:
The ADPCM encode and decode functions available in the software pack allows a rather small implementation to play audio files / music with all STM32. With some additional steps, you can enhance the storage to an external memory and create your own audio player
Enjoy your STM32 playing musics!
Part 1
Part 2
Part 3
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Email to a Friend
- Report Inappropriate Content
Hello, thank you for this nice arcticle. It says that with additional steps the audio can be read from a file stored in external memory. Is there an existing article describing how to play a music file this way ? And if possible, using the SAI peripheral and PCM protocol.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Email to a Friend
- Report Inappropriate Content
Hello.
I'm interested too about loading file from external memory.
For now I've run this project on NUCLEO L476RG and everything is working fine except one thing. Only first few second are played.
My *.wav file is almost 40 seconds long and it has 6,72MB. After converting the *.ima file has 305kb. The *.c file has 1882kb and memory size described in header of this file is as below:
/*StartOffset(h): 00000000, EndOffset(h): 0004C489, Długość(h): 0004C48A */
The original file size from this article is changed to 312458b (#define ADPCMD_PI 312458).
First question: What I should change to play whole file?
Second question: Could you write the next part of this article - How to load files from external memory?
Best regards,
Sebastian.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Email to a Friend
- Report Inappropriate Content
Hello
What to add/modify in code to play two wav files ?