Core Audio running two AudioQueues at once, continuous record/playback

from:  http://stackoverflow.com/questions/10806813/core-audio-running-two-audioqueues-at-once-continuous-record-playback
    
Core Audio running two AudioQueues at once, continuous record/playback

So lets say I wanted to record into my input queue by going through the usual process of setting everything up and receiving the audio data in my input callback. Instead of writing this to a file I would like to start buffering it somewhere briefly and then supply it out to an output queue that would start running shortly after my input queue, consuming the data that I would be buffering from the input queue, playing back the audio as I am recording it. Is this possible? I have tried implementing this but I am running into an issue with starting my output queue, I initialize and start it with no errors reported but after calling the AudioQueueStart function my supplied output callback is never called. Perhaps this is a problem with my implementation but I just wanted to make sure I am not crawling into a dead end first.

Thanks

EDIT: Code Added

Im running this POC in a command line app. In main I initialize a recorder:

    Recorder recorder = {0};

    AudioStreamBasicDescription asbd;
    memset(&asbd, 0, sizeof(asbd));

    asbd.mFormatID  = kAudioFormatLinearPCM;
    asbd.mSampleRate = SAMPLE_RATE;
    asbd.mBytesPerPacket = 4;
    asbd.mBytesPerFrame = 4;
    asbd.mChannelsPerFrame = 2;
    asbd.mBitsPerChannel = 16;
    asbd.mFramesPerPacket = 1;
    asbd.mFormatFlags = kAudioFormatFlagIsBigEndian |
    kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;

    AudioQueueRef queue = {0};


    reportError(AudioQueueNewInput(&asbd, MyAQInputCallback, &recorder, NULL, NULL, 0, &queue), "AudioQueue Input Create");

     int bufferSize = 88200;

    for (int i = 0; i < BUFFER_COUNT; i++) {

        AudioQueueBufferRef retBuffer;
        reportError(AudioQueueAllocateBuffer(queue, bufferSize, &retBuffer), "Error Allocating Buffer");
        reportError(AudioQueueEnqueueBuffer(queue, retBuffer, 0, NULL), "Error enqueuing buffer");


    }

    recorder.running = YES;
    reportError(AudioQueueStart(queue, NULL), "Start Failed");
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 3, false);

I declared a global void pointer array to hold data that comes in, this will change I just wanted to see if I can get it running:

   static void *buffer[1000];

My Input Callback. This does get called up to a certain point so the recorder has been running fine for me I have been recording to files and such before this:

   static void MyAQInputCallback(void *inUserData,
                          AudioQueueRef inQueue,
                          AudioQueueBufferRef inBuffer,
                          const AudioTimeStamp *inStartTime,
                          UInt32 inNumPackets,
                          const AudioStreamPacketDescription *inPacketDesc)
{

Recorder *recorder = (Recorder *) inUserData;

buffer[globalBufferIndex] = (short *)inBuffer->mAudioData;
++globalBufferIndex;

if (globalBufferIndex == 1000) {
    globalBufferIndex = 0;
    clearBuffer();
}
if ( recorder->running ) {
    reportError(AudioQueueEnqueueBuffer(inQueue, inBuffer, 0, NULL), "CallbackEnqueue Failed");
}
}

Basically the goal here is just to pull chunks off and store it in the buffer. I believe this works as it should.

The player is initialized:

Player player = {0};
AudioQueueRef que = {0};

reportError(AudioQueueNewOutput(&asbd, MyAQOutputCallback, &player, NULL, NULL, 0, &que), "New Output Error");

AudioQueueBufferRef buffers[BUFFER_COUNT];

 for (int i = 0; i < BUFFER_COUNT; ++i) {

        reportError(AudioQueueAllocateBuffer(que, bufferSize, &buffers[i]), "Error Buffer Allocating");

        MyAQOutputCallback(&player, que, buffers[i]);

  }

 reportError(AudioQueueStart(que, NULL), "Start Failed");

The player callback:

static void MyAQOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef   inCompleteAQBuffer)
{

Player *player;

player = (Player *) inUserData;

short *chunk = (short *) inCompleteAQBuffer->mAudioData;
chunk = buffer[globalOutputBufferIndex];
globalOutputBufferIndex++;

AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, sizeof(chunk)/4, player->packetDescs);

}

The goal being to store whats in the global buffer into the queue and send it off.

So I know this is not great structure but the behavior I get when I run it is that the recorder will run making its calls to the input callback and storing the data but then I start the player initialization and the output callback is called 3 times (my for loop calls) and never gets called again. I block the termination of the app at the end by making a call to getchar(). I have had the player work to read from files and play it, obviously this was a lot different. My recorder keeps on doing its job but my player callback is never called. I thought maybe its a problem with my descriptions but an error is never reported to me during allocation. Any guidance here would be great.

Thanks
ios core-audio
share|edit
    
edited May 30 at 15:15

    
asked May 29 at 21:14
Greg Price
6261210

85% accept rate
    
    
Show your code. – Robert Harvey♦ May 29 at 21:16
feedback
1 Answer
active oldest votes
up vote 0 down vote accepted
    

Since no one seems to know this, here is a link to a pretty good sample project that does this: https://github.com/alexbw/novocaine
share|edit

你可能感兴趣的:(Core Audio running two AudioQueues at once, continuous record/playback)