Browse Source

Implement legato note support/voicing modes

master
Ian Ford 4 years ago committed by ferris
parent
commit
27d12b76f0
  1. 3
      Vsts/Adultery/AdulteryEditor.cpp
  2. 2
      Vsts/Adultery/AdulteryVst.cpp
  3. 14
      Vsts/Falcon/FalconEditor.cpp
  4. 3
      Vsts/Falcon/FalconVst.cpp
  5. 16
      Vsts/Slaughter/SlaughterEditor.cpp
  6. 2
      Vsts/Slaughter/SlaughterVst.cpp
  7. 3
      Vsts/Specimen/SpecimenEditor.cpp
  8. 2
      Vsts/Specimen/SpecimenVst.cpp
  9. 4
      WaveSabreCore/include/WaveSabreCore/Adultery.h
  10. 4
      WaveSabreCore/include/WaveSabreCore/Falcon.h
  11. 3
      WaveSabreCore/include/WaveSabreCore/Helpers.h
  12. 4
      WaveSabreCore/include/WaveSabreCore/Slaughter.h
  13. 4
      WaveSabreCore/include/WaveSabreCore/Specimen.h
  14. 30
      WaveSabreCore/include/WaveSabreCore/SynthDevice.h
  15. 1
      WaveSabreCore/include/WaveSabreCore/Thunder.h
  16. 16
      WaveSabreCore/src/Adultery.cpp
  17. 14
      WaveSabreCore/src/Falcon.cpp
  18. 10
      WaveSabreCore/src/Helpers.cpp
  19. 15
      WaveSabreCore/src/Slaughter.cpp
  20. 16
      WaveSabreCore/src/Specimen.cpp
  21. 138
      WaveSabreCore/src/SynthDevice.cpp
  22. 5
      WaveSabreCore/src/Thunder.cpp
  23. 2
      WaveSabreVstLib/WaveSabreVstLib.vcxproj

3
Vsts/Adultery/AdulteryEditor.cpp

@ -211,6 +211,9 @@ void AdulteryEditor::Open()
addSpacer();
addKnob((VstInt32)Adultery::ParamIndices::FineTune, "FINE TUNE");
addSpacer();
addKnob((VstInt32)Adultery::ParamIndices::VoiceMode, "MODE");
addKnob((VstInt32)Adultery::ParamIndices::SlideTime, "SLIDE");
addSpacer();
addKnob((VstInt32)Adultery::ParamIndices::Master, "MASTER");
VstEditor::Open();

2
Vsts/Adultery/AdulteryVst.cpp

@ -51,6 +51,8 @@ void AdulteryVst::getParameterName(VstInt32 index, char *text)
case Adultery::ParamIndices::VoicesPan: vst_strncpy(text, "Vcs Pan", kVstMaxParamStrLen); break;
case Adultery::ParamIndices::Master: vst_strncpy(text, "Master", kVstMaxParamStrLen); break;
case Adultery::ParamIndices::VoiceMode: vst_strncpy(text, "Mode", kVstMaxParamStrLen); break;
case Adultery::ParamIndices::SlideTime: vst_strncpy(text, "Slide", kVstMaxParamStrLen); break;
}
}

14
Vsts/Falcon/FalconEditor.cpp

@ -4,7 +4,7 @@
using namespace WaveSabreCore;
FalconEditor::FalconEditor(AudioEffect *audioEffect)
: VstEditor(audioEffect, 760, 220, "FALCON")
: VstEditor(audioEffect, 820, 220, "FALCON")
{
}
@ -26,6 +26,9 @@ void FalconEditor::Open()
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addKnob((VstInt32)Falcon::ParamIndices::Osc1Attack, "ATTACK");
addKnob((VstInt32)Falcon::ParamIndices::Osc1Decay, "DECAY");
@ -34,6 +37,7 @@ void FalconEditor::Open()
addSpacer();
addSpacer();
addSpacer();
addKnob((VstInt32)Falcon::ParamIndices::MasterLevel, "MASTER");
@ -54,6 +58,9 @@ void FalconEditor::Open()
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addKnob((VstInt32)Falcon::ParamIndices::Osc2Attack, "ATTACK");
addKnob((VstInt32)Falcon::ParamIndices::Osc2Decay, "DECAY");
@ -66,12 +73,11 @@ void FalconEditor::Open()
addKnob((VstInt32)Falcon::ParamIndices::VoicesDetune, "DETUNE");
addKnob((VstInt32)Falcon::ParamIndices::VoicesPan, "PAN");
addSpacer();
addKnob((VstInt32)Falcon::ParamIndices::VibratoFreq, "VIB FREQ");
addKnob((VstInt32)Falcon::ParamIndices::VibratoAmount, "VIB AMT");
addSpacer();
addKnob((VstInt32)Falcon::ParamIndices::VoiceMode, "MODE");
addKnob((VstInt32)Falcon::ParamIndices::SlideTime, "SLIDE");
addKnob((VstInt32)Falcon::ParamIndices::Rise, "RISE");

3
Vsts/Falcon/FalconVst.cpp

@ -58,7 +58,8 @@ void FalconVst::getParameterName(VstInt32 index, char *text)
case Falcon::ParamIndices::PitchRelease: vst_strncpy(text, "Ptch Rls", kVstMaxParamStrLen); break;
case Falcon::ParamIndices::PitchEnvAmt1: vst_strncpy(text, "Ptc Env1", kVstMaxParamStrLen); break;
case Falcon::ParamIndices::PitchEnvAmt2: vst_strncpy(text, "Ptc Env2", kVstMaxParamStrLen); break;
case Falcon::ParamIndices::VoiceMode: vst_strncpy(text, "Mode", kVstMaxParamStrLen); break;
case Falcon::ParamIndices::SlideTime: vst_strncpy(text, "Slide", kVstMaxParamStrLen); break;
}
}

16
Vsts/Slaughter/SlaughterEditor.cpp

@ -4,7 +4,7 @@
using namespace WaveSabreCore;
SlaughterEditor::SlaughterEditor(AudioEffect *audioEffect)
: VstEditor(audioEffect, 500, 580, "SLAUGHTER")
: VstEditor(audioEffect, 520, 600, "SLAUGHTER")
{
}
@ -21,7 +21,15 @@ void SlaughterEditor::Open()
addKnob((VstInt32)Slaughter::ParamIndices::Osc1DetuneFine, "DET FINE");
addSpacer();
addKnob((VstInt32)Slaughter::ParamIndices::Osc1Volume, "VOLUME");
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addSpacer();
addKnob((VstInt32)Slaughter::ParamIndices::MasterLevel, "MASTER");
startNextRow();
addKnob((VstInt32)Slaughter::ParamIndices::Osc2Waveform, "WAVEFORM");
@ -95,13 +103,13 @@ void SlaughterEditor::Open()
addKnob((VstInt32)Slaughter::ParamIndices::VibratoFreq, "VIB FREQ");
addKnob((VstInt32)Slaughter::ParamIndices::VibratoAmount, "VIB AMT");
addSpacer();
addKnob((VstInt32)Slaughter::ParamIndices::Rise, "RISE");
addSpacer();
addKnob((VstInt32)Slaughter::ParamIndices::MasterLevel, "MASTER");
addKnob((VstInt32)Slaughter::ParamIndices::VoiceMode, "MODE");
addKnob((VstInt32)Slaughter::ParamIndices::SlideTime, "SLIDE");
VstEditor::Open();
}

2
Vsts/Slaughter/SlaughterVst.cpp

@ -71,6 +71,8 @@ void SlaughterVst::getParameterName(VstInt32 index, char *text)
case Slaughter::ParamIndices::VibratoAmount: vst_strncpy(text, "Vib Amt", kVstMaxParamStrLen); break;
case Slaughter::ParamIndices::Rise: vst_strncpy(text, "Rise", kVstMaxParamStrLen); break;
case Slaughter::ParamIndices::VoiceMode: vst_strncpy(text, "Mode", kVstMaxParamStrLen); break;
case Slaughter::ParamIndices::SlideTime: vst_strncpy(text, "Slide", kVstMaxParamStrLen); break;
}
}

3
Vsts/Specimen/SpecimenEditor.cpp

@ -90,6 +90,9 @@ void SpecimenEditor::Open()
addSpacer();
addKnob((VstInt32)Specimen::ParamIndices::FineTune, "FINE TUNE");
addSpacer();
addKnob((VstInt32)Slaughter::ParamIndices::VoiceMode, "MODE");
addKnob((VstInt32)Slaughter::ParamIndices::SlideTime, "SLIDE");
addSpacer();
addKnob((VstInt32)Specimen::ParamIndices::Master, "MASTER");
VstEditor::Open();

2
Vsts/Specimen/SpecimenVst.cpp

@ -50,6 +50,8 @@ void SpecimenVst::getParameterName(VstInt32 index, char *text)
case Specimen::ParamIndices::VoicesPan: vst_strncpy(text, "Vcs Pan", kVstMaxParamStrLen); break;
case Specimen::ParamIndices::Master: vst_strncpy(text, "Master", kVstMaxParamStrLen); break;
case Specimen::ParamIndices::VoiceMode: vst_strncpy(text, "Mode", kVstMaxParamStrLen); break;
case Specimen::ParamIndices::SlideTime: vst_strncpy(text, "Slide", kVstMaxParamStrLen); break;
}
}

4
WaveSabreCore/include/WaveSabreCore/Adultery.h

@ -48,6 +48,9 @@ namespace WaveSabreCore
Master,
VoiceMode,
SlideTime,
NumParams,
};
@ -62,6 +65,7 @@ namespace WaveSabreCore
{
public:
AdulteryVoice(Adultery *adultery);
virtual WaveSabreCore::SynthDevice *SynthDevice() const;
virtual void Run(double songPosition, float **outputs, int numSamples);

4
WaveSabreCore/include/WaveSabreCore/Falcon.h

@ -50,6 +50,9 @@ namespace WaveSabreCore
PitchEnvAmt1,
PitchEnvAmt2,
VoiceMode,
SlideTime,
NumParams,
};
@ -63,6 +66,7 @@ namespace WaveSabreCore
{
public:
FalconVoice(Falcon *falcon);
virtual WaveSabreCore::SynthDevice *SynthDevice() const;
virtual void Run(double songPosition, float **outputs, int numSamples);

3
WaveSabreCore/include/WaveSabreCore/Helpers.h

@ -3,6 +3,7 @@
#include "StateVariableFilter.h"
#include "Twister.h"
#include "SynthDevice.h"
namespace WaveSabreCore
{
@ -69,6 +70,8 @@ namespace WaveSabreCore
static Spread ParamToSpread(float param);
static float SpreadToParam(Spread spread);
static VoiceMode ParamToVoiceMode(float param);
static float VoiceModeToParam(VoiceMode type);
private:
static const int fastCosTabLog2Size = 9; // size = 512
static const int fastCosTabSize = (1 << fastCosTabLog2Size);

4
WaveSabreCore/include/WaveSabreCore/Slaughter.h

@ -64,6 +64,9 @@ namespace WaveSabreCore
PitchRelease,
PitchEnvAmt,
VoiceMode,
SlideTime,
NumParams,
};
@ -77,6 +80,7 @@ namespace WaveSabreCore
{
public:
SlaughterVoice(Slaughter *slaughter);
virtual WaveSabreCore::SynthDevice *SynthDevice() const;
virtual void Run(double songPosition, float **outputs, int numSamples);

4
WaveSabreCore/include/WaveSabreCore/Specimen.h

@ -53,6 +53,9 @@ namespace WaveSabreCore
Master,
VoiceMode,
SlideTime,
NumParams,
};
@ -74,6 +77,7 @@ namespace WaveSabreCore
{
public:
SpecimenVoice(Specimen *thunder);
virtual WaveSabreCore::SynthDevice *SynthDevice() const;
virtual void Run(double songPosition, float **outputs, int numSamples);

30
WaveSabreCore/include/WaveSabreCore/SynthDevice.h

@ -5,6 +5,12 @@
namespace WaveSabreCore
{
enum class VoiceMode
{
Polyphonic,
MonoLegatoTrill,
};
class SynthDevice : public Device
{
public:
@ -17,6 +23,9 @@ namespace WaveSabreCore
virtual void NoteOn(int note, int velocity, int deltaSamples);
virtual void NoteOff(int note, int deltaSamples);
void SetVoiceMode(VoiceMode voiceMode);
VoiceMode GetVoiceMode() const;
int VoicesUnisono;
float VoicesDetune;
float VoicesPan;
@ -26,9 +35,12 @@ namespace WaveSabreCore
float Rise;
float Slide;
protected:
static const int maxVoices = 256;
static const int maxEvents = 256;
static const int maxActiveNotes = 128;
class Voice
{
@ -36,10 +48,14 @@ namespace WaveSabreCore
Voice();
virtual ~Voice();
virtual SynthDevice *SynthDevice() const = 0;
virtual void Run(double songPosition, float **outputs, int numSamples) = 0;
virtual void NoteOn(int note, int velocity, float detune, float pan);
virtual void NoteOff();
virtual void NoteSlide(int note);
virtual double GetNote();
bool IsOn;
int Note;
@ -48,6 +64,13 @@ namespace WaveSabreCore
float Pan;
double vibratoPhase;
private:
bool slideActive;
double slideDelta;
int slideSamples;
int destinationNote;
double currentNote;
};
enum class EventType
@ -65,10 +88,15 @@ namespace WaveSabreCore
int Note, Velocity;
};
bool monoActive;
int noteLog[maxActiveNotes];
int noteCount;
bool activeNotes[maxActiveNotes];
void clearEvents();
Voice *voices[maxVoices];
VoiceMode voiceMode;
Event events[maxEvents];
};
}

1
WaveSabreCore/include/WaveSabreCore/Thunder.h

@ -31,6 +31,7 @@ namespace WaveSabreCore
{
public:
ThunderVoice(Thunder *thunder);
virtual WaveSabreCore::SynthDevice *SynthDevice() const;
virtual void Run(double songPosition, float **outputs, int numSamples);

16
WaveSabreCore/src/Adultery.cpp

@ -196,6 +196,9 @@ namespace WaveSabreCore
case ParamIndices::VoicesDetune: VoicesDetune = value; break;
case ParamIndices::VoicesPan: VoicesPan = value; break;
case ParamIndices::VoiceMode: SetVoiceMode(Helpers::ParamToVoiceMode(value)); break;
case ParamIndices::SlideTime: Slide = value; break;
case ParamIndices::Master: masterLevel = value; break;
}
}
@ -237,6 +240,9 @@ namespace WaveSabreCore
case ParamIndices::VoicesUnisono: return Helpers::UnisonoToParam(VoicesUnisono);
case ParamIndices::VoicesDetune: return VoicesDetune;
case ParamIndices::VoicesPan: return VoicesPan;
case ParamIndices::VoiceMode: return Helpers::VoiceModeToParam(GetVoiceMode());
case ParamIndices::SlideTime: return Slide;
case ParamIndices::Master: return masterLevel;
}
@ -247,6 +253,11 @@ namespace WaveSabreCore
this->adultery = adultery;
}
SynthDevice *Adultery::AdulteryVoice::SynthDevice() const
{
return adultery;
}
void Adultery::AdulteryVoice::Run(double songPosition, float **outputs, int numSamples)
{
filter.SetType(adultery->filterType);
@ -261,7 +272,6 @@ namespace WaveSabreCore
samplePlayer.Reverse = adultery->reverse;
samplePlayer.RunPrep();
calcPitch();
float amp = Helpers::VolumeToScalar(adultery->masterLevel);
float panLeft = Helpers::PanToScalarLeft(Pan);
@ -269,6 +279,8 @@ namespace WaveSabreCore
for (int i = 0; i < numSamples; i++)
{
calcPitch();
filter.SetFreq(Helpers::Clamp(adultery->filterFreq + modEnv.GetValue() * (20000.0f - 20.0f) * (adultery->filterModAmt * 2.0f - 1.0f), 0.0f, 20000.0f - 20.0f));
float sample = samplePlayer.Next();
@ -340,6 +352,6 @@ namespace WaveSabreCore
void Adultery::AdulteryVoice::calcPitch()
{
samplePlayer.CalcPitch(Note - 60 + Detune + adultery->fineTune * 2.0f - 1.0f + AdulteryVoice::coarseDetune(adultery->coarseTune));
samplePlayer.CalcPitch(GetNote() - 60 + Detune + adultery->fineTune * 2.0f - 1.0f + AdulteryVoice::coarseDetune(adultery->coarseTune));
}
}

14
WaveSabreCore/src/Falcon.cpp

@ -83,6 +83,9 @@ namespace WaveSabreCore
case ParamIndices::PitchRelease: pitchRelease = Helpers::ScalarToEnvValue(value); break;
case ParamIndices::PitchEnvAmt1: pitchEnvAmt1 = (value - .5f) * 2.0f * 36.0f; break;
case ParamIndices::PitchEnvAmt2: pitchEnvAmt2 = (value - .5f) * 2.0f * 36.0f; break;
case ParamIndices::VoiceMode: SetVoiceMode(Helpers::ParamToVoiceMode(value)); break;
case ParamIndices::SlideTime: Slide = value; break;
}
}
@ -132,6 +135,8 @@ namespace WaveSabreCore
case ParamIndices::PitchEnvAmt1: return pitchEnvAmt1 / 36.0f / 2.0f + .5f;
case ParamIndices::PitchEnvAmt2: return pitchEnvAmt2 / 36.0f / 2.0f + .5f;
case ParamIndices::VoiceMode: return Helpers::VoiceModeToParam(GetVoiceMode());
case ParamIndices::SlideTime: return Slide;
}
}
@ -140,6 +145,11 @@ namespace WaveSabreCore
this->falcon = falcon;
}
SynthDevice *Falcon::FalconVoice::SynthDevice() const
{
return falcon;
}
void Falcon::FalconVoice::Run(double songPosition, float **outputs, int numSamples)
{
double vibratoFreq = falcon->VibratoFreq / Helpers::CurrentSampleRate;
@ -153,12 +163,14 @@ namespace WaveSabreCore
float leftPanScalar = Helpers::PanToScalarLeft(Pan);
float rightPanScalar = Helpers::PanToScalarRight(Pan);
double baseNote = (double)Note + Detune + falcon->Rise * 24.0f;
double osc1RatioScalar = ratioScalar((double)falcon->osc1RatioCoarse, (double)falcon->osc1RatioFine);
double osc2RatioScalar = ratioScalar((double)falcon->osc2RatioCoarse, (double)falcon->osc2RatioFine);
for (int i = 0; i < numSamples; i++)
{
double baseNote = GetNote() + Detune + falcon->Rise * 24.0f;
double osc1Input = osc1Phase / Helpers::CurrentSampleRate * 2.0 * 3.141592 + osc1Output * osc1Feedback;
osc1Output = ((Helpers::FastSin(osc1Input) + Helpers::Square35(osc1Input) * (double)falcon->osc1Waveform)) * osc1Env.GetValue() * 13.25;

10
WaveSabreCore/src/Helpers.cpp

@ -355,4 +355,14 @@ namespace WaveSabreCore
{
return (float)spread / 2.0f;
}
VoiceMode Helpers::ParamToVoiceMode(float param)
{
return (VoiceMode)(int)(param * 1.0f);
}
float Helpers::VoiceModeToParam(VoiceMode voiceMode)
{
return (float)voiceMode / 1.0f;
}
}

15
WaveSabreCore/src/Slaughter.cpp

@ -96,6 +96,9 @@ namespace WaveSabreCore
case ParamIndices::VibratoAmount: VibratoAmount = value; break;
case ParamIndices::Rise: Rise = value; break;
case ParamIndices::VoiceMode: SetVoiceMode(Helpers::ParamToVoiceMode(value)); break;
case ParamIndices::SlideTime: Slide = value; break;
}
}
@ -157,6 +160,9 @@ namespace WaveSabreCore
case ParamIndices::VibratoAmount: return VibratoAmount;
case ParamIndices::Rise: return Rise;
case ParamIndices::VoiceMode: return Helpers::VoiceModeToParam(GetVoiceMode());
case ParamIndices::SlideTime: return Slide;
}
}
@ -170,6 +176,11 @@ namespace WaveSabreCore
osc1.Integral = osc2.Integral = osc3.Integral = 0.0;
}
SynthDevice *Slaughter::SlaughterVoice::SynthDevice() const
{
return slaughter;
}
void Slaughter::SlaughterVoice::Run(double songPosition, float **outputs, int numSamples)
{
double vibratoFreq = slaughter->VibratoFreq / Helpers::CurrentSampleRate;
@ -193,8 +204,8 @@ namespace WaveSabreCore
for (int i = 0; i < numSamples; i++)
{
filter.SetFreq(Helpers::Clamp(slaughter->filterFreq + modEnv.GetValue() * (20000.0f - 20.0f) * (slaughter->filterModAmt * 2.0f - 1.0f), 0.0f, 20000.0f - 20.0f));
double baseNote = (double)Note + Detune + pitchEnv.GetValue() * slaughter->pitchEnvAmt + Helpers::FastSin(vibratoPhase) * slaughter->VibratoAmount + slaughter->Rise * 24.0f;
double baseNote = GetNote() + Detune + pitchEnv.GetValue() * slaughter->pitchEnvAmt + Helpers::FastSin(vibratoPhase) * slaughter->VibratoAmount + slaughter->Rise * 24.0f;
float oscMix = 0.0;
if (osc1VolumeScalar > 0.0f) oscMix += (float)(osc1.Next(baseNote + osc1Detune, slaughter->osc1Waveform, slaughter->osc1PulseWidth) * osc1VolumeScalar);
if (osc2VolumeScalar > 0.0f) oscMix += (float)(osc2.Next(baseNote + osc2Detune, slaughter->osc2Waveform, slaughter->osc2PulseWidth) * osc2VolumeScalar);

16
WaveSabreCore/src/Specimen.cpp

@ -98,6 +98,9 @@ namespace WaveSabreCore
case ParamIndices::VoicesPan: VoicesPan = value; break;
case ParamIndices::Master: masterLevel = value; break;
case ParamIndices::VoiceMode: SetVoiceMode(Helpers::ParamToVoiceMode(value)); break;
case ParamIndices::SlideTime: Slide = value; break;
}
}
@ -135,6 +138,9 @@ namespace WaveSabreCore
case ParamIndices::VoicesPan: return VoicesPan;
case ParamIndices::Master: return masterLevel;
case ParamIndices::VoiceMode: return Helpers::VoiceModeToParam(GetVoiceMode());
case ParamIndices::SlideTime: return Slide;
}
}
@ -283,6 +289,11 @@ namespace WaveSabreCore
this->specimen = specimen;
}
SynthDevice *Specimen::SpecimenVoice::SynthDevice() const
{
return specimen;
}
void Specimen::SpecimenVoice::Run(double songPosition, float **outputs, int numSamples)
{
filter.SetType(specimen->filterType);
@ -297,7 +308,6 @@ namespace WaveSabreCore
samplePlayer.Reverse = specimen->reverse;
samplePlayer.RunPrep();
calcPitch();
float amp = Helpers::VolumeToScalar(specimen->masterLevel);
float panLeft = Helpers::PanToScalarLeft(Pan);
@ -305,6 +315,8 @@ namespace WaveSabreCore
for (int i = 0; i < numSamples; i++)
{
calcPitch();
filter.SetFreq(Helpers::Clamp(specimen->filterFreq + modEnv.GetValue() * (20000.0f - 20.0f) * (specimen->filterModAmt * 2.0f - 1.0f), 0.0f, 20000.0f - 20.0f));
float sample = samplePlayer.Next();
@ -376,7 +388,7 @@ namespace WaveSabreCore
void Specimen::SpecimenVoice::calcPitch()
{
samplePlayer.CalcPitch(Note - 60 + Detune + specimen->fineTune * 2.0f - 1.0f + SpecimenVoice::coarseDetune(specimen->coarseTune));
samplePlayer.CalcPitch(GetNote() - 60 + Detune + specimen->fineTune * 2.0f - 1.0f + SpecimenVoice::coarseDetune(specimen->coarseTune));
}
BOOL __stdcall Specimen::driverEnumCallback(HACMDRIVERID driverId, DWORD dwInstance, DWORD fdwSupport)

138
WaveSabreCore/src/SynthDevice.cpp

@ -15,6 +15,17 @@ namespace WaveSabreCore
VibratoAmount = 0.0f;
Rise = 0.0f;
Slide = 0.0f;
voiceMode = VoiceMode::Polyphonic;
monoActive = false;
noteCount = 0;
for (int i = 0; i < maxActiveNotes; i++)
{
activeNotes[i] = false;
noteLog[i] = 0;
}
clearEvents();
}
@ -48,22 +59,89 @@ namespace WaveSabreCore
case EventType::NoteOn:
{
int j = VoicesUnisono;
for (int k = 0; j && k < maxVoices; k++)
switch (voiceMode)
{
if (!voices[k]->IsOn)
case VoiceMode::Polyphonic:
default:
for (int k = 0; j && k < maxVoices; k++)
{
if (!voices[k]->IsOn)
{
j--;
float f = (float)j / (VoicesUnisono > 1 ? (float)(VoicesUnisono - 1) : 1.0f);
voices[k]->NoteOn(e->Note, e->Velocity, f * VoicesDetune, (f - .5f) * (VoicesPan * 2.0f - 1.0f) + .5f);
}
}
break;
case VoiceMode::MonoLegatoTrill:
activeNotes[e->Note] = true;
noteLog[noteCount] = e->Note;
noteCount++;
if (!monoActive) // no current note active, start new one
{
monoActive = true;
for (int k = 0; j && k < maxVoices; k++)
{
if (!voices[k]->IsOn)
{
j--;
float f = (float)j / (VoicesUnisono > 1 ? (float)(VoicesUnisono - 1) : 1.0f);
voices[k]->NoteOn(e->Note, e->Velocity, f * VoicesDetune, (f - .5f) * (VoicesPan * 2.0f - 1.0f) + .5f);
}
}
}
else // note active, slide to new note
{
j--;
float f = (float)j / (VoicesUnisono > 1 ? (float)(VoicesUnisono - 1) : 1.0f);
voices[k]->NoteOn(e->Note, e->Velocity, f * VoicesDetune, (f - .5f) * (VoicesPan * 2.0f - 1.0f) + .5f);
for (int j = 0; j < maxVoices; j++)
{
if (voices[j]->IsOn)
voices[j]->NoteSlide(e->Note);
}
}
break;
}
}
break;
case EventType::NoteOff:
for (int j = 0; j < maxVoices; j++)
switch (voiceMode)
{
if (voices[j]->IsOn && voices[j]->Note == e->Note) voices[j]->NoteOff();
case VoiceMode::Polyphonic:
default:
for (int j = 0; j < maxVoices; j++)
{
if (voices[j]->IsOn && voices[j]->Note == e->Note) voices[j]->NoteOff();
}
break;
case VoiceMode::MonoLegatoTrill:
activeNotes[e->Note] = false;
if (e->Note == noteLog[noteCount - 1]) // note off is last note played, find last active note
{
for (; noteCount > 0; noteCount--)
{
if (activeNotes[noteLog[noteCount - 1]])
{
for (int j = 0; j < maxVoices; j++)
{
if (voices[j]->IsOn)
voices[j]->NoteSlide(noteLog[noteCount - 1]);
}
break;
}
}
if (noteCount == 0) // no notes left, switch off the voices
{
monoActive = false;
for (int j = 0; j < maxActiveNotes; j++) activeNotes[j] = false;
for (int j = 0; j < maxVoices; j++)
{
if (voices[j]->IsOn)
voices[j]->NoteOff();
}
}
}
break;
}
}
events[i].Type = EventType::None;
@ -96,6 +174,9 @@ namespace WaveSabreCore
{
if (voices[i]->IsOn) voices[i]->NoteOff();
}
monoActive = false;
noteCount = 0;
for (int i = 0; i < maxActiveNotes; i++) activeNotes[i] = false;
clearEvents();
}
@ -128,6 +209,21 @@ namespace WaveSabreCore
}
}
void SynthDevice::SetVoiceMode(VoiceMode voiceMode)
{
if (this->voiceMode != voiceMode)
{
AllNotesOff();
for (int i = 0; i < maxVoices; i++) voices[i]->IsOn = false;
this->voiceMode = voiceMode;
}
}
VoiceMode SynthDevice::GetVoiceMode() const
{
return voiceMode;
}
SynthDevice::Voice::Voice()
{
IsOn = false;
@ -142,10 +238,36 @@ namespace WaveSabreCore
Note = note;
Detune = detune;
Pan = pan;
currentNote = (double)note;
slideActive = false;
}
void SynthDevice::Voice::NoteOff()
void SynthDevice::Voice::NoteOff() { }
void SynthDevice::Voice::NoteSlide(int note)
{
slideActive = true;
destinationNote = note;
double slideTime = 10.f * Helpers::Pow(this->SynthDevice()->Slide,4.0);
slideDelta = ((double)note - currentNote) / (Helpers::CurrentSampleRate * slideTime);
slideSamples = (int)(Helpers::CurrentSampleRate * slideTime);
}
double SynthDevice::Voice::GetNote()
{
if (slideActive)
{
currentNote += slideDelta;
slideSamples--;
if (slideSamples < 0)
{
Note = (int)destinationNote;
slideActive = false;
currentNote = (double)destinationNote;
}
}
return currentNote;
}
void SynthDevice::clearEvents()

5
WaveSabreCore/src/Thunder.cpp

@ -120,6 +120,11 @@ namespace WaveSabreCore
this->thunder = thunder;
}
SynthDevice *Thunder::ThunderVoice::SynthDevice() const
{
return thunder;
}
void Thunder::ThunderVoice::Run(double songPosition, float **outputs, int numSamples)
{
for (int i = 0; i < numSamples; i++)

2
WaveSabreVstLib/WaveSabreVstLib.vcxproj

@ -180,7 +180,7 @@
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;USE_LIBPNG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

Loading…
Cancel
Save