Search code examples
iphoneobjective-caudioqueueservices

Simultaneous playback (10+) with AudioQueueServices


Can anyone show me how this is done for for the iPhone? I am trying to make a game to play about 12 sounds at exactly the same time and I can't figure out how to use AudioQueueServices. I understand you have to initialize, add buffers, play them back and use AudioQueueEnqueueBufferWithParameters to get simultaneous playback, but I don't know how to turn that into code. Anyone with code on this or someone that could explain it to me would be amazing!

If you've heard of a Tone Grid/Tone Board that's exactly what I'm trying to do. I know there are a few apps in the Appstore already that do this, but I don't know how it is done.

TLDR; Need help with AudioQueueServices simultaneous playback with 10+ sounds.

Example:

New playback

    if (isPlaying == NO) {
err = AudioQueueNewOutput (&streamFormat, AudioEngineOutputBufferCallback, self, nil, nil, 0, &outputQueue);
if (err != noErr) NSLog(@"AudioQueueNewOutput() error: %d", err);

Enqueue buffers

outputBuffersToRewrite = 3;
bufferByteSize = (sampleRate > 16000)? 2176 : 512; // 40.5 Hz : 31.25 Hz 
for (i=0; i<3; i++) {
    err = AudioQueueAllocateBuffer (outputQueue, bufferByteSize, &buffer); 
    if (err == noErr) {
        [self generateTone: buffer];
        err = AudioQueueEnqueueBuffer (outputQueue, buffer, 0, nil);
        if (err != noErr) NSLog(@"AudioQueueEnqueueBuffer() error: %d", err);
    } else {
        NSLog(@"AudioQueueAllocateBuffer() error: %d", err); 
        return;
    }
}

Starting playback

isPlaying = YES;
err = AudioQueueStart(outputQueue, nil);
if (err != noErr) { NSLog(@"AudioQueueStart() error: %d", err); isPlaying= NO; return; }
} else {
NSLog (@"Error: audio is already playing back.");

Set up stream format fields

BOOL isHighSampleRate = (sampleRate > 16000);
int bufferByteSize;
AudioQueueBufferRef buffer;

AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = sampleRate;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
streamFormat.mBitsPerChannel = 16;
streamFormat.mChannelsPerFrame = 1;
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mFramesPerPacket = 1;
streamFormat.mReserved = 0;

Solution

  • AudioQueue can play sounds at the same time.

    from apple:

    How do I play multiple sounds simultaneously?

    Use the interfaces in Audio Queue Services (AudioToolbox/AudioQueue.h). Create one audio queue object for each sound that you want to play. Then specify simultaneous start times for the first audio buffer in each audio queue, using the AudioQueueEnqueueBufferWithParameters function.

    The following limitations pertain for simultaneous sounds in iPhone OS, depending on the audio data format:

    AAC, MP3, and ALAC (Apple Lossless) audio: You may play multiple AAC, MP3, and ALAC format sounds simultaneously; playback of multiple sounds of these formats will require CPU resources for decoding.

    Linear PCM and IMA/ADPCM (IMA4 audio): You can play multiple linear PCM or IMA4 format sounds simultaneously without CPU resource concerns.