on 2022-06-22 06:46 AM
/* 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:
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.
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.
Hello
What to add/modify in code to play two wav files ?