OSStatus CAPlayThrough::MakeGraph() { OSStatus err = noErr; AudioComponentDescription varispeedDesc,outDesc, mixerDesc; //Q:Why do we need a varispeed unit? //A:If the input device and the output device are running at different sample rates //we will need to move the data coming to the graph slower/faster to avoid a pitch change. varispeedDesc.componentType = kAudioUnitType_FormatConverter; varispeedDesc.componentSubType = kAudioUnitSubType_Varispeed; varispeedDesc.componentManufacturer = kAudioUnitManufacturer_Apple; varispeedDesc.componentFlags = 0; varispeedDesc.componentFlagsMask = 0; outDesc.componentType = kAudioUnitType_Output; outDesc.componentSubType = kAudioUnitSubType_DefaultOutput; outDesc.componentManufacturer = kAudioUnitManufacturer_Apple; outDesc.componentFlags = 0; outDesc.componentFlagsMask = 0; mixerDesc.componentType = kAudioUnitType_Mixer; mixerDesc.componentSubType = kAudioUnitSubType_StereoMixer; mixerDesc.componentManufacturer = kAudioUnitManufacturer_Apple; mixerDesc.componentFlags = 0; mixerDesc.componentFlagsMask = 0; ////////////////////////// ///MAKE NODES //This creates a node in the graph that is an AudioUnit, using //the supplied ComponentDescription to find and open that unit err = AUGraphAddNode(mGraph, &varispeedDesc, &mVarispeedNode); checkErr(err); //add a mixer node after the input to use for metering err = AUGraphAddNode(mGraph, &mixerDesc, &mMixerNode); checkErr(err); err = AUGraphAddNode(mGraph, &outDesc, &mOutputNode); checkErr(err); //Get Audio Units from AUGraph node err = AUGraphNodeInfo(mGraph, mVarispeedNode, NULL, &mVarispeedUnit); checkErr(err); //get the mixer node err = AUGraphNodeInfo(mGraph, mMixerNode, NULL, &mMixerUnit); checkErr(err); err = AUGraphNodeInfo(mGraph, mOutputNode, NULL, &mOutputUnit); checkErr(err); // don't connect nodes until the varispeed unit has input and output formats set return err; }
OSStatus FCoreAudioSoundSource::CreateAudioUnit( OSType Type, OSType SubType, OSType Manufacturer, AudioStreamBasicDescription* InputFormat, AudioStreamBasicDescription* OutputFormat, AUNode* OutNode, AudioUnit* OutUnit ) { AudioComponentDescription Desc; Desc.componentFlags = 0; Desc.componentFlagsMask = 0; Desc.componentType = Type; Desc.componentSubType = SubType; Desc.componentManufacturer = Manufacturer; OSStatus Status = AUGraphAddNode( AudioDevice->GetAudioUnitGraph(), &Desc, OutNode ); if( Status == noErr ) { Status = AUGraphNodeInfo( AudioDevice->GetAudioUnitGraph(), *OutNode, NULL, OutUnit ); } if( Status == noErr ) { if( InputFormat ) { Status = AudioUnitSetProperty( *OutUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, InputFormat, sizeof( AudioStreamBasicDescription ) ); } if( Status == noErr ) { if( OutputFormat ) { Status = AudioUnitSetProperty( *OutUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, OutputFormat, sizeof( AudioStreamBasicDescription ) ); } } } return Status; }
bool CCoreAudioUnit::Open(AUGraph audioGraph, AudioComponentDescription desc) { if (m_audioUnit) Close(); OSStatus ret; m_Initialized = false; ret = AUGraphAddNode(audioGraph, &desc, &m_audioNode); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error add m_outputNode. Error = %s", GetError(ret).c_str()); return false; } ret = AUGraphNodeInfo(audioGraph, m_audioNode, NULL, &m_audioUnit); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error getting m_outputNode. Error = %s", GetError(ret).c_str()); return false; } m_audioGraph = audioGraph; m_Initialized = true; Start(); return true; }
AudioUnitNode::AudioUnitNode(AUGraph graph, const AudioComponentDescription& cd) : mGraph(graph) { OSStatus err; err = AUGraphAddNode(graph, &cd, &mNode); if ((int)err == -2005) { AudioNodeException exception("badComponentType."); throw exception; } err = AUGraphNodeInfo(graph, mNode, NULL, &mUnit); }
void setupAUGraph(MyMIDIPlayer *player) { CheckError(NewAUGraph(&player->graph), "Couldn't open AU Graph"); // generate description that will match our output device (speakers) AudioComponentDescription outputcd = {0}; outputcd.componentType = kAudioUnitType_Output; outputcd.componentSubType = kAudioUnitSubType_DefaultOutput; outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; // adds a node with above description to the graph AUNode outputNode; CheckError(AUGraphAddNode(player->graph, &outputcd, &outputNode), "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed"); AudioComponentDescription instrumentcd = {0}; instrumentcd.componentManufacturer = kAudioUnitManufacturer_Apple; instrumentcd.componentType = kAudioUnitType_MusicDevice; instrumentcd.componentSubType = kAudioUnitSubType_Sampler; // changed! AUNode instrumentNode; CheckError(AUGraphAddNode(player->graph, &instrumentcd, &instrumentNode), "AUGraphAddNode[kAudioUnitSubType_DLSSynth] failed"); // opening the graph opens all contained audio units but does not allocate any resources yet CheckError(AUGraphOpen(player->graph), "AUGraphOpen failed"); // get the reference to the AudioUnit object for the instrument graph node CheckError(AUGraphNodeInfo(player->graph, instrumentNode, NULL, &player->instrumentUnit), "AUGraphNodeInfo failed"); // connect the output source of the instrument AU to the input source of the output node CheckError(AUGraphConnectNodeInput(player->graph, instrumentNode, 0, outputNode, 0), "AUGraphConnectNodeInput"); // now initialize the graph (causes resources to be allocated) CheckError(AUGraphInitialize(player->graph), "AUGraphInitialize failed"); // configure the AUSampler // 2nd parameter obviously needs to be a full path on your system, and 3rd param is its length in characters CFURLRef presetURL = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, "/Users/cadamson/Library/Audio/Presets/Apple/AUSampler/ch12-aupreset.aupreset", 77, false); // load preset file into a CFDataRef CFDataRef presetData = NULL; SInt32 errorCode = noErr; Boolean gotPresetData = CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, presetURL, &presetData, NULL, NULL, &errorCode); CheckError(errorCode, "couldn't load .aupreset data"); CheckError(!gotPresetData, "couldn't load .aupreset data"); // convert this into a property list CFPropertyListFormat presetPlistFormat = {0}; CFErrorRef presetPlistError = NULL; CFPropertyListRef presetPlist = CFPropertyListCreateWithData(kCFAllocatorSystemDefault, presetData, kCFPropertyListImmutable, &presetPlistFormat, &presetPlistError); if (presetPlistError) { printf ("Couldn't create plist object for .aupreset"); return; } // set this plist as the kAudioUnitProperty_ClassInfo on _auSampler if (presetPlist) { CheckError(AudioUnitSetProperty(player->instrumentUnit, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &presetPlist, sizeof(presetPlist)), "Couldn't set aupreset plist as sampler's class info"); } }
void start(int midiChannel, char const*const bankPath) { if (auGraph != 0) return; // don't multiply init midiChannelInUse = midiChannel; OSStatus result; //create the nodes of the graph AUNode synthNode; AudioComponentDescription cd; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; require_noerr (result = NewAUGraph (&auGraph), home); cd.componentType = kAudioUnitType_MusicDevice; cd.componentSubType = kAudioUnitSubType_DLSSynth; require_noerr (result = AUGraphAddNode (auGraph, &cd, &synthNode), home); cd.componentType = kAudioUnitType_Effect; cd.componentSubType = kAudioUnitSubType_PeakLimiter; require_noerr (result = AUGraphAddNode (auGraph, &cd, &limiterNode), home); cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; require_noerr (result = AUGraphAddNode (auGraph, &cd, &outNode), home); require_noerr (result = AUGraphOpen (auGraph), home); require_noerr (result = AUGraphConnectNodeInput(auGraph, synthNode, 0, limiterNode, 0), home); require_noerr (result = AUGraphConnectNodeInput(auGraph, limiterNode, 0, outNode, 0), home); // ok we're good to go - get the Synth Unit... require_noerr (result = AUGraphNodeInfo(auGraph, synthNode, 0, &synthUnit), home); // if the user supplies a sound bank, we'll set that before we initialize and start playing if (bankPath) { // note: bankpath is a soundfont CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)bankPath, strlen(bankPath), false); if (url) { require_noerr (result = AudioUnitSetProperty(synthUnit, kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global, 0, &url, sizeof(url) ), home); CFRelease(url); } } // ok we're set up to go - initialize and start the graph require_noerr (result = AUGraphInitialize (auGraph), home); //set our bank require_noerr (result = MusicDeviceMIDIEvent(synthUnit, kMidiMessage_ControlChange << 4 | midiChannelInUse, kMidiMessage_BankMSBControl, 0, 0/*sample offset*/), home); require_noerr (result = MusicDeviceMIDIEvent(synthUnit, kMidiMessage_ProgramChange << 4 | midiChannelInUse, 0/*prog change num*/, 0, 0/*sample offset*/), home); CAShow(auGraph); // prints out the graph so we can see what it looks like... require_noerr (result = AUGraphStart(auGraph), home); return; home: shutdown(); }
bool FIOSAudioDevice::InitializeHardware() { SIZE_T SampleSize = sizeof(AudioSampleType); double GraphSampleRate = 44100.0; if (!SetHardwareSampleRate(GraphSampleRate) || !SetAudioSessionActive(true)) { HandleError(TEXT("Failed to establish the audio session!")); return false; } // Retrieve the actual hardware sample rate GetHardwareSampleRate(GraphSampleRate); // Linear PCM stream format MixerFormat.mFormatID = kAudioFormatLinearPCM; MixerFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; MixerFormat.mBytesPerPacket = SampleSize; MixerFormat.mFramesPerPacket = 1; MixerFormat.mBytesPerFrame = SampleSize; MixerFormat.mChannelsPerFrame = 1; MixerFormat.mBitsPerChannel = 8 * SampleSize; MixerFormat.mSampleRate = GraphSampleRate; OSStatus Status = NewAUGraph(&AudioUnitGraph); if (Status != noErr) { HandleError(TEXT("Failed to create audio unit graph!")); return false; } AudioComponentDescription UnitDescription; // Setup audio output unit UnitDescription.componentType = kAudioUnitType_Output; UnitDescription.componentSubType = kAudioUnitSubType_RemoteIO; UnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; UnitDescription.componentFlags = 0; UnitDescription.componentFlagsMask = 0; Status = AUGraphAddNode(AudioUnitGraph, &UnitDescription, &OutputNode); if (Status != noErr) { HandleError(TEXT("Failed to initialize audio output node!"), true); return false; } // Setup audo mixer unit UnitDescription.componentType = kAudioUnitType_Mixer; UnitDescription.componentSubType = kAudioUnitSubType_AU3DMixerEmbedded; UnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; UnitDescription.componentFlags = 0; UnitDescription.componentFlagsMask = 0; Status = AUGraphAddNode(AudioUnitGraph, &UnitDescription, &MixerNode); if (Status != noErr) { HandleError(TEXT("Failed to initialize audio mixer node!"), true); return false; } Status = AUGraphOpen(AudioUnitGraph); if (Status != noErr) { HandleError(TEXT("Failed to open audio unit graph"), true); return false; } Status = AUGraphNodeInfo(AudioUnitGraph, OutputNode, NULL, &OutputUnit); if (Status != noErr) { HandleError(TEXT("Failed to retrieve output unit reference!"), true); return false; } Status = AUGraphNodeInfo(AudioUnitGraph, MixerNode, NULL, &MixerUnit); if (Status != noErr) { HandleError(TEXT("Failed to retrieve mixer unit reference!"), true); return false; } uint32 BusCount = MaxChannels * CHANNELS_PER_BUS; Status = AudioUnitSetProperty(MixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &BusCount, sizeof(BusCount)); if (Status != noErr) { HandleError(TEXT("Failed to set kAudioUnitProperty_ElementCount for audio mixer unit!"), true); return false; } // Initialize sound source early on, allowing for render callback hookups InitSoundSources(); // Setup the mixer unit sample rate Status = AudioUnitSetProperty(MixerUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &GraphSampleRate, sizeof(GraphSampleRate)); if (Status != noErr) { HandleError(TEXT("Failed to set kAudioUnitProperty_SampleRate for audio mixer unit!"), true); return false; } // Connect mixer node output to output node input Status = AUGraphConnectNodeInput(AudioUnitGraph, MixerNode, 0, OutputNode, 0); if (Status != noErr) { HandleError(TEXT("Failed to connect mixer node to output node!"), true); return false; } // Initialize and start the audio unit graph Status = AUGraphInitialize(AudioUnitGraph); if (Status == noErr) { Status = AUGraphStart(AudioUnitGraph); } if (Status != noErr) { HandleError(TEXT("Failed to start audio graph!"), true); return false; } return true; }
void CreateMyAUGraph(MyAUGraphPlayer *player) { // create a new AUGraph CheckError(NewAUGraph(&player->graph), "NewAUGraph failed"); // generate description that will match our output device (speakers) AudioComponentDescription outputcd = {0}; outputcd.componentType = kAudioUnitType_Output; outputcd.componentSubType = kAudioUnitSubType_DefaultOutput; outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; // adds a node with above description to the graph AUNode outputNode; CheckError(AUGraphAddNode(player->graph, &outputcd, &outputNode), "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed"); // generate description that will match a generator AU of type: speech synthesizer AudioComponentDescription speechcd = {0}; speechcd.componentType = kAudioUnitType_Generator; speechcd.componentSubType = kAudioUnitSubType_SpeechSynthesis; speechcd.componentManufacturer = kAudioUnitManufacturer_Apple; // adds a node with above description to the graph AUNode speechNode; CheckError(AUGraphAddNode(player->graph, &speechcd, &speechNode), "AUGraphAddNode[kAudioUnitSubType_SpeechSynthesis] failed"); // opening the graph opens all contained audio units but does not allocate any resources yet CheckError(AUGraphOpen(player->graph), "AUGraphOpen failed"); // get the reference to the AudioUnit object for the speech synthesis graph node CheckError(AUGraphNodeInfo(player->graph, speechNode, NULL, &player->speechAU), "AUGraphNodeInfo failed"); // // debug - get the asbd // UInt32 propSize = sizeof (AudioStreamBasicDescription); // CheckError(AudioUnitGetProperty(player->speechAU, // kAudioUnitProperty_StreamFormat, // kAudioUnitScope_Output, // 0, // &player->streamFormat, // &propSize), // "Couldn't get ASBD"); #ifdef PART_II // // FUN! re-route the speech thru a reverb effect before sending to speakers // // generate description that will match out reverb effect AudioComponentDescription reverbcd = {0}; reverbcd.componentType = kAudioUnitType_Effect; reverbcd.componentSubType = kAudioUnitSubType_MatrixReverb; reverbcd.componentManufacturer = kAudioUnitManufacturer_Apple; // adds a node with above description to the graph AUNode reverbNode; CheckError(AUGraphAddNode(player->graph, &reverbcd, &reverbNode), "AUGraphAddNode[kAudioUnitSubType_MatrixReverb] failed"); // connect the output source of the speech synthesizer AU to the input source of the reverb node CheckError(AUGraphConnectNodeInput(player->graph, speechNode, 0, reverbNode, 0), "AUGraphConnectNodeInput"); // connect the output source of the reverb AU to the input source of the output node CheckError(AUGraphConnectNodeInput(player->graph, reverbNode, 0, outputNode, 0), "AUGraphConnectNodeInput"); // get the reference to the AudioUnit object for the reverb graph node AudioUnit reverbUnit; CheckError(AUGraphNodeInfo(player->graph, reverbNode, NULL, &reverbUnit), "AUGraphNodeInfo failed"); /* enum { kReverbRoomType_SmallRoom = 0, kReverbRoomType_MediumRoom = 1, kReverbRoomType_LargeRoom = 2, kReverbRoomType_MediumHall = 3, kReverbRoomType_LargeHall = 4, kReverbRoomType_Plate = 5, kReverbRoomType_MediumChamber = 6, kReverbRoomType_LargeChamber = 7, kReverbRoomType_Cathedral = 8, kReverbRoomType_LargeRoom2 = 9, kReverbRoomType_MediumHall2 = 10, kReverbRoomType_MediumHall3 = 11, kReverbRoomType_LargeHall2 = 12 }; */ // now initialize the graph (causes resources to be allocated) CheckError(AUGraphInitialize(player->graph), "AUGraphInitialize failed"); // set the reverb preset for room size // UInt32 roomType = kReverbRoomType_SmallRoom; // UInt32 roomType = kReverbRoomType_MediumRoom; UInt32 roomType = kReverbRoomType_LargeHall; // UInt32 roomType = kReverbRoomType_Cathedral; CheckError(AudioUnitSetProperty(reverbUnit, kAudioUnitProperty_ReverbRoomType, kAudioUnitScope_Global, 0, &roomType, sizeof(UInt32)), "AudioUnitSetProperty[kAudioUnitProperty_ReverbRoomType] failed"); #else // connect the output source of the speech synthesis AU to the input source of the output node CheckError(AUGraphConnectNodeInput(player->graph, speechNode, 0, outputNode, 0), "AUGraphConnectNodeInput"); // now initialize the graph (causes resources to be allocated) CheckError(AUGraphInitialize(player->graph), "AUGraphInitialize failed"); #endif CAShow(player->graph); }
/** * Initializes the audio device and creates sources. * * @return true if initialization was successful, false otherwise */ bool FCoreAudioDevice::InitializeHardware() { if (IsRunningDedicatedServer()) { return false; } // Load ogg and vorbis dlls if they haven't been loaded yet LoadVorbisLibraries(); InverseTransform = FMatrix::Identity; for( SInt32 Index = 0; Index < MAX_AUDIOCHANNELS; ++Index ) { Mixer3DInputStatus[ Index ] = false; } for( SInt32 Index = 0; Index < MAX_MULTICHANNEL_AUDIOCHANNELS; ++Index ) { MatrixMixerInputStatus[ Index ] = false; } // Make sure the output audio device exists AudioDeviceID HALDevice; UInt32 Size = sizeof( AudioDeviceID ); AudioObjectPropertyAddress PropertyAddress; PropertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice; PropertyAddress.mScope = kAudioObjectPropertyScopeGlobal; PropertyAddress.mElement = kAudioObjectPropertyElementMaster; OSStatus Status = AudioObjectGetPropertyData( kAudioObjectSystemObject, &PropertyAddress, 0, NULL, &Size, &HALDevice ); if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "No audio devices found!" ) ); return false; } Status = NewAUGraph( &AudioUnitGraph ); if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to create audio unit graph!" ) ); return false; } AudioComponentDescription Desc; Desc.componentFlags = 0; Desc.componentFlagsMask = 0; Desc.componentType = kAudioUnitType_Output; Desc.componentSubType = kAudioUnitSubType_DefaultOutput; Desc.componentManufacturer = kAudioUnitManufacturer_Apple; Status = AUGraphAddNode( AudioUnitGraph, &Desc, &OutputNode ); if( Status == noErr ) { Status = AUGraphOpen( AudioUnitGraph ); if( Status == noErr ) { Status = AUGraphNodeInfo( AudioUnitGraph, OutputNode, NULL, &OutputUnit ); if( Status == noErr ) { Status = AudioUnitInitialize( OutputUnit ); } } } if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to initialize audio output unit!" ) ); Teardown(); return false; } Desc.componentFlags = 0; Desc.componentFlagsMask = 0; Desc.componentType = kAudioUnitType_Mixer; Desc.componentSubType = kAudioUnitSubType_3DMixer; Desc.componentManufacturer = kAudioUnitManufacturer_Apple; Status = AUGraphAddNode( AudioUnitGraph, &Desc, &Mixer3DNode ); if( Status == noErr ) { Status = AUGraphNodeInfo( AudioUnitGraph, Mixer3DNode, NULL, &Mixer3DUnit ); if( Status == noErr ) { Status = AudioUnitInitialize( Mixer3DUnit ); } } if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to initialize audio 3D mixer unit!" ) ); Teardown(); return false; } Desc.componentFlags = 0; Desc.componentFlagsMask = 0; Desc.componentType = kAudioUnitType_Mixer; Desc.componentSubType = kAudioUnitSubType_MatrixMixer; Desc.componentManufacturer = kAudioUnitManufacturer_Apple; Status = AUGraphAddNode( AudioUnitGraph, &Desc, &MatrixMixerNode ); if( Status == noErr ) { Status = AUGraphNodeInfo( AudioUnitGraph, MatrixMixerNode, NULL, &MatrixMixerUnit ); // Set number of buses for input uint32 NumBuses = MAX_MULTICHANNEL_AUDIOCHANNELS; Size = sizeof( NumBuses ); Status = AudioUnitSetProperty( MatrixMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &NumBuses, Size ); if( Status == noErr ) { // Set number fo buses for output NumBuses = 1; Status = AudioUnitSetProperty( MatrixMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 0, &NumBuses, Size ); } if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to setup audio matrix mixer unit!" ) ); Teardown(); return false; } // Get default input stream format Size = sizeof( AudioStreamBasicDescription ); Status = AudioUnitGetProperty( MatrixMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &MatrixMixerInputFormat, &Size ); // Set output stream format to SPEAKER_COUT (6 channels) MatrixMixerInputFormat.mChannelsPerFrame = SPEAKER_COUNT; MatrixMixerInputFormat.mFramesPerPacket = 1; MatrixMixerInputFormat.mBytesPerPacket = MatrixMixerInputFormat.mBytesPerFrame; MatrixMixerInputFormat.mFormatFlags |= kAudioFormatFlagIsNonInterleaved; for( int32 Index = 0; Index < MAX_MULTICHANNEL_AUDIOCHANNELS; Index++ ) { Status = AudioUnitSetProperty( MatrixMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, Index, &MatrixMixerInputFormat, Size ); if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to setup audio matrix mixer unit input format!" ) ); Teardown(); return false; } } // Set output stream format Size = sizeof( AudioStreamBasicDescription ); Status = AudioUnitGetProperty( MatrixMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &MatrixMixerOutputFormat, &Size ); if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to setup audio matrix mixer unit output format!" ) ); Teardown(); return false; } // Initialize Matrix Mixer unit Status = AudioUnitInitialize( MatrixMixerUnit ); if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to initialize audio matrix mixer unit!" ) ); Teardown(); return false; } // Enable Output AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Enable, kAudioUnitScope_Output, 0, 1.0, 0 ); // Set Output volume AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, 0, 1.0, 0 ); AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, 1, 1.0, 0 ); // Set Master volume AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFFFFFF, 1.0, 0 ); } Size = sizeof( AudioStreamBasicDescription ); Status = AudioUnitGetProperty( Mixer3DUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &Mixer3DFormat, &Size ); if( Status == noErr ) { // Connect 3D Mixer to Output node Status = AUGraphConnectNodeInput( AudioUnitGraph, Mixer3DNode, 0, OutputNode, 0 ); } if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to start audio graph!" ) ); Teardown(); return false; } // Connect Matrix Mixer to 3D Mixer node Status = AUGraphConnectNodeInput( AudioUnitGraph, MatrixMixerNode, 0, Mixer3DNode, 0 ); Mixer3DInputStatus[0] = true; if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to start audio graph!" ) ); Teardown(); return false; } Status = AUGraphInitialize( AudioUnitGraph ); if( Status == noErr ) { Status = AUGraphStart( AudioUnitGraph ); } if( Status != noErr ) { UE_LOG(LogInit, Log, TEXT( "Failed to start audio graph!" ) ); Teardown(); return false; } return true; }
OutputImplAudioUnit::OutputImplAudioUnit() : mAvailableBuses(), OutputImpl() { OSStatus err = noErr; NewAUGraph( &mGraph ); AudioComponentDescription cd; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; //output node cd.componentType = kAudioUnitType_Output; cd.componentSubType = CINDER_AUDIOUNIT_OUTPUT_TYPE; //connect & setup AUGraphOpen( mGraph ); //initialize component - todo add error checking if( AUGraphAddNode( mGraph, &cd, &mOutputNode ) != noErr ) { std::cout << "Error 1!" << std::endl; } if( AUGraphNodeInfo( mGraph, mOutputNode, NULL, &mOutputUnit ) != noErr ) { std::cout << "Error 2!" << std::endl; } UInt32 dsize; #if defined( CINDER_MAC ) //get default output device id and set it as the outdevice for the output unit, unnessary on the iphone dsize = sizeof( AudioDeviceID ); err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, &dsize, &mOutputDeviceId ); if( err != noErr ) { std::cout << "Error getting default output device" << std::endl; } err = AudioUnitSetProperty( mOutputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &mOutputDeviceId, sizeof( mOutputDeviceId ) ); if( err != noErr ) { std::cout << "Error setting current output device" << std::endl; } #endif //Tell the output unit not to reset timestamps //Otherwise sample rate changes will cause sync los UInt32 startAtZero = 0; err = AudioUnitSetProperty( mOutputUnit, kAudioOutputUnitProperty_StartTimestampsAtZero, kAudioUnitScope_Global, 0, &startAtZero, sizeof( startAtZero ) ); if( err != noErr ) { std::cout << "Error telling output unit not to reset timestamps" << std::endl; } //stereo mixer node cd.componentType = kAudioUnitType_Mixer; cd.componentSubType = kAudioUnitSubType_MultiChannelMixer;//kAudioUnitSubType_StereoMixer; AUGraphAddNode( mGraph, &cd, &mMixerNode ); //setup mixer AU err = AUGraphNodeInfo( mGraph, mMixerNode, NULL, &mMixerUnit ); if( err ) { std::cout << "Error 4" << std::endl; } //TODO: cleanup error checking in all of this //check the element count, if it's less than our default element count, increase, or else just leave it alone err = AudioUnitGetProperty( mMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &mNumberBuses, &dsize ); if( err ) { std::cout << "Error getting mixer unit input elements" << std::endl; } if( mNumberBuses < sDefaultNumberBuses ) { mNumberBuses = sDefaultNumberBuses; err = AudioUnitSetProperty( mMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &mNumberBuses, sizeof(mNumberBuses) ); if( err ) { std::cout << "Error setting mixer unit input elements" << std::endl; } } for( uint32_t i = 1; i <= mNumberBuses; i++ ) { mAvailableBuses.push( mNumberBuses - i ); } AUGraphConnectNodeInput( mGraph, mMixerNode, 0, mOutputNode, 0 ); AudioStreamBasicDescription outDesc; UInt32 size = sizeof( outDesc ); err = AudioUnitGetProperty( mOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &outDesc, &size ); if( err ) { std::cout << "Error getting output unit stream format" << std::endl; } AUGraphInitialize( mGraph ); //Do all StreamFormat getting/setting after initialization, //since that's when the output unit is actually hooked up to the hardware dsize = sizeof( AudioStreamBasicDescription ); mPlayerDescription = new AudioStreamBasicDescription; err = AudioUnitGetProperty( mOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, mPlayerDescription, &dsize ); if( err ) { std::cout << "Error reading output unit stream format" << std::endl; } err = AudioUnitSetProperty( mMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, mPlayerDescription, dsize ); if( err ) { std::cout << "Error setting mixer unit output stream format" << std::endl; } err = AudioUnitSetProperty( mOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, mPlayerDescription, dsize ); if( err ) { std::cout << "Error setting output unit input stream format" << std::endl; } //race condition work around?? usleep( 10 * 1000 ); //TODO: tell the output AU about the order of the channels if there are more than 2 // turn metering ON //UInt32 data = 1; //AudioUnitSetProperty( mMixerUnit, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Global, 0, &data, sizeof(data) ); err = AudioUnitSetParameter( mMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, CINDER_DEFAULT_VOLUME, 0 ); if( err ) { std::cout << "error setting default volume" << std::cout; } err = AUGraphStart( mGraph ); if( err ) { //throw } }
void CreateMyAUGraph(MyAUGraphPlayer *player) { // create a new AUGraph CheckError(NewAUGraph(&player->graph), "NewAUGraph failed"); // generate description that will match default output // ComponentDescription outputcd = {0}; // outputcd.componentType = kAudioUnitType_Output; // outputcd.componentSubType = kAudioUnitSubType_DefaultOutput; // outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; // // Component comp = FindNextComponent(NULL, &outputcd); // if (comp == NULL) { // printf ("can't get output unit"); exit (-1); // } AudioComponentDescription outputcd = {0}; outputcd.componentType = kAudioUnitType_Output; outputcd.componentSubType = kAudioUnitSubType_DefaultOutput; outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; AudioComponent comp = AudioComponentFindNext(NULL, &outputcd); if (comp == NULL) { printf ("can't get output unit"); exit (-1); } // adds a node with above description to the graph AUNode outputNode; CheckError(AUGraphAddNode(player->graph, &outputcd, &outputNode), "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed"); #ifdef PART_II // add a mixer to the graph, AudioComponentDescription mixercd = {0}; mixercd.componentType = kAudioUnitType_Mixer; mixercd.componentSubType = kAudioUnitSubType_StereoMixer; // doesn't work: kAudioUnitSubType_MatrixMixer mixercd.componentManufacturer = kAudioUnitManufacturer_Apple; AUNode mixerNode; CheckError(AUGraphAddNode(player->graph, &mixercd, &mixerNode), "AUGraphAddNode[kAudioUnitSubType_StereoMixer] failed"); // adds a node with above description to the graph AudioComponentDescription speechcd = {0}; speechcd.componentType = kAudioUnitType_Generator; speechcd.componentSubType = kAudioUnitSubType_SpeechSynthesis; speechcd.componentManufacturer = kAudioUnitManufacturer_Apple; AUNode speechNode; CheckError(AUGraphAddNode(player->graph, &speechcd, &speechNode), "AUGraphAddNode[kAudioUnitSubType_AudioFilePlayer] failed"); // opening the graph opens all contained audio units but does not allocate any resources yet CheckError(AUGraphOpen(player->graph), "AUGraphOpen failed"); // get the reference to the AudioUnit objects for the various nodes CheckError(AUGraphNodeInfo(player->graph, outputNode, NULL, &player->outputUnit), "AUGraphNodeInfo failed"); CheckError(AUGraphNodeInfo(player->graph, speechNode, NULL, &player->speechUnit), "AUGraphNodeInfo failed"); AudioUnit mixerUnit; CheckError(AUGraphNodeInfo(player->graph, mixerNode, NULL, &mixerUnit), "AUGraphNodeInfo failed"); // set ASBDs here UInt32 propertySize = sizeof (AudioStreamBasicDescription); CheckError(AudioUnitSetProperty(player->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &player->streamFormat, propertySize), "Couldn't set stream format on output unit"); // problem: badComponentInstance (-2147450879) CheckError(AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &player->streamFormat, propertySize), "Couldn't set stream format on mixer unit bus 0"); CheckError(AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &player->streamFormat, propertySize), "Couldn't set stream format on mixer unit bus 1"); // connections // mixer output scope / bus 0 to outputUnit input scope / bus 0 // mixer input scope / bus 0 to render callback (from ringbuffer, which in turn is from inputUnit) // mixer input scope / bus 1 to speech unit output scope / bus 0 CheckError(AUGraphConnectNodeInput(player->graph, mixerNode, 0, outputNode, 0), "Couldn't connect mixer output(0) to outputNode (0)"); CheckError(AUGraphConnectNodeInput(player->graph, speechNode, 0, mixerNode, 1), "Couldn't connect speech synth unit output (0) to mixer input (1)"); AURenderCallbackStruct callbackStruct; callbackStruct.inputProc = GraphRenderProc; callbackStruct.inputProcRefCon = player; CheckError(AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &callbackStruct, sizeof(callbackStruct)), "Couldn't set render callback on mixer unit"); #else // opening the graph opens all contained audio units but does not allocate any resources yet CheckError(AUGraphOpen(player->graph), "AUGraphOpen failed"); // get the reference to the AudioUnit object for the output graph node CheckError(AUGraphNodeInfo(player->graph, outputNode, NULL, &player->outputUnit), "AUGraphNodeInfo failed"); // set the stream format on the output unit's input scope UInt32 propertySize = sizeof (AudioStreamBasicDescription); CheckError(AudioUnitSetProperty(player->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &player->streamFormat, propertySize), "Couldn't set stream format on output unit"); AURenderCallbackStruct callbackStruct; callbackStruct.inputProc = GraphRenderProc; callbackStruct.inputProcRefCon = player; CheckError(AudioUnitSetProperty(player->outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &callbackStruct, sizeof(callbackStruct)), "Couldn't set render callback on output unit"); #endif // now initialize the graph (causes resources to be allocated) CheckError(AUGraphInitialize(player->graph), "AUGraphInitialize failed"); player->firstOutputSampleTime = -1; printf ("Bottom of CreateSimpleAUGraph()\n"); }
int MidiDriver_CORE::open() { OSStatus err = 0; if (isOpen()) return MERR_ALREADY_OPEN; // Open the Music Device. RequireNoErr(NewAUGraph(&_auGraph)); AUNode outputNode, synthNode; #if USE_DEPRECATED_COREAUDIO_API ComponentDescription desc; #else AudioComponentDescription desc; #endif // The default output device desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; #if USE_DEPRECATED_COREAUDIO_API RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &outputNode)); #else RequireNoErr(AUGraphAddNode(_auGraph, &desc, &outputNode)); #endif // The built-in default (softsynth) music device desc.componentType = kAudioUnitType_MusicDevice; desc.componentSubType = kAudioUnitSubType_DLSSynth; desc.componentManufacturer = kAudioUnitManufacturer_Apple; #if USE_DEPRECATED_COREAUDIO_API RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &synthNode)); #else RequireNoErr(AUGraphAddNode(_auGraph, &desc, &synthNode)); #endif // Connect the softsynth to the default output RequireNoErr(AUGraphConnectNodeInput(_auGraph, synthNode, 0, outputNode, 0)); // Open and initialize the whole graph RequireNoErr(AUGraphOpen(_auGraph)); RequireNoErr(AUGraphInitialize(_auGraph)); // Get the music device from the graph. #if USE_DEPRECATED_COREAUDIO_API RequireNoErr(AUGraphGetNodeInfo(_auGraph, synthNode, NULL, NULL, NULL, &_synth)); #else RequireNoErr(AUGraphNodeInfo(_auGraph, synthNode, NULL, &_synth)); #endif // Load custom soundfont, if specified if (ConfMan.hasKey("soundfont")) { FSRef fsref; FSSpec fsSpec; const char *soundfont = ConfMan.get("soundfont").c_str(); err = FSPathMakeRef ((const byte *)soundfont, &fsref, NULL); if (err == noErr) { err = FSGetCatalogInfo (&fsref, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL); } if (err == noErr) { // TODO: We should really check here whether the file contains an // actual soundfont... err = AudioUnitSetProperty ( _synth, kMusicDeviceProperty_SoundBankFSSpec, kAudioUnitScope_Global, 0, &fsSpec, sizeof(fsSpec) ); } if (err != noErr) warning("Failed loading custom sound font '%s' (error %ld)\n", soundfont, (long)err); } #ifdef COREAUDIO_DISABLE_REVERB // Disable reverb mode, as that sucks up a lot of CPU power, which can // be painful on low end machines. // TODO: Make this customizable via a config key? UInt32 usesReverb = 0; AudioUnitSetProperty (_synth, kMusicDeviceProperty_UsesInternalReverb, kAudioUnitScope_Global, 0, &usesReverb, sizeof (usesReverb)); #endif // Finally: Start the graph! RequireNoErr(AUGraphStart(_auGraph)); return 0; bail: if (_auGraph) { AUGraphStop(_auGraph); DisposeAUGraph(_auGraph); _auGraph = 0; } return MERR_CANNOT_CONNECT; }
void CoreAudio_MakeSimpleGraph(AUGraph * theGraph, AudioUnit * fileAU, AudioStreamBasicDescription * fileFormat, AudioFileID audioFile) { CoreAudioChkError(NewAUGraph(theGraph), "NewAUGraph",); AudioComponentDescription cd; memset(&cd, 0, sizeof(cd)); /* Initialize and add Output Node */ cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; cd.componentManufacturer = kAudioUnitManufacturer_Apple; AUNode outputNode; CoreAudioChkError(AUGraphAddNode(*theGraph, &cd, &outputNode), "AUGraphAddNode Output",); /* Initialize and add the AU node */ AUNode fileNode; cd.componentType = kAudioUnitType_Generator; cd.componentSubType = kAudioUnitSubType_AudioFilePlayer; CoreAudioChkError(AUGraphAddNode(*theGraph, &cd, &fileNode), "AUGraphAddNode AU",); /* Make connections */ CoreAudioChkError(AUGraphOpen(*theGraph), "AUGraphOpen",); /* Set Schedule properties and initialize the graph with the file */ AudioUnit anAU; memset(&anAU, 0, sizeof(anAU)); CoreAudioChkError(AUGraphNodeInfo(*theGraph, fileNode, NULL, &anAU), "AUGraphNodeInfo",);
void MakeSimpleGraph (AUGraph &theGraph, CAAudioUnit &fileAU, CAStreamBasicDescription &fileFormat, AudioFileID audioFile) { XThrowIfError (NewAUGraph (&theGraph), "NewAUGraph"); CAComponentDescription cd; // output node cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; cd.componentManufacturer = kAudioUnitManufacturer_Apple; AUNode outputNode; XThrowIfError (AUGraphAddNode (theGraph, &cd, &outputNode), "AUGraphAddNode"); // file AU node AUNode fileNode; cd.componentType = kAudioUnitType_Generator; cd.componentSubType = kAudioUnitSubType_AudioFilePlayer; XThrowIfError (AUGraphAddNode (theGraph, &cd, &fileNode), "AUGraphAddNode"); // connect & setup XThrowIfError (AUGraphOpen (theGraph), "AUGraphOpen"); // install overload listener to detect when something is wrong AudioUnit anAU; XThrowIfError (AUGraphNodeInfo(theGraph, fileNode, NULL, &anAU), "AUGraphNodeInfo"); fileAU = CAAudioUnit (fileNode, anAU); // prepare the file AU for playback // set its output channels XThrowIfError (fileAU.SetNumberChannels (kAudioUnitScope_Output, 0, fileFormat.NumberChannels()), "SetNumberChannels"); // set the output sample rate of the file AU to be the same as the file: XThrowIfError (fileAU.SetSampleRate (kAudioUnitScope_Output, 0, fileFormat.mSampleRate), "SetSampleRate"); // load in the file XThrowIfError (fileAU.SetProperty(kAudioUnitProperty_ScheduledFileIDs, kAudioUnitScope_Global, 0, &audioFile, sizeof(audioFile)), "SetScheduleFile"); XThrowIfError (AUGraphConnectNodeInput (theGraph, fileNode, 0, outputNode, 0), "AUGraphConnectNodeInput"); // AT this point we make sure we have the file player AU initialized // this also propogates the output format of the AU to the output unit XThrowIfError (AUGraphInitialize (theGraph), "AUGraphInitialize"); // workaround a race condition in the file player AU usleep (10 * 1000); // if we have a surround file, then we should try to tell the output AU what the order of the channels will be if (fileFormat.NumberChannels() > 2) { UInt32 layoutSize = 0; OSStatus err; XThrowIfError (err = AudioFileGetPropertyInfo (audioFile, kAudioFilePropertyChannelLayout, &layoutSize, NULL), "kAudioFilePropertyChannelLayout"); if (!err && layoutSize) { char* layout = new char[layoutSize]; err = AudioFileGetProperty(audioFile, kAudioFilePropertyChannelLayout, &layoutSize, layout); XThrowIfError (err, "Get Layout From AudioFile"); // ok, now get the output AU and set its layout XThrowIfError (AUGraphNodeInfo(theGraph, outputNode, NULL, &anAU), "AUGraphNodeInfo"); err = AudioUnitSetProperty (anAU, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, layout, layoutSize); XThrowIfError (err, "kAudioUnitProperty_AudioChannelLayout"); delete [] layout; } } }
OSStatus add_node(OSType type, OSType subtype, OSType manufacturer) { AudioComponentDescription const desc = { type, subtype, manufacturer, 0, 0 }; return AUGraphAddNode(m_graph, &desc, &m_node_details[m_node_count].m_node); }
OSStatus SetUpGraph (AUGraph &inGraph, UInt32 numFrames, Float64 &sampleRate, bool isOffline) { OSStatus result = noErr; AudioUnit outputUnit = 0; AUNode outputNode; // the frame size is the I/O size to the device // the device is going to run at a sample rate it is set at // so, when we set this, we also have to set the max frames for the graph nodes UInt32 nodeCount; FailIf ((result = AUGraphGetNodeCount (inGraph, &nodeCount)), home, "AUGraphGetNodeCount"); for (int i = 0; i < (int)nodeCount; ++i) { AUNode node; FailIf ((result = AUGraphGetIndNode(inGraph, i, &node)), home, "AUGraphGetIndNode"); AudioComponentDescription desc; AudioUnit unit; FailIf ((result = AUGraphNodeInfo(inGraph, node, &desc, &unit)), home, "AUGraphNodeInfo"); if (desc.componentType == kAudioUnitType_Output) { if (outputUnit == 0) { outputUnit = unit; FailIf ((result = AUGraphNodeInfo(inGraph, node, 0, &outputUnit)), home, "AUGraphNodeInfo"); if (!isOffline) { // these two properties are only applicable if its a device we're playing too FailIf ((result = AudioUnitSetProperty (outputUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Output, 0, &numFrames, sizeof(numFrames))), home, "AudioUnitSetProperty: kAudioDevicePropertyBufferFrameSize"); FailIf ((result = AudioUnitAddPropertyListener (outputUnit, kAudioDeviceProcessorOverload, OverlaodListenerProc, 0)), home, "AudioUnitAddPropertyListener: kAudioDeviceProcessorOverload"); // if we're rendering to the device, then we render at its sample rate UInt32 theSize; theSize = sizeof(sampleRate); FailIf ((result = AudioUnitGetProperty (outputUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, &theSize)), home, "AudioUnitGetProperty: kAudioUnitProperty_SampleRate"); } else { // remove device output node and add generic output FailIf ((result = AUGraphRemoveNode (inGraph, node)), home, "AUGraphRemoveNode"); desc.componentSubType = kAudioUnitSubType_GenericOutput; FailIf ((result = AUGraphAddNode (inGraph, &desc, &node)), home, "AUGraphAddNode"); FailIf ((result = AUGraphNodeInfo(inGraph, node, NULL, &unit)), home, "AUGraphNodeInfo"); outputUnit = unit; outputNode = node; // we render the output offline at the desired sample rate FailIf ((result = AudioUnitSetProperty (outputUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate))), home, "AudioUnitSetProperty: kAudioUnitProperty_SampleRate"); } // ok, lets start the loop again now and do it all... i = -1; } } else { // we only have to do this on the output side // as the graph's connection mgmt will propogate this down. if (outputUnit) { // reconnect up to the output unit if we're offline if (isOffline && desc.componentType != kAudioUnitType_MusicDevice) { FailIf ((result = AUGraphConnectNodeInput (inGraph, node, 0, outputNode, 0)), home, "AUGraphConnectNodeInput"); } FailIf ((result = AudioUnitSetProperty (unit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate))), home, "AudioUnitSetProperty: kAudioUnitProperty_SampleRate"); } } FailIf ((result = AudioUnitSetProperty (unit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &numFrames, sizeof(numFrames))), home, "AudioUnitSetProperty: kAudioUnitProperty_MaximumFramesPerSlice"); } home: return result; }
int main(int argc, char *argv[]) { AUGraph audioGraph; NewAUGraph(&audioGraph); AudioComponentDescription cd; AUNode outputNode; AudioUnit outputUnit; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; AUGraphAddNode(audioGraph, &cd, &outputNode); AUGraphNodeInfo(audioGraph, outputNode, &cd, &outputUnit); AUNode mixerNode; AudioUnit mixerUnit; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; cd.componentType = kAudioUnitType_Mixer; cd.componentSubType = kAudioUnitSubType_StereoMixer; AUGraphAddNode(audioGraph, &cd, &mixerNode); AUGraphNodeInfo(audioGraph, mixerNode, &cd, &mixerUnit); AUGraphConnectNodeInput(audioGraph, mixerNode, 0, outputNode, 0); AUGraphOpen(audioGraph); AUGraphInitialize(audioGraph); AUGraphStart(audioGraph); AUNode synthNode; AudioUnit synthUnit; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; cd.componentType = kAudioUnitType_MusicDevice; cd.componentSubType = kAudioUnitSubType_DLSSynth; AUGraphAddNode(audioGraph, &cd, &synthNode); AUGraphNodeInfo(audioGraph, synthNode, &cd, &synthUnit); AUGraphConnectNodeInput(audioGraph, synthNode, 0, mixerNode, 0); AUGraphUpdate(audioGraph, NULL); CAShow(audioGraph); MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 127, 0); sleep(1); MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 127, 0); sleep(1); MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 127, 0); sleep(1); sleep(5); return(0); }
int QBSoundMac::initGraph() { OSStatus err; mAudioFormat.mSampleRate = 44100.000000; mAudioFormat.mFormatID = kAudioFormatLinearPCM; #ifdef __FLOAT_BUFFER__ mAudioFormat.mFormatFlags = 0 | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsFloat #if __BIG_ENDIAN__ | kLinearPCMFormatFlagIsBigEndian #endif ; mAudioFormat.mBytesPerPacket = 8; mAudioFormat.mFramesPerPacket = 1; mAudioFormat.mBytesPerFrame = 8; mAudioFormat.mChannelsPerFrame = 2; mAudioFormat.mBitsPerChannel = 32; mAudioFormat.mReserved = 0; #else mAudioFormat.mFormatFlags = 0 | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger #if __BIG_ENDIAN__ | kLinearPCMFormatFlagIsBigEndian #endif ; mAudioFormat.mBytesPerPacket = 4; mAudioFormat.mFramesPerPacket = 1; mAudioFormat.mBytesPerFrame = 4; mAudioFormat.mChannelsPerFrame = 2; mAudioFormat.mBitsPerChannel = 16; mAudioFormat.mReserved = 0; #endif err = NewAUGraph(&mGraph); #if !TARGET_OS_IPHONE AudioComponentDescription description; description.componentSubType = kAudioUnitSubType_DefaultOutput; #else AudioComponentDescription description; description.componentSubType = kAudioUnitSubType_RemoteIO; #endif description.componentType = kAudioUnitType_Output; description.componentManufacturer = kAudioUnitManufacturer_Apple; description.componentFlags = 0; description.componentFlagsMask = 0; #if 1 err = AUGraphAddNode(mGraph,&description,&mOutputNode); #else err = AUGraphNewNode(mGraph,&description, 0, NULL, &mOutputNode); #endif err = AUGraphOpen(mGraph); #if 1 err = AUGraphNodeInfo(mGraph,mOutputNode,NULL,&mAudioUnit); #else err = AUGraphGetNodeInfo(mGraph,mOutputNode,NULL,NULL,NULL,&mAudioUnit); #endif err = AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &mAudioFormat, sizeof(AudioStreamBasicDescription)); { AURenderCallbackStruct input; input.inputProc = callback; input.inputProcRefCon = this; err = AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)); } // { // AudioUnitSetParameter (mAudioUnit, // kHALOutputParam_Volume, // kAudioUnitScope_Global,0,1,0); // } err = AUGraphInitialize(mGraph); //err = AUGraphStart(mGraph); //pthread_mutex_init(&mLoaderThreadMutex,NULL); #ifdef __USE_OGG_VORBIS__ mThreadEnd = false; pthread_create(&mLoaderThread,NULL,LoaderThreadProc,this); #endif // mOpenGraph = false; // mInitGraph = false; // startAUGraph(); //printf("openAUGraph\n"); return err; }