a-EQ: Transfer function curves improvement
[ardour.git] / libs / plugins / reasonablesynth.lv2 / rsynth.c
index c876c5b067048930657e98f00b384ec4769e8f43..5848bee14c06a391d5d0ddb7f1262f9bf0383c7b 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <stdint.h>
+
+#ifndef COMPILER_MSVC
+#include <stdbool.h>
+#endif
+
 #include <assert.h>
 
 #ifndef BUFFER_SIZE_SAMPLES
@@ -71,6 +76,8 @@ typedef struct _RSSynthChannel {
   float     adsr_amp[128];
   float     phase[128];      // various use, zero'ed on note-on
   int8_t    miditable[128];  // internal, note-on/off velocity
+  int8_t    midimsgs [128];  // internal, note-off + on in same cycle, sustained-off
+  int8_t    sustain;         // sustain pedal pressed
   ADSRcfg   adsr;
   void      (*synthesize) (struct _RSSynthChannel* sc,
       const uint8_t note, const float vol, const float pc,
@@ -89,6 +96,8 @@ typedef struct {
   float          kcgain;
   float          kcfilt;
   double         rate;
+  uint32_t       xmas_on;
+  uint32_t       xmas_off;
 } RSSynthesizer;
 
 
@@ -182,28 +191,31 @@ static void synthesize_sineP (RSSynthChannel* sc,
     float env = adsr_env(sc, note);
     if (sc->adsr_cnt[note] == 0) break;
     const float amp = vol * env;
-
-    left[i]  += amp * sinf(2.0 * M_PI * phase);
-    left[i]  += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
-    left[i]  += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
-    left[i]  += .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
-  //left[i]  -= .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
-  //left[i]  += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
-  //left[i]  += .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
-    phase += fq;
-    right[i] += amp * sinf(2.0 * M_PI * phase);
-    right[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
-    right[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
-    right[i] -= .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
-  //right[i] += .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
-  //right[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
-  //right[i] -= .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
+    if (amp > 1e-10) {
+      left[i]  += amp * sinf(2.0 * M_PI * phase);
+      left[i]  += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
+      left[i]  += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
+      left[i]  += .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
+      //left[i]  -= .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
+      //left[i]  += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
+      left[i]  += .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
+      phase += fq;
+      right[i] += amp * sinf(2.0 * M_PI * phase);
+      right[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
+      right[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
+      right[i] -= .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
+      //right[i] += .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
+      //right[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
+      right[i] -= .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
+    } else {
+      phase += fq;
+    }
     if (phase > 1.0) phase -= 2.0;
   }
   sc->phase[note] = phase;
 }
 
-static const ADSRcfg piano_adsr = {{   5, 1300,  100}, { 1.0,  0.0}, {0,0,0}};
+static const ADSRcfg piano_adsr = {{   5, 800,  100}, { 1.0,  0.0}, {0,0,0}};
 
 /*****************************************************************************/
 
@@ -216,11 +228,15 @@ static void process_key (void *synth,
   RSSynthesizer*  rs = (RSSynthesizer*)synth;
   RSSynthChannel* sc = &rs->sc[chn];
   const int8_t vel = sc->miditable[note];
-  const float vol = /* master_volume */ 0.25 * fabsf(vel) / 127.0;
+  const int8_t msg = sc->midimsgs[note];
+  const float vol = /* master_volume */ 0.1f * abs(vel) / 127.f;
   const float phase = sc->phase[note];
+  const int8_t sus = sc->sustain;
+  sc->midimsgs[note] &= ~3;
 
   if (phase == -10 && vel > 0) {
     // new note on
+    sc->midimsgs[note] &= ~4;
     assert(sc->adsr_cnt[note] == 0);
     sc->adsr_amp[note] = 0;
     sc->adsr_cnt[note] = 0;
@@ -230,35 +246,43 @@ static void process_key (void *synth,
   }
   else if (phase >= -1.0 && phase <= 1.0 && vel > 0) {
     // sustain note or re-start note while adsr in progress:
-    if (sc->adsr_cnt[note] > sc->adsr.off[1]) {
+    if (sc->adsr_cnt[note] > sc->adsr.off[1] || msg == 3 || msg == 5 || msg == 7) {
+      sc->midimsgs[note] &= ~4;
       // x-fade to attack
       sc->adsr_amp[note] = adsr_env(sc, note);
       sc->adsr_cnt[note] = 0;
     }
   }
   else if (phase >= -1.0 && phase <= 1.0 && vel < 0) {
+    sc->midimsgs[note] |= 4;
     // note off
-    if (sc->adsr_cnt[note] <= sc->adsr.off[1]) {
+    if (sc->adsr_cnt[note] <= sc->adsr.off[1] && !sus) {
       if (sc->adsr_cnt[note] != sc->adsr.off[1]) {
-       // x-fade to release
-       sc->adsr_amp[note] = adsr_env(sc, note);
+        // x-fade to release
+        sc->adsr_amp[note] = adsr_env(sc, note);
       }
       sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
     }
+    else if (sus && sc->adsr_cnt[note] == sc->adsr.off[1]) {
+      sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
+    }
   }
   else {
+    //printf("FORCE NOTE OFF: %d %d\n", vel, sus);
     /* note-on + off in same cycle */
     sc->miditable[note] = 0;
     sc->adsr_cnt[note] = 0;
     sc->phase[note] = -10;
     return;
   }
+  //printf("NOTE: %d (%d %d %d)\n", sc->adsr_cnt[note], sc->adsr.off[0], sc->adsr.off[1], sc->adsr.off[2]);
 
   // synthesize actual sound
   sc->synthesize(sc, note, vol, rs->freqs[note], n_samples, left, right);
 
   if (sc->adsr_cnt[note] == 0) {
     //printf("Note %d,%d released\n", chn, note);
+    sc->midimsgs[note] = 0;
     sc->miditable[note] = 0;
     sc->adsr_amp[note] = 0;
     sc->phase[note] = -10;
@@ -305,6 +329,7 @@ static void synth_reset_channel(RSSynthChannel* sc) {
     sc->adsr_amp[k]  = 0;
     sc->phase[k]     = -10;
     sc->miditable[k] = 0;
+    sc->midimsgs[k]  = 0;
   }
   sc->keycomp = 0;
 }
@@ -336,32 +361,30 @@ static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
   RSSynthesizer* rs = (RSSynthesizer*)synth;
   switch(ev->type) {
     case NOTE_ON:
+      rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 1;
       if (rs->sc[ev->channel].miditable[ev->d.tone.note] <= 0)
-       rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
+        rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
       break;
     case NOTE_OFF:
+      rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 2;
       if (rs->sc[ev->channel].miditable[ev->d.tone.note] > 0)
-       rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
+        rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
       break;
     case PROGRAM_CHANGE:
       break;
     case CONTROL_CHANGE:
       if (ev->d.control.param == 0x00 || ev->d.control.param == 0x20) {
-       /*  0x00 and 0x20 are used for BANK select */
-       break;
-      } else
-      if (ev->d.control.param == 121) {
-       /* reset all controllers */
-       break;
-      } else
-      if (ev->d.control.param == 120 || ev->d.control.param == 123) {
-       /* Midi panic: 120: all sound off, 123: all notes off*/
-       synth_reset_channel(&(rs->sc[ev->channel]));
-       break;
-      } else
-      if (ev->d.control.param >= 120) {
-       /* params 122-127 are reserved - skip them. */
-       break;
+        /*  0x00 and 0x20 are used for BANK select */
+      } else if (ev->d.control.param == 64) {
+        /* damper pedal*/
+        rs->sc[ev->channel].sustain = ev->d.control.value < 64 ? 0: 1;
+      } else if (ev->d.control.param == 121) {
+        /* reset all controllers */
+      } else if (ev->d.control.param == 120 || ev->d.control.param == 123) {
+        /* Midi panic: 120: all sound off, 123: all notes off*/
+        synth_reset_channel(&(rs->sc[ev->channel]));
+      } else if (ev->d.control.param >= 120) {
+        /* params 122-127 are reserved - skip them. */
       }
       break;
     default:
@@ -390,8 +413,9 @@ static uint32_t synth_sound (void *synth, uint32_t written, const uint32_t nfram
     uint32_t nremain = nframes - written;
 
     if (rs->boffset >= BUFFER_SIZE_SAMPLES)  {
-      rs->boffset = 0;
-      synth_fragment(rs, BUFFER_SIZE_SAMPLES, rs->buf[0], rs->buf[1]);
+      const uint32_t tosynth = MIN(BUFFER_SIZE_SAMPLES, nremain);
+      rs->boffset = BUFFER_SIZE_SAMPLES - tosynth;
+      synth_fragment(rs, tosynth, &(rs->buf[0][rs->boffset]), &(rs->buf[1][rs->boffset]));
     }
 
     uint32_t nread = MIN(nremain, (BUFFER_SIZE_SAMPLES - rs->boffset));
@@ -430,6 +454,9 @@ static void synth_parse_midi(void *synth, const uint8_t *data, const size_t size
       ev.type=NOTE_ON;
       ev.d.tone.note=data[1]&0x7f;
       ev.d.tone.velocity=data[2]&0x7f;
+      if (ev.d.tone.velocity == 0) {
+        ev.type=NOTE_OFF;
+      }
       break;
     case 0xB0:
       ev.type=CONTROL_CHANGE;
@@ -446,6 +473,44 @@ static void synth_parse_midi(void *synth, const uint8_t *data, const size_t size
   synth_process_midi_event(synth, &ev);
 }
 
+static const uint8_t jingle[] = { 71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,66 ,74 ,76 ,74 ,72 ,69 ,71 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,74 ,74 ,74 ,74 ,76 ,74 ,72 ,69 ,67 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 };
+
+static void synth_parse_xmas(void *synth, const uint8_t *data, const size_t size) {
+  RSSynthesizer* rs = (RSSynthesizer*)synth;
+  if (size < 2 || size > 3) return;
+  // All messages need to be 3 bytes; except program-changes: 2bytes.
+  if (size == 2 && (data[0] & 0xf0)  != 0xC0) return;
+
+  struct rmidi_event_t ev;
+
+  ev.channel = data[0]&0x0f;
+  switch (data[0] & 0xf0) {
+    case 0x80:
+      ev.type=NOTE_OFF;
+      ev.d.tone.note=jingle[rs->xmas_off++];
+      ev.d.tone.velocity=data[2]&0x7f;
+      if (rs->xmas_off >= sizeof(jingle)) rs->xmas_off = 0;
+      break;
+    case 0x90:
+      ev.type=NOTE_ON;
+      ev.d.tone.note=jingle[rs->xmas_on++];
+      ev.d.tone.velocity=data[2]&0x7f;
+      if (rs->xmas_on >= sizeof(jingle)) rs->xmas_on = 0;
+      break;
+    case 0xB0:
+      ev.type=CONTROL_CHANGE;
+      ev.d.control.param=data[1]&0x7f;
+      ev.d.control.value=data[2]&0x7f;
+      break;
+    case 0xC0:
+      ev.type=PROGRAM_CHANGE;
+      ev.d.control.value=data[1]&0x7f;
+      break;
+    default:
+      return;
+  }
+  synth_process_midi_event(synth, &ev);
+}
 /**
  * initialize the synth
  * This should be called after synth_alloc()
@@ -461,7 +526,7 @@ static void synth_init(void *synth, double rate) {
   const float tuning = 440;
   int c,k;
   for (k=0; k < 128; k++) {
-    rs->freqs[k] = (2.0 * tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
+    rs->freqs[k] = (tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
     assert(rs->freqs[k] < M_PI/2); // otherwise spatialization may phase out..
   }
   rs->kcfilt = 12.0 / rate;
@@ -470,6 +535,8 @@ static void synth_init(void *synth, double rate) {
   for (c=0; c < 16; c++) {
     synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
   }
+  rs->xmas_on = 0;
+  rs->xmas_off = 0;
 }
 
 /**
@@ -493,4 +560,4 @@ static void * synth_alloc(void) {
 static void synth_free(void *synth) {
   free(synth);
 }
-/* vi:set ts=8 sts=2 sw=2: */
+/* vi:set ts=8 sts=2 sw=2 et: */