From 7f1350581a42ff02003e4164008dd0b20914abf2 Mon Sep 17 00:00:00 2001 From: rekado Date: Sun, 28 Jul 2013 11:42:18 +0800 Subject: 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. --- src/mdaPiano.cpp | 105 ++++++++++++++++++++++++++++++++++-- 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 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 } -- cgit v1.2.3