connect audio outputs
[software/lv2-mdametapiano.git] / src / mdaPiano.cpp
index 9912c7569b5dfcf1cb4dfdcca0843595c586ff3b..48747bb3d372492e6d2fdddf5044ba84ed8fcbb3 100644 (file)
@@ -27,8 +27,6 @@ static const char* sample_file = "samples.raw";
 mdaPiano::mdaPiano(double rate)
   : LV2::Synth<mdaPianoVoice, mdaPiano>(p_n_ports, p_midi) {
 
-  cmax = 0x7F;  //just in case...
-
   load_samples(&waves);
   load_kgrp(kgrp);
 
@@ -37,11 +35,9 @@ mdaPiano::mdaPiano(double rate)
     add_voices(voices[i]);
   }
 
-  notes[0] = EVENTS_DONE;
-  cpos = sustain = activevoices = 0;
-  comb = new float[256];
+  sustain = 0;
 
-  update();
+  add_audio_outputs(p_left, p_right);
 }
 
 //parameter change
@@ -52,6 +48,31 @@ void mdaPiano::update() {
 }
 
 
+unsigned mdaPiano::find_free_voice(unsigned char key, unsigned char velocity) {
+  //is this a retriggered note during sustain?
+  if (sustain) {
+    for (unsigned i = 0; i < NVOICES; ++i) {
+      if ((voices[i]->get_key() == key) && (voices[i]->is_sustained())) {
+        return i;
+      }
+    }
+  }
+
+  //take the next free voice if
+  // ... notes are sustained but not this new one
+  // ... notes are not sustained
+  for (unsigned i = 0; i < NVOICES; ++i) {
+    if (voices[i]->get_key() == LV2::INVALID_KEY)
+    {
+      return i;
+    }
+  }
+
+  //TODO: steal quietest note if all voices are used up
+  return 0;
+}
+
+
 void mdaPiano::setVolume(float value)
 {
   for (uint32_t v=0; v<NVOICES; ++v)
@@ -84,22 +105,35 @@ void mdaPiano::handle_midi(uint32_t size, unsigned char* data) {
   switch(data[0] & 0xf0)
   {
     case 0x80: //note off
-      notes[npos++] = data[1] & 0x7F; //note
-      notes[npos++] = 0;                  //vel
+      for (unsigned i = 0; i < NVOICES; ++i) {
+        if (voices[i]->get_key() == data[1]) {
+          voices[i]->release(data[2]);
+          break;
+        }
+      }
       break;
 
     case 0x90: //note on
-      notes[npos++] = data[1] & 0x7F; //note
-      notes[npos++] = data[2] & 0x7F; //vel
-      break;
+      {
+        unsigned int v = find_free_voice(data[1], data[2]);
+        if (v < NVOICES) {
+          voices[v]->on(data[1], data[2]);
+        }
+        break;
+      }
 
     case 0xB0: //controller
       switch(data[1])
       {
         case 0x01:  //mod wheel
         case 0x43:  //soft pedal
-          muff = 0.01f * (float)((127 - data[2]) * (127 - data[2]));
-          break;
+          {
+            float muff = 0.01f * (float)((127 - data[2]) * (127 - data[2]));
+            for (unsigned i = 0; i < NVOICES; ++i) {
+              voices[i]->set_muff(muff);
+            }
+            break;
+          }
 
         case 0x07:  //volume
           setVolume(0.00002f * (float)(data[2] * data[2]));
@@ -108,10 +142,13 @@ void mdaPiano::handle_midi(uint32_t size, unsigned char* data) {
         case 0x40:  //sustain pedal
         case 0x42:  //sustenuto pedal
           sustain = data[2] & 0x40;
-          if(sustain==0)
-          {
-            notes[npos++] = SUSTAIN; //end all sustained notes
-            notes[npos++] = 0;
+
+          for (unsigned i = 0; i < NVOICES; ++i) {
+            voices[i]->set_sustain(sustain);
+            //if pedal was released: dampen sustained notes
+            if((sustain==0) && (voices[i]->is_sustained())) {
+              voices[i]->release(0);
+            }
           }
           break;
 
@@ -191,3 +228,5 @@ void mdaPiano::load_samples(short **buffer)
   fclose (f);
   return;
 }
+
+static int _ = mdaPiano::register_class(p_uri);