1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/blumia-PineappleSynth

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Synthesis.cpp 17 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Gary Wang Отправлено 30.09.2016 21:31 70a157a
#include "Synthesis.h"
#include "IPlug_include_in_plug_src.h"
#include "IControl.h"
#include "IKeyboardControl.h"
#include "resource.h"
const int kNumPrograms = 5;
enum EAdsr
{
E_Att = 0,
E_Dec,
E_Sus,
E_Rel,
};
enum EParams
{
mOsc1Waveform = 0,
mOsc1Coarse,
mOsc1Fine,
mOsc2Waveform,
mOsc2Coarse,
mOsc2Fine,
mOscillatorMix,
mPhaseStart,
mBitCrusher,
mTejiBooster,
mAmpAmount,
mAttack,
mDecay,
mSustain,
mRelease,
mFilterMode,
mFilterCutoff,
mFilterResonance,
mFilterAttack,
mFilterDecay,
mFilterSustain,
mFilterRelease,
mFilterEnvelopeAmount,
mVerbRoomSize,
mVerbDamp,
mVerbWidth,
mVerbDry,
mVerbWet,
mVerbOn,
kNumParams
};
enum ELayout
{
kWidth = GUI_WIDTH,
kHeight = GUI_HEIGHT,
kKeybX = 12,
kKeybY = 297,
kGreenRow = 10,
kOrangeRow = 80,
kBlueRow = 150,
kPurpleRow = 220,
kSwitcherTopPadding = 10,
};
Synthesis::Synthesis(IPlugInstanceInfo instanceInfo)
: IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo),
lastVirtualKeyboardNoteNumber(virtualKeyboardMinimumNoteNumber - 1) {
TRACE;
IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight);
pGraphics->AttachBackground(BG_ID, BG_FN);
IBitmap pianoKeyImage = pGraphics->LoadIBitmap(PIANO_KEY_ID, PIANO_KEY_FN);
// C# D# F# G# A#
int keyCoordinates[12] = { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 };
mVirtualKeyboard = new IKeyboardControl(this, kKeybX, kKeybY, virtualKeyboardMinimumNoteNumber, /* octaves: */ 10, &pianoKeyImage, &pianoKeyImage, keyCoordinates);
pGraphics->AttachControl(mVirtualKeyboard);
// Bitmaps
IBitmap greenKnobBitmap = pGraphics->LoadIBitmap(GREEN_KNOB_ID, GREEN_KNOB_FN, 31);
IBitmap greenKnobCenterBitmap = pGraphics->LoadIBitmap(GREEN_KNOB_CENTER_ID, GREEN_KNOB_CENTER_FN, 31);
IBitmap blueKnobBitmap = pGraphics->LoadIBitmap(BLUE_KNOB_ID, BLUE_KNOB_FN, 31);
IBitmap blueKnobCenterBitmap = pGraphics->LoadIBitmap(BLUE_KNOB_CENTER_ID, BLUE_KNOB_CENTER_FN, 31);
IBitmap orangeKnobBitmap = pGraphics->LoadIBitmap(ORANGE_KNOB_ID, ORANGE_KNOB_FN, 31);
IBitmap purpleKnobBitmap = pGraphics->LoadIBitmap(PURPLE_KNOB_ID, PURPLE_KNOB_FN, 31);
IBitmap waveformBitmap = pGraphics->LoadIBitmap(WAVEFORM_ID, WAVEFORM_FN, 5);
IBitmap filtermodeBitmap = pGraphics->LoadIBitmap(FILTERMODE_ID, FILTERMODE_FN, 3);
IBitmap switcherLightBitmap = pGraphics->LoadIBitmap(SWITCHER_LIGHT_ID, SWITCHER_LIGHT_FN, 2);
IBitmap switcherOnOffBitmap = pGraphics->LoadIBitmap(SWITCHER_ONOFF_ID, SWITCHER_ONOFF_FN, 2);
// OSC1 Waveform switch
GetParam(mOsc1Waveform)->InitEnum("Waveform1", Oscillator::OSCILLATOR_MODE_SINE, Oscillator::kNumOscillatorModes);
GetParam(mOsc1Waveform)->SetDisplayText(0, "Sine");
pGraphics->AttachControl(new ISwitchControl(this, 42, kGreenRow + kSwitcherTopPadding, mOsc1Waveform, &waveformBitmap));
// OSC1 Coarse knob:
GetParam(mOsc1Coarse)->InitInt("Coarse1", 0, -24, 24);
GetParam(mOsc1Coarse)->SetShape(1);
pGraphics->AttachControl(new IKnobMultiControl(this, 136, kGreenRow, mOsc1Coarse, &greenKnobCenterBitmap));
// OSC1 Fine knob:
GetParam(mOsc1Fine)->InitInt("Fine1", 0, -100, 100);
GetParam(mOsc1Fine)->SetShape(1);
pGraphics->AttachControl(new IKnobMultiControl(this, 195, kGreenRow, mOsc1Fine, &greenKnobCenterBitmap));
// OSC2 Waveform switch
GetParam(mOsc2Waveform)->InitEnum("Waveform2", Oscillator::OSCILLATOR_MODE_SINE, Oscillator::kNumOscillatorModes);
GetParam(mOsc2Waveform)->SetDisplayText(0, "Sine");
pGraphics->AttachControl(new ISwitchControl(this, 346, kGreenRow + kSwitcherTopPadding, mOsc2Waveform, &waveformBitmap));
// OSC2 Coarse knob:
GetParam(mOsc2Coarse)->InitInt("Coarse2", 0, -24, 24);
GetParam(mOsc2Coarse)->SetShape(1);
pGraphics->AttachControl(new IKnobMultiControl(this, 437, kGreenRow, mOsc2Coarse, &greenKnobCenterBitmap));
// OSC2 Fine knob:
GetParam(mOsc2Fine)->InitInt("Fine2", 0, -100, 100);
GetParam(mOsc2Fine)->SetShape(1);
pGraphics->AttachControl(new IKnobMultiControl(this, 491, kGreenRow, mOsc2Fine, &greenKnobCenterBitmap));
// mOscillatorMix
GetParam(mOscillatorMix)->InitDouble("Osc Mix", 0.0, 0.0, 1.0, 0.001);
GetParam(mOscillatorMix)->SetShape(1);
pGraphics->AttachControl(new IKnobMultiControl(this, 275, kGreenRow, mOscillatorMix, &greenKnobCenterBitmap));
// OSC Phase Start switch
GetParam(mPhaseStart)->InitEnum("Start", 1, 2);
GetParam(mPhaseStart)->SetDisplayText(0, "Start");
pGraphics->AttachControl(new ISwitchControl(this, 564, kGreenRow + 7, mPhaseStart, &switcherLightBitmap));
// OSC1 Waveform switch
GetParam(mBitCrusher)->InitEnum("Bit Crusher", 0, 2);
GetParam(mBitCrusher)->SetDisplayText(0, "Bit Crusher");
pGraphics->AttachControl(new ISwitchControl(this, 564, kGreenRow + 25, mBitCrusher, &switcherLightBitmap));
// OSC1 Waveform switch
GetParam(mTejiBooster)->InitEnum("Mono/Poly", 0, 2);
GetParam(mTejiBooster)->SetDisplayText(0, "Teji Booster");
pGraphics->AttachControl(new ISwitchControl(this, 564, kGreenRow + 43 + 1, mTejiBooster, &switcherLightBitmap));
// Amp amount knob:
GetParam(mAmpAmount)->InitDouble("Amp Amount", 50., 0., 100.0, 0.01, "%");
GetParam(mAmpAmount)->SetShape(2);
pGraphics->AttachControl(new IKnobMultiControl(this, 255, kOrangeRow, mAmpAmount, &orangeKnobBitmap));
// Attack knob:
ampAdsrKnobs[E_Att] = new IKnobMultiControl(this, 329, kOrangeRow, mAttack, &orangeKnobBitmap);
ampAdsrKnobs[E_Att]->SetTooltip("Amp Attach Envelope"); // Seems doesn't work. tested in savihost, fl studio and ableton live 9.
GetParam(mAttack)->InitDouble("Attack", 0.01, 0.01, 10.0, 0.001);
GetParam(mAttack)->SetShape(3);
pGraphics->AttachControl(ampAdsrKnobs[E_Att]);
// Decay knob:
ampAdsrKnobs[E_Dec] = new IKnobMultiControl(this, 383, kOrangeRow, mDecay, &orangeKnobBitmap);
GetParam(mDecay)->InitDouble("Decay", 0.5, 0.01, 15.0, 0.001);
GetParam(mDecay)->SetShape(3);
pGraphics->AttachControl(ampAdsrKnobs[E_Dec]);
// Sustain knob:
ampAdsrKnobs[E_Sus] = new IKnobMultiControl(this, 437, kOrangeRow, mSustain, &orangeKnobBitmap);
GetParam(mSustain)->InitDouble("Sustain", 0.1, 0.001, 1.0, 0.001);
GetParam(mSustain)->SetShape(2);
pGraphics->AttachControl(ampAdsrKnobs[E_Sus]);
// Release knob:
ampAdsrKnobs[E_Rel] = new IKnobMultiControl(this, 491, kOrangeRow, mRelease, &orangeKnobBitmap);
GetParam(mRelease)->InitDouble("Release", 1.0, 0.001, 15.0, 0.001);
GetParam(mRelease)->SetShape(3);
pGraphics->AttachControl(ampAdsrKnobs[E_Rel]);
// ADSR Visualization
ampAdsrVisualization = new ADSRVisualizationControl(this, IRECT(546, kOrangeRow + 7, 648, kOrangeRow + 55));
ampAdsrVisualization->setColor(IColor(100, 235, 124, 6));
pGraphics->AttachControl(ampAdsrVisualization);
// Filter switch
GetParam(mFilterMode)->InitEnum("Filter Mode", Filter::FILTER_MODE_LOWPASS, Filter::kNumFilterModes);
GetParam(mFilterMode)->SetDisplayText(0, "LP"); // Needed for VST3, thanks plunntic
pGraphics->AttachControl(new ISwitchControl(this, 42, kBlueRow + kSwitcherTopPadding, mFilterMode, &filtermodeBitmap));
// Filter options
// Cutoff knob:
GetParam(mFilterCutoff)->InitDouble("Cutoff", 0.99, 0.01, 0.99, 0.001);
GetParam(mFilterCutoff)->SetShape(2);
pGraphics->AttachControl(new IKnobMultiControl(this, 137, kBlueRow, mFilterCutoff, &blueKnobBitmap));
// Resonance knob:
GetParam(mFilterResonance)->InitDouble("Resonance", 0.01, 0.01, 1.0, 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 195, kBlueRow, mFilterResonance, &blueKnobBitmap));
// Filter envelope amount knob:
GetParam(mFilterEnvelopeAmount)->InitDouble("Filter Env Amount", 0.0, -1.0, 1.0, 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 255, kBlueRow, mFilterEnvelopeAmount, &blueKnobCenterBitmap));
// Attack knob:
filterAdsrKnobs[E_Att] = new IKnobMultiControl(this, 329, kBlueRow, mFilterAttack, &blueKnobBitmap);
GetParam(mFilterAttack)->InitDouble("Filter Env Attack", 0.01, 0.01, 10.0, 0.001);
GetParam(mFilterAttack)->SetShape(3);
pGraphics->AttachControl(filterAdsrKnobs[E_Att]);
// Decay knob:
filterAdsrKnobs[E_Dec] = new IKnobMultiControl(this, 383, kBlueRow, mFilterDecay, &blueKnobBitmap);
GetParam(mFilterDecay)->InitDouble("Filter Env Decay", 0.5, 0.01, 15.0, 0.001);
GetParam(mFilterDecay)->SetShape(3);
pGraphics->AttachControl(filterAdsrKnobs[E_Dec]);
// Sustain knob:
filterAdsrKnobs[E_Sus] = new IKnobMultiControl(this, 437, kBlueRow, mFilterSustain, &blueKnobBitmap);
GetParam(mFilterSustain)->InitDouble("Filter Env Sustain", 0.1, 0.001, 1.0, 0.001);
GetParam(mFilterSustain)->SetShape(2);
pGraphics->AttachControl(filterAdsrKnobs[E_Sus]);
// Release knob:
filterAdsrKnobs[E_Rel] = new IKnobMultiControl(this, 491, kBlueRow, mFilterRelease, &blueKnobBitmap);
GetParam(mFilterRelease)->InitDouble("Filter Env Release", 1.0, 0.001, 15.0, 0.001);
GetParam(mFilterRelease)->SetShape(3);
pGraphics->AttachControl(filterAdsrKnobs[E_Rel]);
// Filter ADSR Visualization
filterEnvAdsrVisualization = new ADSRVisualizationControl(this, IRECT(546, kBlueRow + 7, 648, kBlueRow + 55));
filterEnvAdsrVisualization->setColor(IColor(100, 25, 121, 173));
pGraphics->AttachControl(filterEnvAdsrVisualization);
// Reverb
// Reverb switch
GetParam(mVerbOn)->InitEnum("Reverb On/Off", 0, 2);
GetParam(mVerbOn)->SetDisplayText(0, "On");
pGraphics->AttachControl(new ISwitchControl(this, 42, kPurpleRow + kSwitcherTopPadding, mVerbOn, &switcherOnOffBitmap));
GetParam(mVerbRoomSize)->InitDouble("Room Size", 0.5, 0.3, 0.99, 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 137, kPurpleRow, mVerbRoomSize, &purpleKnobBitmap));
GetParam(mVerbDamp)->InitDouble("Dampening", 0.5, 0., 1., 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 195, kPurpleRow, mVerbDamp, &purpleKnobBitmap));
GetParam(mVerbWidth)->InitDouble("Width", 1., -1., 1., 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 255, kPurpleRow, mVerbWidth, &purpleKnobBitmap));
GetParam(mVerbDry)->InitDouble("Dry", 1., 0., 1., 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 329, kPurpleRow, mVerbDry, &purpleKnobBitmap));
GetParam(mVerbWet)->InitDouble("Wet", 0.5, 0., 1., 0.001);
pGraphics->AttachControl(new IKnobMultiControl(this, 383, kPurpleRow, mVerbWet, &purpleKnobBitmap));
AttachGraphics(pGraphics);
CreatePresets();
mMIDIReceiver.noteOn.Connect(&voiceManager, &VoiceManager::onNoteOn);
mMIDIReceiver.noteOff.Connect(&voiceManager, &VoiceManager::onNoteOff);
mMIDIReceiver.pbChanged.Connect(&voiceManager, &VoiceManager::onPbChanged);
// Some host will not auto-reset the params so it will not set the adsr value, do it here.
ampAdsrVisualization->setADSR(ampAdsrKnobs[E_Att]->GetValue(), ampAdsrKnobs[E_Dec]->GetValue(),
ampAdsrKnobs[E_Sus]->GetValue(), ampAdsrKnobs[E_Rel]->GetValue());
filterEnvAdsrVisualization->setADSR(filterAdsrKnobs[E_Att]->GetValue(), filterAdsrKnobs[E_Dec]->GetValue(),
filterAdsrKnobs[E_Sus]->GetValue(), filterAdsrKnobs[E_Rel]->GetValue());
}
Synthesis::~Synthesis() {
if (ori_l != nullptr) free(ori_l);
if (ori_r != nullptr) free(ori_r);
}
void Synthesis::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
// Mutex is already locked for us.
/*
if (mDry == 0. && mWet == 1.)
{
// Process the entire sample block at once (more efficient?).
// Inputs should from voiceManager. **inputs is NOT writeable for such a vsti.
mVerbEngine.ProcessSampleBlock(inputs[0], inputs[1], outputs[0], outputs[1], nFrames);
return; // MIDIReceiver.
}
*/
// don't alloc new mem space every time we call ProcessDoubleReplacing. Will faster?
if (ori_l == nullptr || sizeof(*ori_l) != nFrames * sizeof(double)) ori_l = (double*)malloc(nFrames * sizeof(double));
if (ori_r == nullptr || sizeof(*ori_r) != nFrames * sizeof(double)) ori_r = (double*)malloc(nFrames * sizeof(double));
double *leftOutput = outputs[0];
double *rightOutput = outputs[1];
bool verbFxOn = GetParam(mVerbOn)->Int() == 0;
processVirtualKeyboard();
for (int i = 0; i < nFrames; ++i) {
mMIDIReceiver.advance();
if (!verbFxOn) {
//Off
leftOutput[i] = rightOutput[i] = voiceManager.nextSample();
} else {
ori_l[i] = ori_r[i] = leftOutput[i] = rightOutput[i] = voiceManager.nextSample();
// Reverb
mVerbEngine.ProcessSample(leftOutput + i, rightOutput + i);
// Mix dry/wet
leftOutput[i] = mDry * ori_l[i] + mWet * leftOutput[i];
rightOutput[i] = mDry * ori_r[i] + mWet * rightOutput[i];
}
}
mMIDIReceiver.Flush(nFrames);
}
void Synthesis::CreatePresets()
{
}
void Synthesis::Reset()
{
TRACE;
IMutexLock lock(this);
voiceManager.setSampleRate(GetSampleRate());
mVerbEngine.SetSampleRate(GetSampleRate());
}
void Synthesis::OnParamChange(int paramIdx)
{
IMutexLock lock(this);
switch (paramIdx) {
case mOsc1Waveform:
voiceManager.setOscillatorModeForEachVoice(1, static_cast<Oscillator::OscillatorMode>(GetParam(mOsc1Waveform)->Int()));
break;
case mOsc1Coarse:
voiceManager.setSemiOffsetForEachVoice(1, GetParam(paramIdx)->Value());
break;
case mOsc1Fine:
voiceManager.setCentOffsetForEachVoice(1, GetParam(paramIdx)->Value());
break;
case mOsc2Waveform:
voiceManager.setOscillatorModeForEachVoice(2, static_cast<Oscillator::OscillatorMode>(GetParam(mOsc2Waveform)->Int()));
break;
case mOsc2Coarse:
voiceManager.setSemiOffsetForEachVoice(2, GetParam(paramIdx)->Value());
break;
case mOsc2Fine:
voiceManager.setCentOffsetForEachVoice(2, GetParam(paramIdx)->Value());
break;
case mOscillatorMix:
voiceManager.setOscillatorMixForEachVoice(GetParam(paramIdx)->Value());
break;
case mPhaseStart:
voiceManager.setPhaseStartForEachVoice(static_cast<bool>(GetParam(paramIdx)->Int()));
break;
case mBitCrusher:
voiceManager.setBitCrusherEnabledForEachVoice(static_cast<bool>(GetParam(paramIdx)->Int()));
break;
case mTejiBooster:
voiceManager.setNumberOfVoices(GetParam(paramIdx)->Int() == 0 ? 64 : 32);
break;
case mAmpAmount:
voiceManager.setAmpAmountForEachVoice(GetParam(paramIdx)->Value());
break;
case mAttack:
case mDecay:
case mSustain:
case mRelease:
voiceManager.setAmpEnvStageValueForEachVoice(static_cast<EnvelopeGenerator::EnvelopeStage>(paramIdx - mAttack + 1), GetParam(paramIdx)->Value());
ampAdsrVisualization->setADSR(ampAdsrKnobs[E_Att]->GetValue(), ampAdsrKnobs[E_Dec]->GetValue(),
ampAdsrKnobs[E_Sus]->GetValue(), ampAdsrKnobs[E_Rel]->GetValue());
break;
case mFilterCutoff:
voiceManager.setFilterCutoffForEachVoice(GetParam(paramIdx)->Value());
break;
case mFilterResonance:
voiceManager.setFilterResonanceForEachVoice(GetParam(paramIdx)->Value());
break;
case mFilterMode:
voiceManager.setFilterModeForEachVoice(static_cast<Filter::FilterMode>(GetParam(paramIdx)->Int()));
break;
case mFilterAttack:
case mFilterDecay:
case mFilterSustain:
case mFilterRelease:
voiceManager.setFilterEnvStageValueForEachVoice(static_cast<EnvelopeGenerator::EnvelopeStage>(paramIdx - mFilterAttack + 1), GetParam(paramIdx)->Value());
filterEnvAdsrVisualization->setADSR(filterAdsrKnobs[E_Att]->GetValue(), filterAdsrKnobs[E_Dec]->GetValue(),
filterAdsrKnobs[E_Sus]->GetValue(), filterAdsrKnobs[E_Rel]->GetValue());
break;
case mFilterEnvelopeAmount:
voiceManager.setFilterAmountForEachVoice(GetParam(paramIdx)->Value());
break;
case mVerbRoomSize:
mVerbEngine.SetRoomSize(GetParam(paramIdx)->Value());
mVerbEngine.Reset();
break;
case mVerbDamp:
mVerbEngine.SetDampening(GetParam(paramIdx)->Value());
mVerbEngine.Reset();
break;
case mVerbWidth:
mVerbEngine.SetWidth(GetParam(paramIdx)->Value());
break;
case mVerbDry:
mDry = GetParam(paramIdx)->Value();
break;
case mVerbWet:
mWet = GetParam(paramIdx)->Value();
break;
}
}
void Synthesis::ProcessMidiMsg(IMidiMsg* pMsg) {
mMIDIReceiver.onMessageReceived(pMsg);
mVirtualKeyboard->SetDirty();
}
void Synthesis::processVirtualKeyboard() {
IKeyboardControl* virtualKeyboard = (IKeyboardControl*)mVirtualKeyboard;
int virtualKeyboardNoteNumber = virtualKeyboard->GetKey() + virtualKeyboardMinimumNoteNumber;
if (lastVirtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) {
// The note number has changed from a valid key to something else (valid key or nothing). Release the valid key:
IMidiMsg midiMessage;
midiMessage.MakeNoteOffMsg(lastVirtualKeyboardNoteNumber, 0);
mMIDIReceiver.onMessageReceived(&midiMessage);
}
if (virtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) {
// A valid key is pressed that wasn't pressed the previous call. Send a "note on" message to the MIDI receiver:
IMidiMsg midiMessage;
midiMessage.MakeNoteOnMsg(virtualKeyboardNoteNumber, virtualKeyboard->GetVelocity(), 0);
mMIDIReceiver.onMessageReceived(&midiMessage);
}
lastVirtualKeyboardNoteNumber = virtualKeyboardNoteNumber;
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/blumia-PineappleSynth.git
git@api.gitlife.ru:oschina-mirror/blumia-PineappleSynth.git
oschina-mirror
blumia-PineappleSynth
blumia-PineappleSynth
master