 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
dsn

Joined: 09 Nov 2005 Posts: 47 Location: Indianapolis, Indiana, USA
|
Posted: Sat Nov 19, 2005 1:47 am Post subject: Clicking audio |
|
|
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 |
|
 |
bengarney
Joined: 22 Oct 2005 Posts: 24
|
Posted: Sat Nov 19, 2005 9:43 am Post subject: |
|
|
| Tried triple buffering it? :) |
|
| Back to top |
|
 |
dsn

Joined: 09 Nov 2005 Posts: 47 Location: Indianapolis, Indiana, USA
|
Posted: Sat Nov 19, 2005 11:58 am Post subject: |
|
|
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 |
|
 |
bengarney
Joined: 22 Oct 2005 Posts: 24
|
Posted: Sat Nov 19, 2005 12:19 pm Post subject: |
|
|
| 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 |
|
 |
dsn

Joined: 09 Nov 2005 Posts: 47 Location: Indianapolis, Indiana, USA
|
Posted: Sat Nov 19, 2005 12:44 pm Post subject: |
|
|
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 |
|
 |
bengarney
Joined: 22 Oct 2005 Posts: 24
|
Posted: Sat Nov 19, 2005 12:54 pm Post subject: |
|
|
| Cool, thanks! :) |
|
| Back to top |
|
 |
|
|
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
|