//------------------------------------------------------------------------------------------------------- // 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; }