2 classvar defaultParentEvent;
3 classvar <parentEvents;
4 classvar <partialEvents;
6 *new { arg n=8, proto, parent, know=true;
7 ^super.new(n, proto, parent, know)
11 ^Event.new(8, nil, defaultParentEvent, true);
13 *silent { |dur(1.0), inEvent|
14 if(inEvent.isNil) { inEvent = Event.new }
15 { inEvent = inEvent.copy };
16 inEvent.put(\isRest, true).put(\dur, dur).put(\parent, defaultParentEvent)
17 .put(\delta, dur * (inEvent[\stretch] ? 1));
20 *addEventType { arg type, func;
21 var types = partialEvents.playerEvent.eventTypes;
25 next { arg inval; ^composeEvents(inval, this) }
29 ^this.primitiveFailed;
31 // implemented by primitive for speed
33 delta = this.at('delta');
34 if (delta.notNil, { ^delta },{ ^this.at('dur') * this.at('stretch') });
39 parent = defaultParentEvent;
47 // this[\isRest] may be nil
49 ^this[\isRest] == true
50 or: { this[\type] == \rest
53 parent ?? { parent = defaultParentEvent };
54 ~detunedFreq.value.isRest
60 // node watcher interface
63 this.put(\isPlaying, val);
67 this.put(\isRunning, val);
70 // this method is called by EventStreamPlayer so it can schedule Routines as well
71 playAndDelta { | cleanup, mute |
72 if (mute) { this.put(\type, \rest) };
78 // A Quant specifies the quant and phase at which a TempoClock starts an EventStreamPlayer
79 // Its offset specifies how far ahead of time events are actually computed by the EventStream.
80 // offset allows ~strum to be negative, so strummed chords complete on the beat
81 // it also makes it possible for one pattern to run a little ahead of another to set values
82 // This method keeps ~timingOffset and Quant.offset the same.
84 synchWithQuant { | quant |
85 if(quant.timingOffset.notNil) {
86 ^this.copy.put(\timingOffset, quant.timingOffset)
88 quant.timingOffset = this[\timingOffset];
93 // This enables events to represent the server resources they created in an Event
94 // So, ~bufnum = (type: \sine1, amps: 1/(1..10)) is possible
96 ^this[ EventTypesWithCleanup.ugenInputTypes[this[\type] ] ] ;
98 asUGenInput { ^this.asControlInput }
100 printOn { arg stream, itemsPerLine = 5;
101 var max, itemsPerLinem1, i=0;
102 itemsPerLinem1 = itemsPerLine - 1;
105 this.keysValuesDo({ arg key, val;
106 stream <<< key << ": " << val;
107 if ((i=i+1) < max, { stream.comma.space;
108 if (i % itemsPerLine == itemsPerLinem1, { stream.nl.space.space });
114 storeOn { arg stream, itemsPerLine = 5;
115 var max, itemsPerLinem1, i=0;
116 itemsPerLinem1 = itemsPerLine - 1;
119 this.keysValuesDo({ arg key, val;
120 stream <<< key << ": " <<< val;
121 if ((i=i+1) < max, { stream.comma.space;
122 if (i % itemsPerLine == itemsPerLinem1, { stream.nl.space.space });
129 Class.initClassTree(Server);
130 Class.initClassTree(TempoClock);
131 this.makeParentEvents;
134 Event.makeDefaultSynthDef;
138 *makeDefaultSynthDef {
139 SynthDef(\default, { arg out=0, freq=440, amp=0.1, pan=0, gate=1;
142 Mix.new(VarSaw.ar(freq + [0, Rand(-0.4,0.0), Rand(0.0,0.4)], 0, 0.3, 0.3)),
143 XLine.kr(Rand(4000,5000), Rand(2500,3200), 1)
144 ) * Linen.kr(gate, 0.01, 0.7, 0.3, 2);
145 OffsetOut.ar(out, Pan2.ar(z, pan, amp));
150 // define useful event subsets.
158 root: 0.0, // root of the scale
160 scale: #[0, 2, 4, 5, 7, 9, 11], // diatonic major scale
161 stepsPerOctave: 12.0,
162 detune: 0.0, // detune in Hertz
163 harmonic: 1.0, // harmonic ratio
167 (~degree + ~mtranspose).degreeToKey(
169 ~scale.respondsTo(\stepsPerOctave).if(
170 { ~scale.stepsPerOctave },
176 (((~note.value + ~gtranspose + ~root) /
177 ~scale.respondsTo(\stepsPerOctave).if(
178 { ~scale.stepsPerOctave },
179 ~stepsPerOctave) + ~octave - 5.0) *
180 (12.0 * ~scale.respondsTo(\octaveRatio).if
181 ({ ~scale.octaveRatio }, ~octaveRatio).log2) + 60.0);
184 ~freq.value + ~detune
187 (~midinote.value + ~ctranspose).midicps * ~harmonic;
189 freqToNote: #{ arg self, freq; // conversion from frequency to note value
192 var steps = ~scale.respondsTo(\stepsPerOctave).if(
193 { ~scale.stepsPerOctave }, ~stepsPerOctave
195 midinote = cpsmidi((freq / ~harmonic) - ~ctranspose);
196 midinote / 12.0 - ~octave * steps - ~root - ~gtranspose
199 freqToScale: #{ arg self, freq;
200 // conversion from frequency to scale value.
202 var steps = ~scale.respondsTo(\stepsPerOctave).if(
203 { ~scale.stepsPerOctave }, ~stepsPerOctave
205 var degree = self.freqToNote(freq).keyToDegree(~scale, steps)
207 degree.asArray.collect {|x, i|
210 "could not translate: %\n".postf(freq[i]);
223 sustain: #{ ~dur * ~legato * ~stretch },
226 strumEndsTogether: false
232 velocity: 64, // MIDI units 0-127
233 pan: 0.0, // pan center
246 instrument: \default,
249 // this function should return a msgFunc: a Function that
250 // assembles a synth control list from event values
252 getMsgFunc: { |instrument|
253 var synthLib, synthDesc, desc;
254 // if user specifies a msgFunc, prefer user's choice
256 instrument = ~instrument = instrument.asSymbol;
257 synthLib = ~synthLib ?? { SynthDescLib.global };
258 synthDesc = desc = synthLib.at(instrument);
260 ~hasGate = desc.hasGate;
261 ~msgFunc = desc.msgFunc;
263 ~msgFunc = ~defaultMsgFunc;
267 synthDefName: { |instrument, variant, synthDesc|
268 // allow `nil to cancel a variant in a pattern
269 variant = variant.dereference;
270 if(variant.notNil and: { synthDesc.notNil and: { synthDesc.hasVariants } })
271 { (instrument ++ "." ++ variant).asSymbol }
272 { instrument.asSymbol };
275 getBundleArgs: { |instrument|
276 ~getMsgFunc.valueEnvir(instrument).valueEnvir;
279 hasGate: true, // assume SynthDef has gate
280 sendGate: nil, // false => event does not specify note release
282 defaultMsgFunc: #{|freq = 440, amp = 0.1, pan = 0, out = 0|
283 [\freq, freq, \amp, amp, \pan, pan, \out, out] },
286 args: #[\freq, \amp, \pan, \trig],
290 // it is more efficient to directly use schedBundleArrayOnClock
291 // we keep these for compatibility.
293 schedBundle: #{ |lag, offset, server ... bundle |
294 schedBundleArrayOnClock(offset, thisThread.clock, bundle, lag, server);
297 schedBundleArray: #{ | lag, offset, server, bundleArray, latency |
298 schedBundleArrayOnClock(offset, thisThread.clock, bundleArray, lag, server, latency);
301 schedStrummedNote: {| lag, strumTime, sustain, server, msg, sendGate |
302 var dur, schedBundle = ~schedBundle;
303 schedBundle.value(lag, strumTime + ~timingOffset, server, msg);
305 if (~strumEndsTogether) {
308 dur = sustain + strumTime
310 schedBundle.value(lag, dur + ~timingOffset, server,
311 [15 /* \n_set */, msg[2], \gate, 0])
331 midiEventFunctions: (
332 noteOn: #{ arg chan=0, midinote=60, amp=0.1;
333 [chan, midinote, asInteger((amp * 127).clip(0, 127)) ] },
334 noteOff: #{ arg chan=0, midinote=60, amp=0.1;
335 [ chan, midinote, asInteger((amp * 127).clip(0, 127)) ] },
336 polyTouch: #{ arg chan=0, midinote=60, polyTouch=125;
337 [ chan, midinote, polyTouch ] },
338 control: #{ arg chan=0, ctlNum, control=125;
339 [chan, ctlNum, control ] },
340 program: #{ arg chan=0, progNum=1; [ chan, progNum ] },
341 touch: #{ arg chan=0, val=125; [ chan, val ] },
342 bend: #{ arg chan=0, val=125; [ chan, val ] },
343 allNotesOff: #{ arg chan=0; [chan] },
344 smpte: #{ arg frames=0, seconds=0, minutes=0, hours=0, frameRate=25;
345 [frames, seconds, minutes, hours, frameRate] },
346 songPtr: #{ arg songPtr; [songPtr] },
347 sysex: #{ arg uid, array; [array] } // Int8Array
358 instrument: \default,
362 if (~hasGate == true)
363 {currentEnvironment.set(\gate, 0) }
364 {currentEnvironment.sendOSC([11, ~id]) };
369 currentEnvironment.sendOSC([11, ~id]);
372 releaseServerNode: #{
373 currentEnvironment.set(\gate, 0);
376 pauseServerNode: #{ currentEnvironment.sendOSC([12, ~id, false]); },
377 resumeServerNode: #{ currentEnvironment.sendOSC([12, ~id, true]); },
379 // perhaps these should be changed into mapServerNode etc.
381 map: #{ | ev, key, busIndex | ev.sendOSC([14, ev[\id], key, busIndex]) },
384 before: #{ | ev,target |
385 ev.sendOSC([18, ev[\id], target]);
386 ev[\group] = target; ev[\addAction] = 2;
388 after: #{ | ev, target |
389 ev.sendOSC([19, ev[\id], target]);
390 ev[\group] = target; ev[\addAction] = 3;
392 headOf: #{ | ev, group |
393 ev.sendOSC([22, group, ev[\id]]);
394 ev[\group] = group; ev[\addAction] = 0;
396 tailOf: #{ |ev, group |
397 ev.sendOSC([23, group, ev[\id]]);
398 ev[\group] = group; ev[\addAction] = 1;
400 isPlaying: #{ |ev| ^(ev[\isPlaying] == true) },
401 isPlaying_: #{ | ev, flag | ev[\isPlaying] = flag; },
402 nodeID: #{ |ev| ^ev[\id].asArray.last },
405 asEventStreamPlayer: #{|ev| ev }
417 server = ~server ?? { Server.default };
421 thisThread.clock.tempo = tempo;
423 // ~isRest may be nil - force Boolean behavior
424 if(~isRest != true) { ~eventTypes[~type].value(server) };
427 // synth / node interface
428 // this may be better moved into the cleanup events, but for now
429 // it avoids confusion.
430 // this is a preliminary implementation and does not recalculate dependent
431 // values like degree, octave etc.
435 ~server.sendMsg("/n_free", *~id);
440 // for some yet unknown reason, this function is uncommented,
441 // it breaks the play method for gatelesss synths
443 releaseServerNode: #{ |releaseTime|
447 releaseTime = if(releaseTime.isNil) { 0.0 } { -1.0 - releaseTime };
448 sendGate = ~sendGate ? ~hasGate;
451 ~server.sendBundle(~server.latency,
452 *["/n_set", ~id, "gate", releaseTime].flop);
454 ~server.sendBundle(~server.latency, ["/n_free"] ++ ~id);
468 var freqs, lag, strum, sustain;
469 var bndl, addAction, sendGate, ids;
470 var msgFunc, instrumentName, offset, strumOffset;
472 // var schedBundleArray;
474 freqs = ~detunedFreq.value;
475 if (freqs.isRest.not) {
477 // msgFunc gets the synth's control values from the Event
478 msgFunc = ~getMsgFunc.valueEnvir;
479 instrumentName = ~synthDefName.valueEnvir;
481 // determine how to send those commands
482 // sendGate == false turns off releases
484 sendGate = ~sendGate ? ~hasGate;
486 // update values in the Event that may be determined by functions
490 ~sustain = sustain = ~sustain.value;
492 offset = ~timingOffset;
496 addAction = Node.actionNumberFor(~addAction);
498 // compute the control values and generate OSC commands
499 bndl = msgFunc.valueEnvir;
500 bndl = [9 /* \s_new */, instrumentName, ids, addAction, ~group] ++ bndl;
503 if(strum == 0 and: { (sendGate and: { sustain.isArray })
504 or: { offset.isArray } or: { lag.isArray } }) {
507 [sustain, lag, offset]
509 #sustain, lag, offset = bndl[1].flop;
515 // produce a node id for each synth
517 ~id = ids = Array.fill(bndl.size, { server.nextNodeID });
518 bndl = bndl.collect { | msg, i |
523 // schedule when the bundles are sent
526 ~schedBundleArray.(lag, offset, server, bndl, ~latency);
532 [15 /* \n_set */, ids, \gate, 0].flop,
538 if (strum < 0) { bndl = bndl.reverse };
539 strumOffset = offset + Array.series(bndl.size, 0, strum.abs);
541 lag, strumOffset, server, bndl, ~latency
544 if (~strumEndsTogether) {
545 strumOffset = sustain + offset
547 strumOffset = sustain + strumOffset
550 lag, strumOffset, server,
551 [15 /* \n_set */, ids, \gate, 0].flop,
559 // optimized version of type \note, about double as efficient.
560 // Synth must have no gate and free itself after sustain.
561 // Event supports no strum, no conversion of argument objects to controls
566 var freqs, lag, instr;
567 var bndl, addAction, sendGate, ids;
568 var msgFunc, instrumentName, offset;
570 freqs = ~detunedFreq.value;
572 if (freqs.isRest.not) {
574 // msgFunc gets the synth's control values from the Event
575 instr = ( ~synthLib ?? { SynthDescLib.global } ).at(~instrument);
577 "Event: instrument % not found in SynthDescLib"
578 .format(~instrument).warn;
581 msgFunc = instr.msgFunc;
582 instrumentName = ~synthDefName.valueEnvir;
584 // update values in the Event that may be determined by functions
588 ~sustain = ~sustain.value;
590 addAction = Node.actionNumberFor(~addAction);
592 // compute the control values and generate OSC commands
594 bndl = msgFunc.valueEnvir;
595 bndl = [9 /* \s_new */, instrumentName, -1, addAction, ~group] ++ bndl;
609 var bndl, sendGate, ids;
610 var msgFunc, desc, synthLib, bundle, instrumentName;
612 freqs = ~detunedFreq.value;
614 if (freqs.isRest.not) {
617 msgFunc = ~getMsgFunc.valueEnvir;
618 instrumentName = ~synthDefName.valueEnvir;
619 bndl = msgFunc.valueEnvir;
620 bndl = [9 /* \s_new */, instrumentName, ~id,
621 Node.actionNumberFor(~addAction), ~group] ++ bndl;
623 if ( (ids = ~id).isNil ) {
624 ids = Array.fill(bndl.size, {server.nextNodeID });
625 bndl = bndl.collect { | msg, i |
630 bndl = bndl.asOSCArgBundle;
633 ~schedBundleArray.value(~lag, ~timingOffset, server, bndl);
638 ~callback.value(currentEnvironment)
642 var freqs, lag, dur, strum, bndl, msgFunc;
643 freqs = ~freq = ~detunedFreq.value;
645 if (freqs.isRest.not) {
650 if(~args.size == 0) {
651 msgFunc = ~getMsgFunc.valueEnvir;
652 bndl = msgFunc.valueEnvir;
654 bndl = ~args.envirPairs;
657 bndl = ([15 /* \n_set */, ~id] ++ bndl).flop.asOSCArgBundle;
658 ~schedBundleArray.value(~lag, ~timingOffset, server, bndl);
665 gate = min(0.0, ~gate ? 0.0); // accept release times
666 ~schedBundleArray.value(~lag, ~timingOffset, server,
667 [15 /* \n_set */, ~id.asControlInput, \gate, gate].flop)
669 ~schedBundleArray.value(~lag, ~timingOffset, server,
670 [\n_free, ~id.asControlInput].flop)
675 ~schedBundleArray.value(~lag, ~timingOffset, server,
676 [\n_free, ~id.asControlInput].flop)
681 if (~id.isNil) { ~id = server.nextNodeID };
682 bundle = [21 /* \g_new */, ~id.asArray, Node.actionNumberFor(~addAction),
683 ~group.asControlInput].flop;
684 ~schedBundleArray.value(~lag, ~timingOffset, server, bundle);
689 if (~id.isNil) { ~id = server.nextNodeID };
690 bundle = [63 /* \p_new */, ~id.asArray, Node.actionNumberFor(~addAction),
691 ~group.asControlInput].flop;
692 ~schedBundleArray.value(~lag, ~timingOffset, server, bundle);
698 array = ~array.asArray;
699 ~schedBundle.value(~lag, ~timingOffset, server,
700 [\c_setn, ~out.asControlInput, array.size] ++ array);
704 ~schedBundle.value(~lag, ~timingOffset, server,
705 [\b_gen, ~bufnum.asControlInput, ~gencmd, ~genflags] ++ ~genarray);
709 ~schedBundle.value(~lag, ~timingOffset, server,
710 [\b_allocRead, ~bufnum.asControlInput, ~filename,
711 ~frame, ~numframes]);
714 ~schedBundle.value(~lag, ~timingOffset, server,
715 [\b_read, ~bufnum.asControlInput, ~filename,
716 ~frame, ~numframes, ~bufpos, ~leaveOpen]);
719 ~schedBundle.value(~lag, ~timingOffset, server,
720 [\b_alloc, ~bufnum.asControlInput, ~numframes, ~numchannels]);
723 ~schedBundle.value(~lag, ~timingOffset, server,
724 [\b_free, ~bufnum.asControlInput]);
728 var freqs, lag, dur, sustain, strum;
729 var bndl, midiout, hasGate, midicmd;
731 freqs = ~freq = ~detunedFreq.value;
733 if (freqs.isRest.not) {
735 ~midinote = (freqs.cpsmidi).round(1).asInteger;
738 sustain = ~sustain = ~sustain.value;
739 midiout = ~midiout.value;
740 ~uid ?? { ~uid = midiout.uid }; // mainly for sysex cmd
741 hasGate = ~hasGate ? true;
743 bndl = ~midiEventFunctions[midicmd].valueEnvir.asCollection;
745 bndl = bndl.asControlInput.flop;
747 bndl.do {|msgArgs, i|
750 latency = i * strum + lag;
753 midiout.performList(midicmd, msgArgs)
755 thisThread.clock.sched(latency, {
756 midiout.performList(midicmd, msgArgs);
759 if(hasGate and: { midicmd === \noteOn }) {
760 thisThread.clock.sched(sustain + latency, {
761 midiout.noteOff(*msgArgs)
768 var receiver = ~receiver,
771 var selector, value = each.envirGet;
773 selector = each.asSetter;
774 if(~doTrace == true) {
775 postf("%.%_(%)\n",receiver,selector,value)
777 receiver.perform(selector.asSetter, value)
783 // because we'll no longer be in this Event
784 // when defer wakes up
792 if(~hasGate == false) {
793 ~schedBundle.value(~lag, ~timingOffset, server,
794 [\n_free] ++ ~id.asControlInput);
796 ~schedBundle.value(~lag, ~timingOffset, server,
797 *([15 /* \n_set */, ~id.asControlInput, \gate, 0].flop) );
803 var freqs, lag, bndl;
805 freqs = ~freq = ~detunedFreq.value;
807 if (freqs.isRest.not) {
809 ~sustain = ~sustain.value;
811 bndl = ([15 /* \n_set */, ~id.asControlInput] ++ ~msgFunc.valueEnvir).flop;
812 bndl = bndl.collect(_.asOSCArgArray);
813 ~schedBundle.value(~lag, ~timingOffset, server, *bndl);
818 monoNote: #{ |server|
819 var bndl, id, ids, addAction, f;
820 addAction = ~addAction;
821 ~freq = ~detunedFreq.value;
825 bndl = ( [9 /* \s_new */, ~instrument, ids, addAction, ~group.asControlInput]
826 ++ ~msgFunc.valueEnvir).flop;
828 id = server.nextNodeID;
833 if ((addAction == 0) || (addAction == 3)) {
836 bndl = bndl.collect(_.asOSCArgArray);
837 ~schedBundle.value(~lag, ~timingOffset, server, *bndl);
838 ~updatePmono.value(ids, server);
842 var instrumentName, desc, msgFunc, sustain;
843 var bndl, synthLib, addAction, group, latency, ids, id, groupControls;
845 addAction = Node.actionNumberFor(~addAction);
846 group = ~group.asControlInput;
847 ~freq = ~detunedFreq.value;
849 ~sustain = sustain = ~sustain.value;
851 msgFunc = ~getMsgFunc.valueEnvir;
852 instrumentName = ~synthDefName.valueEnvir;
854 bndl = [9 /* \s_new */, instrumentName, ids, addAction, group]
855 ++ msgFunc.valueEnvir;
856 if ((addAction == 0) || (addAction == 3)) {
860 bndl = bndl.collect(_.asOSCArgArray);
862 server.sendBundle(server.latency, *bndl);
865 NodeWatcher.register(currentEnvironment);
870 var ids, group, addAction, bundle;
871 ids = ~id = (~id ?? { server.nextNodeID }).asArray;
872 addAction = Node.actionNumberFor(~addAction);
873 group = ~group.asControlInput;
875 if ((addAction == 0) || (addAction == 3) ) {
878 bundle = ids.collect {|id, i|
879 [21 /* \g_new */, id, addAction, group];
881 server.sendBundle(server.latency, *bundle);
883 NodeWatcher.register(currentEnvironment);
889 var doTree = { |tree, currentNode, addAction=1|
890 if(tree.isKindOf(Association)) {
891 ~bundle = ~bundle.add([21 /* \g_new */,
892 tree.key.asControlInput, Node.actionNumberFor(addAction),
893 currentNode.asControlInput]);
894 currentNode = tree.key;
897 if(tree.isSequenceableCollection) {
899 x ?? { tree[i] = x = server.nextNodeID };
900 doTree.(x, currentNode)
903 ~bundle = ~bundle.add([21 /* \g_new */,
904 tree.asControlInput, Node.actionNumberFor(addAction),
905 currentNode.asControlInput]);
910 ~treeGroups = ~treeGroups ?? { ~tree.deepCopy };
912 doTree.(~treeGroups, ~group, ~addAction);
913 CmdPeriod.doOnce { ~treeGroups = nil };
916 server.sendBundle(server.latency, *~bundle);
926 partialEvents.pitchEvent,
927 partialEvents.ampEvent,
928 partialEvents.durEvent,
929 partialEvents.bufferEvent,
930 partialEvents.serverEvent,
931 partialEvents.playerEvent,
932 partialEvents.midiEvent
938 var server, group, addAction, ids, bundle;
940 group = ~group.asControlInput;
941 addAction = Node.actionNumberFor(~addAction);
942 ~server = server= ~server ?? {Server.default};
943 ids = Event.checkIDs(~id, server);
944 if (ids.isNil) { ids = ~id = server.nextNodeID };
945 if ((addAction == 0) || (addAction == 3) ) {
946 ids = ids.asArray.reverse;
948 bundle = ids.collect {|id, i|
949 [21 /* \g_new */, id, addAction, group];
951 server.sendBundle(server.latency, *bundle);
954 NodeWatcher.register(currentEnvironment);
955 }).putAll(partialEvents.nodeEvent),
961 var server, latency, group, addAction;
962 var instrumentName, synthLib, desc, msgFunc;
966 ~server = server = ~server ?? { Server.default };
967 ~sustain = ~sustain.value;
968 group = ~group.asControlInput;
969 addAction = Node.actionNumberFor(~addAction);
970 synthLib = ~synthLib ?? { SynthDescLib.global };
971 instrumentName = ~instrument.asSymbol;
972 desc = synthLib.synthDescs[instrumentName];
974 msgFunc = desc.msgFunc;
975 ~hasGate = desc.hasGate;
977 msgFunc = ~defaultMsgFunc;
980 msgs = msgFunc.valueEnvir.flop;
981 ids = Event.checkIDs(~id, server);
982 if (ids.isNil) { ids = msgs.collect { server.nextNodeID } };
983 bndl = ids.collect { |id, i|
984 [9 /* \s_new */, instrumentName, id, addAction, group]
988 if ((addAction == 0) || (addAction == 3)) {
991 bndl = bndl.asOSCArgBundle;
993 server.sendBundle(server.latency ? 0 + ~lag, *bndl);
995 server.sendBundle(server.latency, *bndl);
1001 NodeWatcher.register(currentEnvironment);
1003 defaultMsgFunc: #{|freq = 440, amp = 0.1, pan = 0, out = 0|
1004 [\freq, freq, \amp, amp, \pan, pan, \out, out] }
1005 ).putAll(partialEvents.nodeEvent)
1009 defaultParentEvent = parentEvents.default;