forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Clicking audio

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
dsn



Joined: 09 Nov 2005
Posts: 47
Location: Indianapolis, Indiana, USA

PostPosted: Sat Nov 19, 2005 1:47 am    Post subject: Clicking audio Reply with quote

I'm putting together a little audio library. Everything works swimmingly except that I get clicks in my audio with every other buffer swap. I've tried changing the thread delay time (and removing it altogether), as well as changing the number of frames per output call, both with no luck. Can anyone tell me what I'm doing wrong? I've posted the relevant code below; I can post more if necessary.


Code:
#define kAuFramesPerOutputCall     (2048)
#define kAuBytesPerOutputCall      (kAuFramesPerOutputCall * 4)

int              gAuMusicChannel;
int     volatile gAuMusicVolume;
SceUID           gAuMusicThreadID;
SceBool volatile gAuMusicThreadShouldExit;
SceBool volatile gAuMusicThreadShouldPause;
SceBool volatile gAuMusicThreadIsSleeping;
AuMusic volatile gAuCurrentMusic;

Code:
AuErr AuInitializeMusic()
{
   // Reserve hardware channel.
   
   gAuMusicChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL,
                                       kAuFramesPerOutputCall,
                                       PSP_AUDIO_FORMAT_STEREO);
   
   if (gAuMusicChannel < 0)
      return kAuErrNoMoreChannels;
      
   gAuMusicVolume = kAuMaximumVolume;
   
   
   // Start rendering thread.
   
   gAuMusicThreadID = sceKernelCreateThread("Music",
                                            AuMusicRenderingThread,
                                            16,
                                            65536,
                                            0,
                                            NULL);
   
   gAuMusicThreadShouldExit  = NO;
   gAuMusicThreadShouldPause = NO;
   gAuCurrentMusic           = NULL;
   sceKernelStartThread(gAuMusicThreadID, 0, NULL);
   
   
   return kAuErrNone;
}

Code:
int AuMusicRenderingThread(SceSize unused1, void *unused2)
{
   void *buffer1;
   void *buffer2;
   void *buffer;
   
   // Allocate rendering buffers.
   
   buffer1 = malloc(kAuBytesPerOutputCall);
   buffer2 = malloc(kAuBytesPerOutputCall);
   
   if (! (buffer1 && buffer2))
   {
      if (buffer1) free(buffer1);
      if (buffer2) free(buffer2);
      
      sceKernelExitThread(kAuErrMemory);
      return kAuErrMemory;
   }
   
   buffer1 = mCachelessPointer(buffer1);
   buffer2 = mCachelessPointer(buffer2);
   
   buffer = buffer1;
   
   
   // Go to sleep and wait for a wakeup call when music needs to be played.
   
   gAuMusicThreadIsSleeping = YES;
   sceKernelSleepThread();
   gAuMusicThreadIsSleeping = NO;
   
   
   // Rendering loop.
   
   for (;;)
   {
      // Check for messages from the main thread.
      
      if (gAuMusicThreadShouldPause)
      {
         gAuMusicThreadIsSleeping = YES;
         sceKernelSleepThread();
         gAuMusicThreadIsSleeping = NO;
      }
      
      if (gAuMusicThreadShouldExit) break;
      
      
      // Make sure some music has been set.
      
      if (! gAuCurrentMusic)
      {
         gAuMusicThreadShouldPause = YES;
         continue;
      }
      
      
      // Render music.
      
      long bytesSoFar = 0;
      int unused;
      
      while (bytesSoFar < kAuBytesPerOutputCall)
      {
         long bytes = ov_read(&gAuCurrentMusic->vorbis,
                              (void *) ((unsigned) buffer + bytesSoFar),
                              kAuBytesPerOutputCall - bytesSoFar,
                              &unused);
         
         if (bytes == 0)
         {
            ov_time_seek(&gAuCurrentMusic->vorbis, gAuCurrentMusic->loopPoint);
            continue;
         }
         
         if (bytes < 0)
         {
            gAuCurrentMusic = NULL;
            break;
         }
         
         bytesSoFar += bytes;
      }
      
      if (! gAuCurrentMusic) continue;
      
      
      // Send rendered music to audio hardware.
      
      sceKernelDelayThread(20 * sceAudioGetChannelRestLen(gAuMusicChannel));
      while (sceAudioGetChannelRestLen(gAuMusicChannel) > 0) { }
      
      sceAudioOutput(gAuMusicChannel, gAuMusicVolume, buffer);
      
      
      // Swap buffers.
      
      buffer = (buffer == buffer1) ? buffer2 : buffer1;
   }
   
   
   // Clean up.
   
   free(buffer1);
   free(buffer2);
   
   sceKernelExitThread(kAuErrNone);
   return kAuErrNone;
}
Back to top
View user's profile Send private message Send e-mail
bengarney



Joined: 22 Oct 2005
Posts: 24

PostPosted: Sat Nov 19, 2005 9:43 am    Post subject: Reply with quote

Tried triple buffering it? :)
Back to top
View user's profile Send private message
dsn



Joined: 09 Nov 2005
Posts: 47
Location: Indianapolis, Indiana, USA

PostPosted: Sat Nov 19, 2005 11:58 am    Post subject: Reply with quote

At first I thought you were kidding, but that actually worked. Thanks for the tip. :)

I only added three lines and changed one, so unless someone specifically requests it, I won't bother posting the new code.

EDIT: Make that added four and changed two.
Back to top
View user's profile Send private message Send e-mail
bengarney



Joined: 22 Oct 2005
Posts: 24

PostPosted: Sat Nov 19, 2005 12:19 pm    Post subject: Reply with quote

C'mon, if you're going to go to the trouble of counting the changes TWICE, surely you could post the changed lines. :P
Back to top
View user's profile Send private message
dsn



Joined: 09 Nov 2005
Posts: 47
Location: Indianapolis, Indiana, USA

PostPosted: Sat Nov 19, 2005 12:44 pm    Post subject: Reply with quote

I suppose I should mention that my second line count was wrong too. :) Sometimes I wonder why I'm even allowed to operate a computer.

The only part that changed is the playback thread, listed here.

Code:
int AuMusicRenderingThread(SceSize unused1, void *unused2)
{
   void *buffer1;
   void *buffer2;
   void *buffer3;
   void *buffer;

   
   // Allocate rendering buffers.
   
   buffer1 = malloc(kAuBytesPerOutputCall);
   buffer2 = malloc(kAuBytesPerOutputCall);
   buffer3 = malloc(kAuBytesPerOutputCall);
   
   if (! (buffer1 && buffer2 && buffer3))
   {
      if (buffer1) free(buffer1);
      if (buffer2) free(buffer2);
      if (buffer3) free(buffer3);
      
      sceKernelExitThread(kAuErrMemory);
      return kAuErrMemory;
   }
   
   buffer1 = mCachelessPointer(buffer1);
   buffer2 = mCachelessPointer(buffer2);
   buffer3 = mCachelessPointer(buffer3);
   
   buffer = buffer1;
   
   
   // Go to sleep and wait for a wakeup call when music needs to be played.
   
   gAuMusicThreadIsSleeping = YES;
   sceKernelSleepThread();
   gAuMusicThreadIsSleeping = NO;
   
   
   // Rendering loop.
   
   for (;;)
   {
      // Check for messages from the main thread.
      
      if (gAuMusicThreadShouldPause)
      {
         gAuMusicThreadIsSleeping = YES;
         sceKernelSleepThread();
         gAuMusicThreadIsSleeping = NO;
      }
      
      if (gAuMusicThreadShouldExit) break;
      
      
      // Make sure some music has been set.
      
      if (! gAuCurrentMusic)
      {
         gAuMusicThreadShouldPause = YES;
         continue;
      }
      
      
      // Render music.
      
      long bytesSoFar = 0;
      int unused;
      
      while (bytesSoFar < kAuBytesPerOutputCall)
      {
         long bytes = ov_read(&gAuCurrentMusic->vorbis,
                              (void *) ((unsigned) buffer + bytesSoFar),
                              kAuBytesPerOutputCall - bytesSoFar,
                              &unused);
         
         if (bytes == 0)
         {
            ov_time_seek(&gAuCurrentMusic->vorbis, gAuCurrentMusic->loopPoint);
            continue;
         }
         
         if (bytes < 0)
         {
            gAuCurrentMusic = NULL;
            break;
         }
         
         bytesSoFar += bytes;
      }
      
      if (! gAuCurrentMusic) continue;
      
      
      // Send rendered music to audio hardware.
      
      sceKernelDelayThread(20 * sceAudioGetChannelRestLen(gAuMusicChannel));
      while (sceAudioGetChannelRestLen(gAuMusicChannel) > 0) { }
      
      sceAudioOutput(gAuMusicChannel, gAuMusicVolume, buffer);
      
      
      // Swap buffers.
      
      buffer = (buffer == buffer1) ? buffer2 : (buffer == buffer2) ? buffer3 : buffer1;
   }
   
   
   // Clean up.
   
   free(buffer1);
   free(buffer2);
   free(buffer3);
   
   sceKernelExitThread(kAuErrNone);
   return kAuErrNone;
}
Back to top
View user's profile Send private message Send e-mail
bengarney



Joined: 22 Oct 2005
Posts: 24

PostPosted: Sat Nov 19, 2005 12:54 pm    Post subject: Reply with quote

Cool, thanks! :)
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group