connection method: like web audio nodes, scenegraph hierarchy implicitly connects nodes -- Benefit: source nodes can run in their own thread and each note has fine granularity timestamp routing method: source nodes convert to route fields and destination nodes take route fields -- Benefit: simpler implementation -- routes are processed once per frame, and notes would have frame time stamp granulariy Node design choice: connection method, with utility processing nodes converting to/from routes Source and destination nodes: midi messages are routed directly by implicit connections like web audio nodes by scenegraph MidiDestination (MIDIPortDestination, MIDIFileDestination, MIDIOut) MidiSource (MIDIPortSource, MIDIFileSource, MIDIIn) Processing nodes are routed to/from MIDIIn, MIDIOut (MIDIToneSplitter, MIDIToneMerger, MIDIConverterOut, MIDIConverterIn) source node: stop, start, pause, resume, rewind, loop realtime source node: stop, start. Has no loop or rewind, stop and pause do same thing, start and resume do same thing, no content is buffered/saved when paused/stopped Nodes needed for MIDI Level 1: MIDIPortSource : MIDISourceNode { SFInt32 [in,out] port 0 } MIDIFileSource : MIDISourceNode { MFString [in,out] url [] } MIDIPortDestination : MIDIDestinationNode { SFInt32 [in/out] port 0 MFNode [in,out] children NULL } MIDIFileDestination : MIDIDestinationNode { SFString [in/out] url [] MFNode [in,out] children NULL } MIDIPrintDestination : MIDIDestinationNode { MFNode [in,out] children NULL } Level 2: MIDIOut : MIDIDestinationNode { MFInt32 [out] midiMsg MFDouble [out] midiUmp MFNode [in,out] children NULL } MIDIIn : MIDISourceNode { MFInt32 [in] midiMsg MFDouble [in] midiUmp } MidiToneSplitter : X3DMIDINode { SFInt32 [in,out] octaveFilter -1 SFInt32 [in,out] channelFilter -1 MFInt32 [in] midiMsg MFDouble [in] midiUmp SFBool [out] C SFBool [out] Cs SFBool [out] D SFBool [out] Ds SFBool [out] E SFBool [out] F SFBool [out] Fs SFBool [out] G SFBool [out] Gs SFBool [out] A SFBool [out] As SFBool [out] B SFBool [out] pedal } MIDIToneMerger : X3DMIDINode { SFInt32 [in,out] octave 5 SFInt32 [in,out] channel 1 SFBool [in] C SFBool [in] Cs SFBool [in] D SFBool [in] Ds SFBool [in] E SFBool [in] F SFBool [in] Fs SFBool [in] G SFBool [in] Gs SFBool [in] A SFBool [in] As SFBool [in] B SFBool [in] pedal MFInt32 [out] midiMsg MFDouble [out] midiUmp } Level 3: MIDIProgram : X3DMIDINode { SFInt32 [in,out] instrument 1 } MIDIDelay : X3DMIDINode { SFTime [in,out] delay 0.0 } MIDIConverterOut : X3DMIDINode { MFInt32 [out] octave MFInt32 [out] key12 MFInt32 [out] key88 MFInt32 [out] keyPiano MFInt32 [out] pedal MFInt32 [in] midiMsg MFDouble [in] midiUmp } MIDIConverterIn : X3DMIDINode { MFInt32 [in,out] octave 5 MFInt32 [in,out] channel 1 MFInt32 [in] key12 MFInt32 [in] key88 MFInt32 [in] keyPiano MFInt32 [in] pedal MFInt32 [out] midiMsg MFDouble [out] midiUmp } MIDIAudioSynth : X3DMIDIProcessingNode, X3DAudioSourceNode { SFInt32 [in/out] polyphony 10 }