I am making a music app where you can add new instruments to an existing sequencer. These instruments are separate AudioUnitSamplers stored in an array so when a new instrument and track is loaded, It is to load the sound which that track is going to use.
This how I currently add a track to the AUGraph.
// Return count as an id for the new track
- (int) addMusicTrack: (MusicTrack)musicTrack withNode:(AUNode)newSamplerNode withAudioUnit:(AudioUnit)newSamplerUnit {
tracksCount++;
int trackId = tracksCount;
MusicPlayerStop(_musicPlayer);
status = MusicSequenceNewTrack(sequence, &tracks[trackId]);
MusicSequenceSetAUGraph(sequence, graph);
if(status){
printf("Error adding main track: %d", (int)status);
status = 0;
}
timeDiff = 32.f/_tempo;
[self setLoopDuration:DEFAULT_LOOP_DURATION forTrack:trackId];
currentOctaveNumber = 59;
AudioComponentDescription samplerNodeDesc;
samplerNodeDesc.componentManufacturer = (OSType)kAudioUnitManufacturer_Apple;
samplerNodeDesc.componentType = (OSType)kAudioUnitType_MusicDevice;
samplerNodeDesc.componentSubType = (OSType)kAudioUnitSubType_Sampler;
samplerNodeDesc.componentFlags = 0;
samplerNodeDesc.componentFlagsMask = 0;
status = AUGraphAddNode(graph, &samplerNodeDesc, &auSampleNodes[trackId]);
AudioComponentDescription splitterNodeDesc;
splitterNodeDesc.componentManufacturer = (OSType)kAudioUnitManufacturer_Apple;
splitterNodeDesc.componentType = (OSType)kAudioUnitType_FormatConverter;
splitterNodeDesc.componentSubType = (OSType)kAudioUnitSubType_Splitter;
splitterNodeDesc.componentFlags = 0;
splitterNodeDesc.componentFlagsMask = 0;
status = AUGraphAddNode(graph, &splitterNodeDesc, &splitterNodes[trackId]);
// node info
status = AUGraphNodeInfo(graph, auSampleNodes[trackId], 0, &auSampleUnits[trackId]);
status = AUGraphNodeInfo(graph, splitterNodes[trackId], 0, &splitterUnits[trackId]);
// connecting nodes samplernode ==> Splitter ==> Mixer
status = AUGraphConnectNodeInput(graph, auSampleNodes[trackId], 0, splitterNodes[trackId], 0);
status = AUGraphConnectNodeInput(graph, splitterNodes[trackId], 0, mixerNode, trackId);
status = MusicTrackSetDestNode(tracks[trackId], auSampleNodes[trackId]);
status = AUGraphUpdate(graph, NULL);
if (status) {printf("Error updating graph: %ld\n", status);}
MusicPlayerStart(_musicPlayer);
return trackId;
}
And this is how I load the sound for that track:
[self samplerUnit:auSampleUnits[trackId] loadFromDLSOrSoundFont:url withPatch:patchNumber];
soundfont Loading:
- (OSStatus)samplerUnit:(AudioUnit)sampler loadFromDLSOrSoundFont:(NSURL *)bankURL withPatch:(int)presetNumber{
OSStatus result = noErr;
// Fill out the sampler instrument data structure
AUSamplerInstrumentData insdata;
insdata.fileURL = (__bridge CFURLRef) bankURL;
insdata.bankMSB = kAUSampler_DefaultMelodicBankMSB;
insdata.bankLSB = (UInt8)0;
insdata.presetID = (UInt8) presetNumber;
insdata.instrumentType = kInstrumentType_DLSPreset; // DLS and SF2 are the same enum values
// Load the instrument
result = AudioUnitSetProperty(sampler,
kAUSamplerProperty_LoadInstrument,
kAudioUnitScope_Global,
0,
&insdata,
sizeof(insdata));
NSCAssert (result == noErr,
@"Unable to set the preset property on the Sampler. Error code: %d",
(int) result);
return result;
}
So currently, the appropriate sound is loaded for the track that was recently added but the sound for the older tracks is now the default AudioUnitSampler sine wave sound.
I have been trying to fix this for about a day now but haven't found a way around it, any solutions out there?
Cheers !!!
Did you compare trackCount with
MusicSequenceGetTrackCount
?Look at the docs for
MusicSequenceSetAUGraph
. "By default, all music tracks in the sequence are directed to the first node in the graph that is an Instrument unit (of type DLSMusicDevice"What do you want the splitter to do? It's not doing much right now.