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/mdaVocoder.cpp | 382 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 src/mdaVocoder.cpp (limited to 'src/mdaVocoder.cpp') diff --git a/src/mdaVocoder.cpp b/src/mdaVocoder.cpp new file mode 100644 index 0000000..c6a6ed4 --- /dev/null +++ b/src/mdaVocoder.cpp @@ -0,0 +1,382 @@ +// +// Plug-in: "mda Vocoder" v1.0 +// +// Copyright(c)1999-2000 Paul Kellett (maxim digital audio) +// + +#include "mdaVocoder.h" + +#include +#include +#include +#include + +AudioEffect *createEffectInstance(audioMasterCallback audioMaster) +{ + return new mdaVocoder(audioMaster); +} + +mdaVocoderProgram::mdaVocoderProgram() ///default program settings +{ + param[0] = 0.33f; //input select + param[1] = 0.50f; //output dB + param[2] = 0.40f; //hi thru + param[3] = 0.40f; //hi band + param[4] = 0.16f; //envelope + param[5] = 0.55f; //filter q + param[6] = 0.6667f;//freq range + param[7] = 0.33f; //num bands + strcpy(name, "Vocoder"); +} + + +mdaVocoder::mdaVocoder(audioMasterCallback audioMaster): AudioEffectX(audioMaster, NPROGS, NPARAMS) +{ + setNumInputs(2); + setNumOutputs(2); + setUniqueID("mdav"); ///identify plug-in here + //canMono(); + canProcessReplacing(); + + programs = new mdaVocoderProgram[numPrograms]; + setProgram(0); + + ///differences from default program... + programs[1].param[7] = 0.66f; + strcpy(programs[1].name,"16 Band Vocoder"); + programs[2].param[2] = 0.00f; + programs[2].param[3] = 0.00f; + programs[2].param[6] = 0.50f; + strcpy(programs[2].name,"Old Vocoder"); + programs[3].param[3] = 0.00f; + programs[3].param[5] = 0.70f; + programs[3].param[6] = 0.50f; + strcpy(programs[3].name,"Choral Vocoder"); + programs[4].param[4] = 0.78f; + programs[4].param[6] = 0.30f; + strcpy(programs[4].name,"Pad Vocoder"); + + suspend(); +} + +bool mdaVocoder::getProductString(char* text) { strcpy(text, "mda Vocoder"); return true; } +bool mdaVocoder::getVendorString(char* text) { strcpy(text, "mda"); return true; } +bool mdaVocoder::getEffectName(char* name) { strcpy(name, "Vocoder"); return true; } + +void mdaVocoder::resume() ///update internal parameters... +{ + double tpofs = 6.2831853/getSampleRate(); + double rr, th, re; + float sh; + long i; + + swap = 1; if(param[0]>0.5f) swap = 0; + gain = (float)pow(10.0f, 2.0f * param[1] - 3.0f * param[5] - 2.0f); + + thru = (float)pow(10.0f, 0.5f + 2.0f * param[1]); + high = param[3] * param[3] * param[3] * thru; + thru *= param[2] * param[2] * param[2]; + + if(param[7]<0.5f) + { + nbnd=8; + re=0.003f; + f[1][2] = 3000.0f; + f[2][2] = 2200.0f; + f[3][2] = 1500.0f; + f[4][2] = 1080.0f; + f[5][2] = 700.0f; + f[6][2] = 390.0f; + f[7][2] = 190.0f; + } + else + { + nbnd=16; + re=0.0015f; + f[ 1][2] = 5000.0f; //+1000 + f[ 2][2] = 4000.0f; //+750 + f[ 3][2] = 3250.0f; //+500 + f[ 4][2] = 2750.0f; //+450 + f[ 5][2] = 2300.0f; //+300 + f[ 6][2] = 2000.0f; //+250 + f[ 7][2] = 1750.0f; //+250 + f[ 8][2] = 1500.0f; //+250 + f[ 9][2] = 1250.0f; //+250 + f[10][2] = 1000.0f; //+250 + f[11][2] = 750.0f; //+210 + f[12][2] = 540.0f; //+190 + f[13][2] = 350.0f; //+155 + f[14][2] = 195.0f; //+100 + f[15][2] = 95.0f; + } + + if(param[4]<0.05f) //freeze + { + for(i=0;iname); + for(i=0; iparam[i]; + resume(); +} + + +void mdaVocoder::setParameter(LvzInt32 index, float value) { param[index] = value; resume(); } +float mdaVocoder::getParameter(LvzInt32 index) { return param[index]; } +void mdaVocoder::setProgramName(char *name) { strcpy(programName, name); } +void mdaVocoder::getProgramName(char *name) { strcpy(name, programName); } + + +void mdaVocoder::getParameterName(LvzInt32 index, char *label) +{ + switch(index) + { + case 0: strcpy(label, "Mod In:"); break; + case 1: strcpy(label, "Output"); break; + case 2: strcpy(label, "Hi Thru"); break; + case 3: strcpy(label, "Hi Band"); break; + case 4: strcpy(label, "Envelope"); break; + case 5: strcpy(label, "Filter Q"); break; + case 6: strcpy(label, "Mid Freq"); break; + default: strcpy(label, "Quality"); + } +} + + +void mdaVocoder::getParameterDisplay(LvzInt32 index, char *text) +{ + char string[16]; + + switch(index) + { + case 0: if(swap) strcpy(string, "RIGHT"); else strcpy(string, "LEFT"); break; + case 1: sprintf(string, "%.1f", 40.0f * param[index] - 20.0f); break; + case 4: if(param[index]<0.05f) strcpy(string, "FREEZE"); + else sprintf(string, "%.1f", (float)pow(10.0f, 1.0f + 3.0f * param[index])); break; + case 6: sprintf(string, "%.0f", 800.0f * (float)pow(2.0f, 3.0f * param[index] - 2.0f)); break; + case 7: if(nbnd==8) strcpy(string, "8 BAND"); else strcpy(string, "16 BAND"); break; + + default: sprintf(string, "%.0f", 100.0f * param[index]); + } + string[8] = 0; + strcpy(text, (char *)string); +} + + +void mdaVocoder::getParameterLabel(LvzInt32 index, char *label) +{ + switch(index) + { + case 7: + case 0: strcpy(label, ""); break; + case 1: strcpy(label, "dB"); break; + case 4: strcpy(label, "ms"); break; + case 6: strcpy(label, "Hz"); break; + default: strcpy(label, "%"); + } +} + + +void mdaVocoder::process(float **inputs, float **outputs, LvzInt32 sampleFrames) +{ + float *in1 = inputs[0]; + float *in2 = inputs[1]; + float *out1 = outputs[0]; + float *out2 = outputs[1]; + float a, b, c, d, o=0.0f, aa, bb, oo=kout, g=gain, ht=thru, hh=high, tmp; + long i, k=kval, sw=swap, nb=nbnd; + + --in1; + --in2; + --out1; + --out2; + while(--sampleFrames >= 0) + { + a = *++in1; //speech + b = *++in2; //synth + c = out1[1]; + d = out2[1]; + if(sw==0) { tmp=a; a=b; b=tmp; } //swap channels + + tmp = a - f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis + f[0][7] = a; + a = tmp; + + if(tmp<0.0f) tmp = -tmp; + f[0][11] -= f[0][12] * (f[0][11] - tmp); //high band envelope + o = f[0][11] * (ht * a + hh * (b - f[0][3])); //high band + high thru + + f[0][3] = b; //integrate carrier for HF band + + if(++k & 0x1) //this block runs at half sample rate + { + oo = 0.0f; + aa = a + f[0][9] - f[0][8] - f[0][8]; //apply zeros here instead of in each reson + f[0][9] = f[0][8]; f[0][8] = a; + bb = b + f[0][5] - f[0][4] - f[0][4]; + f[0][5] = f[0][4]; f[0][4] = b; + + for(i=1; i16kHz) + + *++out1 = c + o; + *++out2 = d + o; + } + + kout = oo; + kval = k & 0x1; + if(fabs(f[0][11])<1.0e-10) f[0][11] = 0.0f; //catch HF envelope denormal + + for(i=1;i10.0f) suspend(); //catch instability +} + + +void mdaVocoder::processReplacing(float **inputs, float **outputs, LvzInt32 sampleFrames) +{ + float *in1 = inputs[0]; + float *in2 = inputs[1]; + float *out1 = outputs[0]; + float *out2 = outputs[1]; + float a, b, o=0.0f, aa, bb, oo=kout, g=gain, ht=thru, hh=high, tmp; + long i, k=kval, sw=swap, nb=nbnd; + + --in1; + --in2; + --out1; + --out2; + while(--sampleFrames >= 0) + { + a = *++in1; //speech + b = *++in2; //synth + if(sw==0) { tmp=a; a=b; b=tmp; } //swap channels + + tmp = a - f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis + f[0][7] = a; + a = tmp; + + if(tmp<0.0f) tmp = -tmp; + f[0][11] -= f[0][12] * (f[0][11] - tmp); //high band envelope + o = f[0][11] * (ht * a + hh * (b - f[0][3])); //high band + high thru + + f[0][3] = b; //integrate carrier for HF band + + if(++k & 0x1) //this block runs at half sample rate + { + oo = 0.0f; + aa = a + f[0][9] - f[0][8] - f[0][8]; //apply zeros here instead of in each reson + f[0][9] = f[0][8]; f[0][8] = a; + bb = b + f[0][5] - f[0][4] - f[0][4]; + f[0][5] = f[0][4]; f[0][4] = b; + + for(i=1; i16kHz) + + *++out1 = o; + *++out2 = o; + } + + kout = oo; + kval = k & 0x1; + if(fabs(f[0][11])<1.0e-10) f[0][11] = 0.0f; //catch HF envelope denormal + + for(i=1;i10.0f) suspend(); //catch instability +} -- cgit v1.2.1