OSStatus CAPlayThrough::Init(AudioDeviceID input, AudioDeviceID output) { OSStatus err = noErr; //Note: You can interface to input and output devices with "output" audio units. //Please keep in mind that you are only allowed to have one output audio unit per graph (AUGraph). //As you will see, this sample code splits up the two output units. The "output" unit that will //be used for device input will not be contained in a AUGraph, while the "output" unit that will //interface the default output device will be in a graph. //Setup AUHAL for an input device err = SetupAUHAL(input); checkErr(err); //Setup Graph containing Varispeed Unit & Default Output Unit err = SetupGraph(output); checkErr(err); err = SetupBuffers(); checkErr(err); // the varispeed unit should only be conected after the input and output formats have been set err = AUGraphConnectNodeInput(mGraph, mVarispeedNode, 0, mOutputNode, 0); checkErr(err); err = AUGraphInitialize(mGraph); checkErr(err); //Add latency between the two devices ComputeThruOffset(); return err; }
bool midi_init(void) { OSStatus result; result = CreateAUGraph(); if (result != 0) return false; result = AUGraphInitialize(s_graph); if (result != 0) return false; result = AUGraphStart(s_graph); if (result != 0) return false; return true; }
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); }
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); }
MidiDevice * openMidiDevice (int errorLevel, const char *device) { MidiDevice *midi; int result; AUNode synthNode, outNode; ComponentDescription cd; UInt32 propVal; if (!(midi = malloc(sizeof(*midi)))) { logMallocError(); return NULL; } /* Create a graph with a software synth and a default output unit. */ cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; if ((result = NewAUGraph(&midi->graph)) != noErr) { logMessage(errorLevel, "Can't create audio graph component: %d", result); goto err; } cd.componentType = kAudioUnitType_MusicDevice; cd.componentSubType = kAudioUnitSubType_DLSSynth; if ((result = AUGraphNewNode(midi->graph, &cd, 0, NULL, &synthNode)) != noErr) { logMessage(errorLevel, "Can't create software synthersizer component: %d", result); goto err; } cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; if ((result = AUGraphNewNode(midi->graph, &cd, 0, NULL, &outNode)) != noErr) { logMessage(errorLevel, "Can't create default output audio component: %d", result); goto err; } if ((result = AUGraphOpen(midi->graph)) != noErr) { logMessage(errorLevel, "Can't open audio graph component: %d", result); goto err; } if ((result = AUGraphConnectNodeInput(midi->graph, synthNode, 0, outNode, 0)) != noErr) { logMessage(errorLevel, "Can't connect synth audio component to output: %d", result); goto err; } if ((result = AUGraphGetNodeInfo(midi->graph, synthNode, 0, 0, 0, &midi->synth)) != noErr) { logMessage(errorLevel, "Can't get audio component for software synth: %d", result); goto err; } if ((result = AUGraphInitialize(midi->graph)) != noErr) { logMessage(errorLevel, "Can't initialize audio graph: %d", result); goto err; } /* Turn off the reverb. The value range is -120 to 40 dB. */ propVal = false; if ((result = AudioUnitSetProperty(midi->synth, kMusicDeviceProperty_UsesInternalReverb, kAudioUnitScope_Global, 0, &propVal, sizeof(propVal))) != noErr) { /* So, having reverb isn't that critical, is it? */ logMessage(LOG_DEBUG, "Can't turn of software synth reverb: %d", result); } /* TODO: Maybe just start the graph when we are going to use it? */ if ((result = AUGraphStart(midi->graph)) != noErr) { logMessage(errorLevel, "Can't start audio graph component: %d", result); goto err; } return midi; err: if (midi->graph) DisposeAUGraph(midi->graph); free(midi); return NULL; }
int main(int argc, char *argv[]) { WindowRef window; HIViewRef content; HIViewRef combo; HIViewRef group; HIViewRef check; HIViewRef text; HIViewRef slider; HIViewRef quit; MenuRef menu; HIRect rect; // Window bounds Rect bounds = {0, 0, 436, 590}; // Create window CreateNewWindow(kDocumentWindowClass, kWindowStandardFloatingAttributes | kWindowStandardHandlerAttribute | kWindowInWindowMenuAttribute | kWindowCompositingAttribute, &bounds, &window); // Set the title SetWindowTitleWithCFString(window, CFSTR("Accordion")); // Create an application menu CreateNewMenu(0, 0, &menu); // Set menu title SetMenuTitleWithCFString(menu, CFStringCreateWithPascalString(kCFAllocatorDefault, "\p\024", kCFStringEncodingMacRoman)); // Create an about item InsertMenuItemTextWithCFString(menu, CFSTR("About Accordion"), 0, 0, kHICommandAbout); // Insert the menu InsertMenu(menu, 0); // Create a standard window menu CreateStandardWindowMenu(0, &menu); // Insert the menu InsertMenu(menu, 0); // Show and position the window ShowWindow(window); RepositionWindow(window, NULL, kWindowCascadeOnMainScreen); // Find the window content HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &content); // Set bounds for group box bounds.bottom = 92; bounds.right = 550; // Create group box CreateGroupBoxControl(window, &bounds, NULL, true, &group); // Place in the window HIViewAddSubview(content, group); HIViewPlaceInSuperviewAt(group, 20, 20); // Bounds of text bounds.bottom = 16; bounds.right = 74; // Create static text CreateStaticTextControl(window, &bounds, CFSTR("Instrument:"), NULL, &text); // Place in the group box HIViewAddSubview(group, text); HIViewPlaceInSuperviewAt(text, 16, 18); // Bounds of combo box rect.size.height = 20; rect.size.width = 168; // Create combo box HIComboBoxCreate(&rect, CFSTR(" Accordion"), NULL, NULL, kHIComboBoxStandardAttributes, &combo); // Set visible and set command ID HIViewSetVisible(combo, true); HIViewSetCommandID(combo, kCommandInst); // Add the instruments for (int i = 0; i < Length(instruments); i++) { HIComboBoxAppendTextItem(combo, CFStringCreateWithCString(kCFAllocatorDefault, instruments[i], kCFStringEncodingMacRoman), NULL); // Set the current instrument if (strcmp(instruments[i], " Accordion") == 0) instrument = i; } // Place in the group box HIViewAddSubview(group, combo); HIViewPlaceInSuperviewAt(combo, 102, 16); // Bounds of check box bounds.bottom = 18; bounds.right = 121; // Create check box CreateCheckBoxControl(window, &bounds, CFSTR("Reverse"), false, true, &check); // Set the control ID and the command ID HIViewSetID(check, kHIViewIDReverse); HIViewSetCommandID(check, kCommandReverse); // Place in the group box HIViewAddSubview(group, check); HIViewPlaceInSuperviewAt(check, 286, 17); // Bounds of text bounds.bottom = 16; bounds.right = 32; // Create static text CreateStaticTextControl(window, &bounds, CFSTR("Key:"), NULL, &text); // Place in the group box HIViewAddSubview(group, text); HIViewPlaceInSuperviewAt(text, 400, 18); // Bounds of combo box rect.size.width = 90; // Create combo box HIComboBoxCreate(&rect, CFSTR(" A/D/G"), NULL, NULL, kHIComboBoxStandardAttributes, &combo); // Set visible and set command ID HIViewSetVisible(combo, true); HIViewSetID(combo, kHIViewIDKey); HIViewSetCommandID(combo, kCommandKey); // Add keys for (int i = 0; i < Length(keys); i++) { HIComboBoxAppendTextItem(combo, CFStringCreateWithCString(kCFAllocatorDefault, keys[i], kCFStringEncodingMacRoman), NULL); // Set current key if (strcmp(keys[i], " A/D/G") == 0) key = i; } // Place in the group box HIViewAddSubview(group, combo); HIViewPlaceInSuperviewAt(combo, 440, 16); // Bounds of text bounds.bottom = 16; bounds.right = 54; // Create static text CreateStaticTextControl(window, &bounds, CFSTR("Volume:"), NULL, &text); // Place in the group box HIViewAddSubview(group, text); HIViewPlaceInSuperviewAt(text, 16, 56); // Bounds of slider bounds.bottom = 16; bounds.right = 168; // Create slider CreateSliderControl(window, &bounds, MAXVOL, 0, MAXVOL, kControlSliderDoesNotPoint, 0, false, NULL, &slider); // Set command ID HIViewSetCommandID(slider, kCommandVolume); // Place in the group box HIViewAddSubview(group, slider); HIViewPlaceInSuperviewAt(slider, 100, 58); // Bounds of check box bounds.bottom = 18; bounds.right = 121; // Create check box CreateCheckBoxControl(window, &bounds, CFSTR("Notes"), false, true, &check); // Set the control ID and the command ID HIViewSetID(check, kHIViewIDNote); HIViewSetCommandID(check, kCommandNote); // Place in the group box HIViewAddSubview(group, check); HIViewPlaceInSuperviewAt(check, 286, 56); // Bounds of push button bounds.bottom = 20; bounds.right = 90; // Create push button CreatePushButtonControl(window, &bounds, CFSTR("Quit"), &quit); // Set command ID HIViewSetCommandID(quit, kHICommandQuit); // Place in the group box HIViewAddSubview(group, quit); HIViewPlaceInSuperviewAt(quit, 440, 54); // Group box bounds bounds.bottom = 48; bounds.right = 550; // Create group box CreateGroupBoxControl(window, &bounds, NULL, true, &group); // Place in the window HIViewAddSubview(content, group); HIViewPlaceInSuperviewAt(group, 20, 132); // Font style ControlFontStyleRec style; style.flags = kControlUseFontMask|kControlUseJustMask; style.font = kControlFontBigSystemFont; style.just = teCenter; // Bounds of text bounds.bottom = 16; bounds.right = 550; // Create static text CreateStaticTextControl(window, &bounds, CFSTR("Accordion"), &style, &text); // Place in the group box HIViewAddSubview(group, text); HIViewPlaceInSuperviewAt(text, 0, 8); // Bounds of text bounds.bottom = 16; bounds.right = 550; // Create static text CreateStaticTextControl(window, &bounds, CFSTR("Play accordion on your keyboard"), &style, &text); // Place in the group box HIViewAddSubview(group, text); HIViewPlaceInSuperviewAt(text, 0, 24); // Group box bounds bounds.bottom = 196; bounds.right = 550; // Create group box CreateGroupBoxControl(window, &bounds, NULL, true, &group); // Place in the window HIViewAddSubview(content, group); HIViewPlaceInSuperviewAt(group, 20, 200); // Button bounds bounds.bottom = SIZE; bounds.right = SIZE; // Create row of bass buttons for (int i = 0; i < Length(bassdisplay); i++) { int x = 15 + 44 * i; int y = 15; // Create button CreateBevelButtonControl(window, &bounds, NULL, kControlBevelButtonNormalBevel, kControlBehaviorPushbutton, NULL, 0, 0, 0, &bassdisplay[i]); // Place in the group box HIViewAddSubview(group, bassdisplay[i]); HIViewPlaceInSuperviewAt(bassdisplay[i], x, y); } // Create three rows of buttons for (int i = 0; i < Length(display); i++) { for (int j = 0; j < ((i == 1)? Length(display[i]): Length(display[i]) - 1); j++) { int x = (i == 1)? 37 + 44 * j: 59 + 44 * j; int y = 59 + 44 * i; // Create button CreateBevelButtonControl(window, &bounds, NULL, kControlBevelButtonNormalBevel, kControlBehaviorPushbutton, NULL, 0, 0, 0, &display[i][j]); // Place in the group box HIViewAddSubview(group, display[i][j]); HIViewPlaceInSuperviewAt(display[i][j], x, y); } } // Create spacebar button CreateBevelButtonControl(window, &bounds, NULL, kControlBevelButtonNormalBevel, kControlBehaviorPushbutton, NULL, 0, 0, 0, &spacebar); // Place in the group box HIViewAddSubview(group, spacebar); HIViewPlaceInSuperviewAt(spacebar, 16, 147); // Group box bounds, wider than the window to hide rounded corners bounds.bottom = 20; bounds.right = 598; // Create group box for fake status bar CreateGroupBoxControl(window, &bounds, NULL, false, &group); // Place in window at negative offset to hide rounded corners HIViewAddSubview(content, group); HIViewPlaceInSuperviewAt(group, -4, 416); // Text bounds bounds.bottom = 16; bounds.right = 590; // Font style style.flags = kControlUseFontMask|kControlUseJustMask; style.font = kControlFontSmallSystemFont; style.just = teCenter; // Create static text CreateStaticTextControl(window, &bounds, CFSTR("Press the keyboard keys as accordion buttons " "and the space bar as the bellows. 3rd button start."), &style, &text); // Place in group box HIViewAddSubview(group, text); HIViewPlaceInSuperviewAt(text, 0, 2); // Application events type spec EventTypeSpec applicationEvents[] = {{kEventClassApplication, kEventAppFrontSwitched}}; // Install event handler InstallApplicationEventHandler(NewEventHandlerUPP(ApplicationHandler), Length(applicationEvents), applicationEvents, NULL, NULL); // Mouse events type spec EventTypeSpec mouseEvents[] = {{kEventClassMouse, kEventMouseDown}}; // Install event handler on the event dispatcher, so that we can // see mouse events before the default handler gets them InstallEventHandler(GetEventDispatcherTarget(), NewEventHandlerUPP(MouseHandler), Length(mouseEvents), mouseEvents, NULL, NULL); // Window events type spec EventTypeSpec windowEvents[] = {{kEventClassWindow, kEventWindowClose}}; // Install event handler InstallWindowEventHandler(window, NewEventHandlerUPP(WindowHandler), Length(windowEvents), windowEvents, NULL, NULL); // Combo box events type spec EventTypeSpec comboBoxEvents[] = {{kEventClassHIComboBox, kEventComboBoxListItemSelected}}; // Install event handler InstallApplicationEventHandler(NewEventHandlerUPP(ComboBoxHandler), Length(comboBoxEvents), comboBoxEvents, NULL, NULL); // Command events type spec EventTypeSpec commandEvents[] = {{kEventClassCommand, kEventCommandProcess}}; // Install event handler InstallApplicationEventHandler(NewEventHandlerUPP(CommandHandler), Length(commandEvents), commandEvents, NULL, NULL); // Keyboard events type spec EventTypeSpec keyboardEvents[] = {{kEventClassKeyboard, kEventRawKeyDown}, {kEventClassKeyboard, kEventRawKeyUp}, {kEventClassKeyboard, kEventRawKeyModifiersChanged}}; // Install event handler on the event dispatcher InstallEventHandler(GetEventDispatcherTarget(), NewEventHandlerUPP(KeyboardHandler), Length(keyboardEvents), keyboardEvents, NULL, NULL); // Audio Unit graph AUGraph graph; // Audio Unit synthesizer and output node AUNode synthNode; AUNode outNode; // Component description ComponentDescription cd; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; do { // New AU graph OSStatus status = NewAUGraph(&graph); if (status != noErr) { DisplayAlert(CFSTR("NewAUGraph"), CFSTR("Can't create a new AUGraph"), status); break; } // Synthesizer cd.componentType = kAudioUnitType_MusicDevice; cd.componentSubType = kAudioUnitSubType_DLSSynth; // New synthesizer node status = AUGraphNewNode(graph, &cd, 0, NULL, &synthNode); if (status != noErr) { DisplayAlert(CFSTR("AUGraphNewNode"), CFSTR("Can't create a new AUGraph node"), status); break; } // Output cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; // New output node status = AUGraphNewNode(graph, &cd, 0, NULL, &outNode); if (status != noErr) { DisplayAlert(CFSTR("AUGraphNewNode"), CFSTR("Can't create a new AUGraph node"), status); break; } // Open graph status = AUGraphOpen(graph); if (status != noErr) { DisplayAlert(CFSTR("AUGraphOpen"), CFSTR("Can't open AUGraph"), status); break; } // Connect synthesizer node to output node status = AUGraphConnectNodeInput(graph, synthNode, 0, outNode, 0); if (status != noErr) { DisplayAlert(CFSTR("AUGraphConnectNodeInput"), CFSTR("Can't connect AUGraph input node"), status); break; } // Get a synthesizer unit status = AUGraphGetNodeInfo(graph, synthNode, NULL, 0, NULL, &synthUnit); if (status != noErr) { DisplayAlert(CFSTR("AUGraphGetNodeInfo"), CFSTR("Can't get AUGraph node info"), status); break; } // Initialise status = AUGraphInitialize(graph); if (status != noErr) { DisplayAlert(CFSTR("AUGraphInitialize"), CFSTR("Can't initialize AUGraph"), status); break; } // Start status = AUGraphStart(graph); if (status != noErr) { DisplayAlert(CFSTR("AUGraphStart"), CFSTR("Can't start AUGraph"), status); break; } // Show the graph // CAShow(graph); } while (false); // Change instrument ChangeInstrument(instrument); // Run the application event loop RunApplicationEventLoop(); // Stop the graph AUGraphStop(graph); // Dispose of the graph DisposeAUGraph(graph); // Exit return 0; }
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; }
int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-t", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%ld", &numFrames); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; str2OSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; require_noerr (result = LoadSMF (filePath, sequence, loadFlags), fail); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; require_noerr (result = MusicSequenceGetAUGraph (sequence, &graph), fail); require_noerr (result = AUGraphOpen (graph), fail); require_noerr (result = GetSynthFromGraph (graph, theSynth), fail); require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad)), fail); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } require_noerr (result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0)), fail); } else { if (shouldSetBank) { FSRef soundBankRef; require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &soundBankRef, 0), fail); printf ("Setting Sound Bank:%s\n", bankPath); require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankFSRef, kAudioUnitScope_Global, 0, &soundBankRef, sizeof(soundBankRef)), fail); } if (diskStream) { UInt32 value = diskStream; require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } require_noerr (result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL)), fail); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } require_noerr (result = AUGraphInitialize (graph), fail); if (shouldPrint) CAShow (graph); } MusicPlayer player; require_noerr (result = NewMusicPlayer (&player), fail); require_noerr (result = MusicPlayerSetSequence (player, sequence), fail); // figure out sequence length UInt32 ntracks; require_noerr(MusicSequenceGetTrackCount (sequence, &ntracks), fail); MusicTimeStamp sequenceLength = 0; for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); require_noerr (result = MusicSequenceGetIndTrack(sequence, i, &track), fail); require_noerr (result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize), fail); if (trackLength > sequenceLength) sequenceLength = trackLength; } // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; require_noerr (result = MusicPlayerSetTime (player, startTime), fail); require_noerr (result = MusicPlayerPreroll (player), fail); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = AudioGetCurrentHostTime (); require_noerr (result = MusicPlayerStart (player), fail); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); require_noerr (result = MusicPlayerStop (player), fail); if (shouldPrint) printf ("finished playing\n"); // this shows you how you should dispose of everything require_noerr (result = DisposeMusicPlayer (player), fail); require_noerr (result = DisposeMusicSequence(sequence), fail); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { require_noerr (result = DisposeMusicSequence(sequence), fail); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", result); return result; }
void I_InitMusic (void) { #ifdef UNIX struct stat buf; if(stat("/etc/timidity.cfg", &buf) && stat("/etc/timidity/timidity.cfg", &buf)) Args.AppendArg("-nomusic"); #endif if(Args.CheckParm("-nomusic")) { Printf (PRINT_HIGH, "I_InitMusic: Music playback disabled\n"); return; } #ifdef OSX NewAUGraph(&graph); ComponentDescription d; d.componentType = kAudioUnitType_MusicDevice; d.componentSubType = kAudioUnitSubType_DLSSynth; d.componentManufacturer = kAudioUnitManufacturer_Apple; d.componentFlags = 0; d.componentFlagsMask = 0; AUGraphNewNode(graph, &d, 0, NULL, &synth); d.componentType = kAudioUnitType_Output; d.componentSubType = kAudioUnitSubType_DefaultOutput; d.componentManufacturer = kAudioUnitManufacturer_Apple; d.componentFlags = 0; d.componentFlagsMask = 0; AUGraphNewNode(graph, &d, 0, NULL, &output); if(AUGraphConnectNodeInput(graph, synth, 0, output, 0) != noErr) { Printf (PRINT_HIGH, "I_InitMusic: AUGraphConnectNodeInput failed\n"); return; } if(AUGraphOpen(graph) != noErr) { Printf (PRINT_HIGH, "I_InitMusic: AUGraphOpen failed\n"); return; } if(AUGraphInitialize(graph) != noErr) { Printf (PRINT_HIGH, "I_InitMusic: AUGraphInitialize failed\n"); return; } if(AUGraphGetNodeInfo(graph, output, NULL, NULL, NULL, &unit) != noErr) { Printf (PRINT_HIGH, "I_InitMusic: AUGraphGetNodeInfo failed\n"); return; } if(NewMusicPlayer(&player) != noErr) { Printf (PRINT_HIGH, "I_InitMusic: Music player creation failed using AudioToolbox\n"); return; } Printf (PRINT_HIGH, "I_InitMusic: Music playback enabled using AudioToolbox\n"); #else Printf (PRINT_HIGH, "I_InitMusic: Music playback enabled\n"); #endif music_initialized = true; }
/* 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",); *fileAU = anAU; CoreAudioChkError(AudioUnitSetProperty(*fileAU, kAudioUnitProperty_ScheduledFileIDs, kAudioUnitScope_Global, 0, &audioFile, sizeof(audioFile)), "SetScheduleFile",); CoreAudioChkError(AUGraphConnectNodeInput(*theGraph, fileNode, 0, outputNode, 0), "AUGraphConnectNodeInput",); CoreAudioChkError(AUGraphInitialize(*theGraph), "AUGraphInitialize",); } #elif HAVE_CANBERRA #include <canberra.h> #include <canberra-gtk.h> #endif const char *sound_description[NUM_SOUNDS] = { N_("Starting GNU Backgammon"), N_("Exiting GNU Backgammon"), N_("Agree"), N_("Doubling"), N_("Drop"), N_("Chequer movement"), N_("Move"),
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; } } }
JNIEXPORT jint JNICALL Java_com_apple_audio_toolbox_AUGraph_AUGraphInitialize (JNIEnv *, jclass, jint inGraph) { return (jint)AUGraphInitialize((AUGraph)inGraph); }
int main (int argc, const char * argv[]) { AUGraph graph = 0; AudioUnit synthUnit; OSStatus result; char* bankPath = 0; UInt8 midiChannelInUse = 0; //we're using midi channel 1... // this is the only option to main that we have... // just the full path of the sample bank... // On OS X there are known places were sample banks can be stored // Library/Audio/Sounds/Banks - so you could scan this directory and give the user options // about which sample bank to use... if (argc > 1) bankPath = const_cast<char*>(argv[1]); require_noerr (result = CreateAUGraph (graph, synthUnit), home); // if the user supplies a sound bank, we'll set that before we initialize and start playing if (bankPath) { FSSpec soundBankSpec; require_noerr (result = PathToFSSpec (bankPath, soundBankSpec), home); printf ("Setting Sound Bank:%s\n", bankPath); require_noerr (result = AudioUnitSetProperty (synthUnit, kMusicDeviceProperty_SoundBankFSSpec, kAudioUnitScope_Global, 0, &soundBankSpec, sizeof(soundBankSpec)), home); } // ok we're set up to go - initialize and start the graph require_noerr (result = AUGraphInitialize (graph), 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 (graph); // prints out the graph so we can see what it looks like... require_noerr (result = AUGraphStart (graph), home); // we're going to play an octave of MIDI notes: one a second for (int i = 0; i < 13; i++) { UInt32 noteNum = i + 60; UInt32 onVelocity = 127; UInt32 noteOnCommand = kMidiMessage_NoteOn << 4 | midiChannelInUse; printf ("Playing Note: Status: 0x%lX, Note: %ld, Vel: %ld\n", noteOnCommand, noteNum, onVelocity); require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, noteNum, onVelocity, 0), home); // sleep for a second usleep (1 * 1000 * 1000); require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, noteNum, 0, 0), home); } // ok we're done now home: if (graph) { AUGraphStop (graph); // stop playback - AUGraphDispose will do that for us but just showing you what to do DisposeAUGraph (graph); } return result; }
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"); }
bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, AudioDeviceID deviceId, bool allowMixing, AudioChannelLayoutTag layoutTag) { AudioStreamBasicDescription fmt = {0}; AudioStreamBasicDescription inputFormat = {0}; AudioStreamBasicDescription outputFormat = {0}; m_deviceId = deviceId; m_allowMixing = allowMixing; OSStatus ret = NewAUGraph(&m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error create audio grpah. Error = %s", GetError(ret).c_str()); return false; } ret = AUGraphOpen(m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error open audio grpah. Error = %s", GetError(ret).c_str()); return false; } // get output unit if (m_audioUnit) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error audio unit already open. double call ?"); return false; } m_audioUnit = new CAUOutputDevice(); if (!m_audioUnit->Open(m_audioGraph, kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple)) return false; m_audioUnit->SetBus(GetFreeBus()); m_audioUnit->GetFormatDesc(format, &inputFormat, &fmt); if (!m_audioUnit->EnableInputOuput()) return false; if (!m_audioUnit->SetCurrentDevice(deviceId)) return false; if (allowMixing) { delete m_mixMap; m_mixMap = CCoreAudioMixMap::CreateMixMap(m_audioUnit, format, layoutTag); if (m_mixMap || m_mixMap->IsValid()) { // maximum input channel ber input bus //fmt.mChannelsPerFrame = MAXIMUM_MIXER_CHANNELS; // get output unit if (m_inputUnit) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?"); return false; } m_inputUnit = new CAUOutputDevice(); if (!m_inputUnit->Open(m_audioGraph, kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple)) return false; if (!m_inputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus)) return false; if (!m_inputUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus)) return false; // get mixer unit if (m_mixerUnit) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?"); return false; } m_mixerUnit = new CAUMatrixMixer(); if (!m_mixerUnit->Open(m_audioGraph, kAudioUnitType_Mixer, kAudioUnitSubType_MatrixMixer, kAudioUnitManufacturer_Apple)) return false; // set number of input buses if (!m_mixerUnit->SetInputBusCount(MAX_CONNECTION_LIMIT)) return false; // set number of output buses if (!m_mixerUnit->SetOutputBusCount(1)) return false; if (!m_mixerUnit->SetInputBusFormat(MAX_CONNECTION_LIMIT, &fmt)) return false; if (!m_mixerUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus)) return false; ret = AUGraphConnectNodeInput(m_audioGraph, m_mixerUnit->GetNode(), 0, m_audioUnit->GetNode(), 0); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error connecting m_m_mixerNode. Error = %s", GetError(ret).c_str()); return false; } m_mixerUnit->SetBus(0); // configure output unit int busNumber = GetFreeBus(); ret = AUGraphConnectNodeInput(m_audioGraph, m_inputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error connecting m_converterNode. Error = %s", GetError(ret).c_str()); return false; } m_inputUnit->SetBus(busNumber); ret = AUGraphUpdate(m_audioGraph, NULL); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error update graph. Error = %s", GetError(ret).c_str()); return false; } ret = AUGraphInitialize(m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error initialize graph. Error = %s", GetError(ret).c_str()); return false; } // Update format structure to reflect the desired format from the mixer // The output format of the mixer is identical to the input format, except for the channel count fmt.mChannelsPerFrame = m_mixMap->GetOutputChannels(); UInt32 inputNumber = m_inputUnit->GetBus(); int channelOffset = GetMixerChannelOffset(inputNumber); if (!CCoreAudioMixMap::SetMixingMatrix(m_mixerUnit, m_mixMap, &inputFormat, &fmt, channelOffset)) return false; // Regenerate audio format and copy format for the Output AU outputFormat = fmt; } else { outputFormat = inputFormat; } } else { outputFormat = inputFormat; } if (!m_audioUnit->SetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus)) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error setting input format on audio device. Channel count %d, set it to %d", (int)outputFormat.mChannelsPerFrame, format.m_channelLayout.Count()); outputFormat.mChannelsPerFrame = format.m_channelLayout.Count(); if (!m_audioUnit->SetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus)) return false; } std::string formatString; // asume we are in dd-wave mode if (!m_inputUnit) { if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus)) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error setting Device Output Stream Format %s", StreamDescriptionToString(inputFormat, formatString)); } } ret = AUGraphUpdate(m_audioGraph, NULL); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error update graph. Error = %s", GetError(ret).c_str()); return false; } AudioStreamBasicDescription inputDesc_end, outputDesc_end; m_audioUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus); m_audioUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kInputBus); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString)); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString)); if (m_mixerUnit) { m_mixerUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus); m_mixerUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString)); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString)); } if (m_inputUnit) { m_inputUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus); m_inputUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString)); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString)); } ret = AUGraphInitialize(m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " "Error initialize graph. Error = %s", GetError(ret).c_str()); return false; } UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize(); if (!m_audioUnit->SetMaxFramesPerSlice(bufferFrames)) return false; SetInputSource(pSource); return Start(); }
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 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"); } }
/** * 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; }
bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing) { OSStatus ret; AudioStreamBasicDescription inputFormat; AudioStreamBasicDescription outputFormat; m_allowMixing = allowMixing; ret = NewAUGraph(&m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error create audio grpah. Error = %s", GetError(ret).c_str()); return false; } ret = AUGraphOpen(m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error open audio grpah. Error = %s", GetError(ret).c_str()); return false; } // get output unit if (m_audioUnit) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error audio unit already open. double call ?"); return false; } m_audioUnit = new CAUOutputDevice(); if (!m_audioUnit->Open(m_audioGraph, kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple)) return false; if (!m_audioUnit->EnableInputOuput()) return false; m_audioUnit->GetFormatDesc(format, &inputFormat); //if(!allowMixing) //{ if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus)) return false; if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus)) return false; //} if (allowMixing) { // get mixer unit if (m_mixerUnit) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?"); return false; } m_mixerUnit = new CAUMultiChannelMixer(); if (!m_mixerUnit->Open(m_audioGraph, kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer, kAudioUnitManufacturer_Apple)) return false; // set number of input buses if (!m_mixerUnit->SetInputBusCount(MAX_CONNECTION_LIMIT)) return false; //if(!m_mixerUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus)) // return false; m_mixerUnit->SetBus(0); if (!m_audioUnit->GetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus)) return false; /* if(!m_mixerUnit->SetInputBusFormat(MAX_CONNECTION_LIMIT, &outputFormat)) return false; */ ret = AUGraphConnectNodeInput(m_audioGraph, m_mixerUnit->GetNode(), 0, m_audioUnit->GetNode(), 0); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error connecting m_m_mixerNode. Error = %s", GetError(ret).c_str()); return false; } // get output unit if (m_inputUnit) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?"); return false; } m_inputUnit = new CAUOutputDevice(); if (!m_inputUnit->Open(m_audioGraph, kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple)) return false; if (!m_inputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus)) return false; /* if(!m_inputUnit->SetFormat(&outputFormat, kAudioUnitScope_Output, kOutputBus)) return false; */ // configure output unit int busNumber = GetFreeBus(); ret = AUGraphConnectNodeInput(m_audioGraph, m_inputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error connecting m_converterNode. Error = %s", GetError(ret).c_str()); return false; } m_inputUnit->SetBus(busNumber); ret = AUGraphUpdate(m_audioGraph, NULL); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error update graph. Error = %s", GetError(ret).c_str()); return false; } ret = AUGraphInitialize(m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error initialize graph. Error = %s", GetError(ret).c_str()); return false; } // Regenerate audio format and copy format for the Output AU } ret = AUGraphUpdate(m_audioGraph, NULL); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error update graph. Error = %s", GetError(ret).c_str()); return false; } std::string formatString; AudioStreamBasicDescription inputDesc_end, outputDesc_end; m_audioUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus); m_audioUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kInputBus); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString)); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString)); if (m_mixerUnit) { m_mixerUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus); m_mixerUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString)); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString)); } if (m_inputUnit) { m_inputUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus); m_inputUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString)); CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString)); } ret = AUGraphInitialize(m_audioGraph); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error initialize graph. Error = %s", GetError(ret).c_str()); return false; } UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize(); m_audioUnit->SetMaxFramesPerSlice(bufferFrames); if (m_inputUnit) m_inputUnit->SetMaxFramesPerSlice(bufferFrames); SetInputSource(pSource); ShowGraph(); return Start(); }
int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; std::set<int> trackSet; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-s", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp ("-t", argv[i])) { int index; if (++i == argc) goto malformedInput; sscanf (argv[i], "%d", &index); trackSet.insert(--index); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%lu", (unsigned long*)(&numFrames)); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; StrToOSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; FailIf ((result = LoadSMF (filePath, sequence, loadFlags)), fail, "LoadSMF"); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; FailIf ((result = MusicSequenceGetAUGraph (sequence, &graph)), fail, "MusicSequenceGetAUGraph"); FailIf ((result = AUGraphOpen (graph)), fail, "AUGraphOpen"); FailIf ((result = GetSynthFromGraph (graph, theSynth)), fail, "GetSynthFromGraph"); FailIf ((result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad))), fail, "AudioUnitSetProperty: kAudioUnitProperty_CPULoad"); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } FailIf ((result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0))), fail, "MusicSequenceSetMIDIEndpoint"); } else { if (shouldSetBank) { CFURLRef soundBankURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)bankPath, strlen(bankPath), false); printf ("Setting Sound Bank:%s\n", bankPath); result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global, 0, &soundBankURL, sizeof(soundBankURL)); if (soundBankURL) CFRelease(soundBankURL); FailIf (result, fail, "AudioUnitSetProperty: kMusicDeviceProperty_SoundBankURL"); } if (diskStream) { UInt32 value = diskStream; FailIf ((result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value))), fail, "AudioUnitSetProperty: kMusicDeviceProperty_StreamFromDisk"); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; FailIf ((result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value))), fail, "AudioUnitSetProperty: kAudioUnitProperty_OfflineRender"); } FailIf ((result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL))), fail, "SetUpGraph"); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } FailIf ((result = AUGraphInitialize (graph)), fail, "AUGraphInitialize"); if (shouldPrint) CAShow (graph); } MusicPlayer player; FailIf ((result = NewMusicPlayer (&player)), fail, "NewMusicPlayer"); FailIf ((result = MusicPlayerSetSequence (player, sequence)), fail, "MusicPlayerSetSequence"); // figure out sequence length UInt32 ntracks; FailIf ((MusicSequenceGetTrackCount (sequence, &ntracks)), fail, "MusicSequenceGetTrackCount"); MusicTimeStamp sequenceLength = 0; bool shouldPrintTracks = shouldPrint && !trackSet.empty(); if (shouldPrintTracks) printf ("Only playing specified tracks:\n\t"); for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); FailIf ((result = MusicSequenceGetIndTrack(sequence, i, &track)), fail, "MusicSequenceGetIndTrack"); FailIf ((result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize)), fail, "MusicTrackGetProperty: kSequenceTrackProperty_TrackLength"); if (trackLength > sequenceLength) sequenceLength = trackLength; if (!trackSet.empty() && (trackSet.find(i) == trackSet.end())) { Boolean mute = true; FailIf ((result = MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mute, sizeof(mute))), fail, "MusicTrackSetProperty: kSequenceTrackProperty_MuteStatus"); } else if (shouldPrintTracks) { printf ("%d, ", int(i+1)); } } if (shouldPrintTracks) printf ("\n"); // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; FailIf ((result = MusicPlayerSetTime (player, startTime)), fail, "MusicPlayerSetTime"); FailIf ((result = MusicPlayerPreroll (player)), fail, "MusicPlayerPreroll"); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = CAHostTimeBase::GetTheCurrentTime(); /* if (waitAtEnd && graph) AUGraphStart(graph); */ FailIf ((result = MusicPlayerStart (player)), fail, "MusicPlayerStart"); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); FailIf ((result = MusicPlayerStop (player)), fail, "MusicPlayerStop"); if (shouldPrint) printf ("finished playing\n"); /* if (waitAtEnd) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); if (graph) AUGraphStop(graph); if (shouldPrint) printf ("disposing\n"); } */ // this shows you how you should dispose of everything FailIf ((result = DisposeMusicPlayer (player)), fail, "DisposeMusicPlayer"); FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence"); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence"); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", (long)result); return result; }
/** * Starts playing a new song. * * @param filename Path to a MIDI file. */ void MusicDriver_Cocoa::PlaySong(const char *filename) { DEBUG(driver, 2, "cocoa_m: trying to play '%s'", filename); this->StopSong(); if (_sequence != NULL) { DisposeMusicSequence(_sequence); _sequence = NULL; } if (NewMusicSequence(&_sequence) != noErr) { DEBUG(driver, 0, "cocoa_m: Failed to create music sequence"); return; } const char *os_file = OTTD2FS(filename); CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file, strlen(os_file), false); #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (MacOSVersionIsAtLeast(10, 5, 0)) { if (MusicSequenceFileLoad(_sequence, url, 0, 0) != noErr) { DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file"); CFRelease(url); return; } } else #endif { #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) FSRef ref_file; if (!CFURLGetFSRef(url, &ref_file)) { DEBUG(driver, 0, "cocoa_m: Failed to make FSRef"); CFRelease(url); return; } if (MusicSequenceLoadSMFWithFlags(_sequence, &ref_file, 0) != noErr) { DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file old style"); CFRelease(url); return; } #endif } CFRelease(url); /* Construct audio graph */ AUGraph graph = NULL; MusicSequenceGetAUGraph(_sequence, &graph); AUGraphOpen(graph); if (AUGraphInitialize(graph) != noErr) { DEBUG(driver, 0, "cocoa_m: Failed to initialize AU graph"); return; } /* Figure out sequence length */ UInt32 num_tracks; MusicSequenceGetTrackCount(_sequence, &num_tracks); _seq_length = 0; for (UInt32 i = 0; i < num_tracks; i++) { MusicTrack track = NULL; MusicTimeStamp track_length = 0; UInt32 prop_size = sizeof(MusicTimeStamp); MusicSequenceGetIndTrack(_sequence, i, &track); MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &track_length, &prop_size); if (track_length > _seq_length) _seq_length = track_length; } /* Add 8 beats for reverb/long note release */ _seq_length += 8; DoSetVolume(); MusicPlayerSetSequence(_player, _sequence); MusicPlayerPreroll(_player); if (MusicPlayerStart(_player) != noErr) return; _playing = true; DEBUG(driver, 3, "cocoa_m: playing '%s'", filename); }
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; }