OSStatus Preroll (CAAudioUnit & inAU, UInt32 inFrameSize) { CAStreamBasicDescription desc; OSStatus result = inAU.GetFormat (kAudioUnitScope_Input, 0, desc); bool hasInput = false; //we have input if (result == noErr) { sRenderCallback.inputProc = PrerollRenderProc; sRenderCallback.inputProcRefCon = 0; result = inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &sRenderCallback, sizeof(sRenderCallback)); if (result) return result; hasInput = true; } AudioUnitRenderActionFlags flags = 0; AudioTimeStamp time; memset (&time, 0, sizeof(time)); time.mFlags = kAudioTimeStampSampleTimeValid; CAStreamBasicDescription outputFormat; ca_require_noerr (result = inAU.GetFormat (kAudioUnitScope_Output, 0, outputFormat), home); { AUOutputBL list (outputFormat, inFrameSize); list.Prepare (); result = inAU.Render (&flags, &time, 0, inFrameSize, list.ABL()); if (result) { printf("A result %d\n", (int)result); goto home; } } home: if (hasInput) { // remove our installed callback sRenderCallback.inputProc = 0; sRenderCallback.inputProcRefCon = 0; inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &sRenderCallback, sizeof(sRenderCallback)); } return result; }
void WriteOutputFile (const char* outputFilePath, OSType dataFormat, Float64 srate, MusicTimeStamp sequenceLength, bool shouldPrint, AUGraph inGraph, UInt32 numFrames, MusicPlayer player) { OSStatus result = 0; UInt32 size; CAStreamBasicDescription outputFormat; outputFormat.mChannelsPerFrame = 2; outputFormat.mSampleRate = srate; outputFormat.mFormatID = dataFormat; AudioFileTypeID destFileType; CAAudioFileFormats::Instance()->InferFileFormatFromFilename (outputFilePath, destFileType); if (dataFormat == kAudioFormatLinearPCM) { outputFormat.mBytesPerPacket = outputFormat.mChannelsPerFrame * 2; outputFormat.mFramesPerPacket = 1; outputFormat.mBytesPerFrame = outputFormat.mBytesPerPacket; outputFormat.mBitsPerChannel = 16; if (destFileType == kAudioFileWAVEType) outputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; else outputFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; } else { // use AudioFormat API to fill out the rest. size = sizeof(outputFormat); FailIf ((result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputFormat)), fail, ""); } if (shouldPrint) { printf ("Writing to file: %s with format:\n* ", outputFilePath); outputFormat.Print(); } CFURLRef url; url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)outputFilePath, strlen(outputFilePath), false); // create output file, delete existing file ExtAudioFileRef outfile; result = ExtAudioFileCreateWithURL(url, destFileType, &outputFormat, NULL, kAudioFileFlags_EraseFile, &outfile); if (url) CFRelease (url); FailIf (result, fail, "ExtAudioFileCreateWithURL"); AudioUnit outputUnit; outputUnit = NULL; UInt32 nodeCount; FailIf ((result = AUGraphGetNodeCount (inGraph, &nodeCount)), fail, "AUGraphGetNodeCount"); for (UInt32 i = 0; i < nodeCount; ++i) { AUNode node; FailIf ((result = AUGraphGetIndNode(inGraph, i, &node)), fail, "AUGraphGetIndNode"); AudioComponentDescription desc; FailIf ((result = AUGraphNodeInfo(inGraph, node, &desc, NULL)), fail, "AUGraphNodeInfo"); if (desc.componentType == kAudioUnitType_Output) { FailIf ((result = AUGraphNodeInfo(inGraph, node, 0, &outputUnit)), fail, "AUGraphNodeInfo"); break; } } FailIf ((result = (outputUnit == NULL)), fail, "outputUnit == NULL"); { CAStreamBasicDescription clientFormat = CAStreamBasicDescription(); size = sizeof(clientFormat); FailIf ((result = AudioUnitGetProperty (outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &size)), fail, "AudioUnitGetProperty: kAudioUnitProperty_StreamFormat"); size = sizeof(clientFormat); FailIf ((result = ExtAudioFileSetProperty(outfile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat)), fail, "ExtAudioFileSetProperty: kExtAudioFileProperty_ClientDataFormat"); { MusicTimeStamp currentTime; AUOutputBL outputBuffer (clientFormat, numFrames); AudioTimeStamp tStamp; memset (&tStamp, 0, sizeof(AudioTimeStamp)); tStamp.mFlags = kAudioTimeStampSampleTimeValid; int i = 0; int numTimesFor10Secs = (int)(10. / (numFrames / srate)); do { outputBuffer.Prepare(); AudioUnitRenderActionFlags actionFlags = 0; FailIf ((result = AudioUnitRender (outputUnit, &actionFlags, &tStamp, 0, numFrames, outputBuffer.ABL())), fail, "AudioUnitRender"); tStamp.mSampleTime += numFrames; FailIf ((result = ExtAudioFileWrite(outfile, numFrames, outputBuffer.ABL())), fail, "ExtAudioFileWrite"); FailIf ((result = MusicPlayerGetTime (player, ¤tTime)), fail, "MusicPlayerGetTime"); if (shouldPrint && (++i % numTimesFor10Secs == 0)) printf ("current time: %6.2f beats\n", currentTime); } while (currentTime < sequenceLength); } } // close ExtAudioFileDispose(outfile); return; fail: printf ("Problem: %ld\n", (long)result); exit(1); }
void WriteOutputFile (const char* outputFilePath, OSType dataFormat, Float64 srate, MusicTimeStamp sequenceLength, bool shouldPrint, AUGraph inGraph, UInt32 numFrames, MusicPlayer player) { // delete existing output file TestFile (outputFilePath, true); OSStatus result = 0; UInt32 size; CAStreamBasicDescription outputFormat; outputFormat.mChannelsPerFrame = 2; outputFormat.mSampleRate = srate; outputFormat.mFormatID = dataFormat; AudioFileTypeID destFileType; CAAudioFileFormats::Instance()->InferFileFormatFromFilename (outputFilePath, destFileType); if (dataFormat == kAudioFormatLinearPCM) { outputFormat.mBytesPerPacket = outputFormat.mChannelsPerFrame * 2; outputFormat.mFramesPerPacket = 1; outputFormat.mBytesPerFrame = outputFormat.mBytesPerPacket; outputFormat.mBitsPerChannel = 16; if (destFileType == kAudioFileWAVEType) outputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; else outputFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; } else { // use AudioFormat API to fill out the rest. size = sizeof(outputFormat); require_noerr (result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputFormat), fail); } if (shouldPrint) { printf ("Writing to file: %s with format:\n* ", outputFilePath); outputFormat.Print(); } FSRef parentDir; CFStringRef destFileName; require_noerr (result = PosixPathToParentFSRefAndName(outputFilePath, parentDir, destFileName), fail); ExtAudioFileRef outfile; result = ExtAudioFileCreateNew (&parentDir, destFileName, destFileType, &outputFormat, NULL, &outfile); CFRelease (destFileName); require_noerr (result, fail); AudioUnit outputUnit; UInt32 nodeCount; require_noerr (result = AUGraphGetNodeCount (inGraph, &nodeCount), fail); for (UInt32 i = 0; i < nodeCount; ++i) { AUNode node; require_noerr (result = AUGraphGetIndNode(inGraph, i, &node), fail); ComponentDescription desc; require_noerr (result = AUGraphNodeInfo(inGraph, node, &desc, NULL), fail); if (desc.componentType == kAudioUnitType_Output) { require_noerr (result = AUGraphNodeInfo(inGraph, node, 0, &outputUnit), fail); break; } } { CAStreamBasicDescription clientFormat; size = sizeof(clientFormat); require_noerr (result = AudioUnitGetProperty (outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &size), fail); size = sizeof(clientFormat); require_noerr (result = ExtAudioFileSetProperty(outfile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat), fail); { MusicTimeStamp currentTime; AUOutputBL outputBuffer (clientFormat, numFrames); AudioTimeStamp tStamp; memset (&tStamp, 0, sizeof(AudioTimeStamp)); tStamp.mFlags = kAudioTimeStampSampleTimeValid; int i = 0; int numTimesFor10Secs = (int)(10. / (numFrames / srate)); do { outputBuffer.Prepare(); AudioUnitRenderActionFlags actionFlags = 0; require_noerr (result = AudioUnitRender (outputUnit, &actionFlags, &tStamp, 0, numFrames, outputBuffer.ABL()), fail); tStamp.mSampleTime += numFrames; require_noerr (result = ExtAudioFileWrite(outfile, numFrames, outputBuffer.ABL()), fail); require_noerr (result = MusicPlayerGetTime (player, ¤tTime), fail); if (shouldPrint && (++i % numTimesFor10Secs == 0)) printf ("current time: %6.2f beats\n", currentTime); } while (currentTime < sequenceLength); } } // close ExtAudioFileDispose(outfile); return; fail: printf ("Problem: %ld\n", result); exit(1); }