PDA

View Full Version : MP3-Player Lib, with example



Frank B
11-13-2014, 07:55 PM
EDIT : Plays from SD, Flash, Serial Flash
EDIT : added FLAC-Support (Blocksize max 1024, 4-24 Bits)
EDIT : Last Version: now as Audio-Library-Object usable. With AAC.
EDIT : Renamed to Arduino-Teensy-Codec-lib



Hi,

i wrote a lib for teensy 3 which is able to play mp3.

https://github.com/FrankBoesing/Arduino-Teensy-MP3-lib
There's an example too.

It plays mono/stereo mp3 files from sd-card,
up to 320kbps, 44.1 khz, 16 Bit with good quality
with Pauls famous Audiolib.

Later, i'll extend this to more formats like aac (maybe aac+), flacc, etc.
But feel free to do push-requests :-)

Tests are very welcome...

Regards, Frank.

p.s. I deleted the old, quick,dirty&buggy example at github.

christoph
11-13-2014, 08:15 PM
There's surely some hardware other than the bare teensy involved. I had a look at the repo, but couldn't find a schematic. Is it just the audio board?

Apart form that - awesome! I'll try to find some time to test it.

Regards

Christoph

Frank B
11-13-2014, 08:23 PM
No... ok, you need an sd-slot for the files :-)

But you can use pcm or whatever as sound-output - all audio-lib supported devices.
I tested the audioboard only.

PaulStoffregen
11-13-2014, 08:43 PM
Is it just the audio board?


The audio library gives you a collection of audio components, which you can connect with each other. They're interchangeable. It's very easy to connect something that creates sound to either the I2S output (to the audio board) or to the built-in DAC, or to PWM. You can even wire the output to 2 or all 3.

To get a visual idea of how it works, give this design tool a try.

http://www.pjrc.com/teensy/gui/

For now, Frank's MP3 stuff uses the Play Queue object. Eventually, I want to create a dedicated MP3 decoding object... but that will take quite a lot of work to restructure the code and break the CPU intensive part into sub-tasks (eg, divide up the polyphase filter bank) so it plays nicely. In the meantime, the Queue object is meant to allow easy development outside of the library. The queue allows bursts of data to be queued up for code that isn't structured to use CPU time the was the audio library works internally.

christoph
11-13-2014, 08:51 PM
Going through the feature list: stereo is only available with the SGTL5000 (or something equivalent)?

Frank B
11-13-2014, 08:51 PM
For now, Frank's MP3 stuff uses the Play Queue object. Eventually, I want to create a dedicated MP3 decoding object... but that will take quite a lot of work to restructure the code and break the CPU intensive part into sub-tasks (eg, divide up the polyphase filter bank) so it plays nicely. In the meantime, the Queue object is meant to allow easy development outside of the library. The queue allows bursts of data to be queued up for code that isn't structured to use CPU time the was the audio library works internally.

I'll look at this too (but first i want aac suppport)

Yesterday, i had the idea to do the decoding in an extra timerinterrupt. That's not really the audiolib-way, but it would be more easy and give the same result.
Paul, what do you think ?
You can take a look at the "madlib" (from linux) too, maybe this is easier to split - but i don't know if it has the same speed on our Teensy.

edit: sorry, "madplay", not "madlib" :-)

PaulStoffregen
11-13-2014, 10:28 PM
Yesterday, i had the idea to do the decoding in an extra timerinterrupt. That's not really the audiolib-way, but it would be more easy and give the same result.
Paul, what do you think ?

Sure, go for it.

Eventually I want to work on really integrating MP3 into the library, but this sounds like a pretty reasonable intermediate step.

Frank B
11-15-2014, 02:04 PM
Yes!!!

It plays the first aac !! Seems to be a bit faster than mp3.
I have to optimize some things, (and there are some issues in the aac-decoder too), but i'll update github as soon as possible.
Maybe tomorrow.

Paul, if you want to integrate it, i can give you some tips. for mp3 for example there is a loop, which can be spilted.
Then, there are some places where some thing can be optimized for the newer cores (the lib is quite old).
AAC has for example a loop for reversering bits..
More optimizing can be done with using the DSP. But thats goes over my free time :-)

Pensive
11-15-2014, 02:33 PM
Very interesting gentlemen.

I have three questions:
1) How many MP3s could you play concurrently from the same SDCard? (Of course, this uses playqueue so perhaps we can't do that yet...?)
With less bits comes less bandwidth and SDCard bandwidth is one of the limiting factors at the moment. Teensy can probably handle 64 plus mixed tracks if it could just get at the data quick enough.

2) I wonder; How easy would it be to pipe encoded .h files through instead of using the SDCard?, A-la WAV2SKETCH, instead an MP32SKETCH?

3) And how much of the CPU is being used during playback? How CPU intensive is it? Compared to say, U-law decoding (which i'm using for all my samples)

I think a lot of people are making sonic sacrifices due to the limited amounts of RAM available and using mono files, at 22khz instead of 44khz stereo etc.
I'm pretty sure I could get twice the quality from the same number of bits if I used AAC or MP3 instead, at a cost of CPU ticks of course. I wonder where the sweet spot falls.

Frank B
11-15-2014, 02:47 PM
Very interesting gentlemen.

I have three questions:
1) How many MP3s could you play concurrently from the same SDCard? (Of course, this uses playqueue so perhaps we can't do that yet...?)
With less bits comes less bandwidth and SDCard bandwidth is one of the limiting factors at the moment. Teensy can probably handle 64 plus mixed tracks if it could just get at the data quick enough.

2) I wonder; How easy would it be to pipe encoded .h files through instead of using the SDCard?, A-la WAV2SKETCH, instead an MP32SKETCH?

3) And how much of the CPU is being used during playback? How CPU intensive is it? Compared to say, U-law decoding (which i'm using for all my samples)

I think a lot of people are making sonic sacrifices due to the limited amounts of RAM available and using mono files, at 22khz instead of 44khz stereo etc.
I'm pretty sure I could get twice the quality from the same number of bits if I used AAC or MP3 instead, at a cost of CPU ticks of course. I wonder where the sweet spot falls.

Hi Pensive,

1,3)The lib is at a very early stage. It can only one mp3 be played at a time.
At 48MHz, the decoding takes ~16ms for 26ms audio, at 144MHz 5-6ms. Calc yourself :-)
But on the plus-side is, the blocks that are read from SD are much smaller than wav, because of the high compression. Therefore, less time for that.
There is very complex math involved... and to decode these formats, the teensy hat as a lot to do. Take a look at the decode-source, its on my github-repro. My current version for both, mp3 + aac take 100k flash.. ~80% for the decoders :-)
Its not compareable to u-law.

2) seems to be possible, but not at the moment.

Pensive
11-15-2014, 03:43 PM
Thank you frank; with that much sketch used for decoding code, I doubt MP32Sketch would be practical :)

I guess we must realise we have a teensy here and it cannot be all things to all men :)

Great work ;)

Frank B
11-15-2014, 03:46 PM
As far as i know, it's the first "Arduino" mp3-player in software.
Am i right ?

christoph
11-15-2014, 03:46 PM
Pensive, if your mp3 is really tiny, it might fit. Teensy 3.1 has 256 kB flash, and there would surely be space for things like a 100ms long button click sound.

Frank B
11-15-2014, 03:48 PM
I you use aac only (the better format, higher compression, better quality, faster decoding), there is much more space.

Frank B
11-16-2014, 01:27 AM
I've uploaded the updated lib with aac-support :-)

Pensive
11-16-2014, 07:59 AM
Well played sir!

That puts the teensy plus audio board head and shoulders above Due plus Adafruit MP3 shield :)

The MP3 shield is monophonic ;)

Frank B
11-16-2014, 08:45 AM
The MP3 shield is monophonic ;)
The lib too. Paul, we need more RAM :)

Pensive
11-16-2014, 09:28 AM
We do. with this kind of power and capability we really need 16 or 32 megabytes.

On the plus side with over clocking, I could see 2 x mp3s playing at the same time, with effects, which means you could make a standalone DJ station with a bit of polyphony hacking :)

PaulStoffregen
11-18-2014, 03:19 PM
Paul, if you want to integrate it, i can give you some tips. for mp3 for example there is a loop, which can be spilted.
Then, there are some places where some thing can be optimized for the newer cores (the lib is quite old).
AAC has for example a loop for reversering bits..
More optimizing can be done with using the DSP. But thats goes over my free time :-)

Yes, I definitely want to integrate this into the next version of the library.

Just to be realistic, it'll probably be a few months until I can do any really serious work on this. I'm currently working on new hardware, and juggling time to make small fixes to about a dozen Arduino libraries (currently nRF8001).

PaulStoffregen
11-18-2014, 03:23 PM
I added this to the audio lib roadmap page, with a link to this thread. Hopefully that'll help anyone interested in this to find the code and follow this development.

http://www.pjrc.com/teensy/td_libs_AudioRoadmap.html

Frank B
11-18-2014, 07:09 PM
I added this to the audio lib roadmap page, with a link to this thread. Hopefully that'll help anyone interested in this to find the code and follow this development.

http://www.pjrc.com/teensy/td_libs_AudioRoadmap.html

Hi,

i have *.mp4 and *.m4a (=apple-style mp4) 90% running now... the fileformat is horror :-) ( "ISO14496-14" if anyone wants to study it)

I have plans to add flac as well. I think the code/ram usage will be smaller and it should be little bit faster. If it is fast enough (have to test this), maybe encoding is possible too ?
I'll find this out...
Flac is interesting, because it is open source, lossless, and the files are 30%-70% (depends on the content) smaller than *.wav.

But first, when i have mp4 running (maybe tomorrow, (or this evening?)), i spend some time, and try to modifiy the mp3/aac/mp4/m4a codecs and build audiolib-objects.
I already took a quick look at the audiolib - i had the idea to use a software-interrupt (triggered by "update") - but i have seen, the audiolib uses it already - and teensy has only one :-)
Ok, any interrupt can be triggered in software, so i use one of the others.. which one is rarely used ?
Then, the audiolib uses the lowest priority,but the decoding should use a lower priority. Would it be a problem to increase the "update"-priority on level ? I know how, but i don't know if any problems can occur.

Frank.

Frank B
11-18-2014, 10:54 PM
Hi,
i have *.mp4 and *.m4a (=apple-style mp4) 90% running now... the fileformat is horror :-) ( "ISO14496-14" if anyone wants to study it)


Gotcha :-)
Ok, basic functionality for mp3, mp4, m4a & aac is now given.

Great soundquality :-)

Frank.

Pensive
11-18-2014, 11:31 PM
You guys are awesome.

Does the m4a support apple's lossless out of interest?

PaulStoffregen
11-18-2014, 11:59 PM
Would it be a problem to increase the "update"-priority on level ? I know how, but i don't know if any problems can occur.


Yes, I believe this can be done. Maybe 224 or even 208 would work?

I'm imagining a distant future where we'd want audio software interrupt running ever 2.9 ms and a video software interrupt running every 33.3 ms.

Frank B
11-19-2014, 04:44 PM
Does the m4a support apple's lossless out of interest?
No, and it is not planned . I plan instead to take care of the equivalent/better (faster decoding, files have less overhead) flac. But it can take some time.
It is possible to convert apple lossles <-> flac without losses.
But contributions are welcome, the m4a-parser is already there and only the audiodecoding is missing.

Dnstje
11-20-2014, 09:49 PM
Hi there,
It looks like a great library! however, I cannot compile it out of the box.
Did I mis something to make a change in the arduino IDE?
oh and used hardware/software "Teensy 3.1" Arduino 1.0.6.




Arduino-Teensy-MP3-lib\Helix.cpp.o: In function `HelixMp3::play(char const*, AudioPlayQueue*, AudioPlayQueue*)':
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:208: undefined reference to `MP3InitDecoder'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:239: undefined reference to `MP3FindSyncWord'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:251: undefined reference to `MP3Decode'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:279: undefined reference to `MP3GetLastFrameInfo'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:310: undefined reference to `MP3FreeDecoder'
Arduino-Teensy-MP3-lib\Helix.cpp.o: In function `HelixAac::play(char const*, AudioPlayQueue*, AudioPlayQueue*)':
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:423: undefined reference to `AACInitDecoder'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:450: undefined reference to `AACSetRawBlockParams'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:470: undefined reference to `AACFindSyncWord'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:485: undefined reference to `AACDecode'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:494: undefined reference to `AACGetLastFrameInfo'
C:\Program Files (x86)\Arduino\libraries\Arduino-Teensy-MP3-lib/Helix.cpp:528: undefined reference to `AACFreeDecoder'
collect2.exe: error: ld returned 1 exit status

Frank B
11-20-2014, 10:15 PM
Hi there,
It looks like a great library! however, I cannot compile it out of the box.
Did I mis something to make a change in the arduino IDE?
oh and used hardware/software "Teensy 3.1" Arduino 1.0.6.


Have you copied the subdirectories as on Github ?? You need all.

Frank B
11-20-2014, 10:25 PM
Uh... my fault.. i forgot to upload two files.
please do a new download and try again.

Dnstje
11-20-2014, 10:27 PM
Yes, i've downloaded them all. (atleast > download as zip etc.) (few minuts ago)
Ah, that explains, ill try again.
Thanks!

Frank B
11-20-2014, 10:34 PM
ok.. sorry :-)

obviously, you're the first who tries it :-)

Dnstje
11-20-2014, 10:44 PM
Hehe, noproblem!
I gues so, I just finished a simple wav player, reading all wav files from a SD card, but them in a String etc, and a FFT with a LCD. then I went looking for more projects. until I found this thread on the PJRC roadmap.
However, a few weeks ago, I though mp3 or aac needed a FPU, so I actually stopped looking. (Also looking forward for FLAC!)
But I gues I try out this library in my small project, so it can play wav aac mp3, like an ordinairy player, but just faster and open source + visualizing:).

I'm still learning about alot of coding, how stuff works, Im glad there are opensource projects to look through :)

Also thanks for the very fast reply! I never had that on alot of forums, just they were 2 ~ 4 years old.

Frank B
11-20-2014, 10:56 PM
It is at a very early stage, there is only one function : "play()" . There is more to come...
But it would be great if could do some tests with different files ?!?!

No, the lib is all fixed-point, no FPU is needed. It is optimized to ARM/Teensy and very very fast.

I'm still learning too.. :-) Arduino is a new world for me.

Frank B
11-23-2014, 04:07 PM
I have a working version the audio-lib-mp3-object now (not on github yet).

I think, that i have to add the used cpucycles somehow to the ones of the stream, because it's running in an own interrupt (software-triggered by "update()").
What I need to do to achieve this?
Or do you have another suggestion ?

Frank.

Frank B
11-23-2014, 10:49 PM
Ok, i've uploaded the updated library. It is now an object integratedble into to the audiolibrary like sdwavplayer, but plays mp3 instead.
See the example.

Currently only MP3, aac follows.

https://github.com/FrankBoesing/Arduino-Teensy-MP3-lib

Dnstje
11-24-2014, 06:12 PM
I tried to implant stop(); myself, looking at the wav stop(); although a hard sd.close() didnt really like it. but I see in your new lib that stop is there, doing a bit other stuff then only sd.close. You have done a great job right now :).
As for the current possition, I tried a simple way of using millis. as example~
in Play, I added a line:

if (!file) curtime = millis();

before opening the file.
so it will store the current millis in the int32 curtime, and will stop after the file is opened.

in position I added:

uint32_t AudioPlaySdMp3::positionMillis(void){ //dat smiley <
int32_t curpos = millis() - curtime;
return curpos; //TODO
}

this will just count up until stop or if closing of the SD card.
after that I went looking at the reading bytes, maybe to use that as a simple position thing. I didnt look up the wav library yet though, how it was done there, but I think theres another way to get the current position. I didnt look up yet about the lenght op the song.

Also, doing Play and Stop() things, Pause() and maybe setPos() could be usefull aswell. As it said, pause will pause the track, and maybe setPos(time_in_millis) could be usefull to skip from 0:00 to 1:23:22 as for example~

Great job!

Frank B
11-24-2014, 06:38 PM
Hi Dnstje,

good idea :-)

There'a a big update comming the next days, an audiolib-integrated object for aac/mp4/m4a (for mp3, it already there and @github) and some restructuring.
It will calc the positionMillis with a sample-counter. I've implemented a little function like processorUsageMax() too.
There are some other improvements too.

The new objects are using an interrupt which is called by ( exact: chained to) the update()-function, but has a lower priority than the update() interrupt. This way, it is easyly possible to
spend more time than 2.9ms with calculations. Maybe, that's a good idea for other audioobjects which need more time, too ??
This works without any problem, perfectly so far :-)

Regards,
Frank.

Frank B
11-24-2014, 06:45 PM
setPos is not easy... i remember the first mp3-players which were not able to do this.
now, i know why. you have to read the whole file and count the frames. :-(
i don't know a better solution.

Dnstje
11-24-2014, 06:53 PM
hmm thats why A-B function is slow on those simple mp3 players. I know a few methodes but I think it will require too much RAM. and probably not efficient.
I don't know/tested it yet, or modified/added code yet, but have you tested how fast it can play a mp3 without output? (benchmarking stuff)

Frank B
11-24-2014, 06:57 PM
there's a function to find frames - MP3FindSyncWord() - maybe this helps.

Dnstje
11-24-2014, 08:51 PM
I will look into that.

there's a function to find frames - MP3FindSyncWord() - maybe this helps.


It seems "AudioAnalyzeFFT1024" wont get along with your library. Changing AudioMemory() does something but no sound. I gues memory issues with the FFT, though "AudioAnalyzeFFT256" works.

trying more :).

Frank B
11-24-2014, 09:33 PM
I will look into that.



It seems "AudioAnalyzeFFT1024" wont get along with your library. Changing AudioMemory() does something but no sound. I gues memory issues with the FFT, though "AudioAnalyzeFFT256" works.

trying more :).

I don't know, never tried fft :-) mp3 needs only AudioMemory(2) - but much ram via malloc.
Maybe the others know more about AudioAnalyzeFFT1024 (?!)
It is also possible that it takes too much time, (because it's interrupt-priority is higher than mp3-decoding - fft runs in update()!!)

Dnstje
11-24-2014, 09:37 PM
According to Audio system design tool it uses 52% peak CPU. ^^
http://puu.sh/d47U8/eebebf7460.png

Frank B
11-24-2014, 10:03 PM
Did you try 144MHz ?

Dnstje
11-24-2014, 10:04 PM
Did you try 144MHz ?

Not yet, even not modded my teensy IDE, it's still on 96mhz max.

Frank B
11-25-2014, 06:04 PM
I've added pause(bool).

Frank B
11-26-2014, 10:39 PM
Ok.. aac as audiolib-obj. is now uploaded too.

Paul, please, can you have a look at it ? I'm asking because i need to know if i have to change some things before it can be integrated into the audio library.
Is the structure ok.. the technique with using the additional Interrupt.. other things i might not think of ? Ideas ?

regards,
Frank.

p.s. Dnstje made a video with mp3+fft display

PaulStoffregen
11-26-2014, 10:46 PM
I'll try to get this going over the weekend. Right now, I have another project on my (very small) test bench.

Dnstje
12-01-2014, 11:56 AM
This is what I made from with some PCB laying around and a LCD~ resistors audio jack. I dont have a audioboard yet or plans to get one. (maybe i will) To get stereo I'm currently using the onboard DAC and PWM output at pin3 and 4, and I hear difference with timing/phase shiftings, but is fixed with a delay on one channel(for a minut orso).
Here's a preview :).

http://tsukiko.dnstje.nl/vids/index.htm

(the lcd contrast is bad, slowish response rate due cheap module I gues around 2005 ~ 20 euro's)

cebrusjki7
12-02-2014, 06:33 PM
Hey, it looks great!

How are you reading the SD card?
I am working in a similar project, but as I need to record sound with a mic and then store it on the card I'm using the Adafruit VS1053b breakout.

Frank B
12-02-2014, 06:57 PM
#include "SD.h"
But maybe i don't understand your Question, sorry.

Yes, some years ago i used this VS1053 in a project, too. A nice chip.
But now decoding can be done in software.

Frank B
12-11-2014, 10:53 PM
Before I do the job, and nobody needs it: Is anybody interested in * .flac ?

Pensive
12-11-2014, 11:11 PM
I am, with respect to our 16Mbyte of flash you might double the storage without sacrificing quality, in the first instance.

But it is dependant on CPU load.

Although my SDCard is far bigger than I need so in that respect, from SDcard, I think the applications might be limited.

PaulStoffregen
12-12-2014, 12:24 AM
Is anybody interested in * .flac ?

Yes. At least 3 people I can recall have asked for flac. But they might also be people who wanted "audiophile" features, like 24 or 32 bit data and 192 kHz sample rates. I've heard so many requests for so many features over the last year, it's hard to keep them all in mind.

If the CPU usage is moderate and easier to break into 2.9 ms chunk, Flac could also be really compelling to use with SPIFlash, where only 16 Mbyte of storage is available.

fretless_kb
12-12-2014, 03:35 AM
I am interested, I have a lrage archive of .flac and would love to be able to play them through a teensy

Pensive
12-12-2014, 08:26 AM
It is also worth considering that flac can support any bitrate and frequency so could have applications for short samples using wav2sketch (or flac2sketch), sitting between 8bit u-law and 22khz mono.

If wav2sketch supported flac it is conceivable one could offer a full drum kit in sketch ram @22khz 16bit without resorting to 8bit u-law which would sound a lot better.

I don't think your efforts would be wasted long term.

Frank B
12-12-2014, 04:38 PM
mp3 and especially aac theortically support a whole bunch of bitrates..unfortunately we can only play 44.1. Now.
Maybe this changes sometime (I'll look at this, maybe in summer. Maybe a fast bitrate-converter, at minimum for 11khz and 22khz which should be easy)

Ok, i'll do first *.flac, then support for different sources (sd, additional flash, and streaming). Is Apple lossless of any use ? I found some sources, but hav'nt looked at the License..

Pensive
12-12-2014, 07:40 PM
I think FLAC would be enough for now, I use ALAC but only because I have apple devices and iTunes doesn't support FLAC.

Frank B
12-12-2014, 09:40 PM
I think FLAC would be enough for now, I use ALAC but only because I have apple devices and iTunes doesn't support FLAC.

Isn't there a way to stream ALAC from ipad/iphone ? Or is it encrypted in this case ?
If not, maybe I would be interested . Unfortunately, I have currently no information yet . Who knows more ?.

p.s. has anyone tried *.aac ? with high bitrates, i bet you hear no difference to lossless. and it's smaller... ;-) ok..needs much ram, that's the downside.
p.s.s. looks good with flac. compiles without errors now (after i have fixed some things..;-))

Pensive
12-12-2014, 11:10 PM
Yes, AirPlay is what you refer to, and there is working open source code within XBMC.

It's true that high bitrate AAC is very good, and no audiophiles have had the patience to try and beat double blind tests against it.

But I have a 4tb mirror drive on my NAS, and don't see why I should compromise quality when space is abundant :D

Frank B
12-12-2014, 11:24 PM
Yes I have a NAS too :-)

Ok.. then, i can assume, that Airplay is not encrypted in every case. Maybe i'll look at the XBMC source when i have flac running.
My wife has an ipad , I hope that I can borrow it ;)

p.s. I hope your *.flac are 16 Bit 44.1kHz... :-)

Frank B
12-13-2014, 07:25 PM
:mad:

We have a problem.
Currently FLAC wants too much RAM... i don't know why.
a) it's normal
b) It's a bug whith "Flacie" (i used this, not the Original flac-lib)
c) ...??

Then, i'm using the Teensy 1.21beta.
The last malloc() which is called does not return (at this point, more than 32K are already allocated). I don't have the source, so i can't look at this. But i think, there is not enough RAM and something breaks... i will check this..

Frank B
12-13-2014, 07:52 PM
ok..before this last malloc(), FreeRam() reports -10828 Bytes

pixelk
12-13-2014, 08:36 PM
Noobish question :

I downloaded the git zip, extracted in my libraries folder, loaded the Mp3FilePlayer example and got those errors while compiling :


In file included from D:\Projets\_SVN_\Dev\Arduino\libraries\Teensy-Codec\aac.cpp:24:0:
D:\Projets\_SVN_\Dev\Arduino\libraries\Teensy-Codec\aac/imdct.c:48:1: error: 'erte' does not name a type
In file included from D:\Projets\_SVN_\Dev\Arduino\libraries\Teensy-Codec\aac.cpp:24:0:
D:\Projets\_SVN_\Dev\Arduino\libraries\Teensy-Codec\aac/imdct.c: In function 'int raac_IMDCT(AACDecInfo*, int, int, short int*)':
D:\Projets\_SVN_\Dev\Arduino\libraries\Teensy-Codec\aac/imdct.c:573:127: error: 'DecWindowOverlap' was not declared in this scope

Frank B
12-13-2014, 09:33 PM
Noobish question :

I downloaded the git zip, extracted in my libraries folder, loaded the Mp3FilePlayer example and got those errors while compiling :

oops..
delete the line with "erte".

i don't know where "erte" comes from.. :-)
i'll update the github this evening.

pixelk
12-13-2014, 09:47 PM
Thank you, it works flawlessly now.

Frank B
12-13-2014, 11:47 PM
ok..before this last malloc(), FreeRam() reports -10828 Bytes

Tried the official version (edited hours... 1000's of warnings away, found a bug: #pragma GCC diagnostic ignored "-fpermissive" is ignored by the compiler)
The same.

Ok... something for the next Teensy, i think :mad:
Flac maybe is fast, but the ram-usage is...:confused:

Frank B
12-14-2014, 10:55 AM
Tried the official version (edited hours... 1000's of warnings away, found a bug: #pragma GCC diagnostic ignored "-fpermissive" is ignored by the compiler)
The same.

Ok... something for the next Teensy, i think :mad:
Flac maybe is fast, but the ram-usage is...:confused:

It think,it could work with a smaller framesize.
Standard-Framesize of Flac is 4096 samples, all of my files have this.
I converted a few to a framesize of 512, now it seems that we have enough memory... the downside is, that you have to convert the files.
Tool-Download: http://downloads.xiph.org/releases/flac/

Ok , now I can go on...

Edit:
First test:
With 2 Channels (stereo), Framesize 512, the decoder needs 2ms. This includes reading from SD.

For a first working version, i'll choose framesize=128, because i need no additional buffer-handling. the compression-ratio is not as good as with 512, but i plan to support other framesizes in the next versions.

Frank B
12-14-2014, 07:12 PM
FLAC is working - currently only 128Byte Blocks (see above)
I've uploaded it at Github, + minimal player example + example flac-file.

Comments welcome.

It's the very first (a bit experimental) version.
It needs much more time than mp3 or aac, because it reads much more from SD. I hope it's more useful when reading from flash.

Edit: with this small blocksize, the RAM-usage is very low, around ~10KB

Dnstje
12-15-2014, 03:10 AM
Yeah, i'm also interested in FLAC playback indeed. I should try out your latest experimental version soon, I just got too many other projects running at this board :), I just bought a second teensy3.1 from Velleman, toobad Velleman doesnt sell the audioboard yet, though they said soon at the next year.

like above said, I have also have a lot of flac files laying around, just because of the better soundings, though most of them are 44~48khz.

my current solution is using PWM output and the dac output, but there's alot of difference on the sound output. sounds like one output is inverted and not always in sync :), so it sounds like you are moving phases a few degrees over time. but thats not your code!

But awesome that you bring these decodings to teensy!

Frank B
12-21-2014, 11:54 AM
Yeah, i'm also interested in FLAC playback indeed. I should try out your latest experimental version soon, I just got too many other projects running at this board :), I just bought a second teensy3.1 from Velleman, toobad Velleman doesnt sell the audioboard yet, though they said soon at the next year.

like above said, I have also have a lot of flac files laying around, just because of the better soundings, though most of them are 44~48khz.

my current solution is using PWM output and the dac output, but there's alot of difference on the sound output. sounds like one output is inverted and not always in sync :), so it sounds like you are moving phases a few degrees over time. but thats not your code!

But awesome that you bring these decodings to teensy!

Hi, maybe you can buy one from exp-tech in Germany: http://www.exp-tech.de/teensy-audio-adaptor-board?gclid=CIv5rZ6J18ICFdQZtAodg3oAHA

Frank B
12-21-2014, 12:00 PM
Hi,

the Teensy FLAC-Codec now supports:

- Blocksizes from 128..1024 bytes, in 128-byte steps (for example 128, 256, 512...)
- 4..24 bits per sample. For 24 bits per sample, blocksize 512/stereo is maximum (because of memory-usage). All are "on the fly" converted to 16 bps for the audio-library.

You can save (very!) much RAM with smaller blocksizes. The downside is a slightly worse compression-ratio (-> the codec has to read more from sd!)

It's now full functional. For those, who like to experiment: there's a switch which lets you choose if decoding is done in a additional software-int or in the originl 2.9ms audio-lib int. Because of SD-accesses, the default (additional swi) is better at the moment. This may change when playing from flash is available.

I got the serial-flash from china now. I hope my eyes are good enough to solder it to the board.... :-)

pixelk
12-22-2014, 04:13 PM
Thank you so much for your work !

Frank B
12-22-2014, 05:33 PM
Thank you so much for your work !

Thank you very much, I take the work on the codecs as a sporting challenge which is fun. I still have many further plans.

Next:
- Playing from teensy-flash & serial flash. Eventually, a flashing-tool for musicfiles on sd.. (the one for serial flash is allready done (https://forum.pjrc.com/threads/27335-W25Q128FV-Serial-Flasher))
- improvements to the internal structure of the lib

Frank

Frank B
12-27-2014, 04:16 PM
Next:
- Playing from teensy-flash & serial flash.
- improvements to the internal structure of the lib


Done.

I feel I have to write a documentation.... any volunteers ? :)

In short :
- play(filename) plays from SD
- play(int position, int size) plays from Serial Flash (Audioshield) There's a tool in "examples" to fill the Serial Flash with files from SD.
- play( (uint8_t*), int size) plays from Teensy Flash (a short example is in the "examples directory"). Use a tool like https://code.google.com/p/bin2h/ (for example) to convert music-files to *.h

It's amazing how much fits into the flash of the Teensy, especially if it is AAC-encoded.

New plan: Try to play multiple files simultanous.. mixed mp3/aac/flac or flac only (from flash). But i don't know when i have time to do it.

mxxx
12-27-2014, 05:44 PM
i was just trying out to play a mp3 from the Serial flash, but it seems to get stuck (or, more likely, I'm doing something wrong).


i've copied a few mp3s into the flash, and took down the position and length info. that worked.

for instance:

size_t pos = 0x0;
size_t len = 44287;

in the Mp3FilePlayer Example, all i did was change play(filename) to play(pos, len);

it compiles fine (as long as I use "size_t" for the position and size), but there's no audio and it looks as if calling play(pos, len); crashes the program (there's no repeated calls to "play"). any hints?

Frank B
12-27-2014, 06:10 PM
Hmmm... maybe...

there's a (minor) bug in AudioStream.h, the codec use 32-Bit accesses.

Can you try to add two lines:


typedef struct audio_block_struct {
unsigned char ref_count;
unsigned char memory_pool_index;
unsigned char reserve1; // Add this Line
unsigned char reserve2; // Add this Line
int16_t data[AUDIO_BLOCK_SAMPLES];
} audio_block_t;

This patch will be in Teensyduino 121, i think.

Is your serial flash on the Audioshield, or do you use an other connection ?
Does the same file play from SD ?

Edit : You should get warning when compiling ;-) Hm, maybe i should use a slower copy-variant till 121 is out...

mxxx
12-27-2014, 06:22 PM
cool. thanks, that was that. it's playing now! (at least starting from position 0x0)


i'll be curious to compare the latency vs SDcard (ie. that comes with opening the file)


edit:

pretty neat! it's down from ~500-1000us + (SD, stereo .wav) to 5us (SPI Flash, mp3)

edit2:

well, not quite. with mp3, the latency goes up somewhat; it's more consistent though.

Frank B
12-27-2014, 06:31 PM
Glad that it works now :-)

It's a "bug by design"..or "in silicon"...or however you want to call it. There is a special adress in the middle of the RAM which does not allow unaligned access. Ok, it's not really a bug, but the result is the same...

The latency when opening will be a bit less. But it#s relatively large, because the first audioframe is decoded when opening the file. This takes time, more than opening the file.

Frank B
12-28-2014, 11:49 AM
Hmmm... maybe...
there's a (minor) bug in AudioStream.h, the codec use 32-Bit accesses.
Can you try to add two lines:

I added a #if TEENSYDUINO < 121 and a memcpy_frominterleaved() in c.
The assembler-optimzed function is now automatically used when teensyduino 121 is released.
So, the patching is not needed anymore.

Frank B
12-29-2014, 08:32 PM
I discovered a new codec:
http://opus-codec.org/comparison/
Great Specs... I asked the Mailing-List, the RAM-usage is the roughly the same as MP3/AAC.

A new challenge for the next weeks ;-)

Edit: http://opus-codec.org/examples/
It's already in Firefox.

Frank B
12-29-2014, 09:18 PM
Mxxx, let me ask, is the latency whith opening important for you ?
If so, i could add a switch (#define) that disables decoding the first frame when opening.

The latency with "Opus" is the best of all codecs, according to their webpage. Minimum 2.x ms.

mxxx
12-29-2014, 10:10 PM
hi frank,

it's not terribly important, but if disabling is possible without major hassle, why not. low latency will be of interest to anyone trying to build a drum machine or the like, where timing needs to be tight. drum samples are fairly small, so the spi flash is an attractive alternative to the SD card.

presently, i see the mp3 function returns in about ~ 5000 us consistently, which isn't too bad (that's by simply calling micros() before and after play( )). playSDwav and playSDraw return a bit faster, actually it's quite good. they fluctuate around ~500 - 2000 us (though i didn't test this with lots of files, just 20 or so; RAW vs parsing the file doesn't seem to make much of a difference; probably bypassing the open-by-filename approach would. that's compared to playing PCM from RAM, in which case the play function returns in just 1 us)*. i meant to try to adapt your SPI Flash stuff for PCM, to see what the difference is, if any, but have been sick in bed for a couple of days now and can't think straight ...

* i still have to test how all this actually translates into practice, ie compared to triggering some analog sound source from the same signal.

Frank B
12-29-2014, 10:31 PM
Hmm..okay, in this case, it does not help to disable the first-frame-decoding. I can do nothing, becaus the decoding needs time, and the frames are fixed size. It depends on the number of channels (ok, for your case mono i think?) and bitrate.
You can try to overclock to 144MHz, and edit the robots.txt (add -O2 to the compiler options)
The bitrate is important for reading from SD too: higher bitrate -> more to read.

In theory, RAW from serial flash is the best solution for you if there is enough space. The latency should be very low.

Edit: AAC is a little bit faster than MP3, especially with Mono. But be aware of Audacity and export of mono-AAC: It seems to me, that there is a Bug. In the AAC-Frame is a field which tells how many channels there are. In case of mono, Audacity writes "2" - which is wrong. This results in noise in the first frame. Later, the codec handles this automatically.

mxxx
12-30-2014, 09:00 AM
ok, not a problem. but true, mono would be sufficient and for drum samples 22.05kHz will be more than ok, too.

i'll look into RAW from serial flash, that's the relevant function, right? --



//__attribute__ ((optimize("O2")))
inline void readserflash(uint8_t* buffer, const size_t position, const size_t bytes)
{//flash_spi.h has no such function.
digitalWriteFast(SERFLASH_CS, LOW);
SPI.transfer(0x0b);//CMD_READ_HIGH_SPEED
SPI.transfer((position >> 16) & 0xff);
SPI.transfer((position >> 8) & 0xff);
SPI.transfer(position & 0xff);
SPI.transfer(0);
for(unsigned i = 0;i < bytes;i++) {
*buffer++ = SPI.transfer(0);
}
digitalWriteFast(SERFLASH_CS, HIGH);
}

Frank B
12-30-2014, 10:29 AM
i'll look into RAW from serial flash, that's the relevant function, right? --


Yes.
Adding RAW to the codecs is trivial, I had planned it anyway.
I'll do this in the next days.

Frank B
12-30-2014, 01:26 PM
Yes.
Adding RAW to the codecs is trivial, I had planned it anyway.
I'll do this in the next days.

No, I think it's better to add it to the audiolibrary.
I'll provide a wav2raw.exe too. Maybe Paul accepts a pullrequest for this addition to the audiolib ?

mxxx
12-30-2014, 01:42 PM
No, I think it's better to add it to the audiolibrary.
I'll provide a wav2raw.exe too. Maybe Paul accepts a pullrequest for this addition to the audiolib ?

probably. i was looking at play_memory as a template, assuming those u-law and reduced sample rate options will be useful for the flash, too.

(though triviality is a relative thing)

Frank B
12-30-2014, 02:13 PM
yes, that's my intention.
i just compiled a variant of wav2sketch ("wav2raw.exe"), seems to work.. you can use my sketch to load the files to the serial flash.
But now, i think it's better to open a new thread.

Edit: Done, thread is here : https://forum.pjrc.com/threads/27409-Play-RAW-from-Serial-Flash

xxxajk
07-27-2015, 05:45 AM
Hey frank, sorry I'm late to the party, but I've been terribly busy. Nice work on the library.
This gives me a chunk of what I needed to play streaming audio from the 'net.
I still need to do a little bit of code to make it easily connect to ethernet (which is in the works) however for now, SLIP will do just fine for initial testing... when I finally get time to play.
If you would like to play ahead of me with networking, just use my stack, which already works on little endian <insert microcontroller or CPU here>.
Source for the stack is here: http://https://github.com/xxxajk/ajkstack
Note that this is a real IP stack, and does not require a WIFI board or anything else in particular, since it can just do SLIP. You also get REAL sockets, not fake stuff like many Arduino/spinoff libraries have.

Frank B
07-27-2015, 08:57 PM
Hey frank, sorry I'm late to the party, but I've been terribly busy. Nice work on the library.
This gives me a chunk of what I needed to play streaming audio from the 'net.
I still need to do a little bit of code to make it easily connect to ethernet (which is in the works) however for now, SLIP will do just fine for initial testing... when I finally get time to play.
If you would like to play ahead of me with networking, just use my stack, which already works on little endian <insert microcontroller or CPU here>.
Source for the stack is here: http://https://github.com/xxxajk/ajkstack
Note that this is a real IP stack, and does not require a WIFI board or anything else in particular, since it can just do SLIP. You also get REAL sockets, not fake stuff like many Arduino/spinoff libraries have.

Yes streaming is a good thing.
I'd prefer to make it more generic. Currently i have streaming with ESP8266 working, this board uses it's own stack. For overseas radiostations the available RAM on the teensy is too small (half of it is needed for the decodingprocess). I learned that a *really* large buffer is needed (several hundred kilobyte, esp. for high-bitrate streams) , so streaming without too much hardware-requirements (= additional external RAM) make only sense for very reliable internetconnections, or local LAN/WLAN . For local streaming, having no external RAM may be ok.

(I created a board with six spi-rams. The perfect solution would be a single extension board with WLAN and RAM, and ideally, an interface for a good Display. The Teensy-SPI is currently used heavily, and a second SPI would be wonderful (and more on-board ram... i hope for the next-gen teensy...)

Unfortunately i'll have no time for the next couple of weeks, but i work on this.. i hope i can find a good way to use your stack.
I'll have to buy some lan/wlan-breakouts, too...

Generally, the interest to audio streaming seems not be particularly large. And i did not get any requests.

xxxajk
07-27-2015, 11:11 PM
I think there will be no problem space wise on a teensy 3.1. 3.0 should be close, but possible with a small MTU. How large is an MP3 frame anyway?

Frank B
07-28-2015, 08:50 PM
I think there will be no problem space wise on a teensy 3.1. 3.0 should be close, but possible with a small MTU. How large is an MP3 frame anyway?

I never tried a teensy 3.0. Maybe it works ?
But there is no reason to try it :)
3.1 has enough memory to play it, important is, that the transfer-speed is sufficiant and "realtime" enough to have fresh data when it is needed.

Since internetstations sometimes have hundreds of users per stream there are some limitations...
For example, most servers try to send some seconds (i've seen a german station that tried to send more than one minute) audiodata at the beginning of the streaming to fill the buffers of the client.
You could try to ignore most of these packets at startup, but the server thinks you have enough data buffered and will send new data at irregular intervals, which may be too long. The servers know the amount of data that they sent to you and they *think* that they know when the buffer of the client is nearly empty. But this only works if you buffered all data.
There is no handshake on a higher level. It's simple http, like transferring a download or picture. So, MTU and Framesize(1152+header for MP3, for AAC something in this range too..i forgot it :) ) are not important. The Buffer ist important, nothing else.
To make it even worse, the metadata are embedded in the mp3 stream and you only have a byte-counter which indicates the position of the data. If you're out of sync because you lost a packet (or ignored it), you don't know the position ... and hear blips, chirps and noise from the decoder - the decoders are not able to handle metadata. You must restart the stream. Syncing to the frameheader does not help because the only point where the bytecounter is set to zero is at the beginning...(well, and with every metadata-packet, but when you don't know its position...->crap)

For a local setup with your own streamingservice in your lan, there are ways to fine-tune this, or to use better protocols - this should'nt be a problem (i did not try it).



Edit: It may work to send no "ack" or something like this when you run out of free buffers, and indeed i remember that this helped a bit when i did my first streamingradio some years ago (it had LAN with a STM Cortex-M3 + FRAM + mp3-decoder-chip) (I do the same with the ESP8266 with RTS/CTS)
But i remember too that some servers (or proxy?)stopped the streaming after a minute or so. It was not reliable.
Maybe too much workload for the server, or too much handling for your particular client is detected and classified as "not acceptable". Don't know.

All good clients have large buffers..

If there is a way, i don't know it :)

Edit:
This is all no show-stopper for any ethernet stack - but i see no way to do really reliable streaming without enough memory in the range of minimum 128..256 KB, better much more, esp. with bitrates > 128kbits/sec

Directgumby
01-09-2016, 07:27 PM
Will this run on the Tinsey LC processor?

Frank B
01-09-2016, 07:41 PM
Will this run on the Tinsey LC processor?

No.. not enough ram

Directgumby
01-09-2016, 07:47 PM
No.. not enough ram

What is the min RAM.
Could I trade off lower quality or another processor in the same line with more ram (if it is available)?
Basically I love the setup and the ability to decode some compression but I'd like to lower the cup cost for a future project.

Note: I have a few devices on the way to start the initial.

Thank you for the information and your work on this as it will be a great help to my initial prototype!

Brett

Frank B
01-09-2016, 08:08 PM
No, currently, the only board is teensy 3.2 (or the former 3.1). As far as i know, no other Arduino can decode MP3 or work with the Teensy-Audiolibrary.

Directgumby
01-09-2016, 10:25 PM
No, currently, the only board is teensy 3.2 (or the former 3.1). As far as i know, no other Arduino can decode MP3 or work with the Teensy-Audiolibrary.

Great to know and I'm super happy I came across the libraries. It is a huge help.

Thank you for your time in doing the work and answering my questions.

Brett

Franky_74
01-17-2016, 02:21 AM
Hi Frank,
at first - many thanks for your great work with the mp3 decoder.

I try it first time and it Works really fine.

I try to use it for an audio player for my little child.

My child player has 2 hmi .
1. movement detection and interaction with teensy player by serial control commands by Pico-platinchen with a bno055 from fablab.eu (Stuttgart) and rgb strip.

2. Teensy player with Teensy Audio board and with 12 capacitive Inputs realized with MPR121 capactive sensing chip connected to second I2c modul.
The teensy player should be controlled by serial commands from the pico-platinchen and the 12 capacitive inputs.


To use the second I2C the new I2c t3 library is used. (https://forum.pjrc.com/threads/21680-New-I2C-library-for-Teensy3 )

i comment out the Wire libray and use the i2c_t3 library instead but everytime i get errors.
I replaced later also the includes of wire.h in other files ( audio lib .... but i get everytimes errors because the orginal arduino wire lib and the i2c_t3 conflicts.

I need the help really because it is for the 1. birthday of my child which was yesterday.

So if someone can help it would be really nice.

Best regards,
Frank

Frank B
01-17-2016, 10:22 AM
Hi Frank,
at first - many thanks for your great work with the mp3 decoder.

I try it first time and it Works really fine.

I try to use it for an audio player for my little child.

My child player has 2 hmi .
1. movement detection and interaction with teensy player by serial control commands by Pico-platinchen with a bno055 from fablab.eu (Stuttgart) and rgb strip.

2. Teensy player with Teensy Audio board and with 12 capacitive Inputs realized with MPR121 capactive sensing chip connected to second I2c modul.
The teensy player should be controlled by serial commands from the pico-platinchen and the 12 capacitive inputs.


To use the second I2C the new I2c t3 library is used. (https://forum.pjrc.com/threads/21680-New-I2C-library-for-Teensy3 )

i comment out the Wire libray and use the i2c_t3 library instead but everytime i get errors.
I replaced later also the includes of wire.h in other files ( audio lib .... but i get everytimes errors because the orginal arduino wire lib and the i2c_t3 conflicts.

I need the help really because it is for the 1. birthday of my child which was yesterday.

So if someone can help it would be really nice.

Best regards,
Frank

Hi Frank,

hm, this is not related to the mp3 library, it does not use i2c. Could you open a new thread please ?

And it would be good to know which errors do you get. Is it possible to post a minimal-example which does not work ?
Btw, the SGTL5000 control uses i2c, too. Maybe that is a reason for your problems.
And maybe it's more easy to use the first I2C ? It's connected to the Audioboard, but that is no problem, I2C is a bus.

Franky_74
01-17-2016, 05:11 PM
Hi Frank,
thanks for your fast answer.
As you reccommend i will open a new thread.

Which errors i get?
the errors is because of double initialisation of i2c0_isr (more or less this name - sorry my little child is crying for me, the most time for things like this is the night....)
the solution would be to replace all #include Wire.h with #include I2c_t3
I was surprised at which modules all the Wire.h is used ( i think in 34 places in my project)
But as i replaced all also the original wire.h is comüpiled which brings an error.
Last night i roll all what i had done back because i get lost more and more.
At the end i had done some lib modification.... which brings me to totally trouble.

I will try next modification tomorow after work - open a new thread and hope that a solution can be found.

One question to you is also posible to use your player with more than 255 files?
wat is necessary to increase the arrays from 255 to let me say 800 and what should also modified?

I increase this Arrays :
int trackext[800]; // 0= nothing, 1= mp3, 2= aac, 3= wav.
String tracklist[800];

but in this case the player crased....

eventually easy and stupid question and for me at this point not so important (lower priority) because my complete project is not running at this time.
But if i solved this point this would be the next.

Best regards,
Frank

Frank B
01-17-2016, 05:23 PM
Hi,

that's only example code, it's not intended to be "complete" or "perfect" - take it as a starting point for your own projects.

Are your sure that you need an array ? Perhaps you can live without reading the whole directory. Or you don't need it at all.
Or, maybe use subirectories and only read ther content. Or alphabetically i.e. read only "'A*", 'B*", or...... maybe you have a better idea :)

pix-os
04-03-2016, 12:21 PM
just wondering if this will work with the ili9341_t3 library?

Frank B
04-03-2016, 04:22 PM
just wondering if this will work with the ili9341_t3 library?

Yes, no Problem. The lib itself does not need any Hardware, but of course you need a source for the mp3 file, like SD. I will update the lib to use the SerialFlash.

MichaelMeissner
04-03-2016, 05:50 PM
Yes, no Problem. The lib itself does not need any Hardware, but of course you need a source for the mp3 file, like SD. I will update the lib to use the SerialFlash.

Cool! That will be helpful for those of with the prop shield that want to play longer pre-recorded sounds.

Frank B
04-03-2016, 06:54 PM
In theory it can already play it from flash ( long time ago i wrote that for my old serflash lib).
Play (unsigned int address_in_serflash, length unsigned int) should do it. (totally untested with SerFlash)

But it's better to wait a few days :)

Frank B
04-04-2016, 10:04 PM
I just tried that, just for fun. It works without any changes to my codec-lib "out of the box"...
Is it still worth the effort to add the SerialFlash support ?

Example code to play from serial flash:
Upload the file with TeensyTransfer"
Adjust the filename.



// Simple MP3 file player example
//
// Requires the prop-shield
// This example code is in the public domain.

#include <Audio.h>
#include <SerialFlash.h>
#include <play_sd_mp3.h>
//#include <play_sd_aac.h>


// GUItool: begin automatically generated code
//AudioPlaySdWav playSdWav1; //xy=154,422
AudioPlaySdMp3 playMp31; //xy=154,422
AudioMixer4 mixer1; //xy=327,432
AudioOutputAnalog dac1; //xy=502,412
AudioConnection patchCord1(playMp31, 0, mixer1, 0);
AudioConnection patchCord2(playMp31, 1, mixer1, 1);
AudioConnection patchCord3(mixer1, dac1);
// GUItool: end automatically generated code


#define PROP_AMP_ENABLE 5
#define FLASH_CHIP_SELECT 6

void setup() {
AudioMemory(8); //4
delay(2000);

// Start SerialFlash
if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
while (1)
{
Serial.println ("Cannot access SPI Flash chip");
delay (1000);
}
}

//Set Volume
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);

//Start Amplifier
pinMode(PROP_AMP_ENABLE , OUTPUT);
digitalWrite(PROP_AMP_ENABLE , 1);
}

void playFile(const char *filename)
{

SerialFlashFile ff = SerialFlash.open(filename);
Serial.print("Playing file: ");
Serial.println(filename);

uint32_t sz = ff.size();
uint32_t pos = ff.getFlashAddress();

// Start playing the file. This sketch continues to
// run while the file plays.
playMp31.play(pos,sz);

// Simply wait for the file to finish playing.
while (playMp31.isPlaying()) {yield();}
}


void loop() {
playFile("rain.mp3");
delay(1000);
}


Michael: You might want to try an *.aac file. Better quality at same bitrate. Or same quality with less bitrate... you could try 80KB/s or less - depends on your files. .. and use mono to save space!
To use aac, exchange all "mp3" in the code with "aac"...

MichaelMeissner
04-05-2016, 12:30 AM
Evidently I missed a few updates (I don't seem to have play_sd_mp3.h), so I will need to root around for these, or wait until 1.28 beta 2 is released.

Thanks!

Frank B
04-05-2016, 05:55 AM
Michael,

it is not part of Teensyduino - you can find it on Github. Link is in the first post of this thread.

MichaelMeissner
04-05-2016, 01:33 PM
Michael,

it is not part of Teensyduino - you can find it on Github. Link is in the first post of this thread.

Got it. Thanks.

I'll look into converting the file to aac mono files.

Note, mp3/imdct.c contains calls to Serial without using


#include <Arduino.h>

in the header. I also found it annoying if I had the Teensy serial monitor running that it wouldn't print a newline every so often. I put in this quick and dirty patch, but perhaps just removing the Serial calls all together would be best:



-gnome-king-> cvs diff -r1.1 mp3/imdct.c
Index: mp3/imdct.c
================================================== =================
RCS file: /home/michaelmeissner/global/cvs/meissner/arduino/libraries/Arduino-Teensy-Codec-lib/mp3/imdct.c,v
retrieving revision 1.1
retrieving revision 1.3
diff -p -c -r1.1 -r1.3
*** mp3/imdct.c 5 Apr 2016 11:52:38 -0000 1.1
--- mp3/imdct.c 5 Apr 2016 12:26:11 -0000 1.3
***************
*** 44,49 ****
--- 44,50 ----

#include "coder.h"
//#include "assembly.h"
+ #include "Arduino.h" /* add from meissner */

/************************************************** ************************************
* Function: AntiAlias
***************
*** 187,197 ****
--- 188,209 ----
{
int i, d, mOut;
int y0, y1, y2, y3, y4, y5, y6, y7, y8;
+ static int serial_cnt = 0;
Serial.print("!");
+ if (++serial_cnt == 79)
+ {
+ Serial.println ("");
+ serial_cnt = 0;
+ }
if (es == 0) {
/* fast case - frequency invert only (no rescaling) - can fuse into overlap-add for speed, if desired */
if (blockIdx & 0x01) {
Serial.print(".");
+ if (++serial_cnt == 79)
+ {
+ Serial.println ("");
+ serial_cnt = 0;
+ }
y += NBANDS;
y0 = *y; y += 2*NBANDS;
y1 = *y; y += 2*NBANDS;

Frank B
04-05-2016, 01:47 PM
There shouldnt be any prints - perhaps i uploaded a testversion by accident...
I look at this, this evening.

PaulStoffregen
04-05-2016, 01:59 PM
There shouldnt be any prints

Ha, I believe I've managed to do that at least once in every library I've written.

MichaelMeissner
04-05-2016, 02:06 PM
Ha, I believe I've managed to do that at least once in every library I've written.

Yep, been there, done that.

BTW, I did convert it to AAC, and the AAC encoding is 2.1 megabytes vs. the 4.4 megabytes for mp3 (and 3.3 megabytes for ogg). Note, I haven't yet converted it to mono.

Frank B
04-05-2016, 04:44 PM
FIXED the prints are removed.


Yep, been there, done that.

BTW, I did convert it to AAC, and the AAC encoding is 2.1 megabytes vs. the 4.4 megabytes for mp3 (and 3.3 megabytes for ogg). Note, I haven't yet converted it to mono.

Note, for mono you don't need two mixers - you can remove one connection.

MichaelMeissner
04-05-2016, 05:44 PM
FIXED the prints are removed.



Note, for mono you don't need two mixers - you can remove one connection.
Yep, I figured that (and bumping the 0.5 to 1.0 in the remaining mixer). I just hadn't delved into the sound converter's options to produce a mono stream before having to leave for work.

Frank B
04-05-2016, 07:06 PM
Yep, I figured that (and bumping the 0.5 to 1.0 in the remaining mixer). I just hadn't delved into the sound converter's options to produce a mono stream before having to leave for work.

if you want it loud, yes :)

I don't know if helps, but for UBUNTU the conversion is :


sudo apt-get install libav-tools libavcodec-extra-54 libavformat-extra-54

avconv -i in.mp3 -c:v copy -ac 1 out.aac


But this converts to 64kbps (MONO) only. For small speakers this might be ok (i'd test it!) For better quality, the bitrate (kbps) should be higher..
I havn't found out, how to set the bitrate, or "quality" setting, yet...

ffmpeg should work, too.

You can use sox to convert to mono, too.


sox in.mp3 out.flac remix 1,2

then from flac (a lossless format) to aac, somehow...

Frank B
04-05-2016, 07:50 PM
Google helps...


avconv -i x.mp3 -map_metadata -1 -c:v copy -ac 1 -b 96k o.aac


It removes the metadata which can really big (embedded jpegs for example) , and sets the bitrate to 96kbps (one channel = mono).

There are better-quality codecs for aac (from german fraunhofer institute) too, but i stopped "googling" at this point...

Frank B
04-06-2016, 09:46 PM
Prop Shield - Code example which iterates trough all *.acc and *.mp3 and plays them.



// AAC + MP3 file player example
//
// Requires the prop-shield
// This example code is in the public domain.

#include <string.h>

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <play_sd_mp3.h>
#include <play_sd_aac.h>

// GUItool: begin automatically generated code
//AudioPlaySdWav playSdWav1; //xy=154,422
AudioPlaySdMp3 playMp3; //xy=154,422
AudioPlaySdAac playAac; //xy=154,422
AudioMixer4 mixer1; //xy=327,432
AudioOutputAnalog dac1; //xy=502,412
AudioConnection patchCord1(playMp3, 0, mixer1, 0);
AudioConnection patchCord2(playMp3, 1, mixer1, 1);
AudioConnection patchCord3(playAac, 0, mixer1, 2);
AudioConnection patchCord4(playAac, 1, mixer1, 3);
AudioConnection patchCord5(mixer1, dac1);
// GUItool: end automatically generated code


#define PROP_AMP_ENABLE 5
#define FLASH_CHIP_SELECT 6

float volume = 0.5f;

void setup() {

AudioMemory(10);
delay(2000);

// Start SerialFlash
if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
while (1)
{
Serial.println ("Cannot access SPI Flash chip");
delay (1000);
}
}

//Start Amplifier
pinMode(PROP_AMP_ENABLE , OUTPUT);
digitalWrite(PROP_AMP_ENABLE , 1);

}

void playFile(const char *filename)
{
int filetype;
uint32_t sz, pos;

SerialFlashFile ff = SerialFlash.open(filename);

if (strcasestr(filename, ".aac") ) filetype = 1;
else if (strcasestr(filename, ".mp3")) filetype = 2;
else
filetype = 0;

if (filetype > 0) {

Serial.print("Playing file: ");
Serial.println(filename);

sz = ff.size();
pos = ff.getFlashAddress();

switch (filetype) {
case 1 :
mixer1.gain(0, 0.0f);
mixer1.gain(1, 0.0f);
mixer1.gain(2, volume);
mixer1.gain(3, volume);
playAac.play(pos, sz);
break;
case 2 :
mixer1.gain(0, volume);
mixer1.gain(1, volume);
mixer1.gain(2, 0.0f);
mixer1.gain(3, 0.0f);
playMp3.play(pos, sz);
break;
}
}
}


void loop() {

char filename[64];
uint32_t filesize;

if (!playAac.isPlaying() && !playMp3.isPlaying()) {
if (SerialFlash.readdir(filename, sizeof(filename), filesize)) {
playFile(filename);
} else {
SerialFlash.opendir();
}
}
}





Needs > 100KB of Teensy-Flash and takes some time to compile.. :)

Edit: Just for fun-test: It's able to play my 64kbps aac file with Teensy @ 24MHz !
So..you see, CPU Usage is less than 25% (compared to 96MHz) for this type of files in flash.. (RAM Usage (dynamic, only while playing > 34KB)

Edit: No, 16MHz ...

brucethehoon
09-16-2016, 10:27 PM
I fear this is impossible, though I can drop back and punt if necessary (and use two boards), but is it possible to use this library, along with sending data to APA102 leds at the same time?
The idea would be to essentially interrupt the data going to the amp momentarily to send SPI data to the buffered 5V output on the prop shield.

The code below will not run as-is. deleting the code within the play function that addresses the LEDS will cause the audio to play as expected.
WILDLY GARBAGE code would look like this - please note bolded // comments at ends of lines are intended to point out my likely pitfalls:



#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <FastLED.h>

#define NUM_LEDS 12
CRGB leds[NUM_LEDS];
#include <play_sd_mp3.h>


AudioPlaySdMp3 playMp31; //xy=154,422
AudioMixer4 mixer1; //xy=327,432
AudioOutputAnalog dac1; //xy=502,412
AudioConnection patchCord1(playMp31, 0, mixer1, 0);
AudioConnection patchCord2(playMp31, 1, mixer1, 1);
AudioConnection patchCord3(mixer1, dac1);

#define PROP_AMP_ENABLE 5
#define FLASH_CHIP_SELECT 6
//#define FLASH_CHIP_SELECT 21 // Arduino 101 built-in SPI Flash

void setup() {
Serial.begin(115200);
FastLED.addLeds<APA102, BGR>(leds, NUM_LEDS);
pinMode(7, OUTPUT);
delay(1000);

// Start SerialFlash
if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
while (1) {
Serial.println ("Cannot access SPI Flash chip");
delay (1000);
}
}

//Set Volume
mixer1.gain(0, 0.2);
mixer1.gain(1, 0.2);

AudioMemory(20);
dac1.analogReference(EXTERNAL);
delay(50);
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);
delay(10);
pinMode(7,OUTPUT);
digitalWrite(7,LOW); //I'm turning off access to 5V buffer in an attempt to prevent SPI data from SerialFlash from bitspamming the LEDS
}

void playFile(const char *filename)
{
SerialFlashFile ff = SerialFlash.open(filename);
Serial.print("Playing file: ");
Serial.println(filename);

uint32_t sz = ff.size();
uint32_t pos = ff.getFlashAddress();

// Start playing the file. This sketch continues to
// run while the file plays.
playMp31.play(pos,sz);

// Simply wait for the file to finish playing.
while (playMp31.isPlaying()) {

Serial.println("sending audio");


for(int n = 0; n < NUM_LEDS; n++) {
leds[n] = CRGB::Red;

SPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0)); //I have tried both 12000000 and 24000000 in an ignorance fueled attempt to make it work. If this is utterly meaningless in this context, forgive my ignorance
digitalWrite(7, HIGH); // enable access to LEDs (PJRC comment)
FastLED.show();
digitalWrite(7, LOW);
SPI.endTransaction(); // allow other libs to use SPI again PJRC comment
leds[n] = CRGB::Black;
}
//side note: I can put all sorts of code within this WHILE and it will run as expected - from serial output to analogReads and other code that I only WANT to run while the audio is playing. I strongly suspect that I am only having an issue because I'm attempting to double up on the SPI, doing the proper transactional mojo while the mp3 library is simply not doing the transactions (and nearly never would need to unless you're trying to make one board do everything like this), so I suspect it is either impossible to do what I want, or that it would require a cunning rewrite of the library.


yield();
}
}


void loop() {

playFile("growle.mp3");
}

This is for a prop that needs to be done by next week. Other things it will do include occasionally accessing temperature and time data and occasionally pulling a pin high, then immediately low (delaymicroseconds) that triggers a one shot 555 circuit that makes a solenoid go a bit nuts (the effect I want).

Given that I'm only driving 12 leds, and that the refresh rate need never be higher than 4hz, perhaps it would be better to pull off from a few other pins and bitbang the colors? If I COULD make this work, however, it would be delightful.

I'd sincerely appreciate any assistance anyone might be able to give!

Frank B
09-17-2016, 10:17 AM
I've never used this type of LEDs or FASTLED.h, and don't know if it is doable.
The MP3 itself is fast, and i'm sure it does interfere with FASTLED.
But it needs to read from SD, which uses the SPI. The time it blocks the SPI is much shorter than with RAW or WAV, because it reads so much less data.
But, again, i have no idea how these LEDs work :)

Frank B
10-25-2016, 10:02 PM
This library is deprecated. It will get no more updates (more features).
Of course, if there is a BUG or something else important, i'll fix it.

https://forum.pjrc.com/threads/38466-Audiolib-MP3?p=119744&viewfull=1#post119744

jshooks
01-15-2017, 07:43 PM
I realize this is a old thread (2014), but was wondering if there was a newer effort for MP3 and other formats using the new 3.5/3.6 for more memory and speed on the CPU side. Any new libraries planned for using FFT processing of audio data and audio board? Very interested in following this development.

Frank B
01-15-2017, 09:30 PM
I realize this is a old thread (2014), but was wondering if there was a newer effort for MP3 and other formats using the new 3.5/3.6 for more memory and speed on the CPU side. Any new libraries planned for using FFT processing of audio data and audio board? Very interested in following this development.

Which formats are you missing ?
More memory is not needed, decoding works 100% good - and (automatically) faster with the newer teensys. At the moment, I have no plans re: new features - but if you have n amazing idea, I'll look at it.
FFT can be done with the std-audio-library, just use the design tool.

FLAC could take advantage of more memory - but I've never heard of a user who uses it.

Perhaps, some day, I'll add the "OPUS" Codec (with ENcoding, too, eventually) (and, mayby earlier if some users (more than one or two ;-) ) request it)

Then, it's open source - you can fork it, or, better, provide some pull-request @ github.


The newer version of the lib makes it easier to integrate it into the official audio-library some day. And, a big plus, it's independend of the source for the compressed data (uses a internal in-queue).
At the moment, it lacks support for AAC - i'll add it in the next weeks/month (only a few requests til now...) - (it's likely that i'll drop support for the *.m4a containers - they're CRAP and unusable with the new lib-architecture)

On the other hand, there seems to be no interest re: the new lib, and thus the priority on my "hobby" to-do list is pretty low.

jshooks
01-16-2017, 08:14 PM
Which formats are you missing ?
More memory is not needed, decoding works 100% good - and (automatically) faster with the newer teensys. At the moment, I have no plans re: new features - but if you have n amazing idea, I'll look at it.
FFT can be done with the std-audio-library, just use the design tool.

FLAC could take advantage of more memory - but I've never heard of a user who uses it.

Perhaps, some day, I'll add the "OPUS" Codec (with ENcoding, too, eventually) (and, mayby earlier if some users (more than one or two ;-) ) request it)

Then, it's open source - you can fork it, or, better, provide some pull-request @ github.


The newer version of the lib makes it easier to integrate it into the official audio-library some day. And, a big plus, it's independend of the source for the compressed data (uses a internal in-queue).
At the moment, it lacks support for AAC - i'll add it in the next weeks/month (only a few requests til now...) - (it's likely that i'll drop support for the *.m4a containers - they're CRAP and unusable with the new lib-architecture)

On the other hand, there seems to be no interest re: the new lib, and thus the priority on my "hobby" to-do list is pretty low.

(currently, i'm working on this :
9422
:-)

Hi Frank,

What I am working on is the ability to read PM3 audio files (instead of WAV) from the SD card and doing FFT processing for frequecy analysis. As a newbie to C/sketch coding, I am using Paul's Audio library (PArt _3_02_Fourier_Transform) to get started which works fine for "predetermined" .wav file names. So my questions are: 1) can this code be used with MP3 files and 2) is there some way to read a list of audio MP3 file names for play selection. From the contents of this thread, it does sound like MP3 files can be processed, but what is the best library code to use (different than audio.h?). For question 2, does it require some rudimentary form of OS on the Teensy side to list MP3 files for selection? Not sure what I am up against to do this. If you have any suggestions, I would greatly appreciate the help.

Frank B
01-16-2017, 09:13 PM
Did you see the examples in the examples folder ?

dundakitty
05-06-2017, 03:01 PM
Are there any caveats for using stop()? I have a "next" button in my mp3 player. Upon a button press I call stop() then play() on the next file. After a several presses the player locks up.

The code used to look like:
AudioNoInterrupts(); /* needed to make multiple changes */
mixer1.gain(0, 0); /* turn off MP3 output */
mixer1.gain(1, 0); /* turn off MP3 output */
playMP3_1.stop();
AudioInterrupts();
...
playMP3_1.play(fn);
AudioNoInterrupts();
mixer1.gain(0, 1);
mixer1.gain(1, 1);
AudioInterrupts();

After several "next" presses I get a constant squeal and buttons stop responding.
I've modified the code around the stop() call so it now looks like:

AudioNoInterrupts(); /* needed to make multiple changes */
mixer1.gain(0, 0); /* turn off MP3 output */
mixer1.gain(1, 0); /* turn off MP3 output */
playMP3_1.stop();
AudioInterrupts();
/* drain an audio block (128 samples at 44.1 KHz) */
cnt = 30;
while(--cnt >= 0) {
delayMicroseconds(100);
}
/* wait up to 0.5 seconds for MP3 to stop playing */
cnt = 5000;
while((--cnt >= 0) && playMP3_1.isPlaying()) {
delayMicroseconds(100);
}
...
playMP3_1.play(fn);
AudioNoInterrupts();
mixer1.gain(0, 1);
mixer1.gain(1, 1);
AudioInterrupts();

The good news is with this modification I no longer get the squeal. The bad news is that it still becomes unresponsive after several "next" button pushes.

xxxajk
05-06-2017, 08:58 PM
is fn pointing to a valid MP3 content?

dundakitty
05-07-2017, 01:38 AM
Yes, fn is pointing to valid MP3 content.
I have both a "next" and "previous" button and I can cycle back & forth between two files that play just fine. If I cycle too many times the player locks up and no longer responds to buttons. Any serial debugging statements stop printing.

xxxajk
05-07-2017, 04:38 AM
Smells like a race condition. :eek:
I can't verify it or anything myself right now, because I'm way too deep in work here.

dundakitty
05-07-2017, 04:15 PM
I think I've corrected the problem. I've used my Next/Prev button ~30 times now without an issue.
I added the line:
if (o->playing != codec_playing) return;
to the top of decodeMp3() in play_sd_mp3.cpp.
I also had to move the
playing = codec_playing;
line in play() to be before decodeMP3() is called instead of one of the last lines in play().

I've attached my updated version of play_sd_mp3.cpp

jshooks
07-18-2017, 10:40 PM
Is there any updates to this thread on MP3 library (i.e. does this now work with the audio.h library or something different)? Can it work with Paul's FFT function from the audio library? On a different note, has anyone attempted to read audio files directly from the USB "debug" port on the Teesny 3.2 or 3.5? It would be alot easier for users to plug in a USB thumb drive with music files rather than the SD card. If not does anyone know if such a audio board exists with USB interface?

Frank B
07-18-2017, 11:19 PM
Is there any updates to this thread on MP3 library (i.e. does this now work with the audio.h library or something different)? Can it work with Paul's FFT function from the audio library? On a different note, has anyone attempted to read audio files directly from the USB "debug" port on the Teesny 3.2 or 3.5? It would be alot easier for users to plug in a USB thumb drive with music files rather than the SD card. If not does anyone know if such a audio board exists with USB interface?

It always worked with the audiolibrary and every part of it.

v_zhukov
10-06-2017, 02:10 PM
Hello!

Thank for the giant work! The library really rocks!
But is there a way to play 2 mp3 files simultaniously? I need to mix 2 mp3 files using mixer audio object from Teensy audio library. But when I try to play 2 mp3 files or 1 mp3+ 1 aac only one file plays.

Frank B
10-06-2017, 08:58 PM
No sorry, the time I wrote it, the Teensy 3.2 was the biggest model, with the most memory. But it was not enough to play two files simultanously.

v_zhukov
10-08-2017, 08:51 AM
No sorry, the time I wrote it, the Teensy 3.2 was the biggest model, with the most memory. But it was not enough to play two files simultanously.
Do you plan update your library to support multiple file decoding for teensy 3.5-3.6? It would be really useful function!