TMRpcm wav playback library

Please do not post requests
User avatar
RogerClark
Posts: 7455
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: TMRpcm wav playback library

Post by RogerClark » Sun Jul 05, 2015 10:48 pm

Guys,

Its interesting about using RTOS to overcome blocking on DMA transfers.

I must admit, I'm a bit old school when it comes to Real Time OS's on embedded devices. In days gone by, the microprocessors didn't really have enough grunt to handle an RTOS very well.

However as we now have 128kb to play with and more RAM and more cpu cycles, I guess it makes it more practical

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

Re: TMRpcm wav playback library

Post by victor_pv » Sun Jul 05, 2015 11:44 pm

CPU usage goes up roughly to 53% by playing a wav file at the same time.
That's about 25% for the sd reading and moving data to the timer registers.

Now I have found the hard way that the SDFat library does not like cpu intensive ISRs.
It happens both under CoOS and without CoOS, with a normal single task sketch loading from SD card, and the timer ISR moves the data to the timers.
Well, the symptoms are that the SDCard access slows down to a crawl, and the file doesn't play right any more, it rotates the same buffer a few times before another one is loaded.
When I tried the same in CoOS, I see the CPU usage jump to 100%, and sometimes it even affects the screen. I am not sure what causes it, but I have set the SDFat code to not use DMA, and still happens, so is not the library DMA.
Then I have tried disabling the Timer ISR, and setting the buffer loading one to keep reloading the buffers even though nothing empties it, and then it does not happen any more. So it seems to be the heavy processing in the Timer ISR that causes it.
The TMRpcm library does data conversion between 16bit and 8bit, and mono to stereo, and even volume adjustments all in the timer ISR, which seems to be too much. I measured almost 10% cpu usage in the timer ISR, which seems way too much.
So next I am going to change the wav timer ISR part to just dump the buffer to the registers, and move all the data processing to the same task that loads the buffers. So it will read a 512Bytes buffer, process it, and write it in a new buffer for the timer to dump straight to the registers.
That will help me reach another goal, that's using DMA in circular mode for dumping the audio buffer to the timer CCR. That way I don't even need a timer ISR anymore. Reduces CPU usage, and reduces the effect of the ISR in the SDFat library, win-win :)

Anyway, this is a video of the Wav player running on CoOS at the same time it rotates the cubes, still plenty of CPU left for other stuff
https://www.youtube.com/watch?v=dIfgIt6bNJM

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

Re: TMRpcm wav playback library

Post by victor_pv » Wed Jul 08, 2015 9:06 pm

Ray, you are a master of practical applications.
I want to make a simple nice application showing the features of an RTOS, with display and wav player.

I can take care of the sound playing, and we have RTOS and display drivers working fine, but I have never written any kind of menu system.
Do you know of any library that can manage that, or do can you point me to some example?

I want to make some simple to just show off the features, so rather than having 2 pointless cubes rotating in the screen, have the list of wav files in a folder and provide a menu that you can scroll up and down, and press play with another key. That simple, no need for something super fancy, nice clean interface, perhaps just highlight in a different color on what option of the menu you are.

BTW I solved the problems I described before with sdfat slowing down. I found I had left a bunch of debugging serial.prints enabled, disabled them and problem solved. The gain on that is that it pushed me to try sdfat on SPI2, so I did the modifications in the SPI library to do DMA transfers in SPI2, and I got rid of the interrupts to manage the DMA transfers.

User avatar
mrburnette
Posts: 1879
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: TMRpcm wav playback library

Post by mrburnette » Thu Jul 09, 2015 12:53 am

victor_pv wrote:Ray, you are a master of practical applications.
I want to make a simple nice application showing the features of an RTOS, with display and wav player.
I can take care of the sound playing, and we have RTOS and display drivers working fine, but I have never written any kind of menu system.
Do you know of any library that can manage that, or do can you point me to some example?

Menu System == pointer hell :twisted:

But, the world has changed just in the past 2 years! Once menu systems on the simple were of the text-LCD type:
http://forum.arduino.cc/index.php?topic=62021.0

These days even the Pig-O'scope has a GLCD touch screen! :geek:
(Just look what the iWatch has done to user interfaces!)

Obviously, what looks "good" on an ILI9341 probably will suck on a Nokia 5110, but we do a lots in the forum with ILI9341, so if I were selecting a target GLCD, I'd probably select this one.

While cascading, drop-down menu systems are seen on commercial products, for a demo I would just use an enumerated (1, 2, 3...) system where a short-press increments the items & changes color and a long-press invokes said selection.

Ray

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

Re: TMRpcm wav playback library

Post by victor_pv » Thu Jul 09, 2015 4:00 pm

mrburnette wrote:
victor_pv wrote:Ray, you are a master of practical applications.
I want to make a simple nice application showing the features of an RTOS, with display and wav player.
I can take care of the sound playing, and we have RTOS and display drivers working fine, but I have never written any kind of menu system.
Do you know of any library that can manage that, or do can you point me to some example?

Menu System == pointer hell :twisted:

But, the world has changed just in the past 2 years! Once menu systems on the simple were of the text-LCD type:
http://forum.arduino.cc/index.php?topic=62021.0

These days even the Pig-O'scope has a GLCD touch screen! :geek:
(Just look what the iWatch has done to user interfaces!)

Obviously, what looks "good" on an ILI9341 probably will suck on a Nokia 5110, but we do a lots in the forum with ILI9341, so if I were selecting a target GLCD, I'd probably select this one.

While cascading, drop-down menu systems are seen on commercial products, for a demo I would just use an enumerated (1, 2, 3...) system where a short-press increments the items & changes color and a long-press invokes said selection.

Ray
I think I'll try to just present a list of wav files in the screen, and use short press to scroll to the next one, long press to play, long press to stop.
That would make a $10 wav player ;)

User avatar
mrburnette
Posts: 1879
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: TMRpcm wav playback library

Post by mrburnette » Thu Jul 09, 2015 5:46 pm

victor_pv wrote: <...>
I think I'll try to just present a list of wav files in the screen, and use short press to scroll to the next one, long press to play, long press to stop.
That would make a $10 wav player ;)

There is, IMO, just something magical about being able to create a full project (excepting case, pwr-supply, LiON batteries) for under $10. I fudge a bit sometimes with project published as "$10 ..." by using a quantity price to each in the addition, but seriously, who is going to order a single $3.44 board from China? OK, well maybe some folks would, but I'm like into the x5 and x10 lots because I want a deal for the time I have to wait!

"I think I'll try to just present a list of wav files in the screen, and use short press to scroll to the next one, long press to play, long press to stop."
You may wish to enhance the single button selection to have a 10 (or so) second time-out such that the pointer moves back to the 1st selection if the master timing loop is exceeded. These one-button selections can be rather creative.

Another thing I often do with projects is to invoke a small menu for setting defaults while the program is still in the 'setup()" section. Initially, values are read from eeprom or flash and if null, the menu invokes, accepts the value(s), and writes them to storage. For example, in Magic Morse, the user is prompted for the WPM that they wish to practice. This value is used forever unless the Morse Key is 'closed' when the power is turned on and the user option is again select-able. The one switch therefore has various functions:
  • If closed while the power-up routine occurs and in the setup() section of code
    At a menu prompt
    Anytime pressed while the loop() function is active

Code: Select all


    // Set WPM default and write to EEPROM IF Morse Key is closed at this point...
    WPM = EEPROM.read(EEaddr);
    if (!digitalRead(morseInPin) || WPM == 0 || WPM > 40) setWPM(WPM);
Ray

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

Re: TMRpcm wav playback library

Post by victor_pv » Thu Jul 09, 2015 7:35 pm

Thanks for all the advises. Using the button that way, I only need 1 button for many things, and the mini already includes one button, so one less component I need to add ;)

What do you think of something like:
Print welcome screen (nice BMP of course, that's one advantage of using an sdcard).
If button pressed within welcome screen time out, present a short diagnostic menu.
Diagnostics include checking if the sdcard is present and displaying the information of it, and running a short speaker test with a tone.
Button press again bring you to player screen.
Player screen displays all the tracks available, highlight the first one.
If nothing is presses, start playing with that one, and when it's over go to the next one and so on.
If the user press the button for say 2 seconds, start playing the track.
If the user press the button for 2 seconds while playing stop.
If the user press the button for short while playing, highlight the next track, but nothing else.
If the user press the button for 2 seconds, play that track.

So basically I need one pointer to the track it is playing right now, and one pointer to the track highlighted, which can go down to the next one in a cyclic manner.
An I need an array with all the wav diles discovered. The pointers to the playing track and highlighted track are just index to that array.

I think this is clean and simple enough, doesn't need addional hardware beyond the maple mini, display with sdcard, and speaker. (probably a mosfet, capacitor an resistor for a rudimentary amplifier and low pass filter). And it should fit in the flash left (takes about 40KB now, but removing the cubes should free up some) and in the RAM left (have about 4 or 5KB left, but removing the cubes should free up some). I am using 2 x 1K buffers for the timers, plus a 512bytes one for loading the data from the sdcard, and a bunch of stacks for each task. Lots of that can be reduced or go away.
I am also planning to add a DMA option to the timer CCR update, so that will free up cpu cycles.

User avatar
mrburnette
Posts: 1879
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: TMRpcm wav playback library

Post by mrburnette » Thu Jul 09, 2015 11:40 pm

victor_pv wrote:Thanks for all the advises. Using the button that way, I only need 1 button for many things, and the mini already includes one button, so one less component I need to add ;)

What do you think of something like:
Victor,
I think that should work fine... once you prototype it, you'll soon know if it "feels" right. As you started with button pressed within welcome screen, you still have the magic "button pressed at power-on" before welcome screen for a hidden menu. No-cost menu, pretty cool, ugh?

Ray

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

Re: TMRpcm wav playback library

Post by victor_pv » Sun Jul 26, 2015 4:47 pm

mrburnette wrote:
victor_pv wrote:Thanks for all the advises. Using the button that way, I only need 1 button for many things, and the mini already includes one button, so one less component I need to add ;)

What do you think of something like:
Victor,
I think that should work fine... once you prototype it, you'll soon know if it "feels" right. As you started with button pressed within welcome screen, you still have the magic "button pressed at power-on" before welcome screen for a hidden menu. No-cost menu, pretty cool, ugh?

Ray
Just got around to finishing the little wav player. I followed your advise for using 1 button with different pressed times for different functions.

I haven't added many features to it cause I had a lot of trouble getting the sdcard library to open the files correctly, until I discovered you need to close the previous file before opening a new one with the same object :( hours wasted...
Anyway, it works now.
It discovers up to 50 wav files in the root directory. Created an index of all of them, then plays list the current one and the next 3 in the screen, and plays the top one.
If you press the button for a moment, it scrolls the list up, but keeps playing the same file, so you can keep scrolling down to the one you want without stopping the music.
If you do a long press, it stops playing whatever was playing, and if you do a long press when it is not playing, then it starts playing the file currently at the top of the list.

The hardware is extremely simple:
-Maple mini
-Sdcard connected to SPI1
-Tft screen connected to SPI2
- 2 Speakers connected to pins 26 and 27 and GND(I recommend at least a small serial resistor, but 8ohm small speaker works fine without and did not fry the mini, do it at your own risk). I am using a single mosfet amplifier just to protect the mini.

There are lot of better players out there, but this one does not need a DAC or anything else, it plays audio with PWM in a maple mini, blue pill, red pill, etc. I think it comes handy if you just need to play a few sounds but don't have a need for a bigger MCU or bigger PCB.

This example also serves as a little demonstration on how to use the new setModule function to use multiple SPI ports without changing the existing libraries, with DMA for fast transfers, and using CoOS to run it all.

Short video here:
https://www.youtube.com/watch?v=Zyna1ay3xxQ

The files need are here:
https://github.com/victorpv/Arduino_STM ... setModule2
and here:
https://github.com/victorpv/Arduino_STM ... ies/TMRpcm

I should follow on Ray's way, and put it all in a single folder, but need to do some other more urgent stuff.

Just a note, the code is pretty dirty in the TMRpcm library. I started converting from the original arduino one, but a lot of it is hw specific to manage the timers and a I left lots of pieces here and there to remind me what the original did. I'll clean it up once I have time, and will probably add a function to play sounds from flash, or actually make a separate library for that as it doesn't need any of the sdfat and wav file processing stuff.
Last edited by victor_pv on Mon Jul 27, 2015 7:50 am, edited 1 time in total.

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

Re: TMRpcm wav playback library

Post by RogerClark » Sun Jul 26, 2015 9:19 pm

Ultra Cool..

Thanks for sharing

Post Reply