Re: multiple track synthesizer problem
Re: multiple track synthesizer problem
- Subject: Re: multiple track synthesizer problem
- From: Zak Stone <email@hidden>
- Date: Mon, 30 Dec 2002 12:09:01 -1000
Thanks for the help! I've implemented multiple synth tracks in a
modified version of AUViewTest, but the sound the program produces
isn't correct. The program should load a custom SoundFont and play
three pairs of simultaneous notes, where each pair has one note on
instrument 1 and the other on instrument 2. The code below loads the
custom SoundFont from an FSSpec without a problem, but the first pair
of notes plays staggered incorrectly (though with each note on a
different instrument as desired). The notes in the second two pairs
play simultaneously, but both incorrectly use sounds from instrument 2.
I don't think the custom SoundFont is causing a problem, though,
because I've implemented the same idea using separate MIDI channels in
a single track and the notes always play simultaneously on the correct
instruments. What's going wrong in this multiple track implementation?
These are the relevant functions I've changed in AUViewTest:
void AUViewTest::BuildGraph()
{
RequireNoErr(NewAUGraph(&mGraph));
// Two DLS synths -> mixer -> output
AUNode synthNode, synthNode2, mixerNode, outputNode;
ComponentDescription desc;
// create nodes
desc.componentType = kAudioUnitComponentType;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
// DLS MusicDevice
desc.componentSubType = kAudioUnitSubType_MusicDevice;
desc.componentManufacturer = kAudioUnitID_DLSSynth;
RequireNoErr(AUGraphNewNode(mGraph, &desc, 0, NULL, &synthNode));
RequireNoErr(AUGraphNewNode(mGraph, &desc, 0, NULL, &synthNode2));
//mixer
desc.componentSubType = kAudioUnitSubType_Mixer;
desc.componentManufacturer = kAudioUnitID_StereoMixer;
RequireNoErr(AUGraphNewNode(mGraph, &desc, 0, NULL,
&mixerNode));
// default output unit
desc.componentSubType = kAudioUnitSubType_Output;
desc.componentManufacturer = kAudioUnitID_DefaultOutput;
RequireNoErr(AUGraphNewNode(mGraph, &desc, 0, NULL, &outputNode));
// connect nodes, using synth output 1 since reverb will occupy output
0 below
RequireNoErr(AUGraphConnectNodeInput(mGraph, synthNode, 1, mixerNode,
0 ));
RequireNoErr(AUGraphConnectNodeInput(mGraph, synthNode2, 1,
mixerNode, 1 ));
RequireNoErr(AUGraphConnectNodeInput(mGraph, mixerNode, 0,
outputNode, 0 ));
RequireNoErr(AUGraphOpen(mGraph));
RequireNoErr(AUGraphInitialize(mGraph));
AudioUnit theSynth, theSynth2, theMixer, theOutput;
RequireNoErr(AUGraphGetNodeInfo(mGraph, synthNode, NULL, NULL, NULL,
&theSynth));
RequireNoErr(AUGraphGetNodeInfo(mGraph, synthNode2, NULL, NULL,
NULL, &theSynth2));
RequireNoErr(AUGraphGetNodeInfo(mGraph, mixerNode, NULL, NULL,
NULL, &theMixer));
RequireNoErr(AUGraphGetNodeInfo(mGraph, outputNode, NULL, NULL, NULL,
&theOutput));
mSynth = theSynth;
mSynthNode = synthNode;
mSynthNode2 = synthNode2;
mMixerNode = mixerNode;
UInt32 reverb = 0;
// set both synth units to my custom soundbank
AudioUnitSetProperty(theSynth,
kMusicDeviceProperty_SoundBankFSSpec,
kAudioUnitScope_Global, 0, &fss, sizeof(FSSpec));
AudioUnitSetProperty(theSynth2,
kMusicDeviceProperty_SoundBankFSSpec,
kAudioUnitScope_Global, 0, &fss, sizeof(FSSpec));
// turn off internal reverb
AudioUnitSetProperty(theSynth,
kMusicDeviceProperty_UsesInternalReverb,
kAudioUnitScope_Global, 0, &reverb, sizeof(UInt32));
AudioUnitSetProperty(theSynth2,
kMusicDeviceProperty_UsesInternalReverb,
kAudioUnitScope_Global, 0, &reverb, sizeof(UInt32));
RequireNoErr(AUGraphStart(mGraph));
}
void AUViewTest::BuildSequence()
{
MusicSequence sequence;
MusicTrack instr1, instr2, tempoTrack;
MusicPlayer player;
Float64 beatsPerMinute = 80;
RequireNoErr(NewMusicSequence(&sequence));
RequireNoErr(MusicSequenceGetTempoTrack(sequence, &tempoTrack));
RequireNoErr(MusicTrackNewExtendedTempoEvent(tempoTrack, 0,
beatsPerMinute));
RequireNoErr(MusicSequenceNewTrack(sequence, &instr1));
RequireNoErr(MusicSequenceNewTrack(sequence, &instr2));
MusicTimeStamp t = 0;
MIDIChannelMessage chmsg;
// change to instrument index 0 (in my custom SoundFont)
chmsg.status = 0xC0;
chmsg.data1 = 0;
chmsg.data2 = 0;
chmsg.reserved = 0;
RequireNoErr(MusicTrackNewMIDIChannelEvent(instr1, t, &chmsg));
// change to instrument index 2
chmsg.status = 0xC0;
chmsg.data1 = 2;
chmsg.data2 = 0;
chmsg.reserved = 0;
RequireNoErr(MusicTrackNewMIDIChannelEvent(instr2, t, &chmsg));
float kDuration = 2.0, kInterval = 2.5;
int root = 60;
MIDINoteMessage msg;
msg.channel = 0;
msg.velocity = 96;
msg.reserved = 0;
msg.duration = kDuration;
msg.note = root;
RequireNoErr(MusicTrackNewMIDINoteEvent(instr1, t, &msg));
// sorry for the discordance, but I wanted to make sure all
notes were playing
msg.note = root + 2;
RequireNoErr(MusicTrackNewMIDINoteEvent(instr2, t, &msg));
t += kInterval;
msg.note = root + 3;
RequireNoErr(MusicTrackNewMIDINoteEvent(instr1, t, &msg));
msg.note = root + 5;
RequireNoErr(MusicTrackNewMIDINoteEvent(instr2, t, &msg));
t += kInterval;
msg.note = root;
RequireNoErr(MusicTrackNewMIDINoteEvent(instr1, t, &msg));
msg.note = root + 2;
RequireNoErr(MusicTrackNewMIDINoteEvent(instr2, t, &msg));
RequireNoErr(MusicSequenceSetAUGraph(sequence, mGraph));
RequireNoErr(MusicTrackSetDestNode(instr1, mSynthNode));
RequireNoErr(MusicTrackSetDestNode(instr2, mSynthNode2));
RequireNoErr(NewMusicPlayer(&player));
RequireNoErr(MusicPlayerSetSequence(player, sequence));
RequireNoErr(MusicPlayerPreroll(player));
RequireNoErr(MusicPlayerStart(player));
}
On Monday, December 30, 2002, at 07:50 AM, Christopher Corbell wrote:
On Sunday, December 29, 2002, at 01:07 AM, Zak Stone wrote:
Hello,
I want to connect several MusicTracks to a DLSSynth AUNode. Is that
possible, or do I have to make a synth node for every track, connect
all of the synth nodes to a mixer, and connect the mixer to the
output? If so, how does one actually connect multiple nodes to the
mixer?
Thanks,
Zak Stone
When you add a music track to a MusicSequence and use the MusicPlayer
API's, the tracks are automatically
attached to a default MusicDevice (DLSSynth). If you want to use
multiple music devices for different tracks,
you have to manage their creation in the AUGraph yourself,
re-associate the tracks with each device's node,
and connect the MusicDevice nodes to a mixer using the AUGraph APIs.
Connecting music devices to channels in a mixer is straightforward
using AUGraphConnectNodeInput().
The parameters to this call for a music device node and a stereo mixer
node would be
AUGraphConnectNodeInput( theGraph, dlsNode, 0, mixerNode,
trackIndex);
One more tip learned from help others provided in past postings: turn
off the internal-reverb
for each of your multiple MusicDevice objects or you'll max-out CPU
usage.
Example to check out:
CoreAudio/Services/AUViewTest (esp. AUViewTest::BuildGraph() and
AUViewTest::BuildSequence())
Hope this helps,
Christopher
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.