Reputation: 31
I am using an Altera DE2 FPGA board and playing around with the SD card port and audio Line Out. I'm programming in VHDL and C, but the C portion is where I'm stuck due to lack of experience/knowledge.
Currently, I can play a .wav file from the SD card to the Line Out. I'm doing this by reading and sending the SD card data > FIFO > Audio Codec > Line Out. Ignoring all the other details, the code simply is:
UINT16 Tmp1=0;
...
Tmp1=(Buffer[i+1]<<8)|Buffer[i]; //loads the data from the SD card to Tmp1
//change the buffer rate?
IOWR(AUDIO_BASE, 0, Tmp1); //sends Tmp1 data to Line Out
If I were to print Tmp1, it's basically the points on a sine wave. What I want to do now is fiddle with how the sound plays by changing the play back rate (ideally I want to play the sound up or down an octave, which is just double or half the frequency). Can anyone provide some suggestions on how I can do this in the section:
//change the buffer rate?
Is it possible in C to write a few lines of code in that section to obtain what I'm looking for? ie. change how fast I'm reading from the Tmp1 buffer to the AUDIO_BASE.
Thanks in advance!
~Sarengo
Upvotes: 3
Views: 192
Reputation: 23560
If the IOWR interface provides no such option then you will have to do it yourself: You have to re-sample the sound. The theory can be found here 1 here 2 here 3 and here 4.
Raising the freqency by a multiple is easy: Just drop some samples, eg lower the freqency by factor 2 by just dropping every second sample from the buffer so that it then has half the size.
Lowering the frequency is harder because you need information you dont have: the samples in-between samples. You could start with simple linear interpolation and if you think that it does not sound good enough you can change it for something more advanced. Eg you can half the frequency by inserting a sample between two samples with their average value. If your waveform looks like this: 5 9 7 3 you would get 5 7 9 8 7 5 3
Upvotes: 1