summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrekado <rekado@elephly.net>2013-07-28 11:42:18 +0800
committerrekado <rekado@elephly.net>2013-07-28 11:42:18 +0800
commit7f1350581a42ff02003e4164008dd0b20914abf2 (patch)
tree8ac0932a8126a8ca81df46c536a2fdd7a0412a58
parent27326acadb5afed7cd242f3a02c5307667c05b71 (diff)
crudely merge mdaEPiano and mdaPiano
There are some differences in the types of certain variables that don't seem very important. This will be addressed in future commits.
-rw-r--r--src/mdaPiano.cpp105
-rw-r--r--src/mdaPianoVoice.cpp144
2 files changed, 240 insertions, 9 deletions
diff --git a/src/mdaPiano.cpp b/src/mdaPiano.cpp
index a358988..419939a 100644
--- a/src/mdaPiano.cpp
+++ b/src/mdaPiano.cpp
@@ -1,14 +1,13 @@
-/* ==================================================
- * LV2 port of the famous mda Piano VSTi
- * ==================================================
+/* ======================================================
+ * LV2 port of the popular mda Piano and mda EPiano VSTi
+ * ======================================================
*
* Port
* Author: Ricardo Wurmus (rekado)
* Based on: mda-vst-src-2010-02-14.zip
*
- * mda Piano v1.0
+ * mda Piano / mda EPiano
* Copyright(c)1999-2000 Paul Kellett (maxim digital audio)
- * Based on VST2 SDK (c)1996-1999 Steinberg Soft und Hardware GmbH, All Rights Reserved
*
* ==================================================
*/
@@ -24,6 +23,7 @@ mdaPiano::mdaPiano(double rate)
sustain = 0;
+#ifdef PIANO
static const char* sample_names[] =
{ "0c.raw", "0e.raw", "0g.raw"
, "1c.raw", "1e.raw", "1g.raw"
@@ -31,12 +31,30 @@ mdaPiano::mdaPiano(double rate)
, "3c.raw", "3e.raw", "3g.raw"
, "4c.raw", "4e.raw", "4a.raw"
};
+#elif defined EPIANO
+ static const char* sample_names[] =
+ { "0c-0.raw", "0c-1.raw", "0c-2.raw"
+ , "0g-0.raw", "0g-1.raw", "0g-2.raw"
+ , "1c-0.raw", "1c-1.raw", "1c-2.raw"
+ , "1g-0.raw", "1g-1.raw", "1g-2.raw"
+ , "2c-0.raw", "2c-1.raw", "2c-2.raw"
+ , "2g-0.raw", "2g-1.raw", "2g-2.raw"
+ , "3c-0.raw", "3c-1.raw", "3c-2.raw"
+ , "3g-0.raw", "3g-1.raw", "3g-2.raw"
+ , "4c-0.raw", "4c-1.raw", "4c-2.raw"
+ , "4g-0.raw", "4g-1.raw", "4g-2.raw"
+ , "5c-0.raw", "5c-1.raw", "5c-2.raw"
+ };
+#endif
for (unsigned char i=0; i<NSAMPLES; ++i) {
load_sample(&samples[i], sample_names[i]);
}
load_kgrp(kgrp);
+#ifdef EPIANO
+ tweak_samples();
+#endif
for(uint32_t i=0; i<NVOICES; ++i) {
voices[i] = new mdaPianoVoice(rate, samples, kgrp);
@@ -117,6 +135,7 @@ void mdaPiano::handle_midi(uint32_t size, unsigned char* data) {
case 0xB0:
switch(data[1])
{
+#ifdef PIANO
case 0x01: //mod wheel
case 0x43: //soft pedal
{
@@ -126,6 +145,12 @@ void mdaPiano::handle_midi(uint32_t size, unsigned char* data) {
}
break;
}
+#elif defined EPIANO
+ case 0x01: //mod wheel
+ //scale the mod value to cover the range [0..1]
+ *p(p_modulation) = scale_midi_to_f(data[2]);
+ break;
+#endif
case 0x07: //volume
setVolume(0.00002f * (float)(data[2] * data[2]));
@@ -206,6 +231,7 @@ void mdaPiano::load_sample(Sample *s, const char* name) {
// TODO: load keymapping from a file
void mdaPiano::load_kgrp(KGRP *kgrp) {
+#ifdef PIANO
kgrp[ 0].root = 36; kgrp[ 0].high = 37; kgrp[ 0].loop = 14774;
kgrp[ 1].root = 40; kgrp[ 1].high = 41; kgrp[ 1].loop = 16268;
kgrp[ 2].root = 43; kgrp[ 2].high = 45; kgrp[ 2].loop = 33541;
@@ -221,7 +247,76 @@ void mdaPiano::load_kgrp(KGRP *kgrp) {
kgrp[12].root = 84; kgrp[12].high = 85; kgrp[12].loop = 6011;
kgrp[13].root = 88; kgrp[13].high = 89; kgrp[13].loop = 3414;
kgrp[14].root = 93; kgrp[14].high = 999; kgrp[14].loop = 2399;
+#elif defined EPIANO
+ kgrp[ 0].root = 36; kgrp[ 0].high = 39; //C1
+ kgrp[ 3].root = 43; kgrp[ 3].high = 45; //G1
+ kgrp[ 6].root = 48; kgrp[ 6].high = 51; //C2
+ kgrp[ 9].root = 55; kgrp[ 9].high = 57; //G2
+ kgrp[12].root = 60; kgrp[12].high = 63; //C3
+ kgrp[15].root = 67; kgrp[15].high = 69; //G3
+ kgrp[18].root = 72; kgrp[18].high = 75; //C4
+ kgrp[21].root = 79; kgrp[21].high = 81; //G4
+ kgrp[24].root = 84; kgrp[24].high = 87; //C5
+ kgrp[27].root = 91; kgrp[27].high = 93; //G5
+ kgrp[30].root = 96; kgrp[30].high =999; //C6
+
+ kgrp[0].loop = 4400;
+ kgrp[1].loop = 4903;
+ kgrp[2].loop = 6398;
+ kgrp[3].loop = 3938;
+ kgrp[4].loop = 1633; //was 1636
+ kgrp[5].loop = 5245;
+ kgrp[6].loop = 2937;
+ kgrp[7].loop = 2203; //was 2204
+ kgrp[8].loop = 6368;
+ kgrp[9].loop = 10452;
+ kgrp[10].loop = 5217; //was 5220
+ kgrp[11].loop = 3099;
+ kgrp[12].loop = 4284;
+ kgrp[13].loop = 3916;
+ kgrp[14].loop = 2937;
+ kgrp[15].loop = 4732;
+ kgrp[16].loop = 4733;
+ kgrp[17].loop = 2285;
+ kgrp[18].loop = 4098;
+ kgrp[19].loop = 4099;
+ kgrp[20].loop = 3609;
+ kgrp[21].loop = 2446;
+ kgrp[22].loop = 6278;
+ kgrp[23].loop = 2283;
+ kgrp[24].loop = 2689;
+ kgrp[25].loop = 4370;
+ kgrp[26].loop = 5225;
+ kgrp[27].loop = 2811;
+ kgrp[28].loop = 2811; //ghost
+ kgrp[29].loop = 4522;
+ kgrp[30].loop = 2306;
+ kgrp[31].loop = 2306; //ghost
+ kgrp[32].loop = 2169;
+#endif
}
+#ifdef EPIANO
+void mdaPiano::tweak_samples() {
+ //extra xfade looping...
+ for(uint32_t k=0; k<28; k++)
+ {
+ long p0 = samples[k].size;
+ long p1 = samples[k].size - kgrp[k].loop;
+
+ float xf = 1.0f;
+ float dxf = -0.02f;
+
+ while(xf > 0.0f)
+ {
+ samples[k].buffer[p0] = (short)((1.0f - xf) * (float)samples[k].buffer[p0] + xf * (float)samples[k].buffer[p1]);
+ p0--;
+ p1--;
+ xf += dxf;
+ }
+ }
+}
+#endif
+
static int _ = mdaPiano::register_class(p_uri);
diff --git a/src/mdaPianoVoice.cpp b/src/mdaPianoVoice.cpp
index 116b5ba..9e46e6b 100644
--- a/src/mdaPianoVoice.cpp
+++ b/src/mdaPianoVoice.cpp
@@ -8,6 +8,8 @@ mdaPianoVoice::mdaPianoVoice(double rate, Sample * master_samples, KGRP * master
samples = master_samples;
kgrp = master_kgrp;
+ // TODO: load default values from ttl file
+#ifdef PIANO
default_preset[p_offset(p_envelope_decay)] = 0.500f;
default_preset[p_offset(p_envelope_release)] = 0.500f;
default_preset[p_offset(p_hardness_offset)] = 0.500f;
@@ -20,6 +22,20 @@ mdaPianoVoice::mdaPianoVoice(double rate, Sample * master_samples, KGRP * master
default_preset[p_offset(p_fine_tuning)] = 0.500f;
default_preset[p_offset(p_random_detuning)] = 0.246f;
default_preset[p_offset(p_stretch_tuning)] = 0.500f;
+#elif defined EPIANO
+ default_preset[p_offset(p_envelope_decay)] = 0.500f;
+ default_preset[p_offset(p_envelope_release)] = 0.500f;
+ default_preset[p_offset(p_hardness)] = 0.500f;
+ default_preset[p_offset(p_treble_boost)] = 0.500f;
+ default_preset[p_offset(p_modulation)] = 0.500f;
+ default_preset[p_offset(p_lfo_rate)] = 0.650f;
+ default_preset[p_offset(p_velocity_sensitivity)] = 0.250f;
+ default_preset[p_offset(p_stereo_width)] = 0.500f;
+ default_preset[p_offset(p_polyphony)] = 0.500f; // unused
+ default_preset[p_offset(p_fine_tuning)] = 0.500f;
+ default_preset[p_offset(p_random_tuning)] = 0.146f;
+ default_preset[p_offset(p_overdrive)] = 0.000f;
+#endif
reset();
update(Default);
@@ -40,29 +56,53 @@ void mdaPianoVoice::on(unsigned char key, unsigned char velocity) {
update(Current);
float l=99.0f;
+#ifdef PIANO
uint32_t k, s;
+#elif defined EPIANO
+ long k, s;
+#endif
if(velocity > 0)
{
k = (key - 60) * (key - 60);
l = fine + random * ((float)(k % 13) - 6.5f); //random & fine tune
+#ifdef PIANO
if(key > 60) l += stretch * (float)k; //stretch
+#endif
s = size;
+#ifdef PIANO
if(velocity > 40) s += (uint32_t)(sizevel * (float)(velocity - 40));
+#endif
k = 0;
while(key > (kgrp[k].high + s)) k += SAMPLES_PER_NOTE; // find keygroup
+#ifdef EPIANO
+ if(velocity > 48) k++; // mid velocity sample
+ if(velocity > 80) k++; // high velocity sample
+#endif
sample_index = k; // store sample index
l += (float)(key - kgrp[k].root); // pitch
+#ifdef PIANO
l = 22050.0f * iFs * (float)exp(0.05776226505 * l);
delta = (uint32_t)(65536.0f * l);
+#elif defined EPIANO
+ l = 32000.0f * iFs * (float)exp(0.05776226505 * l);
+ delta = (long)(65536.0f * l);
+#endif
frac = 0;
pos = 0;
+
+#ifdef PIANO
end = samples[sample_index].size;
+#elif defined EPIANO
+ end = samples[sample_index].size - 1;
+#endif
loop = kgrp[sample_index].loop;
+
+#ifdef PIANO
env = (0.5f + velsens) * (float)pow(0.0078f * velocity, velsens); //velocity
l = 50.0f + *p(p_muffling_filter) * *p(p_muffling_filter) * muff + muffvel * (float)(velocity - 64); //muffle
@@ -70,10 +110,19 @@ void mdaPianoVoice::on(unsigned char key, unsigned char velocity) {
if(l > 210.0f) l = 210.0f;
ff = l * l * iFs;
f0 = f1 = 0.0f;
+#elif defined EPIANO
+ env = (3.0f + 2.0f * velsens) * (float)pow(0.0078f * velocity, velsens); // velocity
+ // high notes quieter
+ if(key > 60) {
+ env *= (float)exp(0.01f * (float)(60 - key));
+ }
+#endif
// note->pan
if(key < 12) key = 12;
if(key > 108) key = 108;
+
+#ifdef PIANO
l = volume * trim;
outr = l + l * width * (float)(key - 60);
outl = l + l - outr;
@@ -82,6 +131,13 @@ void mdaPianoVoice::on(unsigned char key, unsigned char velocity) {
l = 2.0f * *p(p_envelope_decay);
if(l < 1.0f) l += 0.25f - 0.5f * *p(p_envelope_decay);
dec = (float)exp(-iFs * exp(-0.6 + 0.033 * (double)key - l));
+#elif defined EPIANO
+ outr = volume + volume * width * (float)(key - 60);
+ outl = volume + volume - outr;
+
+ if(key < 44) key = 44; // limit max decay length
+ dec = (float)exp(-iFs * exp(-1.0 + 0.03 * (double)key - 2.0f * *p(p_envelope_decay)));
+#endif
} else {
// some keyboards send note off events as 'note on' with velocity 0
release(0);
@@ -92,20 +148,29 @@ void mdaPianoVoice::on(unsigned char key, unsigned char velocity) {
void mdaPianoVoice::reset() {
env = 0.0f;
dec = 0.99f;
- muff = 160.0f;
- volume = 0.2f;
sustain = 0;
+ volume = 0.2f;
+#ifdef PIANO
+ muff = 160.0f;
cpos = 0;
+#elif defined EPIANO
+ tl = tr = lfo0 = dlfo = 0.0f;
+ lfo1 = 1.0f;
+#endif
m_key = lvtk::INVALID_KEY;
}
void mdaPianoVoice::release(unsigned char velocity) {
if(sustain==0) {
+#ifdef PIANO
//no release on highest notes
if(m_key < 94 || m_key == SUSTAIN) {
dec = (float)exp(-iFs * exp(2.0 + 0.017 * (double)m_key - 2.0 * *p(p_envelope_release)));
}
+#elif defined EPIANO
+ dec = (float)exp(-iFs * exp(6.0 + 0.01 * (double)m_key - 5.0 * *p(p_envelope_release)));
+#endif
} else {
m_key = SUSTAIN;
}
@@ -125,7 +190,11 @@ void mdaPianoVoice::render(uint32_t from, uint32_t to) {
return;
float x, l, r;
+#ifdef PIANO
uint32_t i;
+#elif defined EPIANO
+ long i;
+#endif
update(Current);
for (uint32_t frame = from; frame < to; ++frame) {
@@ -134,9 +203,10 @@ void mdaPianoVoice::render(uint32_t from, uint32_t to) {
frac += delta; // integer-based linear interpolation
pos += frac >> 16;
- frac &= 0xFFFF;
- if(pos > end) pos -= loop;
+ frac &= 0xFFFF; // why AND it with all ones?
+ if(pos > end) pos -= loop; // jump back to loop sample
+#ifdef PIANO
i = samples[sample_index].buffer[pos];
i = (i << 7) + (frac >> 9) * (samples[sample_index].buffer[pos + 1] - i) + 0x40400000;
x = env * (*(float *)&i - 3.0f); //fast int->float
@@ -155,16 +225,56 @@ void mdaPianoVoice::render(uint32_t from, uint32_t to) {
// write to output
p(p_left)[frame] += l + x;
p(p_right)[frame] += r - x;
+#elif defined EPIANO
+ // alternative method (probably faster), said to not work on intel mac
+ //i = samples[sample_index].buffer[pos];
+ //i = (i << 7) + (frac >> 9) * (samples[sample_index].buffer[pos + 1] - i) + 0x40400000;
+
+ i = samples[sample_index].buffer[pos] + ((frac * (samples[sample_index].buffer[pos + 1] - samples[sample_index].buffer[pos])) >> 16);
+ x = env * (float)i / 32768.0f;
+ env = env * dec; // envelope
+
+ // overdrive
+ if(x>0.0f) {
+ x -= overdrive * x * x;
+ if(x < -env)
+ x = -env;
+ }
+
+ l += outl * x;
+ r += outr * x;
+
+ // treble boost
+ tl += tfrq * (l - tl);
+ tr += tfrq * (r - tr);
+ r += treb * (r - tr);
+ l += treb * (l - tl);
+
+ lfo0 += dlfo * lfo1; // LFO for tremolo and autopan
+ lfo1 -= dlfo * lfo0;
+ l += l * lmod * lfo1;
+ r += r * rmod * lfo1; // TODO: worth making all these local variables?
+
+ // write to output
+ p(p_left)[frame] += l;
+ p(p_right)[frame] += r;
+#endif
}
// turn off further processing when the envelope has rendered the voice silent
if (env < SILENCE) {
m_key = lvtk::INVALID_KEY;
}
+
+#ifdef EPIANO
+ if(fabs(tl)<1.0e-10) tl = 0.0f; // anti-denormal
+ if(fabs(tr)<1.0e-10) tr = 0.0f;
+#endif
}
void mdaPianoVoice::update(Param par) {
+#ifdef PIANO
size = (uint32_t)(12.0f * p_helper(p_hardness_offset, par) - 6.0f);
sizevel = 0.12f * p_helper(p_velocity_to_hardness, par);
muffvel = p_helper(p_velocity_to_muffling, par) * p_helper(p_velocity_to_muffling, par) * 5.0f;
@@ -181,4 +291,30 @@ void mdaPianoVoice::update(Param par) {
cdep = p_helper(p_stereo_width, par) * p_helper(p_stereo_width, par);
trim = 1.50f - 0.79f * cdep;
width = 0.04f * p_helper(p_stereo_width, par); if(width > 0.03f) width = 0.03f;
+#elif defined EPIANO
+ size = (long)(12.0f * p_helper(p_hardness, par) - 6.0f);
+ treb = 4.0f * p_helper(p_treble_boost, par) * p_helper(p_treble_boost, par) - 1.0f; // treble gain
+
+ // treble frequency
+ if(p_helper(p_treble_boost, par) > 0.5f) {
+ tfrq = 14000.0f;
+ } else {
+ tfrq = 5000.0f;
+ }
+ tfrq = 1.0f - (float)exp(-iFs * tfrq);
+
+ rmod = lmod = p_helper(p_modulation, par) + p_helper(p_modulation, par) - 1.0f; // lfo depth
+ if(p_helper(p_modulation, par) < 0.5f) rmod = -rmod;
+ dlfo = 6.283f * iFs * (float)exp(6.22f * p_helper(p_lfo_rate, par) - 2.61f); // lfo rate
+
+ velsens = 1.0f + p_helper(p_velocity_sensitivity, par) + p_helper(p_velocity_sensitivity, par);
+ if(p_helper(p_velocity_sensitivity, par) < 0.25f) {
+ velsens -= 0.75f - 3.0f * p_helper(p_velocity_sensitivity, par);
+ }
+
+ width = 0.03f * p_helper(p_stereo_width, par);
+ fine = p_helper(p_fine_tuning, par) - 0.5f;
+ random = 0.077f * p_helper(p_random_tuning, par) * p_helper(p_random_tuning, par);
+ overdrive = 1.8f * p_helper(p_overdrive, par);
+#endif
}