martin@0: //------------------------------------------------------------------------------------------------------- martin@0: // VST Plug-Ins SDK martin@0: // Version 2.4 $Date: 2006/11/13 09:08:27 $ martin@0: // martin@0: // Category : VST 2.x SDK Samples martin@0: // Filename : adelay.cpp martin@0: // Created by : Steinberg Media Technologies martin@0: // Description : Simple Delay plugin (Mono->Stereo) martin@0: // martin@0: // © 2006, Steinberg Media Technologies, All Rights Reserved martin@0: //------------------------------------------------------------------------------------------------------- martin@0: martin@0: martin@0: #ifndef __SoundField__ martin@0: #include "SoundField.h" martin@0: #endif martin@0: //C++ Headers martin@0: #include martin@0: #include martin@0: #include martin@0: martin@0: //GUI Headers martin@0: #include "aeffguieditor.h" martin@0: martin@0: martin@0: martin@0: //----------------------------------------------------------------------------- martin@0: SoundFieldProgram::SoundFieldProgram () martin@0: { martin@0: //Define name if all programs are to be the same martin@0: martin@0: } martin@0: martin@0: //----------------------------------------------------------------------------- martin@0: SoundField::SoundField (audioMasterCallback audioMaster) martin@0: : AudioEffectX (audioMaster, 1, kNumParameters) martin@0: { martin@0: // init martin@0: programs = new SoundFieldProgram[numPrograms]; martin@0: martin@0: martin@0: // if (programs) martin@0: // setProgram (0); martin@0: martin@0: //Set the number of input and output channels martin@0: setNumInputs (4); // 4 Channel Classic B-Format Input martin@0: setNumOutputs (2); // MAX_CHANNELS 5.1 Output martin@0: martin@0: martin@0: // We initialize the arrangements to default values. martin@0: // Nevertheless, the host should modify them via martin@0: // appropriate calls to setSpeakerArrangement. martin@0: //allocateArrangement (&plugInput, MAX_CHANNELS); martin@0: //plugInput->type = kSpeakerArr51; martin@0: martin@0: //allocateArrangement (&plugOutput, 2); // MAX_CHANNELS, now 2 for stereo martin@0: //plugOutput->type = kSpeakerArrStereo; // kSpeakerArr51, now set output to stereo martin@0: martin@0: martin@0: martin@0: setUniqueID ('MMa2'); // this should be unique, use the Steinberg web page for plugin Id registration martin@0: martin@0: martin@0: if(setProcessPrecision(kVstProcessPrecision64)){ martin@0: setProcessPrecision(kVstProcessPrecision64); martin@0: bits=64; martin@0: } martin@0: else { martin@0: bits=32; martin@0: } martin@0: martin@0: martin@0: martin@0: //Load GUI martin@0: extern AEffGUIEditor* createEditor (AudioEffectX*); martin@0: setEditor (createEditor (this)); martin@0: martin@0: martin@0: resume (); // flush buffer martin@0: martin@0: canProcessReplacing(); //Plugin can use process replacing martin@0: noTail (); martin@0: martin@0: //Default Program Names martin@0: vst_strncpy (programs[0].name, "Default",kVstMaxProgNameLen); martin@0: martin@0: vst_strncpy (programName, "Default", kVstMaxProgNameLen); // default program name martin@0: martin@0: //version = 2300; martin@0: martin@0: martin@0: // Declare any variables to their default values martin@0: // Default Program Values if NOT using a bank of programs martin@0: martin@0: fMode = 0.f; martin@0: fWidth = 0.5f; martin@0: fPattern = 0.5f; martin@0: fRotate = 0.5f; martin@0: fTilt = 0.5f; martin@0: fTumble = 0.5f; martin@0: fZoom = 0.5f; martin@0: fZoomMethod = 0.f; martin@0: fRearVerb = 0.f; martin@0: fHiVerb = 0.f; martin@0: martin@0: myDecoder.Rotate=0.0; martin@0: myDecoder.Tilt=0.0; martin@0: myDecoder.Tumble=0.0; martin@0: myDecoder.Zoom=0.0; martin@0: myDecoder.ZoomMethod=0.0; martin@0: myDecoder.Width=45.0; martin@0: myDecoder.Pattern=0.5; martin@0: myDecoder.Mode=0; martin@0: myDecoder.RearVerb=-100; martin@0: myDecoder.HiVerb=-100; martin@0: myDecoder.outputL=0.0; martin@0: myDecoder.outputR=0.0; martin@0: myDecoder.outputC=0.0; martin@0: myDecoder.outputS=0.0; martin@0: myDecoder.outputSL=0.0; martin@0: myDecoder.outputSR=0.0; martin@0: myDecoder.surMode=0; martin@0: myDecoder.surPattern=0.5; martin@0: myDecoder.surWidth=60.0; martin@0: myDecoder.subGain=0.0; martin@0: myDecoder.centrePattern=0.5; martin@0: myDecoder.centreGain=0.0; martin@0: myDecoder.subGain=0.0; martin@0: myDecoder.decoderMode=2; martin@0: myDecoder.Fs = sampleRate; martin@0: myDecoder.Fc = 120; martin@0: martin@0: myDecoder.filterCoefs(); martin@0: martin@0: } martin@0: martin@0: martin@0: void SoundField::suspend() martin@0: { martin@0: myDecoder.clearFilter(); martin@0: martin@0: if (editor){ martin@0: ((AEffGUIEditor*)editor)->setParameter (100, 0); martin@0: } martin@0: } martin@0: martin@0: void SoundField::close() martin@0: { martin@0: } martin@0: martin@0: martin@0: void SoundField::open() martin@0: { martin@0: } martin@0: martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: //bool SoundField::getSpeakerArrangement (VstSpeakerArrangement** pluginInput, VstSpeakerArrangement** pluginOutput) martin@0: //{ martin@0: // *pluginInput = plugInput; martin@0: // *pluginOutput = plugOutput; martin@0: // return true; martin@0: //} martin@0: martin@0: //------------------------------------------------------------------------ martin@0: bool SoundField::setSpeakerArrangement (VstSpeakerArrangement* pluginInput, martin@0: VstSpeakerArrangement* pluginOutput) martin@0: { martin@0: if (!pluginOutput || !pluginInput) martin@0: return false; martin@0: martin@0: bool result = true; martin@0: martin@0: // This plug-in can act on any speaker arrangement, martin@0: // provided that there are the same number of inputs/outputs. martin@0: // if (pluginInput->numChannels > MAX_CHANNELS) martin@0: // { martin@0: // // This plug-in can't have so many channels. So we answer martin@0: // // false, and we set the input arrangement with the maximum martin@0: // // number of channels possible martin@0: // result = false; martin@0: // allocateArrangement (&plugInput, MAX_CHANNELS); martin@0: // plugInput->type = kSpeakerArr51; martin@0: // } martin@0: // else martin@0: // { martin@0: // matchArrangement (&plugInput, pluginInput); martin@0: // } martin@0: martin@0: // if (pluginOutput->numChannels != plugInput->numChannels) martin@0: if (pluginOutput->numChannels <= MAX_CHANNELS) martin@0: { martin@0: // This plug-in only deals with symetric IO configurations... martin@0: // result = false; martin@0: // matchArrangement (&plugOutput, plugInput); martin@0: myDecoder.decoderMode=pluginOutput->numChannels; martin@0: } martin@0: else martin@0: { martin@0: // matchArrangement (&plugOutput, pluginOutput); martin@0: myDecoder.decoderMode=6; martin@0: } martin@0: martin@0: return result; martin@0: } martin@0: martin@0: martin@0: void SoundField::setProgram (VstInt32 program) //Host to SET the Program martin@0: { martin@0: curProgram = program; //Change the curProgram value martin@0: } martin@0: martin@0: martin@0: void SoundField::setProgramName(char *name) //SET the Program name martin@0: { martin@0: strcpy(programs[curProgram].name, name); //Host SETS the Program[].name martin@0: } martin@0: martin@0: martin@0: martin@0: void SoundField::getProgramName(char *name) //GET the Program name martin@0: { martin@0: strcpy(name, programs[curProgram].name); //Host GETS the Program[].name martin@0: } martin@0: martin@0: martin@0: martin@0: bool SoundField::getProgramNameIndexed (VstInt32 category, VstInt32 which, char* name) martin@0: { martin@0: if ((unsigned int)which < kNumPrograms) //Check the ProgramNameIndexed is within range martin@0: { martin@0: strcpy(name, programs[which].name); //Host GETS the programs[].name martin@0: return true; //TRUE- ProgramNameIndexed does exits martin@0: } martin@0: return false; //FALSE- ProgramNameIndexed does not exits martin@0: } martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: SoundField::~SoundField () //clears protected variables martin@0: { martin@0: if (programs) martin@0: delete[] programs; martin@0: martin@0: deallocateArrangement (&plugInput); martin@0: deallocateArrangement (&plugOutput); martin@0: } martin@0: martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: void SoundField::resume () //Do this on a resume from the host martin@0: { martin@0: AudioEffectX::resume (); martin@0: if (editor){ martin@0: ((AEffGUIEditor*)editor)->setParameter (101, 0); martin@0: } martin@0: } martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: void SoundField::setParameter (VstInt32 index, float value) // SET Parameter value from host martin@0: { martin@0: switch (index) martin@0: { martin@0: case kMode : martin@0: fMode = value; martin@0: if (value<=0.5f) { martin@0: myDecoder.Mode = 0; martin@0: } martin@0: else { martin@0: myDecoder.Mode = 1; martin@0: } martin@0: break; martin@0: case kWidth: martin@0: fWidth = value; martin@0: myDecoder.Width = (double)value*90; martin@0: break; martin@0: case kPattern: martin@0: fPattern = value; martin@0: myDecoder.Pattern = (double)value; martin@0: break; martin@0: case kRotate : martin@0: fRotate = value; martin@0: if (value==0.5f) { martin@0: myDecoder.Rotate=0.0; martin@0: } martin@0: else { martin@0: myDecoder.Rotate = (double)value*-360+180; martin@0: } martin@0: break; martin@0: case kTilt: martin@0: fTilt = value; martin@0: if (value==0.5f) { martin@0: myDecoder.Tilt=0.0; martin@0: } martin@0: else { martin@0: myDecoder.Tilt = (double)value*-360+180; martin@0: } martin@0: break; martin@0: case kTumble: martin@0: fTumble = value; martin@0: if (value==0.5f) { martin@0: myDecoder.Tumble=0.00; martin@0: } martin@0: else { martin@0: myDecoder.Tumble = (double)value*-360+180; martin@0: } martin@0: break; martin@0: case kZoom: martin@0: fZoom = value; martin@0: myDecoder.Zoom = (double)value*200-100; martin@0: break; martin@0: case kZoomMethod: martin@0: fZoomMethod = value; martin@0: if (value<=0.2f) { martin@0: myDecoder.ZoomMethod = 0; martin@0: } martin@0: else if (value>0.2f && value<=0.5f) { martin@0: myDecoder.ZoomMethod = 1; martin@0: } martin@0: else if (value>0.5f && value<=0.8f) { martin@0: myDecoder.ZoomMethod = 2; martin@0: } martin@0: else if (value>0.8f && value<=1.f) { martin@0: myDecoder.ZoomMethod = 3; martin@0: } martin@0: martin@0: break; martin@0: case kRearVerb : martin@0: fRearVerb = value; martin@0: if (value==0.0f) { martin@0: myDecoder.RearVerb=-100; martin@0: } martin@0: else { martin@0: myDecoder.RearVerb = -36+(double)value*36; martin@0: } martin@0: break; martin@0: case kHiVerb : martin@0: fHiVerb = value; martin@0: if (value==0.0f) { martin@0: myDecoder.HiVerb=-100; martin@0: } martin@0: else { martin@0: myDecoder.HiVerb= -36+(double)value*36; martin@0: } martin@0: break; martin@0: } martin@0: if (editor){ martin@0: ((AEffGUIEditor*)editor)->setParameter (index, value); martin@0: } martin@0: } martin@0: martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: float SoundField::getParameter (VstInt32 index) // GET the value of the parameter martin@0: { martin@0: float returnFloat; //Define a float to output martin@0: martin@0: // Use a switch when more than 1 parameter martin@0: switch (index) martin@0: { martin@0: case kMode : martin@0: returnFloat = fMode; martin@0: break; martin@0: case kWidth: martin@0: returnFloat = fWidth; martin@0: break; martin@0: case kPattern: martin@0: returnFloat = fPattern; martin@0: break; martin@0: case kRotate : martin@0: returnFloat = fRotate; martin@0: break; martin@0: case kTilt: martin@0: returnFloat = fTilt; martin@0: break; martin@0: case kTumble: martin@0: returnFloat = fTumble; martin@0: break; martin@0: case kZoom: martin@0: returnFloat = fZoom; martin@0: break; martin@0: case kZoomMethod: martin@0: returnFloat = fZoomMethod; martin@0: break; martin@0: case kRearVerb : martin@0: returnFloat = fRearVerb; martin@0: break; martin@0: case kHiVerb : martin@0: returnFloat = fHiVerb; martin@0: break; martin@0: case 50: martin@0: returnFloat = bits; martin@0: break; martin@0: } martin@0: return returnFloat; //Returns the chosen Parameters value martin@0: } martin@0: martin@0: //------------------------------------------------------------------------ martin@0: void SoundField::getParameterName (VstInt32 index, char *label) //SET display value shown for Parameters martin@0: { martin@0: switch (index) martin@0: { martin@0: case kMode : martin@0: switch (myDecoder.Mode) { martin@0: case 0 : martin@0: strcpy(label, "XY"); martin@0: break; martin@0: case 1 : martin@0: strcpy(label, "MS"); martin@0: break; martin@0: } martin@0: break; martin@0: case kWidth: martin@0: strcpy(label, "Width"); martin@0: break; martin@0: case kPattern: martin@0: strcpy(label, "Pattern"); martin@0: break; martin@0: case kRotate : martin@0: strcpy(label, "Rotate"); martin@0: break; martin@0: case kTilt: martin@0: strcpy(label, "Tilt"); martin@0: break; martin@0: case kTumble: martin@0: strcpy(label, "Tumble"); martin@0: break; martin@0: case kZoom: martin@0: strcpy(label, "Zoom"); martin@0: break; martin@0: case kZoomMethod: martin@0: strcpy(label, "Zoom Method"); martin@0: break; martin@0: case kRearVerb : martin@0: strcpy(label, "RearVerb"); martin@0: break; martin@0: case kHiVerb : martin@0: strcpy(label, "HiVerb"); martin@0: break; martin@0: } martin@0: } martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: void SoundField::getParameterDisplay (VstInt32 index, char *text) //GET display value shown for Parameters martin@0: { martin@0: switch (index) martin@0: { martin@0: case kMode : martin@0: switch (myDecoder.Mode) { martin@0: case 0 : martin@0: strcpy(text, "XY"); martin@0: break; martin@0: case 1 : martin@0: strcpy(text, "MS"); martin@0: break; martin@0: } martin@0: break; martin@0: case kWidth: martin@0: sprintf (text, "%.1f\u00B0", myDecoder.Width); martin@0: break; martin@0: case kPattern: martin@0: //sprintf (text, "%.1f", myDecoder.Pattern); martin@0: if (myDecoder.Pattern<=0.125) { martin@0: strcpy(text, "Fig-of-8"); martin@0: } martin@0: else if (myDecoder.Pattern>0.125 && myDecoder.Pattern<=0.375) { martin@0: strcpy(text, "Hyper-Card."); martin@0: } martin@0: else if (myDecoder.Pattern>0.375 && myDecoder.Pattern<=0.625) { martin@0: strcpy(text, "Cardioid"); martin@0: } martin@0: else if (myDecoder.Pattern>0.625 && myDecoder.Pattern<=0.875) { martin@0: strcpy(text, "Sub-Card."); martin@0: } martin@0: else { martin@0: strcpy(text, "Omni."); martin@0: } martin@0: martin@0: martin@0: break; martin@0: case kRotate : martin@0: sprintf (text, "%.1f\u00B0", myDecoder.Rotate); martin@0: break; martin@0: case kTilt: martin@0: sprintf (text, "%.1f\u00B0", myDecoder.Tilt); martin@0: break; martin@0: case kTumble: martin@0: sprintf (text, "%.1f\u00B0", myDecoder.Tumble); martin@0: break; martin@0: case kZoom: martin@0: sprintf (text, "%.1f%%", myDecoder.Zoom); martin@0: break; martin@0: case kZoomMethod: martin@0: switch (myDecoder.ZoomMethod) { martin@0: case 0: martin@0: strcpy(text, "Dominance"); martin@0: break; martin@0: case 1: martin@0: strcpy(text, "Press"); martin@0: break; martin@0: case 2: martin@0: strcpy(text, "Push"); martin@0: break; martin@0: case 3: martin@0: strcpy(text, "Focus"); martin@0: break; martin@0: default: martin@0: break; martin@0: } martin@0: break; martin@0: case kRearVerb : martin@0: if (myDecoder.RearVerb>-40) { martin@0: sprintf (text, "%.2fdB", myDecoder.RearVerb); martin@0: } martin@0: else { martin@0: strcpy(text, "Off"); martin@0: } martin@0: break; martin@0: case kHiVerb : martin@0: if (myDecoder.HiVerb>-40) { martin@0: sprintf (text, "%.2fdB", myDecoder.HiVerb); martin@0: } martin@0: else { martin@0: strcpy(text, "Off"); martin@0: } martin@0: break; martin@0: } martin@0: //kVstMaxParamStrLen martin@0: } martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: void SoundField::getParameterLabel (VstInt32 index, char *label) // Labels shown for Parameters martin@0: { martin@0: switch (index) martin@0: { martin@0: case kMode : martin@0: strcpy(label, "Microphones"); martin@0: break; martin@0: case kWidth: martin@0: strcpy(label, "Degrees"); martin@0: break; martin@0: case kPattern: martin@0: strcpy(label, "Omni"); martin@0: break; martin@0: case kRotate : martin@0: strcpy(label, "Degrees"); martin@0: break; martin@0: case kTilt: martin@0: strcpy(label, "Degrees"); martin@0: break; martin@0: case kTumble: martin@0: strcpy(label, "Degrees"); martin@0: break; martin@0: case kZoom: martin@0: strcpy(label, "Precentage"); martin@0: break; martin@0: case kZoomMethod: martin@0: strcpy(label, "Selection"); martin@0: break; martin@0: case kRearVerb : martin@0: strcpy(label, "dB"); martin@0: break; martin@0: case kHiVerb : martin@0: strcpy(label, "dB"); martin@0: break; martin@0: } martin@0: } martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: bool SoundField::getEffectName (char* name) // Tha NAME of the effect martin@0: { martin@0: strcpy (name, "SoundField Decoder"); martin@0: return true; martin@0: } martin@0: martin@0: //------------------------------------------------------------------------ martin@0: bool SoundField::getProductString (char* text) // The PRODUCT name martin@0: { martin@0: strcpy (text, "SoundField Decoder"); martin@0: return true; martin@0: } martin@0: martin@0: //------------------------------------------------------------------------ martin@0: bool SoundField::getVendorString (char* text) // Vendor (Creator/Publisher) martin@0: { martin@0: strcpy (text, "Martin J. Morrell"); martin@0: return true; martin@0: } martin@0: martin@0: martin@0: //------------------------------------------------------------------------ martin@0: VstInt32 SoundField::getVendorVersion () martin@0: { martin@0: return VERSION; martin@0: } martin@0: martin@0: martin@0: //--------------------------------------------------------------------------- martin@0: void SoundField::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) //The part that does some actual DSP. This section takes the input audio and gives the output audio back. martin@0: { martin@0: martin@0: martin@0: while (--sampleFrames >= 0) //Do this process if the audio is running martin@0: { martin@0: //Set the internal B-Format values as doubles. martin@0: double w=(double) *inputs[0]++; martin@0: double x=(double) *inputs[1]++; martin@0: double y=(double) *inputs[2]++; martin@0: double z=(double) *inputs[3]++; martin@0: martin@0: if (myDecoder.decoderMode == 2) {//Stereo martin@0: myDecoder.stereoDecoder(w, x, y, z); martin@0: *outputs[0]++ = float(myDecoder.outputL); martin@0: *outputs[1]++ = float(myDecoder.outputR); martin@0: } martin@0: else if (myDecoder.decoderMode == 3) {//2.1 martin@0: myDecoder.twoOneDecoder(w, x, y, z); martin@0: *outputs[0]++ = float(myDecoder.outputL); martin@0: *outputs[1]++ = float(myDecoder.outputR); martin@0: *outputs[2]++ = float(myDecoder.outputS); martin@0: } martin@0: else if (myDecoder.decoderMode == 4) {//LRCS martin@0: myDecoder.fiveOneDecoder(w, x, y, z); martin@0: *outputs[0]++ = float(myDecoder.outputL); martin@0: *outputs[1]++ = float(myDecoder.outputR); martin@0: *outputs[2]++ = float(myDecoder.outputSL); martin@0: *outputs[3]++ = float(myDecoder.outputSR); martin@0: } martin@0: else if (myDecoder.decoderMode == 5) {//5.0 martin@0: myDecoder.fiveOneDecoder(w, x, y, z); martin@0: *outputs[0]++ = float(myDecoder.outputL); martin@0: *outputs[1]++ = float(myDecoder.outputR); martin@0: *outputs[2]++ = float(myDecoder.outputC); martin@0: *outputs[3]++ = float(myDecoder.outputSL); martin@0: *outputs[4]++ = float(myDecoder.outputSR); martin@0: } martin@0: else if (myDecoder.decoderMode == 6) {//5.1 martin@0: myDecoder.fiveOneDecoder(w, x, y, z); martin@0: *outputs[0]++ = float(myDecoder.outputL); martin@0: *outputs[1]++ = float(myDecoder.outputR); martin@0: *outputs[2]++ = float(myDecoder.outputC); martin@0: *outputs[3]++ = float(myDecoder.outputS); martin@0: *outputs[4]++ = float(myDecoder.outputSL); martin@0: *outputs[5]++ = float(myDecoder.outputSR); martin@0: } martin@0: martin@0: martin@0: } martin@0: }