GP2X Using The 2nd Processor For Audio


Incarnate

Still Fresh
Joined
Mar 11, 2006
Messages
13
Hey All,

So I'm starting up a new project, and I'm looking over the failures/successes of my last one. Pretty high up on my failures list is the horrible slowdown I experienced when trying to play background music ingame. Granted, I may have been expecting too much of the GP2X to allow high-quality ogg playback during a fairly complicated (and unoptimized) game, but I'd like to take another stab at it this time around. One idea thats been floating around in my brain is spawning an audio processing thread and executing that on the coprocessor, leaving the main one free to worry about more important stuff. Logic tells me that this should be relativley simple, since the audio doesn't depend on much and the only inter-process communication I'd need would be a queue of sound events to play. However, experience tells me this will be freaking impossible and I should abandon all hope right now. I'm hoping reality is somewhere in between, but given my lack of experience coding at a hardware level on something like the GP2X, I was hoping the community could give me a better idea of what I'm up against.

So here it is: background music and audio playback on the 2nd processor... is it even possible? How hard would it be? Has anything similar been done that I could look at for reference?

Thanks
 
Look at the uboot code for firmware 2.0, that does audio on the second processor whilst the machine boots up :)

Also, the 2X seems to be able to do hardware mp3 decoding, which should speed things up a bit. Just as no one knows how to use it yet!
 
Fascinating. That would be endlessly useful if someone were to make it usable-- I could gain a free 40 or 50 FPS in my engine that way. :D In an ideal world I'd hope for hardware OGG decoding as such files can be smaller and still sound as good as higher-bitrate MP3 counterparts-- but I imagine this functionality would be sharing common components that do MPEG4 decoding.
 
Epicenter posted on Jul 29 2006 at 10:16 PM said:
Yes but how about in a game engine where turning on OGG Vorbis decoding of a song can drop your framerate from 140 to ~100 FPS?

Are you using a pre-built ogg vorbis library or have you built it from sources?

And what is the difference between ogg and vorbis? do you need both to decode a song? (trying to figure out what source I need in case you are not building from source).

I figured out the 920 mmu and turn on the cache and wb (just did a flat mapping). Not sure how I got 177mips on the 920 under linux, perhaps I did. Right now both the 920 and the 940 run at 135 mips on their own.

Quick numbers (920t, no linux):

timer count, mips, gcc optimization level, notes
2691552 3.12 -O3 NOCACHE NOWB
76369 109.89 -O3 CACHE NOWB
61789 135.81 -O3 CACHE WB
74824 112.16 -O2 CACHE WB
76436 109.80 -O1 CACHE WB
122686 68.41 -O0 CACHE WB

Anyway, I then wrote a small program for the 940 to keep its memory interface busy:

CNTER: .word 0

.global _start
_start:
mov r0,#0x1000
mov r1,#0x10000
top:
ldr r2,[r1]
str r2,[r1]
add r1,r1,#4
subs r0,#1
bne top

ldr r7,CNTER
add r7,r7,#1
str r7,CNTER

b _start


With the cache and wb on the 920 goes from 135.80 mips to 135.70 mips, noticeable but barely. Looks like the dhrystone code mostly fits in the cache. If I run with the cache and wb off it goes from 3.12 mips to 2.30 mips if the 940 is jumping on the bus. So that means with both processors banging on memory you get more than one processors worth performance out of two. Had the 920's performance been cut in half (1.56 mips) then the 940 would have taken half the 920s performance and you would get two processors running no faster than one. So IMO this proves it the 940 is useful. I still want to try having both processors run dhrystone somehow at the same time, somehow get the results from both. Not to hard actually just too late to try tonight.

What I would like to do is have the 940 decode the same segment of ogg compressed sound over and over again. Then do some things with the 920, see how the two perform with and without caches and wbs on. The 940 is not running linux so I need to compile the decompressor from sources...Hmm, well maybe I dont, will see, but to be useful to you it needs to be something you can re-build for the 940.
 
Last edited by a moderator:
OGG is the container format and Vorbis is the codec itself. I'd love to decode Vorbis audio on the 940T, but it seems like it'll slow the system down more than it'd speed it up due to how much 'babysitting' the 940T would need.
 
Epicenter posted on Aug 1 2006 at 05:42 AM said:
OGG is the container format and Vorbis is the codec itself. I'd love to decode Vorbis audio on the 940T, but it seems like it'll slow the system down more than it'd speed it up due to how much 'babysitting' the 940T would need.

Is this going to be a continuous stream of audio or just single packet bursts?

For small bursts I was thinking you put the whole thing in shared memory (Assuming we are talking about say 1/2 - 1 meg maybe), write to a dual cpu register, and the 920 walks away the 940 does the rest, decodes and feeds the sound chip.

If it is continuous then double buffer, place half a buffers worth in one half of the buffer (ping),
write to a dual cpu register to enable the 940 to work the ping buffer
write to the pong buffer, tell the 940 the pong buffer is ready,
Periodically poll to see if the 940 is finished with the ping buffer,
write some to the ping buffer, write to a dual cpu register
periodically poll for the pong buffer
...

Its not that much more work than you would be doing anyway if the 920 was doing everything (a single register write versus a whole block decode), the 920 still has to do some work, moving ogg data from the sd to memory. The polling period can be long, it shouldnt be hard to figure out how long you can wait before the 940 is going to run dry, cut that in 1/2 or 1/3 and make sure you poll that often. If you have a game loop you can poll every time through the loop. Can do it without polling perhaps, enable interrupts, the 940 writes to a dual cpu register and the 920 gets interrupted, now how you get from the isr to moving data from the sd to ram still has to be polled unless you can call those functions from the isr.

I am assuming this data is on sd and you are using linux to read the file from sd? If nothing else is on the sd you could use the 940 and to read the sd card itself.
If the ogg data all resides in memory or the 940 reads it from sd, then simply write to the dual cpu register, "play sample 7", okay now "play sample 3"...

I am just trying to help here, there is this underlying belief that the 940 steals so much time from the 920 that it is useless to use. I have already demonstrated (to myself) that I can have both of them sharing memory, with no cache or write buffer on either side, and the two processors still outrun one. I want to try some more tests and I might as well try to do a test that is either something you can use or similar enough to something you can use to make it worth your time to try...

For example if I gave you a module that had the 940 decode the same block of compressed audio over and over again in an endless loop. Run your game without sound, you get 150fps right? Now run with this infinite loop running on the 940, what fps do you get? You dont even have to do that, take the code from my previous post and put it on the 940, see how it affects the frame rate. Then turn the MPU and run the same code on the 940 see how that affects your frame rate. If you want me to give you complete modules that you can link in for that simple 940 busy loop I can do that. I should probably have it poll a register in the loop to to have it hit a different part of the shared system bus.
 
Last edited by a moderator:
quick drystone tests, running dhrystone on both the 920 and 940 at the same time

both running

920 2.13mips 940 2.10 mips

only the 920

920 3.40 mips, 940 not running

only the 940, 920 is actually running and polling the timer waiting for the 940 to finish
I guess I should have turned on the 920 cache for this. the 920 is hitting memory and mio.

920 polling, 940 2.43 mips.

No cache or wb, so both cores were fighting each other to share memory (one operating at 0x0008000 and the other based at 0x01000000), we had a total of 4.23 mips, where the 920 by itself was getting 3.40, two processors outpeform one even when fighting over resources.

I assume when I turn on the caches and write buffers the performance of both will go up dramatically, more like yesterday where the 920 performance had lost less than 1% of its bandwidth.

Ogg is looking like no fun, you sure you dont want MP3?
 
dwelch posted on Aug 1 2006 at 11:56 PM said:
Ogg is looking like no fun, you sure you dont want MP3?
How about starting off with looping a wave file, and slowly work it up from there? I mean, if you get MP3/OGG looping on command with extra sample mixing in (for soundeffects) on command working on the 940 that would mean a boost for almost any game I think. But small steps at a time never hurt anyone.

As I read it now it sounds like most trouble is getting messages quick and easy over from the 920 to the 940.
 
Last edited by a moderator:
Daid posted on Aug 1 2006 at 08:45 PM said:
As I read it now it sounds like most trouble is getting messages quick and easy over from the 920 to the 940.

The dual cpu registers, in theory, make it easy to communicate between the cores.

I needed/used zlib decompression for my gps navigation project so I had it handy.
This test does a single uncompress().

Baseline, 920 only, no cache, no wb, 5373769 timer counts, 1.37 decompressions per second, 1.37 total
920 no cache, no wb, 12065786, 0.611 per second, 940 no cache, no wb, 10731251, 0.687, 1.298 total
920 no cache, no wb, 7530676, 1.00 per second, 940 cache+wb, 310305, 23.67, 24.67 total

Baseline, 920 only, cache, wb, 186254, 39.58, 39.58 total
920 cache+wb, 216111 counts, 34.12 per second. 940 no cache, no wb, 5454701, 1.35 per second, 35.47
920 cache+wb, 217031, 33.97, 940 cache+wb, 253494, 29.08, 63.05 total

It doesnt get any more clear. The 940 will dramatically inprove your processing power, so long as the cache and wb are turned on on both sides.

Bottom line, Yes, splitting off the ogg decode to the 940 should improve your overall performance.
If you compare 920 only no sound to 920 + 940 sound your frame rates will drop a little to add sound
If you compare 920 only with sound to 920 + 940 sound, you should see a noticeable frame rate increase.

I can post a compiler and examples for using the 940 if you are interested, (I have already posted the compiler in other threads, I have not posted an update with these simple 920/940 examples, but plan to soon). If you end up having to fake file i/o to do ogg on the 940, it is not hard at all to do with newlib, which is what this compiler uses, I dont know anything about glibc. If you use mp3 I think you can get away with no file i/o requirements. Newlib makes mallocs easy too, which zlib required.
 
Last edited by a moderator:
I am interested in the supposed hardware MP3 decoder. Ok so its probably just someone being confused and thinking the MPEG2 decoder is an MP3 decoder, but if there actually is one I could put good use to it. Maybe I should email GPH and ask them if theres such a thing.
 
Blah posted on Aug 2 2006 at 03:45 PM said:
I am interested in the supposed hardware MP3 decoder. Ok so its probably just someone being confused and thinking the MPEG2 decoder is an MP3 decoder, but if there actually is one I could put good use to it. Maybe I should email GPH and ask them if theres such a thing.

Why not just use the 940 and software? "hardware" decoders are nothing more than a processor with firmware and a serial goesinta and goesouta. ARM has had a software decoder for years, not free. The iPod uses one, not free. iPodlinux uses the helix code.

I just finished compiling and timing the helix mp3 decoder source, on the 920 with a variable bit rate 128k file it decoded 1,259,616 bytes per second (bytes post-decompression), which is 7x over realtime. Now I need to know how to setup and feed the sound hardware on the gp2x...
 
Last edited by a moderator:
Blah posted on Aug 3 2006 at 02:47 AM said:
What about LibMAD and LibTremor. They're supposed to be fast.

I have tested libmad before, it was fine, when I was messing around with the iPod libmad couldnt make realtime, apparently helix can. Tremor sounds familiar but I dont have any personal experience with it. Helix was easy to compile and use. Finding exactly the right download on their website, that was the challenge.
 
Last edited by a moderator:
dwelch posted on Aug 3 2006 at 08:28 AM said:
Blah posted on Aug 3 2006 at 02:47 AM said:
What about LibMAD and LibTremor. They're supposed to be fast.

I have tested libmad before, it was fine, when I was messing around with the iPod libmad couldnt make realtime, apparently helix can. Tremor sounds familiar but I dont have any personal experience with it. Helix was easy to compile and use. Finding exactly the right download on their website, that was the challenge.
The licensing restrictions on Helix are rather confusing. The closest guess I can make is that your project has to be open source if you use it. That's not necessarily a problem, just something to keep in mind. From the stats they give on the website it looks plenty fast.
 
Last edited by a moderator:
The RockBox project uses libmad. It's faster than real time on ipods using only one of the 75mhz cores. Tremor also runs faster than realtime.
 
Vektar includes a port of the Tremor library that runs on the 940. Craig says it's okay if I share that so in the next couple of weeks I will be trying to get it packaged up in a form where an experienced and dedicated person could adapt it for their own use.
 
Back
Top