Saturday, June 30, 2012

MP3 streaming on ARM7

Even if it's not something I would personally use in my homebrew... it's possible to program the DS 'secondary' processor (called 'ARM7' for short) to stream (I mean play) MP3s directly from the storage. The good thing is that your 'main' processor (the ARM9) will be free to work on more interesting tasks such as elaborating your game logic, while the music goes in the background. The bad thing is that your ARM7 33MHz isn't exactly that super-powered beast, and has no hardware decoding capabilities... so the whole software decoding work of an MP3 can be quite demanding for its somehow limited power.

It all started with this post on gbadev forum. Extrapolating parts of elhobbs' great work on cquake, forum user 'hacker013' created an example (that can be easily turned into a library, if this matters to you...) that makes it very easy to stream a (stereo only, be aware) MP3 audio file on a DS. The provided code, unfortunately, was playing only the left channel of the MP3 file it was streaming, so I made some changes that actually made the code play both left and right channels using two separate DS hardware channels. I've put the whole modified code here, in case you need it.

To say the truth, I hardly see any reason why you should ever use such a thing in your homebrew. MP3 files are quite big (say 1 MB for each minute of a 44100 samples/sec, stereo, 128Kbps encoded file) and the ARM7 processor will surely choke if you try to make it decode a 44.1KHz stereo (CD sample rate) MP3 encoded at more than 128Kbps. Even a common 44.1KHz 128Kbps stereo MP3 could be enough to choke the CPU, sooner or later... at least that's what I found during my tests. Things gets better with stereo MP3s having 32KHz sample rate that is also close to the DS audio output, which is 32768 samples per second. In my tests I could play some 32KHz stereo MP3s encoded up to 256Kbps with no problems.

Anyway, in my opinion, 'tracked music' is the way to go on a DS. MaxMod library, or libXM7, which I wrote myself some time ago, can produce very good quality music even with very little ARM7 CPU load. MaxMod comes with the devkitARM & libnds, and it supports MOD/S3M/XM/IT formats with hardware and software audio mixing. On the other hand, libXM7 only supports MOD and XM formats with hardware mixing only, but the MOD and XM compatibility is very accurate, and it supports the whole range of effects that MOD/XM tunes can use.

7 comments:

  1. i'm glad to have found this goldmine like 5 years ago. i'm currently making a DS homebrew game with many bug fixes on this mp3 decoder

    ReplyDelete
    Replies
    1. I'm happy you found my old blog interesting!
      Let me know if there's a place where I can follow your game development and if you posted the bug fixes to the mp3 decoder somewhere.

      Delete
    2. oh damn, i didn't notice you replied a day later, i wasn't notified
      either way, it's all here in my github, on this specific project https://github.com/headshot2017/ao-nds

      some of these bugfixes on the mp3 player are
      * stopping the mp3 player correctly if looping is false after reaching the end
      * if mp3_fill_buffer() is not called in time, the ARM7 would get stuck in the while loop in mp3_frames(), causing the game to freeze when you call mp3_stop() in ARM9. this no longer happens - the ARM7 will exit out that loop when it sees it's been there for too long, and then wait for either mp3_fill_buffer or mp3_stop

      at some point i was also trying to add the ability to loop from a specific point in the mp3 when reaching the end, though it doesn't work very well but the code is there

      Delete
  2. hi, you might be interested to hear i ported a KallistiOS (Dreamcast homebrew) ADX decoder library and wrote it on top of your existing code: https://github.com/headshot2017/libadx-nds
    i have tested 48000 Hz 128 kbps with no lag

    ReplyDelete
    Replies
    1. Thank you! Note that the original code isn't mine (it's from user 'hacker013' on GbaDev.org forum), I had just fixed a few bugs there...

      Delete
    2. i see, thanks, i'll reflect that on the readme

      Delete