// // 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("mdaVocoder"); ///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 }