1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
   | //
//  Music.cpp
//  test26
//
//  Created by Lion User on 14/03/13.
//  Copyright (c) 2013 Lion User. All rights reserved.
//
 
 
#ifdef _cplusplus
#include "Music.h"
#include <CoreServices/CoreServices.h> //for file stuff
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h> //for AUGraph
#include <unistd.h> // used for usleep...
 
// This call creates the Graph and the Synth unit...
OSStatus	CreateAUGraph (AUGraph &outGraph, AudioUnit &outSynth)
{
	OSStatus result;
	//create the nodes of the graph
	AUNode synthNode, limiterNode, outNode;
 
	AudioComponentDescription cd;
	cd.componentManufacturer = kAudioUnitManufacturer_Apple;
	cd.componentFlags = 0;
	cd.componentFlagsMask = 0;
 
	require_noerr (result = NewAUGraph (&outGraph), home);
 
	cd.componentType = kAudioUnitType_MusicDevice;
	cd.componentSubType = kAudioUnitSubType_DLSSynth;
 
	require_noerr (result = AUGraphAddNode (outGraph, &cd, &synthNode), home);
 
	cd.componentType = kAudioUnitType_Effect;
	cd.componentSubType = kAudioUnitSubType_PeakLimiter;
 
	require_noerr (result = AUGraphAddNode (outGraph, &cd, &limiterNode), home);
 
	cd.componentType = kAudioUnitType_Output;
	cd.componentSubType = kAudioUnitSubType_DefaultOutput;
	require_noerr (result = AUGraphAddNode (outGraph, &cd, &outNode), home);
 
	require_noerr (result = AUGraphOpen (outGraph), home);
 
	require_noerr (result = AUGraphConnectNodeInput (outGraph, synthNode, 0, limiterNode, 0), home);
	require_noerr (result = AUGraphConnectNodeInput (outGraph, limiterNode, 0, outNode, 0), home);
 
	// ok we're good to go - get the Synth Unit...
	require_noerr (result = AUGraphNodeInfo(outGraph, synthNode, 0, &outSynth), home);
 
home:
	return result;
}
 
// some MIDI constants:
enum {
	kMidiMessage_ControlChange 		= 0xB,
	kMidiMessage_ProgramChange 		= 0xC,
	kMidiMessage_BankMSBControl 	= 0,
	kMidiMessage_BankLSBControl		= 32,
	kMidiMessage_NoteOn 			= 0x9
};
 
 
int test() {
 
	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)
	{
		FSRef fsRef;
		require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &fsRef, 0), home);
 
		printf ("Setting Sound Bank:%s\n", bankPath);
 
		require_noerr (result = AudioUnitSetProperty (synthUnit,
                                                      kMusicDeviceProperty_SoundBankFSRef,
                                                      kAudioUnitScope_Global, 0,
                                                      &fsRef, sizeof(fsRef)), 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 < 4; i++) {
		//UInt32 noteNum = i + 60;
		UInt32 onVelocity = 127;
		UInt32 noteOnCommand = 	kMidiMessage_NoteOn << 4 | midiChannelInUse;
 
		require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, 60, onVelocity, 0), home);
        require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, 65, onVelocity, 0), home);
        require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, 68, onVelocity, 0), home);
 
        // sleep for a second
		usleep (1 * 1000 * 1000);
 
		require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, 60, 0, 0), home);
        require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, 65, 0, 0), home);
        require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, 68, 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;
 
}
#endif |