GP32 How To Get Clean Sound From A Streaming Buffer?


SvOlli

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

I've got a problem with putting out correct sound, from what I've seen on other topics this ain't uncommon, but I can't seem to pinpoint it.

Here's what I've got:

Code:
unsigned short *g_buffer;
unsigned int   *g_playpos;
int            g_free;
int            g_use;

void snd_timer()
{
   if( g_free ) return;

   if( *g_playpos < (unsigned int)g_buffer + SNDBUFFERSIZE )
   {
      if( g_use == 0 )
      {
         g_use  = 1;
         g_free = 1;
      }
   }
   else /* *g_playpos >= (unsigned int)g_buffer + SNDBUFFERSIZE ) */
   {
      if( g_use == 1 )
      {
         g_use  = 0;
         g_free = 1;
      }
   }
}

unsigned short* snd_getbuffer()
{
   /* wait for a free buffer */
   while(!g_free);
   g_free = 0;

   if(g_use)
   {
      return g_buffer + SNDBUFFERSIZE;
   }
   else
   {
      return g_buffer;
   }
}

void snd_start()
{
   int i;
   unsigned short *p;

   g_free   = 1;
   g_use    = 0;
   g_buffer = (unsigned short*)gm_malloc(sizeof(unsigned short*) * 2 * SNDBUFFERSIZE);
   for(p = g_buffer, i = SNDBUFFERSIZE * 2; i; i--)
   {
      *(p++) = 0x8000;
   }

   GpTimerOptSet( 0, 60, 0, snd_timer );
   GpTimerSet(0);

   GpPcmInit(PCM_S44, PCM_16BIT);
   GpPcmPlay(g_buffer, SNDBUFFERSIZE * 2 * sizeof(unsigned short), 1);
   GpPcmLock(g_buffer, &i, (unsigned int*)&g_playpos);
}

void snd_stop()
{
   while(!g_free);
   GpPcmStop();
   GpTimerKill(0);
}


the main loop goes something like:
{
   unsigned short *buffer;

   for(;;)
   {
      buffer = snd_getbuffer();
      fancy_fill_buffer_code( (char*)buffer ); /* this really is ov_read() from OggVorbis/Tremor */
   }
}

My Problem now is that the speed is about 10% too slow and crackling. If SNDBUFFERSIZE is big enough and when snd_getbuffer() is waiting for a free buffer, sound is fine. From all that I'm assuming, that my writes to the audio buffer disturb the sound playing. Do my writes have to be in sync with something? If yes, with what? Or where am I going wrong?

As always, any help and clue is appreciated!

Thanks in advanace and greetings from Germany,
SvOlli
 
I use this sound loop in my SDK:

Code:
void gp_playSample2( u16 *add_buffer,int add_size,int add_copyflag) {
   int i;
   add_size=(BSIZE)/2/2;   // half buffer

   // detect playing segment
   if ( gp_getSamplepos2() > (SAMPLEBUFFER0+BSIZE/2) ) {                      // we are in upper segment
     for (i=0;i<add_size;i++) samplebuffer[i] = add_buffer[i];                // fill lower segment
     while (1) {  if (gp_getSamplepos2() < (SAMPLEBUFFER0+BSIZE/2)) break;  } // wait reaches lower segment
   }
   else {
      for (i=0;i<add_size;i++) samplebuffer[add_size+i] = add_buffer[i];       // we are in lower segment, fill upper
      while (1) {  if (gp_getSamplepos2() > (SAMPLEBUFFER0+BSIZE/2)) break;  } // wait reaches upper segment
   }
}

Hope it will help
 
I finally found it. The problem was that I was using the wrong optimisation parameters:
-Os (optimize for size) is no good on a gp32. I guess the code gets out of 32 bit alignment.

But why do I have to learn it the hard way after implementing several different sound drivers? :(

Greetings from Germany,
SvOlli
 
Back
Top