@@ -12,6 +12,11 @@ MIDIClient.init;
1212~m2 = MIDIOut .newByName("IAC Driver" , "Bus 2" ).latency_(0 );
1313~m3 = MIDIOut .newByName("IAC Driver" , "Bus 3" ).latency_(0 );
1414~prog2portchan = { arg prog;
15+ \inst .postln;
16+ prog.postln;
17+ prog.class.postln;
18+ (prog-1 /8 ).asInteger.postln;
19+ (prog-1 %8 ).asInteger.postln;
1520 case
1621 {prog==0 }{"can't convert start token" .postln}
1722 {prog<=128 }{
@@ -64,23 +69,14 @@ MIDIClient.init;
6469 var port = port_chan[\port ];
6570 var chan = port_chan[\chan ];
6671 (vel>0 ).if{
67- port.noteOn(chan, pitch, vel.max( 1 ) );
72+ port.noteOn(chan, pitch, vel);
6873 }{
6974 port.noteOff(chan, pitch);
7075 }
71- }
76+ };
7277)
7378
74- OSCdef .trace(false );
75-
76-
77- // ok so how to actually 'schedule' things?
78- // SystemClock one-offs should do?
79- // schedule notochord-processing of each event for time of
80- // oLatency before occurence
81- // also schedule the actual event to occur
82- // and set up a handle for the OSC return handler to
83- // fill in any predicted fields
79+ // OSCdef.trace(false);
8480
8581(
8682~oLatency = 0.1 ; // must match value at tidal boot
@@ -96,47 +92,41 @@ OSCdef(\from_tidal, {
9692 var args = Dictionary .newFrom(msg[1 ..]);
9793 // `time` is the start time
9894 // args[\delta] is the duration
99- \from_tidal .postln;
95+ \tidal_feed .postln;
10096 time.postln;
10197 // [time - Process.elapsedTime].postln;
10298 args.postln;
10399
104- // note-on events should arrive from tidal in the order they happen
105- // but note-offs do not, since they are implicit in duration of notes
106- // the only guarantee is nothing needs to happen sooner than tidal's
107- // oLatency parameter
108- // so we can schedule all note-on and note-offs as soon as they arrive
109- // (without all sub-events filled in, possibly)
110-
111- // anthing scheduled sooner than ncLatency (e.g. 100ms)
112- // is 'frozen' and ready to (query_)feed notochord.
113-
114- // schedule note-on
115- ~schedule_event .(
116- time, args[\ncinst ], args[\ncpitch ], args[\ncvel ]
117- );
118- // schedule note-off
119- ~schedule_event .(
120- time+args[\delta ], args[\ncinst ], args[\ncpitch ], 0
121- );
122-
123- // pop those off in order of occurence, and call feed or query_feed
124- // in the case of query_feed, pass in some handle which tells the
125- // return OSCdef where to put the result in the scheduler
100+ ((args[\ncreset ]?0 ) > 0 ).if{
101+ \reset .postln;
102+ SystemClock .schedAbs(time-~ncLatency , {
103+ ~python .sendMsg("/notochord/reset" );
104+ ~release_all .(0 );
105+ });
106+ }{
126107
127- // finally pop completed events as they cross the current time,
108+ // note-on events should arrive from tidal in the order they happen
109+ // but note-offs do not, since they are implicit in duration of notes
110+ // the only guarantee is nothing needs to happen sooner than tidal's
111+ // oLatency parameter
112+ // so we can schedule all note-on and note-offs as soon as they arrive
113+ // (without all sub-events filled in, possibly)
128114
115+ // anthing scheduled sooner than ncLatency (e.g. 100ms)
116+ // is 'frozen' and ready to (query_)feed notochord.
129117
130- //when instrument, pitch or velocity is negative or nil,
131- //query notochord
118+ ~schedule_events .(
119+ time, args[\delta ], args[\ncinst ], args[\ncpitch ], args[\ncvel ]
120+ );
121+ }
132122
133123}, "/notochord/tidal_feed" );
134124
135125// create event handle,
136126// schedule processing by notochord,
137127// and schedule triggering the event
138- ~schedule_event = {
139- arg time, inst, pitch, vel;
128+ ~schedule_events = {
129+ arg time, delta, inst, pitch, vel;
140130
141131 var handle = ~event_idx .asSymbol;
142132 var event = (inst: inst?(-1 ), pitch: pitch?(-1 ), vel: vel?(-1 ));
@@ -153,7 +143,7 @@ OSCdef(\from_tidal, {
153143 (event[\time ]<0 ).if{"warning: dt < 0" .postln};
154144
155145 // if any parts not determined
156- (event.collect( _ < 0 ).values.reduce( '||' ) ).if{
146+ ~any_missing .(event ).if{
157147 // query_feed
158148 // include handle to event for writing the result
159149 ~python .sendMsg(
@@ -168,22 +158,52 @@ OSCdef(\from_tidal, {
168158 }
169159 });
170160
171- // schedule event
161+ // schedule note-on
172162 SystemClock .schedAbs(time, {
173163 // send to the synthesizer (MIDI bus or hacked dirth synth?)
174- \playing .postln; event.postln;
164+ \note_on .postln; event.postln;
165+ ~any_missing .(event).if{
166+ "incomplete note-on" .postln;
167+ }{
168+ ~midi_send .(event[\inst ], event[\pitch ], event[\vel ]);
169+ }
170+ });
171+
172+ // schedule note-off: fully determined once note-on is, since timing
173+ // comes from tidal. may revisit if allowing notochord to do micro-timing
174+ // in the future
175+ SystemClock .schedAbs(time+delta, {
176+ // send to the synthesizer (MIDI bus or hacked dirth synth?)
177+ \note_off .postln; event.postln;
178+ ~any_missing .(event).if{
179+ "incomplete note-off" .postln;
180+ }{
181+ ~midi_send .(event[\inst ], event[\pitch ], 0 );
182+ }
175183 });
176184
177185};
186+ // check if any sub-events not predicted yet
187+ ~any_missing = {arg event;
188+ event.collect(_ <0 ).values.reduce('||' )
189+ };
178190
179191// convert an event (constructed in schedule_event from data received from tidal)
180192// to query keyword args for notochord
181193~event_to_query = {
182194 arg event;
183195 var query = List [];
196+ // if instrument is given
184197 (event[\inst ]>=0 ).if{query.add(\fix_instrument ); query.add(event[\inst ])};
198+ // if pitch is given
185199 (event[\pitch ]>=0 ).if{query.add(\fix_pitch ); query.add(event[\pitch ])};
186- (event[\vel ]>=0 ).if{query.add(\fix_vel ); query.add(event[\vel ])};
200+ // if velocity is given
201+ (event[\vel ]>=0 ).if{
202+ query.add(\fix_vel ); query.add(event[\vel ])
203+ }{
204+ // only predicting note-ons
205+ query.add(\min_vel ); query.add(1 )
206+ };
187207 query.add(\fix_time ); query.add(event[\time ]);
188208 query
189209};
@@ -202,7 +222,6 @@ OSCdef(\from_python, {
202222
203223 ~events .removeAt(\handle );
204224
205-
206225 // TODO: spit a warning if it trying to update
207226 // an event which should have happened already)
208227 // (thisThread.seconds > ...).if{
@@ -212,3 +231,9 @@ OSCdef(\from_python, {
212231}, "notochord/query_return" );
213232
214233)
234+
235+
236+ (
237+ ~python .sendMsg("/notochord/reset" );
238+ ~release_all .(0 );
239+ )
0 commit comments