• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: multiple track synthesizer problem
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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.

References: 
 >Re: multiple track synthesizer problem (From: Christopher Corbell <email@hidden>)

  • Prev by Date: AudioStream format problem
  • Next by Date: Intro and ?
  • Previous by thread: Re: multiple track synthesizer problem
  • Next by thread: [slightly OT] Emagic EMI 2|6 driver doesn't work in 10.2.3?
  • Index(es):
    • Date
    • Thread