3

I am constructing audio graph, which has: AudioFilePlayer (Generator unit) -> GenericOutput (Output unit)

The basic idea:

AudioFilePlayer is producing audio frames to it's output. Generic output takes data from AudioFilePlayer's output as input. Than I can take that data and save it to other buffer.

My question is how to pull data from generic output to get data for offline rendering.

I did some research on it, and find out that I have to use AudioUnitRender on GenericOutput unit to pull audio data from it.

Uint32 frames = 512;
timestamp.mSampleTime = 0;

... While Loop ...

timestamp.mFlags = kAudioTimeStampSampleTimeValid;

bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = param->inputFormat.mChannelsPerFrame;
bufferList.mBuffers[0].mDataByteSize = frames * param->inputFormat.mChannelsPerFrame * sizeof(float);
bufferList.mBuffers[0].mData = NULL;

AudioUnitRenderActionFlags flags = 0;

OSStatus error = noErr;
if ((error = AudioUnitRender(param->genericOutput, &flags, &timestamp, 0, frames, &bufferList)) != noErr)
{
    printf("Cannot AudioUnitRender: %d\n", error);
}

timestamp.mSampleTime += frames;

But i get error with number -50.

Am I setting input parameters wrong? Do I need to register any render callback functions to GenericOutput unit?

kestutisb
  • 261
  • 2
  • 13
  • -50 is the parameter list error, debug `param->genericOutput` once and make sure that this isn't NULL. – iluvcapra Mar 01 '13 at 16:51
  • 2
    I got it working. Here you can find my working code. http://stackoverflow.com/questions/15297990/core-audio-offline-rendering-genericoutput/15361251#15361251 – Abdusha M A Mar 12 '13 at 12:58

2 Answers2

2

The problem was that I set GenericOutput StreamFormat after calling AUGraphInitialize(). It must be done before that.

I used CAShow(reader.graph) to get log of audio graph, which helped me to notice that format is't changed after trying to set it.

kestutisb
  • 261
  • 2
  • 13
0

Hope you successfully done the offline rendering using GenericOutput node. Could you please give some details how you did this.

  • You are trying to pass a buffer list with no data in it, in loop.
  • If we need to save the output to a file what i have to do (or where I put ExtAudioFileWriteAsync).
  • What is the exit condition for your while loop.

  • is timestamp is a local declared variable.

Abdusha M A
  • 509
  • 5
  • 13
  • Yes, timeStamp is local variable. – kestutisb Mar 12 '13 at 06:42
  • 1
    I allocate memory for number of frames I want to read. bufferList.mNumberBuffers = 1; bufferList.mBuffers[0].mNumberChannels = pFormat->mChannelsPerFrame; bufferList.mBuffers[0].mDataByteSize = pFormat->mBytesPerFrame * framesToRead; bufferList.mBuffers[0].mData = (UInt8 *) malloc(bufferList.mBuffers[0].mDataByteSize); You should put ExtAudioFileWriteAsync right after AudioUnitRender call. I get total length of file in frames, when i reach that number i terminate loop. – kestutisb Mar 12 '13 at 06:51