Synth in working state with stereo filter

main
Thor 12 months ago
parent 09df1b535f
commit 98181e4cf2
  1. 4
      lib/synth/include/channel.h
  2. 109
      lib/synth/include/dsp/filter.h
  3. 4
      lib/synth/include/dsp/oscillator.h
  4. 2
      lib/synth/include/synth.h
  5. 18
      lib/synth/include/voice.h
  6. 14
      lib/synth/src/channel.cpp
  7. 6
      lib/synth/src/dsp/filter.cpp
  8. 3
      lib/synth/src/voice.cpp

@ -53,8 +53,8 @@ public:
std::fill(out, out + bufferSize, 0.f);
for(Voice** voice = voices; *voice != NULL; ++voice) {
float voiceOut[numFrames];
(*voice)->tick(voiceOut, numFrames, pitchMod, fltMod);
float voiceOut[bufferSize];
(*voice)->tick(voiceOut, bufferSize, pitchMod, fltMod);
for(size_t i = 0; i < bufferSize; ++i) {
out[i] += voiceOut[i];

@ -52,6 +52,46 @@ public:
}
};
class SVF12Stereo {
protected:
float hp[2], bp[2], lp[2];
float as1[2], as2[2];
public:
SVF12Stereo() : hp{0, 0}, bp{0, 0}, lp{0, 0}, as1{0, 0}, as2{0, 0} {}
inline void tick(float *in, float *hpo, float *bpo, float *lpo, size_t bufferSize, float *kK, float *kQ) {
size_t frameCount = bufferSize / 2;
float kQ_1[frameCount];
for(size_t i = 0; i < frameCount; ++i) {
kQ_1[i] = 1.f / kQ[i];
}
float kMul[frameCount];
for(size_t i = 0; i < frameCount; ++i) {
kMul[i] = 1.f / (1.f + kK[i]*kQ_1[i] + kK[i]*kK[i]);
}
for(size_t i = 0, j = 0; i < bufferSize; ++i) {
size_t ch = i & 1;
hp[ch] = (in[i] - (kQ_1[j] + kK[j]) * as1[ch] - as2[ch]) * kMul[j];
float au = hp[ch] * kK[j];
bp[ch] = au + as1[ch];
as1[ch] = au + bp[ch];
au = bp[ch] * kK[j];
lp[ch] = au + as2[ch];
as2[ch] = au + lp[ch];
hpo && (hpo[i] = hp[ch]);
bpo && (bpo[i] = bp[ch]);
lpo && (lpo[i] = lp[ch]);
j += ch;
}
}
};
// 12 and 24 dB/oct
class Filter {
public:
@ -120,5 +160,74 @@ public:
}
};
// 12 and 24 dB/oct
class FilterStereo {
public:
enum Type {
TYPE_LP = 0,
TYPE_BP,
TYPE_HP
};
enum Slope {
SLOPE_12 = 0,
SLOPE_24,
};
typedef struct {
float freq;
float res;
Type type;
Slope slope;
} Settings;
private:
Settings const * settings;
SVF12Stereo fltA, fltB;
float freq, res;
public:
void assign(Settings const * settings);
inline void tick(float *in, float *out, size_t bufferSize, float *freqMod) {
size_t frameCount = bufferSize / 2;
float dt = 1.f / (float) frameCount;
float kK[frameCount];
float dFreq = dt * (settings->freq - freq);
for(size_t i = 0; i < frameCount; i++) {
kK[i] = fastCVtoK(freq + freqMod[i]);
freq += dFreq;
}
float kQ[frameCount];
float dRes = dt * (settings->res - res);
for(size_t i = 0; i < frameCount; i++) {
kQ[i] = (float) M_SQRT1_2 + res;
res += dRes;
}
switch(settings->type) {
case TYPE_LP:
fltA.tick(in, NULL, NULL, out, bufferSize, kK, kQ);
if(settings->slope == SLOPE_24) {
fltB.tick(out, NULL, NULL, out, bufferSize, kK, kQ);
}
break;
case TYPE_BP:
fltA.tick(in, NULL, out, NULL, bufferSize, kK, kQ);
if(settings->slope == SLOPE_24) {
fltB.tick(out, NULL, out, NULL, bufferSize, kK, kQ);
}
break;
case TYPE_HP:
fltA.tick(in, out, NULL, NULL, bufferSize, kK, kQ);
if(settings->slope == SLOPE_24) {
fltB.tick(out, out, NULL, NULL, bufferSize, kK, kQ);
}
break;
}
}
};
#endif

@ -67,8 +67,8 @@ public:
value += polyBlep(phaseBuf[i], phaseStepBuf[i]); // Layer output of Poly BLEP on top (flip)
value -= polyBlep(fmodf(phaseBuf[i] + 0.5f, 1.0f), phaseStepBuf[i]); // Layer output of Poly BLEP on top (flop)
out[j++] = gain[j & 1] * value;
out[j++] = gain[j & 1] * value;
out[j++] += gain[j & 1] * value;
out[j++] += gain[j & 1] * value;
}
}
}

@ -44,12 +44,14 @@ public:
}
}
/*
for(size_t i = 0; i < bufferSize; i += 2) {
frame f = {reverbBus[i], reverbBus[i + 1]};
f = reverb.tick(f);
out[i] += f.l;
out[i + 1] += f.r;
}
*/
for(size_t i = 0; i < bufferSize; ++i) {
out[i] *= 0.125f;

@ -8,7 +8,7 @@
#include "dsp/filter.h"
#include "dsp/adsr.h"
#define MAX_OSCS 8
#define MAX_OSCS 16
class Voice {
public:
@ -23,7 +23,7 @@ public:
float noiseMix;
Filter::Settings filter;
FilterStereo::Settings filter;
ADSR::Envelope ampEnv;
ADSR::Envelope modEnv;
@ -43,7 +43,7 @@ private:
ADSR adsrAmp;
ADSR adsrMod;
Oscillator osc[MAX_OSCS];
Filter filter;
FilterStereo filter;
public:
int note;
@ -64,12 +64,12 @@ public:
basePitchBuf[i] = note + pitchMod[i];
}
float oscCVBuf[MAX_OSCS][frameCount];
float oscPitchBuf[MAX_OSCS][frameCount];
float detune = -settings->oscDetune * 0.5f * (settings->unison - 1);
for(size_t i = 0; i < settings->unison; ++i) {
float transpose = (i & 1) ? settings->osc2Pitch : 0;
for(size_t j = 0; j < frameCount; ++j) {
oscCVBuf[i][j] = noteToCV(basePitchBuf[i] + detune + transpose);
oscPitchBuf[i][j] = noteToCV(basePitchBuf[j] + detune + transpose);
}
detune += settings->oscDetune;
}
@ -88,10 +88,10 @@ public:
for(size_t i = 0; i < settings->unison; ++i) {
float baseGain = (i & 1) ? settings->oscMix : (1 - settings->oscMix);
float gain[2];
gain[0] = sinf((1.f - pan) * (float) M_PI_2);
gain[1] = sinf(pan * (float) M_PI_2);
gain[0] = baseGain * sinf((1.f - pan) * (float) M_PI_2);
gain[1] = baseGain * sinf(pan * (float) M_PI_2);
pan += panStep;
osc[i].tick(oscBuf, bufferSize, oscCVBuf[i], gain);
osc[i].tick(oscBuf, bufferSize, oscPitchBuf[i], gain);
}
float noiseBuf[bufferSize];
@ -117,6 +117,8 @@ public:
for(size_t i = 0; i < frameCount; ++i) {
fltModBuf[i] = settings->modEnvFltGain * adsrMod.tick() + keyTrackVal + fltMod[i];
}
//std::copy(oscBuf, oscBuf + bufferSize, out);
filter.tick(oscBuf, out, bufferSize, fltModBuf);
for(size_t i = 0; i < bufferSize; ++i) {
out[i] *= gain * adsrAmp.tick();

@ -34,7 +34,7 @@ inline float ccToLFOFltMod(int x) {
}
void Channel::loadPreset(const Preset * preset) {
settings.unison = 1 + floorf(preset->unison * 8.f / 128.f);
settings.unison = 1 + floorf(preset->unison * 16.f / 128.f);
settings.osc1Mode = Oscillator::Mode(preset->osc1Mode);
settings.osc2Mode = Oscillator::Mode(preset->osc2Mode);
@ -43,8 +43,8 @@ void Channel::loadPreset(const Preset * preset) {
settings.oscMix = preset->oscMix / 127.f;
settings.noiseMix = preset->noiseMix / 127.f;
settings.filter.type = Filter::Type(floorf(3.f * preset->filter.type / 128.f));
settings.filter.slope = Filter::Slope(floorf(2.f * preset->filter.slope / 128.f));
settings.filter.type = FilterStereo::Type(floorf(3.f * preset->filter.type / 128.f));
settings.filter.slope = FilterStereo::Slope(floorf(2.f * preset->filter.slope / 128.f));
settings.filter.freq = (float) FILTER_CV_MAX * preset->filter.freq / 127.f;
settings.filter.res = preset->filter.Q / 31.75f;
@ -71,7 +71,7 @@ void Channel::noteOn(int note, int velocity) {
//printf("on: midi=%d note=%d\n", note, midiToNote(note));
Voice* const voice = voiceManager->get(number);
voice->assign(&settings);
voice->noteOn(midiToNote(note), velocity / 127.f, 1.f, 0.5f);
voice->noteOn(midiToNote(note), velocity / 127.f, 1.f);
}
void Channel::noteOff(int note) {
@ -159,7 +159,7 @@ void Channel::control(int code, int value) {
break;
case CC_UNISON: // Unison Amount
settings.unison = 1 + floorf(value * 8.f / 128.f);
settings.unison = 1 + floorf(value * 16.f / 128.f);
break;
case CC_OSC_MIX: // Oscillator 1/2 Mix
@ -175,11 +175,11 @@ void Channel::control(int code, int value) {
break;
case CC_FLT_TYP: // Filter Type
settings.filter.type = Filter::Type(floorf(3.f * value / 128.f));
settings.filter.type = FilterStereo::Type(floorf(3.f * value / 128.f));
break;
case CC_FLT_SLP: // Filter Slope
settings.filter.slope = Filter::Slope(floorf(2.f * value / 128.f));
settings.filter.slope = FilterStereo::Slope(floorf(2.f * value / 128.f));
break;
case CC_RVB_SND:

@ -4,4 +4,10 @@ void Filter::assign(Settings const * settings) {
this->settings = settings;
freq = settings->freq;
res = settings->res;
}
void FilterStereo::assign(Settings const * settings) {
this->settings = settings;
freq = settings->freq;
res = settings->res;
}

@ -19,11 +19,10 @@ void Voice::assign(Settings const * settings) {
filter.assign(&settings->filter);
}
void Voice::noteOn(int note, float velocity, float gain, float pan) {
void Voice::noteOn(int note, float velocity, float gain) {
this->note = note;
this->velocity = velocity;
this->gain = gain;
this->pan = pan;
adsrAmp.noteOn();
adsrMod.noteOn();
}

Loading…
Cancel
Save