a-EQ: Transfer function curves improvement
[ardour.git] / libs / plugins / reasonablesynth.lv2 / rsynth.c
index cedbf1ae83b538c1f099d12edb9cc06382732b51..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,
@@ -184,22 +191,25 @@ 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;
@@ -218,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;
@@ -232,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);
       }
       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;
@@ -307,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;
 }
@@ -338,10 +361,12 @@ 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;
       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;
       break;
@@ -350,20 +375,16 @@ static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
     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) {
+      } 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 */
-        break;
-      } else
-      if (ev->d.control.param == 120 || ev->d.control.param == 123) {
+      } 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) {
+      } else if (ev->d.control.param >= 120) {
         /* params 122-127 are reserved - skip them. */
-        break;
       }
       break;
     default:
@@ -392,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));
@@ -432,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;