We have completed all the necessary parts required for developing the Software. From understanding SD-Cards as Storage Medium to choosing the right Audio Format to deal with, we have travelled a long way together in our quest to develop our own Music Player. From this post, we will start the last part of this project i.e the software development.
Let's divide the software into smaller pieces of code and we will then take a bottom-up approach to develop a finished piece of a efficient and user-friendly software. First, we will start with writing the parser of WAV file in C for our PC and then we will move to our embedded platform.
The Input to our WAV parser is a .wav file and it will show the header information as the output. We will create a structure and store the header info in it. The code will open the .wav file, parse it up to the "data" tag in the header and then map the structure from the start of the metadata and hence fill the corresponding values.
From the last post, we can understand the structure of the header and hence write the required code. The structure is named head and is as follows: -
typedef struct{
Now we need to open the .wav file using standard file i/o functions along with declaring a pointer to the head structure. Using malloc we provide the required memory to the structure pointer we declared and then by fread() we can map the file onto the memory pointed by the structure pointer. Here we will use the sizeof() operator to define how many bytes we need to map. If these operations are completed successfully then we will have all the required information in the head pointer and now we just need to print the stored information.
The complete code is available on my Github repository. The code can be used to output the header of any .wav file available on the local directory of the project and also contains a sample wave file "blue.wav". The input to the console must contain the full name of the file as "file.wav". Now we can start writing the code for our embedded platform. The above structure can directly be copied into the stm32 code and we will use the file i/o options provided by the Fatfs module instead of the standard functions as we are using the sd card to store our music file. After we are done with opening the file we move to the next part and start reading the content of the file up to the "data" keyword, and then read 4 bytes of data and now our pointer is at the very start of the raw data section of the music file.
Now we will use the PWM functionalities of our hardware timers and provide each byte to the timer which will output the digital data in the form of a Pulse width modulated wave. This method can be used as DAC but is quite noisy and hence we will use an actual DAC in the future versions of this project.
Every RAW audio file has several parameters such as its sample rate, bit depth etc. The sample rate is very crucial as we need to provide the PWM with the same frequency as the sampling frequency as to have a reconstruction of the audio. Here we use the Timer interrupt capabilities to provide accurate timings. In our case, the recorded audio has a sampling frequency of 44100 Hz and hence we will configure our timer to provide an interrupt at the same rate. We can not use the timer API's inside our Interrupt Service routine so we will use a variable to check whether an interrupt was there and hence we can now output the sound using a Gpio and connect the speaker's Aux to GND and the Gpio.
The final code is available on the GitHub page and the breadboard circuit will look similar to this.
So, now we need to compile and flash the code into our MCU and if everything goes as expected then we will be able to hear the music with some noise. In the future, we will use DAC instead of PWM and make a PCB for our Music Player along with integrating a TFT lcd for user interface. Till then, Enjoy the MUSIC!.


Comments
Post a Comment