TMRpcm wav playback library

Please do not post requests
User avatar
mrburnette
Posts: 1885
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: TMRpcm wav playback library

Post by mrburnette » Mon Jul 27, 2015 11:53 am

Very nice!

Surprised at the video speed with the sound decoding. Awesome.

Ray

victor_pv
Posts: 1745
Joined: Mon Apr 27, 2015 12:12 pm

Re: TMRpcm wav playback library

Post by victor_pv » Mon Jul 27, 2015 12:43 pm

mrburnette wrote:Very nice!

Surprised at the video speed with the sound decoding. Awesome.

Ray
I was thinking on adding something better than the rotating cube, or perhaps make the cube pulsate with the beat, or just make it change colors with the samples.

The output right now is 8bits, I could use 2 timer outputs per channel and achieve 16 bit with at least 5 times the sample frequency in the PWM output, so a low pass filter could filter the noise, but right now with those frequencies, I not using any kind of filter and still wont hear any noise.

So of the CPU usage, about 20% goes to rotating the cube, and the rest goes to reading and formatting the samples. When it's 8bit mono it when it uses the least CPU for that, as it reads half the amount of samples as stereo, and on top the samples goes directly to the play buffer. When it reads 16 bit samples it needs to go to a read buffer, then take the top 8bit, change it from signed to unsigned and write it to a new buffer. When playing 16bit mono, it needs to do the same processing just in half the samples for the same time period.
The best definitely is to just format the files in 8bit before writing them to the sdcard, but the library can deal with 16bit if a file is 16bits.
The sound quality is actually really good for such a simple solution. I was expecting to get some basic crappy noise out of it to have low cpu usage (just needed to play some noises for my laser gun project), but as it is, with a big sdcard I can have it play really long files thru an amplier to add some ambient noise.

For the 16bit to bit converson, I am doing this:
for (uint16 n = 0; n < bytes_read/2; n++){
TMRpcm_buffer[a][bytes_filled+n] = (TMRpcm_read_buffer[n*2]+128);
}

Can you think on a faster operation to discard half the bytes, and convert the other half from signed to unsigned all at once?

User avatar
RogerClark
Posts: 7474
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: TMRpcm wav playback library

Post by RogerClark » Mon Jul 27, 2015 9:30 pm

Victor

I dont think you improve the speed of that code. So assuming you are DMAing the input buffer, the only speed improvement would in in the lib when it processes and plays the audio data

victor_pv
Posts: 1745
Joined: Mon Apr 27, 2015 12:12 pm

Re: TMRpcm wav playback library

Post by victor_pv » Tue Jul 28, 2015 1:37 am

Well, thanks for reminding me because I had forgotten to enable DMA in the sdfat library again after the last time I disabled it, and was not using DMA. That shaved a bit of CPU usage, but I discovered a small bug in the latest code for the SPI functions.
In dmaTransfer and the 2 dmaSend functions, we have this line:
uint8 b;

Now b is not always initialized, and can result in random number returned to the sdfat library, that affects on some cases (pretty random, some times it works, some times it crashes, some times it detects the sdcard but just can't list the content).

At some point I forgot to initialize that to 0, so we just need to add a line next to it:
b = 0;

Or change the line to
uint8 b = 0;

It does not affect DMA operation in the tft library, cause that one doesn't care about the returned value, but the sdfat library uses that value to detect if the transfer timed out without completing. With the random b values returned, it thinks the transfers did not complete some times when it actually did.

I won't send a pull because we can't merge automatically, so just in spi.cpp, functions dmaTransfer, dmaSend (for 8 bits) and the other dmaSend (for 16 bits), change that line to initialize b to 0.

About improving the output, as of right now it only checks if the sound is mono or stereo, and then dumps the value from the buffer to the timer register, but does not do any data conversion, that is done in the loop above when the data is read, so I don't think I can improve the output part much unless I do that with DMA, which I have considered too, but I need to plan carefully cause I already use 2 DMA channels for SPI1, 2 mode for SPI2, and I plan on using 2 more for IR TX and IR RX, that 6 channels, so I need to plan which timers I will use for each thing, so I dont end up with 2 devices needing the same channel at the same time.

The loop above consumes about 20% of my cpu time :( if I read an 8bit wav, which goes straight to the output buffer with no processing, I see 20% less cpu time used than if I read a 16bit wav, which needs to use the loop.
Last edited by victor_pv on Tue Jul 28, 2015 1:52 am, edited 1 time in total.

User avatar
RogerClark
Posts: 7474
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: TMRpcm wav playback library

Post by RogerClark » Tue Jul 28, 2015 1:48 am

Victor

Just let me know what function its in, and I'll update it manually

victor_pv
Posts: 1745
Joined: Mon Apr 27, 2015 12:12 pm

Re: TMRpcm wav playback library

Post by victor_pv » Tue Jul 28, 2015 1:55 am

RogerClark wrote:Victor

Just let me know what function its in, and I'll update it manually
dmaTransfer, and both dmaSend functions (there are 2 of them).

User avatar
RogerClark
Posts: 7474
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: TMRpcm wav playback library

Post by RogerClark » Tue Jul 28, 2015 2:01 am

I've directly edited the file in GitHub

https://github.com/rogerclarkmelbourne/ ... rc/SPI.cpp

Can you take a quick look and confirm I did the correct ones

User avatar
Vassilis
Posts: 320
Joined: Thu May 21, 2015 6:42 am
Location: Thessaloniki, Greece
Contact:

Re: TMRpcm wav playback library

Post by Vassilis » Tue Jul 28, 2015 8:38 am

wow! very cool!
well done victor

victor_pv
Posts: 1745
Joined: Mon Apr 27, 2015 12:12 pm

Re: TMRpcm wav playback library

Post by victor_pv » Tue Jul 28, 2015 1:13 pm

RogerClark wrote:I've directly edited the file in GitHub

https://github.com/rogerclarkmelbourne/ ... rc/SPI.cpp

Can you take a quick look and confirm I did the correct ones
Roger you did, but please do it also in this function (although this one is not used in sdfat, just to be consistent in what to expect as return):
uint8 SPIClass::dmaSend(uint16 *transmitBuf, uint16 length, bool minc)


Vassilis thanks, nothing close to a full fledge mp3 player but provides for producing more sounds than just a simple beep beep :)
At some point I want to try porting libmad or helix to our core, for mcus with 48Kb or more. There are already versions for the stm32f1, but using the std peripheral library. That could help eliminate 1 component in projects like your mp3 webplayer. and an RC board is the same price or cheaper than an mp3 decoder board. If you feel brave to deal with the stm32 DAC and timers, I can pass you the links with the working ports.

User avatar
Vassilis
Posts: 320
Joined: Thu May 21, 2015 6:42 am
Location: Thessaloniki, Greece
Contact:

Re: TMRpcm wav playback library

Post by Vassilis » Tue Jul 28, 2015 3:19 pm

victor_pv wrote:Vassilis thanks, nothing close to a full fledge mp3 player but provides for producing more sounds than just a simple beep beep :)
At some point I want to try porting libmad or helix to our core, for mcus with 48Kb or more. There are already versions for the stm32f1, but using the std peripheral library. That could help eliminate 1 component in projects like your mp3 webplayer. and an RC board is the same price or cheaper than an mp3 decoder board. If you feel brave to deal with the stm32 DAC and timers, I can pass you the links with the working ports.
I just modified my arduino webradio player for using the W5500 ethernet module instead of using the ENC28J60. That gave to the circuit the ability of playing the 128kbps internet MP3 and AAC streams very good. I intend to port it to the STM32F1 series too.

When I finish with that, it's a good idea to work with libmad library. The problem is, that at this time the only STM MCU I have got and supports hardware I2S is the STM32F411RE. the 411RE has plenty of RAM, FLASH and it is fast.
Unfortunetly, the 411RE doesn't have DAC :(

Post Reply