From 58f8437f4b8b741ddc8e7bcde21bf983cc618430 Mon Sep 17 00:00:00 2001 From: pepper Date: Sat, 10 Jan 2015 21:37:24 -0800 Subject: added vstsdk --- .../samples/vst2.x/vstxsynth/source/gmnames.h | 222 ++++++++++++ .../samples/vst2.x/vstxsynth/source/vstxsynth.cpp | 392 +++++++++++++++++++++ .../samples/vst2.x/vstxsynth/source/vstxsynth.h | 139 ++++++++ .../vst2.x/vstxsynth/source/vstxsynthproc.cpp | 178 ++++++++++ 4 files changed, 931 insertions(+) create mode 100644 vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/gmnames.h create mode 100644 vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.cpp create mode 100644 vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.h create mode 100644 vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynthproc.cpp (limited to 'vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source') diff --git a/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/gmnames.h b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/gmnames.h new file mode 100644 index 0000000..78821fc --- /dev/null +++ b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/gmnames.h @@ -0,0 +1,222 @@ +//------------------------------------------------------------------------------------------------------- +// VST Plug-Ins SDK +// Version 2.4 $Date: 2006/11/13 09:08:27 $ +// +// Category : VST 2.x SDK Samples +// Filename : gmnames.h +// Created by : Steinberg Media Technologies +// Description : Example VstXSynth +// +// © 2006, Steinberg Media Technologies, All Rights Reserved +//------------------------------------------------------------------------------------------------------- + +#ifndef __gmnames__ +#define __gmnames__ + +static const long kNumGmCategories = 17; + +static const char* GmCategories[kNumGmCategories] = +{ + "Piano", + "Percussion", + "Organ", + "Guitar", + "Bass", + "Strings", + "Ensemble", + "Brass", + "Reed", + "Pipe", + "Synth Lead", + "SynthPad", + "Synth Effects", + "Ethnic", + "Percussive", + "Effects", + "DrumSets" +}; + +static short GmCategoriesFirstIndices [kNumGmCategories + 1] = +{ + 0, 7, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128 +}; + +static const char* GmNames [128] = +{ + // Piano + "Acoustic Grand Piano", + "Bright Acoustic Piano", + "Electric Grand Piano", + "Honky-tonk Piano", + "Electric Piano 1", + "Electric Piano 2", + "Harpsichord", + + // Percussion + "Clavi", // 7 + "Celesta", + "Glockenspiel", + "Music Box", + "Vibraphone", + "Marimba", + "Xylophone", + "Tubular Bells", + "Dulcimer", + + // Organ + "Drawbar Organ", // 16 + "Percussive Organ", + "Rock Organ", + "Church Organ", + "Reed Organ", + "Accordion", + "Harmonica", + "Tango Accordion", + + // Gitar + "Acoustic Guitar (nylon)", // 24 + "Acoustic Guitar (steel)", + "Electric Guitar (jazz)", + "Electric Guitar (clean)", + "Electric Guitar (muted)", + "Overdriven Guitar", + "Distortion Guitar", + "Guitar harmonics", + + // Bass + "Acoustic Bass", // 32 + "Electric Bass (finger)", + "Electric Bass (pick)", + "Fretless Bass", + "Slap Bass 1", + "Slap Bass 2", + "Synth Bass 1", + "Synth Bass 2", + + // strings + "Violin", // 40 + "Viola", + "Cello", + "Contrabass", + "Tremolo Strings", + "Pizzicato Strings", + "Orchestral Harp", + "Timpani", + + // Ensemble + "String Ensemble 1", // 48 + "String Ensemble 2", + "SynthStrings 1", + "SynthStrings 2", + "Choir Aahs", + "Voice Oohs", + "Synth Voice", + "Orchestra Hit", + + // Brass + "Trumpet", // 56 + "Trombone", + "Tuba", + "Muted Trumpet", + "French Horn", + "Brass Section", + "SynthBrass 1", + "SynthBrass 2", + + // Reed + "Soprano Sax", // 64 + "Alto Sax", + "Tenor Sax", + "Baritone Sax", + "Oboe", + "English Horn", + "Bassoon", + "Clarinet", + + // Pipe + "Piccolo", // 72 + "Flute", + "Recorder", + "Pan Flute", + "Blown Bottle", + "Shakuhachi", + "Whistle", + "Ocarina", + + // Synth Lead + "Lead 1 (square)", // 80 + "Lead 2 (sawtooth)", + "Lead 3 (calliope)", + "Lead 4 (chiff)", + "Lead 5 (charang)", + "Lead 6 (voice)", + "Lead 7 (fifths)", + "Lead 8 (bass + lead)", + + // Synth Pad + "Pad 1 (new age)", // 88 + "Pad 2 (warm)", + "Pad 3 (polysynth)", + "Pad 4 (choir)", + "Pad 5 (bowed)", + "Pad 6 (metallic)", + "Pad 7 (halo)", + "Pad 8 (sweep)", + + // Synth Fx + "FX 1 (rain)", // 96 + "FX 2 (soundtrack)", + "FX 3 (crystal)", + "FX 4 (atmosphere)", + "FX 5 (brightness)", + "FX 6 (goblins)", + "FX 7 (echoes)", + "FX 8 (sci-fi)", + + // Ethnic + "Sitar", // 104 + "Banjo", + "Shamisen", + "Koto", + "Kalimba", + "Bag pipe", + "Fiddle", + "Shanai", + + // Percussive + "Tinkle Bell", // 112 + "Agogo", + "Steel Drums", + "Woodblock", + "Taiko Drum", + "Melodic Tom", + "Synth Drum", + "Reverse Cymbal", + + // Effects + "Guitar Fret Noise", // 120 + "Breath Noise", + "Seashore", + "Bird Tweet", + "Telephone Ring", + "Helicopter", + "Applause", + "Gunshot" +}; + +static const char* GmDrumSets[11] = +{ + "Standard", + "Room", + "Power", + "Electronic", + "Analog", + "Jazz", + "Brush", + "Orchestra", + "Clavinova", + "RX", + "C/M" +}; + +#endif diff --git a/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.cpp b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.cpp new file mode 100644 index 0000000..f23cd02 --- /dev/null +++ b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.cpp @@ -0,0 +1,392 @@ +//------------------------------------------------------------------------------------------------------- +// VST Plug-Ins SDK +// Version 2.4 $Date: 2006/11/13 09:08:27 $ +// +// Category : VST 2.x SDK Samples +// Filename : vstxsynth.cpp +// Created by : Steinberg Media Technologies +// Description : Example VstXSynth +// +// A simple 2 oscillators test 'synth', +// Each oscillator has waveform, frequency, and volume +// +// *very* basic monophonic 'synth' example. you should not attempt to use this +// example 'algorithm' to start a serious virtual instrument; it is intended to demonstrate +// how VstEvents ('MIDI') are handled, but not how a virtual analog synth works. +// there are numerous much better examples on the web which show how to deal with +// bandlimited waveforms etc. +// +// © 2006, Steinberg Media Technologies, All Rights Reserved +//------------------------------------------------------------------------------------------------------- + +#include "vstxsynth.h" +#include "gmnames.h" + +//------------------------------------------------------------------------------------------------------- +AudioEffect* createEffectInstance (audioMasterCallback audioMaster) +{ + return new VstXSynth (audioMaster); +} + +//----------------------------------------------------------------------------------------- +// VstXSynthProgram +//----------------------------------------------------------------------------------------- +VstXSynthProgram::VstXSynthProgram () +{ + // Default Program Values + fWaveform1 = 0.f; // saw + fFreq1 =.0f; + fVolume1 = .33f; + + fWaveform2 = 1.f; // pulse + fFreq2 = .05f; // slightly higher + fVolume2 = .33f; + + fVolume = .9f; + vst_strncpy (name, "Basic", kVstMaxProgNameLen); +} + +//----------------------------------------------------------------------------------------- +// VstXSynth +//----------------------------------------------------------------------------------------- +VstXSynth::VstXSynth (audioMasterCallback audioMaster) +: AudioEffectX (audioMaster, kNumPrograms, kNumParams) +{ + // initialize programs + programs = new VstXSynthProgram[kNumPrograms]; + for (VstInt32 i = 0; i < 16; i++) + channelPrograms[i] = i; + + if (programs) + setProgram (0); + + if (audioMaster) + { + setNumInputs (0); // no inputs + setNumOutputs (kNumOutputs); // 2 outputs, 1 for each oscillator + canProcessReplacing (); + isSynth (); + setUniqueID ('VxS2'); // <<= kNumPrograms) + return; + + VstXSynthProgram *ap = &programs[program]; + curProgram = program; + + fWaveform1 = ap->fWaveform1; + fFreq1 = ap->fFreq1; + fVolume1 = ap->fVolume1; + + fWaveform2 = ap->fWaveform2; + fFreq2 = ap->fFreq2; + fVolume2 = ap->fVolume2; + + fVolume = ap->fVolume; +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::setProgramName (char* name) +{ + vst_strncpy (programs[curProgram].name, name, kVstMaxProgNameLen); +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::getProgramName (char* name) +{ + vst_strncpy (name, programs[curProgram].name, kVstMaxProgNameLen); +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::getParameterLabel (VstInt32 index, char* label) +{ + switch (index) + { + case kWaveform1: + case kWaveform2: + vst_strncpy (label, "Shape", kVstMaxParamStrLen); + break; + + case kFreq1: + case kFreq2: + vst_strncpy (label, "Hz", kVstMaxParamStrLen); + break; + + case kVolume1: + case kVolume2: + case kVolume: + vst_strncpy (label, "dB", kVstMaxParamStrLen); + break; + } +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::getParameterDisplay (VstInt32 index, char* text) +{ + text[0] = 0; + switch (index) + { + case kWaveform1: + if (fWaveform1 < .5) + vst_strncpy (text, "Sawtooth", kVstMaxParamStrLen); + else + vst_strncpy (text, "Pulse", kVstMaxParamStrLen); + break; + + case kFreq1: float2string (fFreq1, text, kVstMaxParamStrLen); break; + case kVolume1: dB2string (fVolume1, text, kVstMaxParamStrLen); break; + + case kWaveform2: + if (fWaveform2 < .5) + vst_strncpy (text, "Sawtooth", kVstMaxParamStrLen); + else + vst_strncpy (text, "Pulse", kVstMaxParamStrLen); + break; + + case kFreq2: float2string (fFreq2, text, kVstMaxParamStrLen); break; + case kVolume2: dB2string (fVolume2, text, kVstMaxParamStrLen); break; + case kVolume: dB2string (fVolume, text, kVstMaxParamStrLen); break; + } +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::getParameterName (VstInt32 index, char* label) +{ + switch (index) + { + case kWaveform1: vst_strncpy (label, "Wave 1", kVstMaxParamStrLen); break; + case kFreq1: vst_strncpy (label, "Freq 1", kVstMaxParamStrLen); break; + case kVolume1: vst_strncpy (label, "Levl 1", kVstMaxParamStrLen); break; + case kWaveform2: vst_strncpy (label, "Wave 2", kVstMaxParamStrLen); break; + case kFreq2: vst_strncpy (label, "Freq 2", kVstMaxParamStrLen); break; + case kVolume2: vst_strncpy (label, "Levl 2", kVstMaxParamStrLen); break; + case kVolume: vst_strncpy (label, "Volume", kVstMaxParamStrLen); break; + } +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::setParameter (VstInt32 index, float value) +{ + VstXSynthProgram *ap = &programs[curProgram]; + switch (index) + { + case kWaveform1: fWaveform1 = ap->fWaveform1 = value; break; + case kFreq1: fFreq1 = ap->fFreq1 = value; break; + case kVolume1: fVolume1 = ap->fVolume1 = value; break; + case kWaveform2: fWaveform2 = ap->fWaveform2 = value; break; + case kFreq2: fFreq2 = ap->fFreq2 = value; break; + case kVolume2: fVolume2 = ap->fVolume2 = value; break; + case kVolume: fVolume = ap->fVolume = value; break; + } +} + +//----------------------------------------------------------------------------------------- +float VstXSynth::getParameter (VstInt32 index) +{ + float value = 0; + switch (index) + { + case kWaveform1: value = fWaveform1; break; + case kFreq1: value = fFreq1; break; + case kVolume1: value = fVolume1; break; + case kWaveform2: value = fWaveform2; break; + case kFreq2: value = fFreq2; break; + case kVolume2: value = fVolume2; break; + case kVolume: value = fVolume; break; + } + return value; +} + +//----------------------------------------------------------------------------------------- +bool VstXSynth::getOutputProperties (VstInt32 index, VstPinProperties* properties) +{ + if (index < kNumOutputs) + { + vst_strncpy (properties->label, "Vstx ", 63); + char temp[11] = {0}; + int2string (index + 1, temp, 10); + vst_strncat (properties->label, temp, 63); + + properties->flags = kVstPinIsActive; + if (index < 2) + properties->flags |= kVstPinIsStereo; // make channel 1+2 stereo + return true; + } + return false; +} + +//----------------------------------------------------------------------------------------- +bool VstXSynth::getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text) +{ + if (index < kNumPrograms) + { + vst_strncpy (text, programs[index].name, kVstMaxProgNameLen); + return true; + } + return false; +} + +//----------------------------------------------------------------------------------------- +bool VstXSynth::getEffectName (char* name) +{ + vst_strncpy (name, "VstXSynth", kVstMaxEffectNameLen); + return true; +} + +//----------------------------------------------------------------------------------------- +bool VstXSynth::getVendorString (char* text) +{ + vst_strncpy (text, "Steinberg Media Technologies", kVstMaxVendorStrLen); + return true; +} + +//----------------------------------------------------------------------------------------- +bool VstXSynth::getProductString (char* text) +{ + vst_strncpy (text, "Vst Test Synth", kVstMaxProductStrLen); + return true; +} + +//----------------------------------------------------------------------------------------- +VstInt32 VstXSynth::getVendorVersion () +{ + return 1000; +} + +//----------------------------------------------------------------------------------------- +VstInt32 VstXSynth::canDo (char* text) +{ + if (!strcmp (text, "receiveVstEvents")) + return 1; + if (!strcmp (text, "receiveVstMidiEvent")) + return 1; + if (!strcmp (text, "midiProgramNames")) + return 1; + return -1; // explicitly can't do; 0 => don't know +} + +//----------------------------------------------------------------------------------------- +VstInt32 VstXSynth::getNumMidiInputChannels () +{ + return 1; // we are monophonic +} + +//----------------------------------------------------------------------------------------- +VstInt32 VstXSynth::getNumMidiOutputChannels () +{ + return 0; // no MIDI output back to Host app +} + +// midi program names: +// as an example, GM names are used here. in fact, VstXSynth doesn't even support +// multi-timbral operation so it's really just for demonstration. +// a 'real' instrument would have a number of voices which use the +// programs[channelProgram[channel]] parameters when it receives +// a note on message. + +//------------------------------------------------------------------------ +VstInt32 VstXSynth::getMidiProgramName (VstInt32 channel, MidiProgramName* mpn) +{ + VstInt32 prg = mpn->thisProgramIndex; + if (prg < 0 || prg >= 128) + return 0; + fillProgram (channel, prg, mpn); + if (channel == 9) + return 1; + return 128L; +} + +//------------------------------------------------------------------------ +VstInt32 VstXSynth::getCurrentMidiProgram (VstInt32 channel, MidiProgramName* mpn) +{ + if (channel < 0 || channel >= 16 || !mpn) + return -1; + VstInt32 prg = channelPrograms[channel]; + mpn->thisProgramIndex = prg; + fillProgram (channel, prg, mpn); + return prg; +} + +//------------------------------------------------------------------------ +void VstXSynth::fillProgram (VstInt32 channel, VstInt32 prg, MidiProgramName* mpn) +{ + mpn->midiBankMsb = + mpn->midiBankLsb = -1; + mpn->reserved = 0; + mpn->flags = 0; + + if (channel == 9) // drums + { + vst_strncpy (mpn->name, "Standard", 63); + mpn->midiProgram = 0; + mpn->parentCategoryIndex = 0; + } + else + { + vst_strncpy (mpn->name, GmNames[prg], 63); + mpn->midiProgram = (char)prg; + mpn->parentCategoryIndex = -1; // for now + + for (VstInt32 i = 0; i < kNumGmCategories; i++) + { + if (prg >= GmCategoriesFirstIndices[i] && prg < GmCategoriesFirstIndices[i + 1]) + { + mpn->parentCategoryIndex = i; + break; + } + } + } +} + +//------------------------------------------------------------------------ +VstInt32 VstXSynth::getMidiProgramCategory (VstInt32 channel, MidiProgramCategory* cat) +{ + cat->parentCategoryIndex = -1; // -1:no parent category + cat->flags = 0; // reserved, none defined yet, zero. + VstInt32 category = cat->thisCategoryIndex; + if (channel == 9) + { + vst_strncpy (cat->name, "Drums", 63); + return 1; + } + if (category >= 0 && category < kNumGmCategories) + vst_strncpy (cat->name, GmCategories[category], 63); + else + cat->name[0] = 0; + return kNumGmCategories; +} + +//------------------------------------------------------------------------ +bool VstXSynth::hasMidiProgramsChanged (VstInt32 channel) +{ + return false; // updateDisplay () +} + +//------------------------------------------------------------------------ +bool VstXSynth::getMidiKeyName (VstInt32 channel, MidiKeyName* key) + // struct will be filled with information for 'thisProgramIndex' and 'thisKeyNumber' + // if keyName is "" the standard name of the key will be displayed. + // if false is returned, no MidiKeyNames defined for 'thisProgramIndex'. +{ + // key->thisProgramIndex; // >= 0. fill struct for this program index. + // key->thisKeyNumber; // 0 - 127. fill struct for this key number. + key->keyName[0] = 0; + key->reserved = 0; // zero + key->flags = 0; // reserved, none defined yet, zero. + return false; +} diff --git a/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.h b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.h new file mode 100644 index 0000000..6212cac --- /dev/null +++ b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynth.h @@ -0,0 +1,139 @@ +//------------------------------------------------------------------------------------------------------- +// VST Plug-Ins SDK +// Version 2.4 $Date: 2006/11/13 09:08:27 $ +// +// Category : VST 2.x SDK Samples +// Filename : vstxsynth.h +// Created by : Steinberg Media Technologies +// Description : Example VstXSynth +// +// A simple 2 oscillators test 'synth', +// Each oscillator has waveform, frequency, and volume +// +// *very* basic monophonic 'synth' example. you should not attempt to use this +// example 'algorithm' to start a serious virtual instrument; it is intended to demonstrate +// how VstEvents ('MIDI') are handled, but not how a virtual analog synth works. +// there are numerous much better examples on the web which show how to deal with +// bandlimited waveforms etc. +// +// © 2006, Steinberg Media Technologies, All Rights Reserved +//------------------------------------------------------------------------------------------------------- + +#ifndef __vstxsynth__ +#define __vstxsynth__ + +#include "public.sdk/source/vst2.x/audioeffectx.h" + +//------------------------------------------------------------------------------------------ +enum +{ + // Global + kNumPrograms = 128, + kNumOutputs = 2, + + // Parameters Tags + kWaveform1 = 0, + kFreq1, + kVolume1, + + kWaveform2, + kFreq2, + kVolume2, + + kVolume, + + kNumParams +}; + +//------------------------------------------------------------------------------------------ +// VstXSynthProgram +//------------------------------------------------------------------------------------------ +class VstXSynthProgram +{ +friend class VstXSynth; +public: + VstXSynthProgram (); + ~VstXSynthProgram () {} + +private: + float fWaveform1; + float fFreq1; + float fVolume1; + + float fWaveform2; + float fFreq2; + float fVolume2; + + float fVolume; + char name[kVstMaxProgNameLen+1]; +}; + +//------------------------------------------------------------------------------------------ +// VstXSynth +//------------------------------------------------------------------------------------------ +class VstXSynth : public AudioEffectX +{ +public: + VstXSynth (audioMasterCallback audioMaster); + ~VstXSynth (); + + virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames); + virtual VstInt32 processEvents (VstEvents* events); + + virtual void setProgram (VstInt32 program); + virtual void setProgramName (char* name); + virtual void getProgramName (char* name); + virtual bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text); + + virtual void setParameter (VstInt32 index, float value); + virtual float getParameter (VstInt32 index); + virtual void getParameterLabel (VstInt32 index, char* label); + virtual void getParameterDisplay (VstInt32 index, char* text); + virtual void getParameterName (VstInt32 index, char* text); + + virtual void setSampleRate (float sampleRate); + virtual void setBlockSize (VstInt32 blockSize); + + virtual bool getOutputProperties (VstInt32 index, VstPinProperties* properties); + + virtual bool getEffectName (char* name); + virtual bool getVendorString (char* text); + virtual bool getProductString (char* text); + virtual VstInt32 getVendorVersion (); + virtual VstInt32 canDo (char* text); + + virtual VstInt32 getNumMidiInputChannels (); + virtual VstInt32 getNumMidiOutputChannels (); + + virtual VstInt32 getMidiProgramName (VstInt32 channel, MidiProgramName* midiProgramName); + virtual VstInt32 getCurrentMidiProgram (VstInt32 channel, MidiProgramName* currentProgram); + virtual VstInt32 getMidiProgramCategory (VstInt32 channel, MidiProgramCategory* category); + virtual bool hasMidiProgramsChanged (VstInt32 channel); + virtual bool getMidiKeyName (VstInt32 channel, MidiKeyName* keyName); + +private: + float fWaveform1; + float fFreq1; + float fVolume1; + float fWaveform2; + float fFreq2; + float fVolume2; + float fVolume; + float fPhase1, fPhase2; + float fScaler; + + VstXSynthProgram* programs; + VstInt32 channelPrograms[16]; + + VstInt32 currentNote; + VstInt32 currentVelocity; + VstInt32 currentDelta; + bool noteIsOn; + + void initProcess (); + void noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta); + void noteOff (); + void fillProgram (VstInt32 channel, VstInt32 prg, MidiProgramName* mpn); +}; + +#endif diff --git a/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynthproc.cpp b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynthproc.cpp new file mode 100644 index 0000000..61debac --- /dev/null +++ b/vendor/vstsdk2.4/public.sdk/samples/vst2.x/vstxsynth/source/vstxsynthproc.cpp @@ -0,0 +1,178 @@ +//------------------------------------------------------------------------------------------------------- +// VST Plug-Ins SDK +// Version 2.4 $Date: 2006/11/13 09:08:27 $ +// +// Category : VST 2.x SDK Samples +// Filename : vstxsynthproc.cpp +// Created by : Steinberg Media Technologies +// Description : Example VstXSynth +// +// A simple 2 oscillators test 'synth', +// Each oscillator has waveform, frequency, and volume +// +// *very* basic monophonic 'synth' example. you should not attempt to use this +// example 'algorithm' to start a serious virtual instrument; it is intended to demonstrate +// how VstEvents ('MIDI') are handled, but not how a virtual analog synth works. +// there are numerous much better examples on the web which show how to deal with +// bandlimited waveforms etc. +// +// © 2006, Steinberg Media Technologies, All Rights Reserved +//------------------------------------------------------------------------------------------------------- + +#include "vstxsynth.h" + +enum +{ + kNumFrequencies = 128, // 128 midi notes + kWaveSize = 4096 // samples (must be power of 2 here) +}; + +const double midiScaler = (1. / 127.); +static float sawtooth[kWaveSize]; +static float pulse[kWaveSize]; +static float freqtab[kNumFrequencies]; + +//----------------------------------------------------------------------------------------- +// VstXSynth +//----------------------------------------------------------------------------------------- +void VstXSynth::setSampleRate (float sampleRate) +{ + AudioEffectX::setSampleRate (sampleRate); + fScaler = (float)((double)kWaveSize / (double)sampleRate); +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::setBlockSize (VstInt32 blockSize) +{ + AudioEffectX::setBlockSize (blockSize); + // you may need to have to do something here... +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::initProcess () +{ + fPhase1 = fPhase2 = 0.f; + fScaler = (float)((double)kWaveSize / 44100.); // we don't know the sample rate yet + noteIsOn = false; + currentDelta = currentNote = currentDelta = 0; + VstInt32 i; + + // make waveforms + VstInt32 wh = kWaveSize / 4; // 1:3 pulse + for (i = 0; i < kWaveSize; i++) + { + sawtooth[i] = (float)(-1. + (2. * ((double)i / (double)kWaveSize))); + pulse[i] = (i < wh) ? -1.f : 1.f; + } + + // make frequency (Hz) table + double k = 1.059463094359; // 12th root of 2 + double a = 6.875; // a + a *= k; // b + a *= k; // bb + a *= k; // c, frequency of midi note 0 + for (i = 0; i < kNumFrequencies; i++) // 128 midi notes + { + freqtab[i] = (float)a; + a *= k; + } +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) +{ + float* out1 = outputs[0]; + float* out2 = outputs[1]; + + if (noteIsOn) + { + float baseFreq = freqtab[currentNote & 0x7f] * fScaler; + float freq1 = baseFreq + fFreq1; // not really linear... + float freq2 = baseFreq + fFreq2; + float* wave1 = (fWaveform1 < .5) ? sawtooth : pulse; + float* wave2 = (fWaveform2 < .5) ? sawtooth : pulse; + float wsf = (float)kWaveSize; + float vol = (float)(fVolume * (double)currentVelocity * midiScaler); + VstInt32 mask = kWaveSize - 1; + + if (currentDelta > 0) + { + if (currentDelta >= sampleFrames) // future + { + currentDelta -= sampleFrames; + return; + } + memset (out1, 0, currentDelta * sizeof (float)); + memset (out2, 0, currentDelta * sizeof (float)); + out1 += currentDelta; + out2 += currentDelta; + sampleFrames -= currentDelta; + currentDelta = 0; + } + + // loop + while (--sampleFrames >= 0) + { + // this is all very raw, there is no means of interpolation, + // and we will certainly get aliasing due to non-bandlimited + // waveforms. don't use this for serious projects... + (*out1++) = wave1[(VstInt32)fPhase1 & mask] * fVolume1 * vol; + (*out2++) = wave2[(VstInt32)fPhase2 & mask] * fVolume2 * vol; + fPhase1 += freq1; + fPhase2 += freq2; + } + } + else + { + memset (out1, 0, sampleFrames * sizeof (float)); + memset (out2, 0, sampleFrames * sizeof (float)); + } +} + +//----------------------------------------------------------------------------------------- +VstInt32 VstXSynth::processEvents (VstEvents* ev) +{ + for (VstInt32 i = 0; i < ev->numEvents; i++) + { + if ((ev->events[i])->type != kVstMidiType) + continue; + + VstMidiEvent* event = (VstMidiEvent*)ev->events[i]; + char* midiData = event->midiData; + VstInt32 status = midiData[0] & 0xf0; // ignoring channel + if (status == 0x90 || status == 0x80) // we only look at notes + { + VstInt32 note = midiData[1] & 0x7f; + VstInt32 velocity = midiData[2] & 0x7f; + if (status == 0x80) + velocity = 0; // note off by velocity 0 + if (!velocity && (note == currentNote)) + noteOff (); + else + noteOn (note, velocity, event->deltaFrames); + } + else if (status == 0xb0) + { + if (midiData[1] == 0x7e || midiData[1] == 0x7b) // all notes off + noteOff (); + } + event++; + } + return 1; +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta) +{ + currentNote = note; + currentVelocity = velocity; + currentDelta = delta; + noteIsOn = true; + fPhase1 = fPhase2 = 0; +} + +//----------------------------------------------------------------------------------------- +void VstXSynth::noteOff () +{ + noteIsOn = false; +} -- cgit v1.2.3-70-g09d2