PDA

View Full Version : Reusing an Audio Queue




cpatch
Nov 5, 2008, 12:04 PM
I've been battling with this for weeks now...how do you reuse an audio queue? I'm trying to modify the AudioPlayer class from SpeakHere so that I can do the following without having to close and reopen the associated sound file:

1. Replay a sound after it's finished playing.
2. Restart a sound in the middle of playing.

This should only require changes to the start and callback methods as far as I can tell (possibly only the start method) but for some reason it's not as straightforward as it seems...I get various audio anomalies depending on when and where I start/stop/flush/reset the queue. (I've tried various combinations of the different methods.)

Has anyone solved this problem already who would be willing to share their solution? Any help would be greatly appreciated, either privately (at this point I'm willing to pay for a working solution) or through this thread.

Craig



PhoneyDeveloper
Nov 5, 2008, 01:52 PM
I've used te AudioPlayer.m and AudioQueueObject.m sources from that project. The main thing is to always send stop before sending play if a sound could still be playing. Without that I got all kinds of weird sounds.

If you're trying to loop you probably have to request a callback when the sound is finished and send play again, but I haven't done this.

cpatch
Nov 5, 2008, 05:20 PM
That was the first thing I tried but it didn't work for a reason I don't recall. (I've changed so many things since then!) I'll take it back to where I started when I get home tonight and post the code for the relevant methods. Maybe it will be obvious to someone more familiar with Audio Queue.

Craig

cpatch
Nov 6, 2008, 02:09 AM
OK, stopping the queue results in no sound when I restart it. Here's what I'm doing that's different from the standard AudioPlayer.m (AudioPlayer.h, AudioQueueObject.m, and AudioQueueObject.h are straight out of CrashLanding).

First, I moved the call to AudioFileClose from the stop method to dealloc. Second, I changed the else statement at the end of the playbackCallback method to:


} else {
[player setDonePlayingFile: YES];
[player setAudioPlayerShouldStopImmediately: NO];
[player stop];
}


Finally, I changed the play method to:


- (void) play {

if (buffers[0] == NULL)
[self setupAudioQueueBuffers];
else
{
if (![self donePlayingFile])
{
// Drop the gain to zero to avoid a pop
[self setGain: 0.0];
AudioQueueSetParameter(queueObject,
kAudioQueueParam_Volume,
gain
);
usleep(50000);
[self setDonePlayingFile: YES];
[self setAudioPlayerShouldStopImmediately: YES];
[self stop];
}
// Make sure we're at the beginning of the file and prime the buffers
startingPacketNumber = 0;
int bufferIndex;
for (bufferIndex = 0; bufferIndex < kNumberAudioDataBuffers; ++bufferIndex)
{
playbackCallback (self,
queueObject,
buffers[bufferIndex]
);
}
}
[self setGain: 1.0];
AudioQueueSetParameter(queueObject,
kAudioQueueParam_Volume,
gain
);
AudioQueueStart(queueObject,
NULL
);
}


The result is that the queue plays fine the first time and then doesn't play after that. Any suggestions?

Craig

cpatch
Nov 9, 2008, 07:25 PM
Anyone?

Craig