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;	
}
Exemple #2
0
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;
}
Exemple #3
0
        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;
}
Exemple #5
0
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);
}
Exemple #6
0
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);
}
Exemple #7
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;
}
Exemple #8
0
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;
}
Exemple #9
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
    /* 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"),
Exemple #13
0
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);
}
Exemple #15
0
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");
}
Exemple #17
0
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;
}
Exemple #21
0
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();
}
Exemple #22
0
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;
}