|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|