diff options
author | rekado <rekado@elephly.net> | 2013-07-28 11:42:18 +0800 |
---|---|---|
committer | rekado <rekado@elephly.net> | 2013-07-28 11:42:18 +0800 |
commit | 7f1350581a42ff02003e4164008dd0b20914abf2 (patch) | |
tree | 8ac0932a8126a8ca81df46c536a2fdd7a0412a58 /src | |
parent | 27326acadb5afed7cd242f3a02c5307667c05b71 (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.
Diffstat (limited to 'src')
-rw-r--r-- | src/mdaPiano.cpp | 105 | ||||
-rw-r--r-- | src/mdaPianoVoice.cpp | 144 |
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 } |