From e360047054117d63fb579ec9231e9dc77c99f12a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 8 Aug 2008 22:45:58 +0000 Subject: Add preliminary (library side only) LV2 port of MDA (open-sourced VST plugins). git-svn-id: http://svn.drobilla.net/lad/mda-lv2@1321 a436a847-0d15-0410-975c-d299462d15a1 --- src/mdaDX10.cpp | 594 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 594 insertions(+) create mode 100644 src/mdaDX10.cpp (limited to 'src/mdaDX10.cpp') diff --git a/src/mdaDX10.cpp b/src/mdaDX10.cpp new file mode 100644 index 0000000..f533bfe --- /dev/null +++ b/src/mdaDX10.cpp @@ -0,0 +1,594 @@ +// +// Plug-in: "mda mdaDX10" v1.0 +// +// Copyright(c)1999-2000 Paul Kellett (maxim digital audio) +// + +#include "mdaDX10.h" + +#include +#include //rand() +#include + +AudioEffect *createEffectInstance(audioMasterCallback audioMaster) +{ + return new mdaDX10(audioMaster); +} + + +mdaDX10::mdaDX10(audioMasterCallback audioMaster) : AudioEffectX(audioMaster, NPROGS, NPARAMS) +{ + long i=0; + Fs = 44100.0f; + + programs = new mdaDX10Program[NPROGS]; + if(programs) + { //Att Dec Rel | Rat C Rat F Att Dec Sus Rel Vel | Vib Oct Fine Rich Thru LFO + fillpatch(i++, "Bright E.Piano", 0.000f, 0.650f, 0.441f, 0.842f, 0.329f, 0.230f, 0.800f, 0.050f, 0.800f, 0.900f, 0.000f, 0.500f, 0.500f, 0.447f, 0.000f, 0.414f); + fillpatch(i++, "Jazz E.Piano", 0.000f, 0.500f, 0.100f, 0.671f, 0.000f, 0.441f, 0.336f, 0.243f, 0.800f, 0.500f, 0.000f, 0.500f, 0.500f, 0.178f, 0.000f, 0.500f); + fillpatch(i++, "E.Piano Pad", 0.000f, 0.700f, 0.400f, 0.230f, 0.184f, 0.270f, 0.474f, 0.224f, 0.800f, 0.974f, 0.250f, 0.500f, 0.500f, 0.428f, 0.836f, 0.500f); + fillpatch(i++, "Fuzzy E.Piano", 0.000f, 0.700f, 0.400f, 0.320f, 0.217f, 0.599f, 0.670f, 0.309f, 0.800f, 0.500f, 0.263f, 0.507f, 0.500f, 0.276f, 0.638f, 0.526f); + fillpatch(i++, "Soft Chimes", 0.400f, 0.600f, 0.650f, 0.760f, 0.000f, 0.390f, 0.250f, 0.160f, 0.900f, 0.500f, 0.362f, 0.500f, 0.500f, 0.401f, 0.296f, 0.493f); + fillpatch(i++, "Harpsichord", 0.000f, 0.342f, 0.000f, 0.280f, 0.000f, 0.880f, 0.100f, 0.408f, 0.740f, 0.000f, 0.000f, 0.600f, 0.500f, 0.842f, 0.651f, 0.500f); + fillpatch(i++, "Funk Clav", 0.000f, 0.400f, 0.100f, 0.360f, 0.000f, 0.875f, 0.160f, 0.592f, 0.800f, 0.500f, 0.000f, 0.500f, 0.500f, 0.303f, 0.868f, 0.500f); + fillpatch(i++, "Sitar", 0.000f, 0.500f, 0.704f, 0.230f, 0.000f, 0.151f, 0.750f, 0.493f, 0.770f, 0.500f, 0.000f, 0.400f, 0.500f, 0.421f, 0.632f, 0.500f); + fillpatch(i++, "Chiff Organ", 0.600f, 0.990f, 0.400f, 0.320f, 0.283f, 0.570f, 0.300f, 0.050f, 0.240f, 0.500f, 0.138f, 0.500f, 0.500f, 0.283f, 0.822f, 0.500f); + fillpatch(i++, "Tinkle", 0.000f, 0.500f, 0.650f, 0.368f, 0.651f, 0.395f, 0.550f, 0.257f, 0.900f, 0.500f, 0.300f, 0.800f, 0.500f, 0.000f, 0.414f, 0.500f); + fillpatch(i++, "Space Pad", 0.000f, 0.700f, 0.520f, 0.230f, 0.197f, 0.520f, 0.720f, 0.280f, 0.730f, 0.500f, 0.250f, 0.500f, 0.500f, 0.336f, 0.428f, 0.500f); + fillpatch(i++, "Koto", 0.000f, 0.240f, 0.000f, 0.390f, 0.000f, 0.880f, 0.100f, 0.600f, 0.740f, 0.500f, 0.000f, 0.500f, 0.500f, 0.526f, 0.480f, 0.500f); + fillpatch(i++, "Harp", 0.000f, 0.500f, 0.700f, 0.160f, 0.000f, 0.158f, 0.349f, 0.000f, 0.280f, 0.900f, 0.000f, 0.618f, 0.500f, 0.401f, 0.000f, 0.500f); + fillpatch(i++, "Jazz Guitar", 0.000f, 0.500f, 0.100f, 0.390f, 0.000f, 0.490f, 0.250f, 0.250f, 0.800f, 0.500f, 0.000f, 0.500f, 0.500f, 0.263f, 0.145f, 0.500f); + fillpatch(i++, "Steel Drum", 0.000f, 0.300f, 0.507f, 0.480f, 0.730f, 0.000f, 0.100f, 0.303f, 0.730f, 1.000f, 0.000f, 0.600f, 0.500f, 0.579f, 0.000f, 0.500f); + fillpatch(i++, "Log Drum", 0.000f, 0.300f, 0.500f, 0.320f, 0.000f, 0.467f, 0.079f, 0.158f, 0.500f, 0.500f, 0.000f, 0.400f, 0.500f, 0.151f, 0.020f, 0.500f); + fillpatch(i++, "Trumpet", 0.000f, 0.990f, 0.100f, 0.230f, 0.000f, 0.000f, 0.200f, 0.450f, 0.800f, 0.000f, 0.112f, 0.600f, 0.500f, 0.711f, 0.000f, 0.401f); + fillpatch(i++, "Horn", 0.280f, 0.990f, 0.280f, 0.230f, 0.000f, 0.180f, 0.400f, 0.300f, 0.800f, 0.500f, 0.000f, 0.400f, 0.500f, 0.217f, 0.480f, 0.500f); + fillpatch(i++, "Reed 1", 0.220f, 0.990f, 0.250f, 0.170f, 0.000f, 0.240f, 0.310f, 0.257f, 0.900f, 0.757f, 0.000f, 0.500f, 0.500f, 0.697f, 0.803f, 0.500f); + fillpatch(i++, "Reed 2", 0.220f, 0.990f, 0.250f, 0.450f, 0.070f, 0.240f, 0.310f, 0.360f, 0.900f, 0.500f, 0.211f, 0.500f, 0.500f, 0.184f, 0.000f, 0.414f); + fillpatch(i++, "Violin", 0.697f, 0.990f, 0.421f, 0.230f, 0.138f, 0.750f, 0.390f, 0.513f, 0.800f, 0.316f, 0.467f, 0.678f, 0.500f, 0.743f, 0.757f, 0.487f); + fillpatch(i++, "Chunky Bass", 0.000f, 0.400f, 0.000f, 0.280f, 0.125f, 0.474f, 0.250f, 0.100f, 0.500f, 0.500f, 0.000f, 0.400f, 0.500f, 0.579f, 0.592f, 0.500f); + fillpatch(i++, "E.Bass", 0.230f, 0.500f, 0.100f, 0.395f, 0.000f, 0.388f, 0.092f, 0.250f, 0.150f, 0.500f, 0.200f, 0.200f, 0.500f, 0.178f, 0.822f, 0.500f); + fillpatch(i++, "Clunk Bass", 0.000f, 0.600f, 0.400f, 0.230f, 0.000f, 0.450f, 0.320f, 0.050f, 0.900f, 0.500f, 0.000f, 0.200f, 0.500f, 0.520f, 0.105f, 0.500f); + fillpatch(i++, "Thick Bass", 0.000f, 0.600f, 0.400f, 0.170f, 0.145f, 0.290f, 0.350f, 0.100f, 0.900f, 0.500f, 0.000f, 0.400f, 0.500f, 0.441f, 0.309f, 0.500f); + fillpatch(i++, "Sine Bass", 0.000f, 0.600f, 0.490f, 0.170f, 0.151f, 0.099f, 0.400f, 0.000f, 0.900f, 0.500f, 0.000f, 0.400f, 0.500f, 0.118f, 0.013f, 0.500f); + fillpatch(i++, "Square Bass", 0.000f, 0.600f, 0.100f, 0.320f, 0.000f, 0.350f, 0.670f, 0.100f, 0.150f, 0.500f, 0.000f, 0.200f, 0.500f, 0.303f, 0.730f, 0.500f); + fillpatch(i++, "Upright Bass 1", 0.300f, 0.500f, 0.400f, 0.280f, 0.000f, 0.180f, 0.540f, 0.000f, 0.700f, 0.500f, 0.000f, 0.400f, 0.500f, 0.296f, 0.033f, 0.500f); + fillpatch(i++, "Upright Bass 2", 0.300f, 0.500f, 0.400f, 0.360f, 0.000f, 0.461f, 0.070f, 0.070f, 0.700f, 0.500f, 0.000f, 0.400f, 0.500f, 0.546f, 0.467f, 0.500f); + fillpatch(i++, "Harmonics", 0.000f, 0.500f, 0.500f, 0.280f, 0.000f, 0.330f, 0.200f, 0.000f, 0.700f, 0.500f, 0.000f, 0.500f, 0.500f, 0.151f, 0.079f, 0.500f); + fillpatch(i++, "Scratch", 0.000f, 0.500f, 0.000f, 0.000f, 0.240f, 0.580f, 0.630f, 0.000f, 0.000f, 0.500f, 0.000f, 0.600f, 0.500f, 0.816f, 0.243f, 0.500f); + fillpatch(i++, "Syn Tom", 0.000f, 0.355f, 0.350f, 0.000f, 0.105f, 0.000f, 0.000f, 0.200f, 0.500f, 0.500f, 0.000f, 0.645f, 0.500f, 1.000f, 0.296f, 0.500f); + + setProgram(0); + } + + if(audioMaster) + { + setNumInputs(0); + setNumOutputs(NOUTS); + canProcessReplacing(); + isSynth(); + setUniqueID("MDAx"); /// + } + + //initialise... + for(i=0; i0.98f) cdec = 1.0f; else + cdec = (float)exp(-ifs * exp(5.0 - 8.0 * param[1])); + crel = (float)exp(-ifs * exp(5.0 - 5.0 * param[2])); + mdec = 1.0f - (float)exp(-ifs * exp(6.0 - 7.0 * param[6])); + mrel = 1.0f - (float)exp(-ifs * exp(5.0 - 8.0 * param[8])); + + rich = 0.50f - 3.0f * param[13] * param[13]; + //rich = -1.0f + 2 * param[13]; + modmix = 0.25f * param[14] * param[14]; + dlfo = 628.3f * ifs * 25.0f * param[15] * param[15]; //these params not in original DX10 +} + + +void mdaDX10::setSampleRate(float sampleRate) +{ + AudioEffectX::setSampleRate(sampleRate); + Fs = sampleRate; +} + + +void mdaDX10::resume() +{ + DECLARE_LVZ_DEPRECATED (wantEvents) (); + lfo0 = 0.0f; + lfo1 = 1.0f; //reset LFO phase +} + + +mdaDX10::~mdaDX10 () //destroy any buffers... +{ + if(programs) delete [] programs; +} + + +void mdaDX10::setProgram(LvzInt32 program) +{ + long i; + + mdaDX10Program *p = &programs[program]; + curProgram = program; + for(i=0; iparam[i]; + update(); +} + + +void mdaDX10::setParameter(LvzInt32 index, float value) +{ + mdaDX10Program *p = &programs[curProgram]; + param[index] = p->param[index] = value; + update(); +} + + +void mdaDX10::fillpatch(long p, const 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 p12, float p13, float p14, float p15) +{ + strcpy(programs[p].name, name); + programs[p].param[0] = p0; programs[p].param[1] = p1; + programs[p].param[2] = p2; programs[p].param[3] = p3; + 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[12] = p12; programs[p].param[13] = p13; + programs[p].param[14] = p14; programs[p].param[15] = p15; +} + + +float mdaDX10::getParameter(LvzInt32 index) { return param[index]; } +void mdaDX10::setProgramName(char *name) { strcpy(programs[curProgram].name, name); } +void mdaDX10::getProgramName(char *name) { strcpy(name, programs[curProgram].name); } +void mdaDX10::setBlockSize(LvzInt32 blockSize) { AudioEffectX::setBlockSize(blockSize); } +bool mdaDX10::getEffectName(char* name) { strcpy(name, "DX10"); return true; } +bool mdaDX10::getVendorString(char* text) { strcpy(text, "mda"); return true; } +bool mdaDX10::getProductString(char* text) { strcpy(text, "mda DX10"); return true; } + + +bool mdaDX10::getOutputProperties(LvzInt32 index, LvzPinProperties* properties) +{ + if(indexlabel, "DX10"); + properties->flags = kLvzPinIsActive; + if(index<2) properties->flags |= kLvzPinIsStereo; //make channel 1+2 stereo + return true; + } + return false; +} + + +bool mdaDX10::getProgramNameIndexed(LvzInt32 category, LvzInt32 index, char* text) +{ + if(index0 || notes[event]sampleFrames) frames = sampleFrames; + frames -= frame; + frame += frames; + + while(--frames>=0) //would be faster with voice loop outside frame loop! + { //but then each voice would need it's own LFO... + VOICE *V = voice; + o = 0.0f; + + if(--k<0) + { + lfo0 += dlfo * lfo1; //sine LFO + lfo1 -= dlfo * lfo0; + mw = lfo1 * (modwhl + vibrato); + k=100; + } + + for(v=0; venv; + if(e > SILENCE) //**** this is the synth **** + { + V->env = e * V->cdec; //decay & release + V->cenv += V->catt * (e - V->cenv); //attack + + x = V->dmod * V->mod0 - V->mod1; //could add more modulator blocks like + V->mod1 = V->mod0; //this for a wider range of FM sounds + V->mod0 = x; + V->menv += V->mdec * (V->mlev - V->menv); + + x = V->car + V->dcar + x * V->menv + mw; //carrier phase + while(x > 1.0f) x -= 2.0f; //wrap phase + while(x < -1.0f) x += 2.0f; + V->car = x; + o += V->cenv * (m * V->mod1 + (x + x * x * x * (w * x * x - 1.0f - w))); + } //amp env //mod thru-mix //5th-order sine approximation + V++; + } + *out1++ += o; + *out2++ += o; + } + + if(frame0 || notes[event]sampleFrames) frames = sampleFrames; + frames -= frame; + frame += frames; + + while(--frames>=0) //would be faster with voice loop outside frame loop! + { //but then each voice would need it's own LFO... + VOICE *V = voice; + o = 0.0f; + + if(--k<0) + { + lfo0 += dlfo * lfo1; //sine LFO + lfo1 -= dlfo * lfo0; + mw = lfo1 * (modwhl + vibrato); + k=100; + } + + for(v=0; venv; + if(e > SILENCE) //**** this is the synth **** + { + V->env = e * V->cdec; //decay & release + V->cenv += V->catt * (e - V->cenv); //attack + + x = V->dmod * V->mod0 - V->mod1; //could add more modulator blocks like + V->mod1 = V->mod0; //this for a wider range of FM sounds + V->mod0 = x; + V->menv += V->mdec * (V->mlev - V->menv); + + x = V->car + V->dcar + x * V->menv + mw; //carrier phase + while(x > 1.0f) x -= 2.0f; //wrap phase + while(x < -1.0f) x += 2.0f; + V->car = x; + o += V->cenv * (m * V->mod1 + (x + x * x * x * (w * x * x - 1.0f - w))); + } //amp env //mod thru-mix //5th-order sine approximation + + /// xx = x * x; + /// x + x + x * xx * (xx - 3.0f); + + V++; + } + *out1++ = o; + *out2++ = o; + } + + if(frame= 0) + { + *out1++ = 0.0f; + *out2++ = 0.0f; + } + } + K=k; MW=mw; //remember these so vibrato speed not buffer size dependant! + notes[0] = EVENTS_DONE; +} + + +void mdaDX10::noteOn(long note, long velocity) +{ + float l = 1.0f; + long v, vl=0; + + if(velocity>0) + { + for(v=0; v50.0f) l = 50.0f; //key tracking + l *= (64.0f + velsens * (velocity - 64)); //vel sens + voice[vl].menv = depth * l; + voice[vl].mlev = dept2 * l; + voice[vl].mdec = mdec; + + voice[vl].dmod = ratio * voice[vl].dcar; //sine oscillator + voice[vl].mod0 = 0.0f; + voice[vl].mod1 = (float)sin(voice[vl].dmod); + voice[vl].dmod = 2.0f * (float)cos(voice[vl].dmod); + //scale volume with richness + voice[vl].env = (1.5f - param[13]) * volume * (velocity + 10); + voice[vl].catt = catt; + voice[vl].cenv = 0.0f; + voice[vl].cdec = cdec; + } + else //note off + { + for(v=0; vnumEvents; i++) + { + if((ev->events[i])->type != kLvzMidiType) continue; + LvzMidiEvent* event = (LvzMidiEvent*)ev->events[i]; + char* midiData = event->midiData; + + switch(midiData[0] & 0xf0) //status byte (all channels) + { + case 0x80: //note off + notes[npos++] = event->deltaFrames; //delta + notes[npos++] = midiData[1] & 0x7F; //note + notes[npos++] = 0; //vel + break; + + case 0x90: //note on + notes[npos++] = event->deltaFrames; //delta + notes[npos++] = midiData[1] & 0x7F; //note + notes[npos++] = midiData[2] & 0x7F; //vel + break; + + case 0xB0: //controller + switch(midiData[1]) + { + case 0x01: //mod wheel + modwhl = 0.00000005f * (float)(midiData[2] * midiData[2]); + break; + + case 0x07: //volume + volume = 0.00000035f * (float)(midiData[2] * midiData[2]); + break; + + case 0x40: //sustain + sustain = midiData[2] & 0x40; + if(sustain==0) + { + notes[npos++] = event->deltaFrames; + notes[npos++] = SUSTAIN; //end all sustained notes + notes[npos++] = 0; + } + break; + + default: //all notes off + if(midiData[1]>0x7A) + { + for(long v=0; v0.0f) pbend = 1.0f + 0.000014951f * pbend; + else pbend = 1.0f + 0.000013318f * pbend; + break; + + default: break; + } + + if(npos>EVENTBUFFER) npos -= 3; //discard events if buffer full!! + event++; + } + notes[npos] = EVENTS_DONE; + return 1; +} + -- cgit v1.2.1