/* ---- These are defined in the .h file -- I want access to them other places int he class. */
AUGraph myGraph;
AudioUnit filePlayerUnit;
AudioUnit *currentFilePlayerUnit;
AudioUnit mixUnit;
AudioUnit outUnit;
AudioFileID anAudioFile;
////////////////////////////////////////////////////////////////////////
- (void)initAUGraph {
OSErr err = noErr;
AUNode filePlayerNode;
AUNode mixNode;
AUNode outNode;
ComponentDescription cd;
UInt32 propSize;
err = NewAUGraph(&myGraph);
NSAssert(err == noErr, @"NewAUGraph failed.");
/* ---- Specify the audio unit types. */
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_HALOutput;
/* ---- All AUHALs use Apple as componentManufacturer, regardless of who makes them. */
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
err = AUGraphNewNode(myGraph, &cd, 0, NULL, &outNode);
NSAssert(err == noErr, @"AUGraphNewNode for output failed.");
cd.componentType = kAudioUnitType_Generator;
cd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
err = AUGraphNewNode(myGraph, &cd, 0, NULL, &filePlayerNode);
NSAssert(err == noErr, @"AUGraphNewNode for file player failed.");
cd.componentType = kAudioUnitType_Mixer;
cd.componentSubType = kAudioUnitSubType_StereoMixer;
err = AUGraphNewNode(myGraph, &cd, 0, NULL, &mixNode);
NSAssert(err == noErr, @"AUGraphNewNode for mixer unit failed.");
/* ---- Connect nodes to each other in the graph. */
err = AUGraphConnectNodeInput(myGraph, filePlayerNode, 0, mixNode, 0);
NSAssert(err == noErr, @"AUGraphConnectNode fp -> mix failed.");
err = AUGraphConnectNodeInput(myGraph, mixNode, 0, outNode, 0);
NSAssert(err == noErr, @"AUGraphConnectNode mix -> out failed.");
err = AUGraphOpen(myGraph);
NSAssert(err == noErr, @"AUGraphOpen failed.");
/* ---- Get references to the audio units each node relates to. */
err = AUGraphGetNodeInfo(myGraph, outNode, NULL, NULL, NULL, &outUnit);
NSAssert(err == noErr, @"AUGraphGetNodeInfo for outUnit failed.");
err = AUGraphGetNodeInfo(myGraph, mixNode, NULL, NULL, NULL, &mixUnit);
NSAssert(err == noErr, @"AUGraphGetNodeInfo for mixNode failed.");
err = AUGraphGetNodeInfo(myGraph, filePlayerNode, NULL, NULL, NULL, &filePlayerUnit);
NSAssert(err == noErr, @"AUGraphGetNodeInfo for filePlayerNode failed.");
/* ---- Set initial pointer to the fp unit. */
currentFilePlayerUnit = &filePlayerUnit;
/* ---- Get the format of the input bus of the output device. */
AudioStreamBasicDescription outputDeviceInputFormat;
propSize = sizeof(AudioStreamBasicDescription);
memset(&outputDeviceInputFormat, 0, propSize);
err = AudioUnitGetProperty(outUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outputDeviceInputFormat, &propSize);
NSAssert(err == noErr, @"Reading output device input bus format failed.");
/* ---- Create a common stream format from the canonical format, with the output device's sample rate and channel count. */
AudioStreamBasicDescription commonFormat;
memset(&commonFormat, 0, sizeof(AudioStreamBasicDescription));
[self setCanonicalStreamFormat:&commonFormat];
commonFormat.mSampleRate = outputDeviceInputFormat.mSampleRate;
commonFormat.mChannelsPerFrame = outputDeviceInputFormat.mChannelsPerFrame;
/* ---- Set the output bus of the file player unit to match the output device's input bus format. */
propSize = sizeof(AudioStreamBasicDescription);
err = AudioUnitSetProperty(filePlayerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &commonFormat, propSize);
NSAssert(err == noErr, @"Setting file player unit A stream format property failed.");
err = AUGraphInitialize(myGraph);
NSAssert(err == noErr, @"AUGraphInitialize() failed.");
err = AUGraphStart(myGraph);
NSAssert(err == noErr, @"AUGraphStart() failed.");
[self setVolume:preFadeTriggerVolume];
}
////////////////////////////////////////////////////////////////////////
- (void)setCanonicalStreamFormat:(AudioStreamBasicDescription*)asbd {
/* ---- 32-bit floating-point linear PCM, deinterleaved. NOTE: leaves sample rate and channel count untouched. */
asbd->mFormatID = kAudioFormatLinearPCM;
asbd->mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
asbd->mBitsPerChannel = 32;
asbd->mFramesPerPacket = 1;
asbd->mBytesPerPacket = asbd->mBytesPerFrame = sizeof(Float32);
}