Added missing methods and functions. Everything is ready for a first try.

chorus
Holger Wirtz 6 years ago
parent 088070cf4c
commit 071d50b99c
  1. 3
      MicroMDAPiano.ino
  2. 365
      mdaEPiano.cpp
  3. 4
      mdaEPiano.h

@ -420,8 +420,7 @@ bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
}
else
#endif
// ret = dexed->processMidiMessage(type, data1, data2); // TODO!!!
;
ret = ep->processMidiMessage(type, data1, data2);
#ifdef MASTER_KEY_MIDI
}

@ -13,13 +13,13 @@
mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster) : AudioEffectX(audioMaster, NPROGS, NPARAMS)
{
Fs = SAMPLE_RATE; iFs = 1.0f/Fs; //just in case...
Fs = SAMPLE_RATE; iFs = 1.0f / Fs; //just in case...
programs = new mdaEPianoProgram[NPROGS];
if(programs)
if (programs)
{
//fill patches...
int32_t i=0;
int32_t i = 0;
fillpatch(i++, "Default", 0.500f, 0.500f, 0.500f, 0.500f, 0.500f, 0.650f, 0.250f, 0.500f, 0.50f, 0.500f, 0.146f, 0.000f);
fillpatch(i++, "Bright", 0.500f, 0.500f, 1.000f, 0.800f, 0.500f, 0.650f, 0.250f, 0.500f, 0.50f, 0.500f, 0.146f, 0.500f);
fillpatch(i++, "Mellow", 0.500f, 0.500f, 0.000f, 0.000f, 0.500f, 0.650f, 0.250f, 0.500f, 0.50f, 0.500f, 0.246f, 0.000f);
@ -31,16 +31,16 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster)
setProgram(0);
}
/*
if(audioMaster)
{
setNumInputs(0);
setNumOutputs(NOUTS);
canProcessReplacing();
isSynth();
setUniqueID('MDAe'); ///
}
*/
/*
if(audioMaster)
{
setNumInputs(0);
setNumOutputs(NOUTS);
canProcessReplacing();
isSynth();
setUniqueID('MDAe'); ///
}
*/
waves = (short*)epianoData;
//Waveform data and keymapping
@ -54,7 +54,7 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster)
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[30].root = 96; kgrp[30].high = 999; //C6
kgrp[0].pos = 0; kgrp[0].end = 8476; kgrp[0].loop = 4400;
kgrp[1].pos = 8477; kgrp[1].end = 16248; kgrp[1].loop = 4903;
@ -91,7 +91,7 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster)
kgrp[32].pos = 414487; kgrp[32].end = 422408; kgrp[32].loop = 2169;
//extra xfade looping...
for(int32_t k=0; k<28; k++)
for (int32_t k = 0; k < 28; k++)
{
int32_t p0 = kgrp[k].end;
int32_t p1 = kgrp[k].end - kgrp[k].loop;
@ -99,7 +99,7 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster)
float xf = 1.0f;
float dxf = -0.02f;
while(xf > 0.0f)
while (xf > 0.0f)
{
waves[p0] = (short)((1.0f - xf) * (float)waves[p0] + xf * (float)waves[p1]);
p0--;
@ -109,7 +109,7 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster)
}
//initialise...
for(int32_t v=0; v<NVOICES; v++)
for (int32_t v = 0; v < NVOICES; v++)
{
voice[v].env = 0.0f;
voice[v].dec = 0.99f; //all notes off
@ -124,7 +124,7 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster)
guiUpdate = 0;
update();
// suspend();
// suspend();
}
void mdaEPiano::update() //parameter change
@ -133,16 +133,16 @@ void mdaEPiano::update() //parameter change
size = (int32_t)(12.0f * param[2] - 6.0f);
treb = 4.0f * param[3] * param[3] - 1.0f; //treble gain
if(param[3] > 0.5f) tfrq = 14000.0f; else tfrq = 5000.0f; //treble freq
if (param[3] > 0.5f) tfrq = 14000.0f; else tfrq = 5000.0f; //treble freq
tfrq = 1.0f - (float)exp(-iFs * tfrq);
rmod = lmod = param[4] + param[4] - 1.0f; //lfo depth
if(param[4] < 0.5f) rmod = -rmod;
if (param[4] < 0.5f) rmod = -rmod;
dlfo = 6.283f * iFs * (float)exp(6.22f * param[5] - 2.61f); //lfo rate
velsens = 1.0f + param[6] + param[6];
if(param[6] < 0.25f) velsens -= 0.75f - 3.0f * param[6];
if (param[6] < 0.25f) velsens -= 0.75f - 3.0f * param[6];
width = 0.03f * param[7];
poly = 1 + (int32_t)(31.9f * param[8]);
@ -156,7 +156,7 @@ void mdaEPiano::update() //parameter change
void mdaEPiano::resume()
{
//Fs = getSampleRate();
Fs=SAMPLE_RATE;
Fs = SAMPLE_RATE;
iFs = 1.0f / Fs;
dlfo = 6.283f * iFs * (float)exp(6.22f * programs[curProgram].param[5] - 2.61f); //lfo rate
@ -166,14 +166,14 @@ void mdaEPiano::resume()
mdaEPiano::~mdaEPiano () //destroy any buffers...
{
if(programs) delete [] programs;
if (programs) delete [] programs;
}
void mdaEPiano::setProgram(int32_t program)
{
curProgram = program;
update();
curProgram = program;
update();
}
@ -189,7 +189,7 @@ void mdaEPiano::setParameter(int32_t index, float value)
void mdaEPiano::fillpatch(int32_t p, char *name, float p0, float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8, float p9, float p10,float p11)
float p5, float p6, float p7, float p8, float p9, float p10, float p11)
{
strcpy(programs[p].name, name);
programs[p].param[0] = p0; programs[p].param[1] = p1;
@ -197,21 +197,23 @@ void mdaEPiano::fillpatch(int32_t p, char *name, float p0, float p1, float p2, f
programs[p].param[4] = p4; programs[p].param[5] = p5;
programs[p].param[6] = p6; programs[p].param[7] = p7;
programs[p].param[8] = p8; programs[p].param[9] = p9;
programs[p].param[10]= p10; programs[p].param[11] = p11;
programs[p].param[10] = p10; programs[p].param[11] = p11;
}
float mdaEPiano::getParameter(int32_t index) { return programs[curProgram].param[index]; }
float mdaEPiano::getParameter(int32_t index) {
return programs[curProgram].param[index];
}
/*
void mdaEPiano::setProgramName(char *name) { strcpy(programs[curProgram].name, name); }
void mdaEPiano::getProgramName(char *name) { strcpy(name, programs[curProgram].name); }
void mdaEPiano::setBlockSize(int32_t blockSize) { AudioEffectX::setBlockSize(blockSize); }
bool mdaEPiano::getEffectName(char* name) { strcpy(name, "ePiano"); return true; }
bool mdaEPiano::getVendorString(char* text) { strcpy(text, "mda"); return true; }
bool mdaEPiano::getProductString(char* text) { strcpy(text, "mda ePiano"); return true; }
void mdaEPiano::setProgramName(char *name) { strcpy(programs[curProgram].name, name); }
void mdaEPiano::getProgramName(char *name) { strcpy(name, programs[curProgram].name); }
void mdaEPiano::setBlockSize(int32_t blockSize) { AudioEffectX::setBlockSize(blockSize); }
bool mdaEPiano::getEffectName(char* name) { strcpy(name, "ePiano"); return true; }
bool mdaEPiano::getVendorString(char* text) { strcpy(text, "mda"); return true; }
bool mdaEPiano::getProductString(char* text) { strcpy(text, "mda ePiano"); return true; }
bool mdaEPiano::getOutputProperties(int32_t index, VstPinProperties* properties)
{
bool mdaEPiano::getOutputProperties(int32_t index, VstPinProperties* properties)
{
if(index<NOUTS)
{
if(index) sprintf(properties->label, "ePiano");
@ -221,41 +223,41 @@ bool mdaEPiano::getOutputProperties(int32_t index, VstPinProperties* properties)
return true;
}
return false;
}
}
bool mdaEPiano::getProgramNameIndexed(int32_t category, int32_t index, char* text)
{
bool mdaEPiano::getProgramNameIndexed(int32_t category, int32_t index, char* text)
{
if ((unsigned int)index < NPROGS)
{
strcpy(text, programs[index].name);
return true;
}
return false;
}
}
bool mdaEPiano::copyProgram(int32_t destination)
{
bool mdaEPiano::copyProgram(int32_t destination)
{
if(destination<NPROGS)
{
programs[destination] = programs[curProgram];
return true;
}
return false;
}
}
int32_t mdaEPiano::canDo(char* text)
{
int32_t mdaEPiano::canDo(char* text)
{
if(strcmp(text, "receiveVstEvents") == 0) return 1;
if(strcmp(text, "receiveVstMidiEvent") == 0) return 1;
return -1;
}
}
void mdaEPiano::getParameterName(int32_t index, char *label)
{
void mdaEPiano::getParameterName(int32_t index, char *label)
{
switch (index)
{
case 0: strcpy(label, "Envelope Decay"); break;
@ -274,11 +276,11 @@ void mdaEPiano::getParameterName(int32_t index, char *label)
case 10: strcpy(label, "Random Tuning"); break;
default: strcpy(label, "Overdrive"); break;
}
}
}
void mdaEPiano::getParameterDisplay(int32_t index, char *text)
{
void mdaEPiano::getParameterDisplay(int32_t index, char *text)
{
char string[16];
float * param = programs[curProgram].param;
@ -302,11 +304,11 @@ void mdaEPiano::getParameterDisplay(int32_t index, char *text)
}
string[8] = 0;
strcpy(text, (char *)string);
}
}
void mdaEPiano::getParameterLabel(int32_t index, char *label)
{
void mdaEPiano::getParameterLabel(int32_t index, char *label)
{
switch(index)
{
case 5: strcpy(label, "Hz"); break;
@ -315,50 +317,55 @@ void mdaEPiano::getParameterLabel(int32_t index, char *label)
case 10: strcpy(label, "cents"); break;
default: strcpy(label, "%");
}
}
}
void mdaEPiano::guiGetDisplay(int32_t index, char *label)
{
void mdaEPiano::guiGetDisplay(int32_t index, char *label)
{
getParameterName(index, label);
strcat(label, " = ");
getParameterDisplay(index, label + strlen(label));
getParameterLabel(index, label + strlen(label));
}
}
*/
void mdaEPiano::process(int16_t **outputs_r, int16_t **outputs_l, int32_t sampleFrames)
{
int16_t* out_l = outputs_r[0];
int16_t* out_r = outputs_l[0];
int32_t event=0, frame=0, frames, v;
float x, l, r, od=overdrive;
int16_t* out_l = outputs_r[0];
int16_t* out_r = outputs_l[0];
int32_t event = 0, frame = 0, frames, v;
float x, l, r, od = overdrive;
int32_t i;
while(frame<sampleFrames)
while (frame < sampleFrames)
{
frames = notes[event++];
if(frames>sampleFrames) frames = sampleFrames;
if (frames > sampleFrames) frames = sampleFrames;
frames -= frame;
frame += frames;
while(--frames>=0)
while (--frames >= 0)
{
VOICE *V = voice;
l = r = 0.0f;
for(v=0; v<activevoices; v++)
for (v = 0; v < activevoices; v++)
{
V->frac += V->delta; //integer-based linear interpolation
V->pos += V->frac >> 16;
V->frac &= 0xFFFF;
if(V->pos > V->end) V->pos -= V->loop;
if (V->pos > V->end) V->pos -= V->loop;
i = waves[V->pos];
i = (i << 7) + (V->frac >> 9) * (waves[V->pos + 1] - i) + 0x40400000;
x = V->env * (*(float *)&i - 3.0f); //fast int->float
//x = V->env * (*(float *)&i - 3.0f); //fast int->float
x = V->env * (float(i) - 3.0f);
V->env = V->env * V->dec; //envelope
if(x>0.0f) { x -= od * x * x; if(x < -V->env) x = -V->env; } //+= 0.5f * x * x; } //overdrive
if (x > 0.0f) {
x -= od * x * x; //overdrive
if (x < -V->env) x = -V->env;
} //+= 0.5f * x * x; }
l += V->outl * x;
r += V->outr * x;
@ -375,109 +382,38 @@ void mdaEPiano::process(int16_t **outputs_r, int16_t **outputs_l, int32_t sample
l += l * lmod * lfo1;
r += r * rmod * lfo1; //worth making all these local variables?
*out_r++ += static_cast<int16_t>(l * 0x8000);
*out_l++ += static_cast<int16_t>(r * 0x8000);
*out_r++ = static_cast<int16_t>(l * 0x8000);
*out_l++ = static_cast<int16_t>(r * 0x8000);
}
if(frame<sampleFrames)
{
if(activevoices == 0 && programs[curProgram].param[4] > 0.5f)
{ lfo0 = -0.7071f; lfo1 = 0.7071f; } //reset LFO phase - good idea?
int32_t note = notes[event++];
int32_t vel = notes[event++];
noteOn(note, vel);
}
}
if(fabs(tl)<1.0e-10) tl = 0.0f; //anti-denormal
if(fabs(tr)<1.0e-10) tr = 0.0f;
for(v=0; v<activevoices; v++) if(voice[v].env < SILENCE) voice[v] = voice[--activevoices];
notes[0] = EVENTS_DONE; //mark events buffer as done
}
void mdaEPiano::processReplacing(float **inputs, float **outputs, int32_t sampleFrames)
{
float* out0 = outputs[0];
float* out1 = outputs[1];
int32_t event=0, frame=0, frames, v;
float x, l, r, od=overdrive;
int32_t i;
while(frame<sampleFrames)
{
frames = notes[event++];
if(frames>sampleFrames) frames = sampleFrames;
frames -= frame;
frame += frames;
while(--frames>=0)
if (frame < sampleFrames)
{
VOICE *V = voice;
l = r = 0.0f;
for(v=0; v<activevoices; v++)
if (activevoices == 0 && programs[curProgram].param[4] > 0.5f)
{
V->frac += V->delta; //integer-based linear interpolation
V->pos += V->frac >> 16;
V->frac &= 0xFFFF;
if(V->pos > V->end) V->pos -= V->loop;
//i = waves[V->pos];
//i = (i << 7) + (V->frac >> 9) * (waves[V->pos + 1] - i) + 0x40400000; //not working on intel mac !?!
//x = V->env * (*(float *)&i - 3.0f); //fast int->float
//x = V->env * (float)i / 32768.0f;
i = waves[V->pos] + ((V->frac * (waves[V->pos + 1] - waves[V->pos])) >> 16);
x = V->env * (float)i / 32768.0f;
V->env = V->env * V->dec; //envelope
if(x>0.0f) { x -= od * x * x; if(x < -V->env) x = -V->env; } //+= 0.5f * x * x; } //overdrive
l += V->outl * x;
r += V->outr * x;
V++;
lfo0 = -0.7071f; //reset LFO phase - good idea?
lfo1 = 0.7071f;
}
tl += tfrq * (l - tl); //treble boost
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; //worth making all these local variables?
*out0++ = l;
*out1++ = r;
}
if(frame<sampleFrames)
{
if(activevoices == 0 && programs[curProgram].param[4] > 0.5f)
{ lfo0 = -0.7071f; lfo1 = 0.7071f; } //reset LFO phase - good idea?
int32_t note = notes[event++];
int32_t vel = notes[event++];
noteOn(note, vel);
}
}
if(fabs(tl)<1.0e-10) tl = 0.0f; //anti-denormal
if(fabs(tr)<1.0e-10) tr = 0.0f;
if (fabs(tl) < 1.0e-10) tl = 0.0f; //anti-denormal
if (fabs(tr) < 1.0e-10) tr = 0.0f;
for(v=0; v<activevoices; v++) if(voice[v].env < SILENCE) voice[v] = voice[--activevoices];
for (v = 0; v < activevoices; v++) if (voice[v].env < SILENCE) voice[v] = voice[--activevoices];
notes[0] = EVENTS_DONE; //mark events buffer as done
}
void mdaEPiano::noteOn(int32_t note, int32_t velocity)
{
float * param = programs[curProgram].param;
float l=99.0f;
int32_t v, vl=0, k, s;
float l = 99.0f;
int32_t v, vl = 0, k, s;
if(velocity > 0)
if (velocity > 0)
{
if(activevoices < poly) //add a note
if (activevoices < poly) //add a note
{
vl = activevoices;
activevoices++;
@ -485,69 +421,143 @@ void mdaEPiano::noteOn(int32_t note, int32_t velocity)
}
else //steal a note
{
for(v=0; v<poly; v++) //find quietest voice
for (v = 0; v < poly; v++) //find quietest voice
{
if(voice[v].env < l) { l = voice[v].env; vl = v; }
if (voice[v].env < l) {
l = voice[v].env;
vl = v;
}
}
}
k = (note - 60) * (note - 60);
l = fine + random * ((float)(k % 13) - 6.5f); //random & fine tune
if(note > 60) l += stretch * (float)k; //stretch
if (note > 60) l += stretch * (float)k; //stretch
s = size;
//if(velocity > 40) s += (int32_t)(sizevel * (float)(velocity - 40)); - no velocity to hardness in ePiano
//if(velocity > 40) s += (VstInt32)(sizevel * (float)(velocity - 40)); - no velocity to hardness in ePiano
k = 0;
while(note > (kgrp[k].high + s)) k += 3; //find keygroup
while (note > (kgrp[k].high + s)) k += 3; //find keygroup
l += (float)(note - kgrp[k].root); //pitch
l = 32000.0f * iFs * (float)exp(0.05776226505 * l);
voice[vl].delta = (int32_t)(65536.0f * l);
voice[vl].frac = 0;
if(velocity > 48) k++; //mid velocity sample
if(velocity > 80) k++; //high velocity sample
if (velocity > 48) k++; //mid velocity sample
if (velocity > 80) k++; //high velocity sample
voice[vl].pos = kgrp[k].pos;
voice[vl].end = kgrp[k].end - 1;
voice[vl].loop = kgrp[k].loop;
voice[vl].env = (3.0f + 2.0f * velsens) * (float)pow(0.0078f * velocity, velsens); //velocity
if(note > 60) voice[vl].env *= (float)exp(0.01f * (float)(60 - note)); //new! high notes quieter
if (note > 60) voice[vl].env *= (float)exp(0.01f * (float)(60 - note)); //new! high notes quieter
l = 50.0f + param[4] * param[4] * muff + muffvel * (float)(velocity - 64); //muffle
if(l < (55.0f + 0.4f * (float)note)) l = 55.0f + 0.4f * (float)note;
if(l > 210.0f) l = 210.0f;
if (l < (55.0f + 0.4f * (float)note)) l = 55.0f + 0.4f * (float)note;
if (l > 210.0f) l = 210.0f;
voice[vl].ff = l * l * iFs;
voice[vl].note = note; //note->pan
if(note < 12) note = 12;
if(note > 108) note = 108;
if (note < 12) note = 12;
if (note > 108) note = 108;
l = volume;
voice[vl].outr = l + l * width * (float)(note - 60);
voice[vl].outl = l + l - voice[vl].outr;
if(note < 44) note = 44; //limit max decay length
if (note < 44) note = 44; //limit max decay length
voice[vl].dec = (float)exp(-iFs * exp(-1.0 + 0.03 * (double)note - 2.0f * param[0]));
}
else //note off
{
for(v=0; v<NVOICES; v++) if(voice[v].note==note) //any voices playing that note?
{
if(sustain==0)
for (v = 0; v < NVOICES; v++) if (voice[v].note == note) //any voices playing that note?
{
voice[v].dec = (float)exp(-iFs * exp(6.0 + 0.01 * (double)note - 5.0 * param[1]));
if (sustain == 0)
{
voice[v].dec = (float)exp(-iFs * exp(6.0 + 0.01 * (double)note - 5.0 * param[1]));
}
else voice[v].note = SUSTAIN;
}
else voice[v].note = SUSTAIN;
}
}
}
int32_t mdaEPiano::processEvents()
bool mdaEPiano::processMidiMessage(uint8_t type, uint8_t data1, uint8_t data2)
{
float* param = programs[curProgram].param;
int32_t npos = 0;
switch (type)
{
case 0x80: //note off
notes[npos++] = 0; //delta
notes[npos++] = data1 & 0x7F; //note
notes[npos++] = 0; //vel
break;
case 0x90: //note on
notes[npos++] = 0; //delta
notes[npos++] = data1 & 0x7F; //note
notes[npos++] = data2 & 0x7F; //vel
break;
case 0xB0: //controller
switch (data1)
{
case 0x01: //mod wheel
modwhl = 0.0078f * (float)(data2);
if (modwhl > 0.05f) //over-ride pan/trem depth
{
rmod = lmod = modwhl; //lfo depth
if (param[4] < 0.5f) rmod = -rmod;
}
break;
case 0x07: //volume
volume = 0.00002f * (float)(data2 * data2);
break;
case 0x40: //sustain pedal
case 0x42: //sustenuto pedal
sustain = data2 & 0x40;
if (sustain == 0)
{
notes[npos++] = 0;
notes[npos++] = SUSTAIN; //end all sustained notes
notes[npos++] = 0;
}
break;
default: //all notes off
if (data1 > 0x7A)
{
for (int32_t v = 0; v < NVOICES; v++) voice[v].dec = 0.99f;
sustain = 0;
muff = 160.0f;
}
break;
}
break;
case 0xC0: //program change
if (data1 < NPROGS) setProgram(data1);
break;
default: break;
}
if (npos > EVENTBUFFER)
npos -= 3; //discard events if buffer full!!
notes[npos] = EVENTS_DONE;
return (true);
}
/*
int32_t mdaEPiano::processEvents()
{
float * param = programs[curProgram].param;
int32_t npos=0;
@ -621,7 +631,8 @@ int32_t mdaEPiano::processEvents()
event++; //?
}
notes[npos] = EVENTS_DONE;
*/
return 1;
}
return 1;
}
*/

@ -60,9 +60,7 @@ public:
~mdaEPiano();
virtual void process(int16_t **outputs_r, int16_t **outputs_l, int32_t sampleFrames);
virtual void processReplacing(float **inputs, float **outputs, int32_t sampleframes);
virtual int32_t processEvents(); // virtual int32_t processEvents(VstEvents* events);
virtual bool processMidiMessage(uint8_t type, uint8_t data1, uint8_t data2);
virtual void setProgram(int32_t program);
//virtual void setProgramName(char *name);
//virtual void getProgramName(char *name);

Loading…
Cancel
Save