GP32 I Guess I Found The Cause Of The Gp32 Sound Bug


SvOlli

Certified Guru
Joined
May 4, 2004
Messages
161
Location
Hannover, Germany
Website
svolli.org
Hi there!

During the discussion with a co-worker from the hardware department we maybe found the cause of the always annoying gp32 sound bug.

The main problem seems to be that the (memory?) bus can't handle all the data, there's just too much traffic. And then the sound dma will not be able to get the needed data in time.

I did some experiments with my OggVorbis Player (Project Bluescreen from the beta board). If I throttle my graphics output down, there's no "static noise" anymore. My next step there will be to replace the loop calling GpPointSet() function with an own graphics routine that'll always write 4 pixels (32 bit) at a time to reduce load on the memory bus.

So maybe the rule "only access the memory on 32bit boundry" can help avoid the sound bug.

I'll keep you informed.

Greetings & good night from Germany,
SvOlli
 
Yes, I think most of the developers know why the sound bugs exists and how to get around it. Some methods are described in the arm documentation - eg. by placing an instruction that doesn't access the memory in the middle of tight memory copying loops and the like to release the bus for dma etc. Unfortunately, it only describes the problems in arm assembly code and the ways around it, so people who don't understand assembler and only know C are pretty much stuck.

I believe Mirko has found a solution in his own SDK though. I've not looked at his code to see how he does it (not particularly interested to be honest), but just from what he says in his SDK thread.
 
I've always thought there should be a sticky on this... Most people don't go looking through the technical specs very often, and on a few occasions people asking why their sound is crackly get a rather snotty reply about it being covered before and a link to that 300 page document.
 
My experience with the Soundbug :



> What is the best setting ???

It depends on how mutch you use the bus, try both ...

>mr.mirko, I don't really get the difference between a much lower access to the
memory bus, and increasing the speed...

once again, youre disabling the cache on the sound DMA buffer, or any other buffer, with fast memory acces, to get a clean sound, and not to speed up something. Disabling cache on a memory region, will slow down the access. And why do we do this? Couse the design of the gp32 soundhardware ( no real soundchip ), needs this.

There is no A-B-C cook book for a work around on the gp32 soundbug.
I found out, that this helped me, developing the modplayer:

- disable write back cache on main sound loop buffer, and all sound related buffers.
- fill the soundbuffer with soundbuffer[x] = *buffer++;
- dont use malloc/free with newlib, the garbage collection will result in sound crap...
- If you still suffer from soundbug, compile memory expensive part with -O0
- try using a high memory region for the main sampleloop, ( near framebuffer )

Sound on gp32 is a real hell, it took me 3 Month developing a clean modplayer, i had to
rewrite all memory access in source...
 
I find it usualtyl comes down to very specific parts of your code causing the bus to fill up; ie: the trick for me was to find out *where* I was filling up the bus, and then to adjust to fit.

Tricks..

1) #if'ing; just #if 0 out some blocks of code until the problem goes away; ie: Turn off your rendering code, as its usually the culprit; if that works, then start turning off smaller and smaller chunks until you go aha! and know where it is

2) Break the code into more files, then use different -O optimizaiton levels on them until the noise goes away; ie: compiel with all the optimizations you can, and if the problem shows up, turn it down to -O0 on one file at a time until it goes away.. then you know which file to narrow in on, and go back to (1)

//etc

In my case, it always came down to tight rendering loops, so futzing with them, or breakign up rendering into additional passes, or refactoring etc, would solve the problem...

jeff
 
I had really crackly sound on DrMD. I found it was caused by my screen rendering code writing outside of the frame buffer :| ( Sloppy, Sloppy I know :) )
 
Hi there,

In my app, I was suffering of the infamous sound bug where if I started playing with the app's UI while it played sound, mini clicks would pop in. After tracing the code a little, I discovered the main problem came when clearing the framebuffer to display the UI. To clear my 8-bit framebuffer, I would simply do

Code:
  memset(framebuffer_[currentBuffer_],currentColor_,320*240);

After reading the thread on the sound bug, I ended up trying to 'relax' the bus by sending a few bytes, waiting, then going on.. and finished with a code like this:

Code:
        // We're going to fill memory with ints

        unsigned int intColor=0;
        for (int i=0;i<4;i++) {
             intColor=(intColor<<8)+currentColor_;  
        }
        unsigned int *dst=(unsigned int *)framebuffer_[currentBuffer_];

        for (int i=0;i<480;i++) {
            for (int j=0;j<40;j++) {
             *dst++=intColor;
            }
            int k=0;
            for (int j=0;j<2000;j++) {
                k++;
            } 
        }

Now, I don't mind a little hack but it seems strange to me that I'm not able to play 44.1Khz stereo sound and can't clear the screen at the same time without noticing crackz & clickz. Plus this is possibly slowing down the interactivity level of my UI which is a bit of a bugger.

So is there any authority over here to tell me if this is my only option or is there anything else I could do ?

On another -but related- note, does anyone knows if, using GCC, I call memset & memcpy using the normal system calls I'll get performance optimization if my buffers position & size are 4_bytes aligned or do I have to code it myself ?

Huge thanks guys !
 
Hi,

Don't know about the sound bug, but there is an ASM version of memcpy on my site (snippet: unknown author - Fast assembler memcpy routine) which much MUCH faster than the standard one.

Yes, memcpy definately suffers from copying when not on a 4-byte boundary. To give you an idea, I implemented my own blitting routine that was up to 40 times faster than the standard Mr.Mirko one in certain conditions. About half of this was due to the memcpy.

EDIT:
Old thread here:
http://www.gp32x.de/board/index.php?showtopic=15954&st=0
Sorry, I made a mistake - it was up to 75 times faster than Mr.Mirkos original (running on geepee32 though).
 
Last edited by a moderator:
Thanks pea,

I had the routine ready to use on my desktop already and my question was directly related towards wheter or not I should include it. I don't do much copy/fill (after all, music apps are more about calculations) but already filling memory by ints rather than chars made me gain a few % of cpu usage so I'm going to add that one too. Maybe I'll use it too to display caracters.

Ceerio,
Marc.
 
I've just encountered the sound bug too and it would be interesting to say that I solved the problem with something I did randomly and I am still not sure why it works. And it's nothing like those solutions here. Perhaps my solution would give more explanations about the sound bug?

I have been coding a 3d engine on GP32 and now I had some 3d object wtih gouraud shading and z-buffering. For the z-buffering I had a big array and there was the problem. While I thought that the most overhead is happening on the polygon rendering routines (comparing the z of the current pixel with the z-buffer, if closer then write both to the screen and z-buffer ram, too much writting in two big arrays),it wasn't. There were a lot of calculations between the writtings in the polygon rendering that served as a good delay between memory writtings and so the problem didn't really appeared there!

The problem was on the much more simpler code which cleans the big z-buffer array.

What I had was:
int i;
for (i=0; i<GP32_Width*GP32_Height; i++)
zbuffer = 2147483647;

At the beginning I did a test:
int i;
for (i=0; i<GP32_Width*GP32_Height; i+=2)
zbuffer = 2147483647;

And that was just to test if writting less data would cure the problem. And it worked well without sound bug! But I wasn't filling my whole table as I wanted.

This one didn't worked even if it copies the same ammount of data:
int i;
for (i=0; i<GP32_Width*GP32_Height/2; i++)
zbuffer = 2147483647;

So I said. Wtf? It's not about data ammount!

And it was about jumping one int per write, the sound bug dissapeared because I wasn't filling the big table serially?

So, I made this one which does the same job with not less speed than the very first code. My z-buffer table is filled by not writting each next int but jumping one int and writting one int and again from the beginning to fill the other half! And absolutelly no sound bug with every complex or simple 3d object I have here in my code!

int i;
for (i=0; i<GP32_Width*GP32_Height; i+=2)
zbuffer = 2147483647;
for (i=1; i<GP32_Width*GP32_Height; i+=2)
zbuffer = 2147483647;

So. I avoided putting a useless code to delay my inner loop. I didn't slowed down the cache or underclocked the GP32. I did nothing of what written here (except from the suggestion to // pieces of code till I found the main core that cause the problem ;). I just filled my big array not as serially as I should, jumping int, writting int, jumping int, writting int. I was amazed that it worked..

WHY DID THIS WORKED?

I am just curious to learn but other than that I am happy because now everything works perfectly without having to slow down my 3d engine! =)))

Just so you know.
 
Why would that work, my thoughts?

1) And it was 32bit copy. Do the compilers automatically allign your arrays? I don't think that was the problem because in both cases the writtings would be the same..
2) I really don't know what compilers generate. What if the second code generated quite diferrent machine code which prevented the bug to occure?
3) Cache? Is it that when you are not writting exactly the next int serially but do it in the second way, suddenly the cache works in another way?
4) Slightly more delay between the writtings, because i++ could be a bit faster than i+=2? But I think the speed diferrence between the two would be almost inexistant..
5) Maybe I should see the produced code. How can I see the produced assembly code from the compiler? Maybe a dissassembler or another tool? Gotta check it..
 
Back
Top