shithub: orca

Download patch

ref: 749a8cdea6c25a5a2ae02da035d51cb70d960518
parent: 73ceecdec47633af90ba738ddedf19a6795d1639
author: cancel <cancel@cancel.fm>
date: Sun Dec 9 14:17:39 EST 2018

Add note off timings to app deadline timing

--- a/osc_out.c
+++ b/osc_out.c
@@ -147,16 +147,21 @@
   *end_removed = rem;
 }
 
-void susnote_list_advance_time(Susnote_list* sl, float delta_time,
+void susnote_list_advance_time(Susnote_list* sl, double delta_time,
                                Usz* restrict start_removed,
-                               Usz* restrict end_removed) {
+                               Usz* restrict end_removed,
+                               double* soonest_deadline) {
   Susnote* restrict buffer = sl->buffer;
   Usz count = sl->count;
   *end_removed = count;
+  float delta_float = (float)delta_time;
+  float soonest = 1.0f;
   for (Usz i = 0; i < count;) {
     Susnote sn = buffer[i];
-    sn.remaining -= delta_time;
+    sn.remaining -= delta_float;
     if (sn.remaining > 0) {
+      if (sn.remaining < soonest)
+        soonest = sn.remaining;
       buffer[i].remaining = sn.remaining;
       ++i;
     } else {
@@ -166,5 +171,17 @@
     }
   }
   *start_removed = count;
+  *soonest_deadline = (double)soonest;
   sl->count = count;
+}
+
+double susnote_list_soonest_deadline(Susnote_list const* sl) {
+  float soonest = 1.0f;
+  Susnote const* buffer = sl->buffer;
+  for (Usz i = 0, n = sl->count; i < n; ++i) {
+    float rem = buffer[i].remaining;
+    if (rem < soonest)
+      soonest = rem;
+  }
+  return (double)soonest;
 }
--- a/osc_out.h
+++ b/osc_out.h
@@ -32,6 +32,10 @@
 void susnote_list_add_notes(Susnote_list* sl, Susnote const* restrict notes,
                             Usz count, Usz* restrict start_removed,
                             Usz* restrict end_removed);
-void susnote_list_advance_time(Susnote_list* sl, float delta_time,
+void susnote_list_advance_time(Susnote_list* sl, double delta_time,
                                Usz* restrict start_removed,
-                               Usz* restrict end_removed);
+                               Usz* restrict end_removed,
+                               // 1.0 if no notes remain or none shorter than 1.0
+                               double* soonest_deadline);
+// 1.0 if no notes remain or none shorter than 1.0
+double susnote_list_soonest_deadline(Susnote_list const* sl);
--- a/tui_main.c
+++ b/tui_main.c
@@ -511,6 +511,7 @@
   Tui_input_mode input_mode;
   Usz bpm;
   double accum_secs;
+  double time_to_next_note_off;
   char const* filename;
   Oosc_dev* oosc_dev;
   Midi_mode const* midi_mode;
@@ -537,6 +538,7 @@
   a->input_mode = Tui_input_mode_normal;
   a->bpm = 120;
   a->accum_secs = 0.0;
+  a->time_to_next_note_off = 1.0;
   a->filename = NULL;
   a->oosc_dev = NULL;
   a->midi_mode = NULL;
@@ -585,6 +587,12 @@
                          Susnote const* start, Susnote const* end) {
   Midi_mode_type midi_mode_type = midi_mode->any.type;
   for (; start != end; ++start) {
+#if 0
+    float under = start->remaining;
+    if (under < 0.0) {
+      fprintf(stderr, "cutoff slop: %f\n", under);
+    }
+#endif
     U16 chan_note = start->chan_note;
     Usz chan = chan_note >> 8u;
     Usz note = chan_note & 0xFFu;
@@ -606,10 +614,11 @@
 void apply_time_to_sustained_notes(Oosc_dev* oosc_dev,
                                    Midi_mode const* midi_mode,
                                    double time_elapsed,
-                                   Susnote_list* susnote_list) {
+                                   Susnote_list* susnote_list,
+                                   double* next_note_off_deadline) {
   Usz start_removed, end_removed;
-  susnote_list_advance_time(susnote_list, (float)time_elapsed, &start_removed,
-                            &end_removed);
+  susnote_list_advance_time(susnote_list, time_elapsed, &start_removed,
+                            &end_removed, next_note_off_deadline);
   if (ORCA_UNLIKELY(start_removed != end_removed)) {
     Susnote const* restrict susnotes_off = susnote_list->buffer;
     send_midi_note_offs(oosc_dev, midi_mode, susnotes_off + start_removed,
@@ -622,6 +631,7 @@
   send_midi_note_offs(a->oosc_dev, a->midi_mode, sl->buffer,
                       sl->buffer + sl->count);
   susnote_list_clear(sl);
+  a->time_to_next_note_off = 1.0;
 }
 
 void send_output_events(Oosc_dev* oosc_dev, Midi_mode const* midi_mode, Usz bpm,
@@ -647,7 +657,7 @@
     switch ((Oevent_types)e->any.oevent_type) {
     case Oevent_type_midi: {
       Oevent_midi const* em = (Oevent_midi const*)&e->midi;
-      Usz note_number = (Usz)(12u * em->octave + em->note);
+      Usz note_number = (Usz)(12u * em->octave + em->note) + 48;
       Usz channel = em->channel;
       Usz bar_div = em->bar_divisor;
       midi_note_ons[midi_note_count] =
@@ -658,6 +668,10 @@
           .remaining =
               bar_div == 0 ? 0.0f : (float)(bar_secs / (double)bar_div),
           .chan_note = (U16)((channel << 8u) | note_number)};
+#if 0
+      fprintf(stderr, "bar div: %d, time: %f\n", (int)bar_div,
+              new_susnotes[midi_note_count].remaining);
+#endif
       ++midi_note_count;
     } break;
     }
@@ -695,8 +709,11 @@
   if (a->is_playing) {
     double secs_span = 60.0 / (double)a->bpm / 4.0;
     double rem = secs_span - a->accum_secs;
+    double next_note_off = a->time_to_next_note_off;
     if (rem < 0.0)
       rem = 0.0;
+    else if (next_note_off < rem)
+      rem = next_note_off;
     return rem;
   } else {
     return 1.0;
@@ -708,7 +725,8 @@
     a->accum_secs += secs;
     Oosc_dev* oosc_dev = a->oosc_dev;
     Midi_mode const* midi_mode = a->midi_mode;
-    apply_time_to_sustained_notes(oosc_dev, midi_mode, secs, &a->susnote_list);
+    apply_time_to_sustained_notes(oosc_dev, midi_mode, secs, &a->susnote_list,
+                                  &a->time_to_next_note_off);
   }
 }
 
@@ -734,6 +752,9 @@
                            a->oevent_list.buffer, count);
       }
     }
+    // note for future: sustained note deadlines may have changed due to note
+    // on. will need to update stored deadline in memory if
+    // app_apply_delta_secs isn't called again immediately after app_do_stuff.
   }
 }