Various changes

main
Thor 1 year ago
parent 2ca29337c3
commit 5389e811eb
  1. 9
      CMakeLists.txt
  2. 3
      include/synth/cc.h
  3. 2
      include/synth/channel.h
  4. 39
      include/synth/dsp/filter.h
  5. 16
      include/synth/dsp/oscillator.h
  6. 6
      include/synth/dsp/reverb.h
  7. 56
      include/synth/dsp/util.h
  8. 1
      include/synth/globals.h
  9. 4
      include/synth/preset.h
  10. 12
      include/synth/synth.h
  11. 10
      include/synth/voice.h
  12. 10
      include/synthframe.h
  13. 44
      src/genluts.cpp
  14. 31
      src/synth/channel.cpp
  15. 6
      src/synth/preset.cpp
  16. 3
      src/synth/voice.cpp
  17. 3
      src/synth/voicemanager.cpp
  18. 14
      src/synthapp.cpp
  19. 24
      src/synthframe.cpp

@ -7,8 +7,8 @@ if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "/W4 /DEBUG:FASTLINK /fp:fast")
set(CMAKE_CXX_FLAGS_RELEASE "/W4 /O2 /fp:fast /DNDEBUG")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Wextra -Wdouble-promotion -g -ffast-math")
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -Wextra -Wdouble-promotion -Ofast -DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-g -ffast-math -Wall -Wextra -Wdouble-promotion ")
set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -DNDEBUG -Wall -Wextra -Wdouble-promotion -Rpass-analysis=loop-vectorize")
endif()
if(WIN32)
@ -42,9 +42,6 @@ add_executable(main
src/synth/dsp/reverb.cpp)
target_include_directories(main PRIVATE include)
add_executable(genluts src/genluts.cpp)
target_include_directories(genluts PRIVATE include)
#target_compile_options(main PRIVATE -fsanitize=thread)
#target_link_options(main PRIVATE -fsanitize=thread)
@ -56,4 +53,4 @@ target_link_libraries(main PRIVATE wxbase)
target_link_libraries(main PRIVATE wxcore)
add_custom_target(synth)
add_dependencies(synth main genluts)
add_dependencies(synth main)

@ -25,4 +25,7 @@
#define CC_OSC2MDE 29 // Oscillator 2 Mode
#define CC_FLT_TYP 30 // Filter Type
#define CC_FLT_SLP 31 // Filter Slope
#define CC_RVB_SND 102 // Reverb Send
#define CC_NOI_MIX 103 // Noise Mix
#endif

@ -36,7 +36,7 @@ public:
out *= volume;
lfoPhase += settings.lfoStep;
while(lfoPhase >= (float) PIx2) {
if(lfoPhase >= (float) PIx2) {
lfoPhase -= PIx2;
}

@ -16,31 +16,9 @@
#define FILTER_K_SCALE (2 * CV_FREQ_MIN / (FILTER_OVERSAMPLE * SAMPLE_RATE))
#define FILTER_CV_MAX 9.25 // MIDI note "135" (19912.126958213178287 Hz)
//#define USE_LUTS
#define K_LUT_SIZE 64
#ifdef USE_LUTS
extern float kLUT[K_LUT_SIZE];
inline float cvToK(float cv) {
float intPart, fracPart = modf(cv * (K_LUT_SIZE - 1) / FILTER_K_LUT_MAX, &intPart);
int index = (int) intPart;
if(index < 0) {
return kLUT[0];
} else if(index >= K_LUT_SIZE - 1) {
return kLUT[K_LUT_SIZE - 1];
} else {
return (1 - fracPart) * kLUT[index] + fracPart * kLUT[index + 1];
}
}
#else
inline float cvToK(float cv) {
return tanf((float) M_PI_2 * std::min(0.5f, std::min(1.f / FILTER_OVERSAMPLE, (float) FILTER_K_SCALE * exp2f(cv))));
}
#endif
inline float cvToK(float cv) {
return tanf((float) M_PI_2 * std::min(0.5f, std::min(1.f / FILTER_OVERSAMPLE, (float) FILTER_K_SCALE * exp2f(cv))));
}
class SVF12 {
public:
@ -72,23 +50,22 @@ public:
class Oversampler {
private:
int times;
float kK, kQ = (float) M_SQRT1_2;
SVF12 aa1, aa2;
public:
Oversampler(int times) : times(times), kK(tanf((float) M_PI_2 * 1.0f / times)) {}
Oversampler() : kK(tanf((float) M_PI_2 * 1.0f / FILTER_OVERSAMPLE)) {}
inline float tick(float in, std::function<float(float)> process) {
if(times < 2) {
if(FILTER_OVERSAMPLE < 2) {
return process(in);
} else {
// float out = aa2.tick(aa1.tick(times * process(in), kK, kQ).lp, kK, kQ).lp;
// for(int i = 1; i < times; ++i) {
// aa2.tick(aa1.tick(process(0), kK, kQ).lp, kK, kQ);
// }
float out = process(aa2.tick(aa1.tick(times * in, kK, kQ).lp, kK, kQ).lp);
for(int i = 1; i < times; ++i) {
float out = process(aa2.tick(aa1.tick(FILTER_OVERSAMPLE * in, kK, kQ).lp, kK, kQ).lp);
for(int i = 1; i < FILTER_OVERSAMPLE; ++i) {
process(aa2.tick(aa1.tick(0, kK, kQ).lp, kK, kQ).lp);
}
@ -121,7 +98,7 @@ public:
private:
Settings const * settings;
SVF12 fltA, fltB;
Oversampler os{FILTER_OVERSAMPLE};
Oversampler os;
public:
void assign(Settings const * settings);

@ -26,15 +26,15 @@ public:
// Generate next output sample and advance the phase angle
inline float tick(float cv) {
const float phaseStep = (float) (2 * CV_FREQ_MIN) * exp2f(cv) / SAMPLE_RATE;
const float phaseStep = (float) (2 * CV_FREQ_MIN) * exp2f(cv) * (float) SAMPLE_RATE_INV;
const float t = phase / PIx2; // Define half phase
const float dt = phaseStep / PIx2;
const float t = phase * (float) PIx2_INV; // Define half phase
const float dt = phaseStep * (float) PIx2_INV;
if (*mode == MODE_SINE) {
value = sinf(phase); // No harmonics in sine so no aliasing!! No Poly BLEPs needed!
} else if (*mode == MODE_SAW) {
value = (2.0f * phase / PIx2) - 1.0f; // Render naive waveshape
value = (2.0f * t) - 1.0f; // Render naive waveshape
value -= polyBlep(t, dt); // Layer output of Poly BLEP on top
} else if (*mode == MODE_SQUARE) {
if (phase < (float) M_PI) {
@ -46,10 +46,10 @@ public:
value -= polyBlep(fmodf(t + 0.5f, 1.0f), dt); // Layer output of Poly BLEP on top (flop)
}
//driftValue += 0.01f * (randFrac() - 0.5f) - 0.00001f * driftValue;
//phase += phaseStep * (1.0f + driftAmount * driftValue);
phase += phaseStep;
while(phase >= (float) PIx2) { // wrap if phase angle >=360º
driftValue += 0.005f * whiteNoise() - 0.00001f * driftValue;
phase += phaseStep * (1.0f + driftAmount * driftValue);
if(phase >= (float) PIx2) { // wrap if phase angle >=360º
phase -= PIx2;
}

@ -25,8 +25,6 @@ private:
float hpfL = 0.f, hpfR = 0.f;
public:
float mix = 0.25f;
Reverb();
frame tick(frame in) {
@ -34,7 +32,7 @@ public:
frame out{0, 0};
for(Tap& tap : taps) {
for(const Tap& tap : taps) {
out.l += tap.lg * dl.tap(tap.lp).l;
out.r += tap.rg * dl.tap(tap.rp).r;
}
@ -48,7 +46,7 @@ public:
out.l = lpfL - hpfL;
out.r = lpfR - hpfR;
return mix * out + (1 - mix) * in;
return out;
}
};

@ -1,36 +1,21 @@
#ifndef __UTIL_H__
#define __UTIL_H__
#include <cstdio>
#include <cmath>
#include <cfloat>
#include <chrono>
#include "../globals.h"
#define PIx2 ((float )(2 * M_PI))
#define PIx2 (2 * M_PI)
#define PIx2_INV (1.0 / PIx2)
#define CV_FREQ_MIN 32.703195662574829 // MIDI note 24 (C1)
//#define USE_NOTE_LUTS
#define NOTE_LUT_SIZE 128
#define CENT_LUT_SIZE 128
#ifdef USE_NOTE_LUTS
extern float noteLUT[NOTE_LUT_SIZE];
extern float centLUT[CENT_LUT_SIZE];
inline float noteToFreq(float note) {
float intPart, fracPart = modf(note, &intPart);
int index = (int) intPart;
return fracPart < FLT_EPSILON ? noteLUT[index] : noteLUT[index] * centLUT[(int) (fracPart * 127.0)];
}
#else
inline float noteToCV(float note) {
return (note - 24) / 12.f;
}
#endif
inline float noteToCV(float note) {
return (note - 24) / 12.f;
}
inline float clamp(float x, float a, float b) {
return fminf(b, fmaxf(a, x));
@ -44,12 +29,37 @@ inline float triangle(float phase) {
}
}
inline float whiteNoise() {
static int32_t x1 = 0x70F4F854;
static int32_t x2 = 0xE1E9F0A7;
x1 ^= x2;
float value = x2 * (2.0f / 0xFFFFFFFF);
x2 += x1;
return value;
}
inline float randFrac() {
return rand() / (float) RAND_MAX;
static uint32_t x1 = 0x70F4F854;
static uint32_t x2 = 0xE1E9F0A7;
x1 ^= x2;
float value = x2 / (float) 0x100000000;
x2 += x1;
return value;
}
inline float randPhase() {
return (float) PIx2 * randFrac();
}
// Get time stamp in nanoseconds.
inline uint64_t nanos() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count();
}
#endif

@ -2,5 +2,6 @@
#define __GLOBALS_H__
#define SAMPLE_RATE 44100
#define SAMPLE_RATE_INV (1.0 / SAMPLE_RATE)
#endif

@ -21,6 +21,8 @@ struct Preset {
uint8_t oscDetune;
uint8_t osc2Pitch;
uint8_t noiseMix;
struct {
uint8_t type;
uint8_t slope;
@ -36,6 +38,8 @@ struct Preset {
uint8_t lfoFreq;
uint8_t lfoPitchMod;
uint8_t lfoFltMod;
uint8_t reverb;
};
extern const Preset DEFAULT_PRESET;

@ -20,13 +20,19 @@ public:
void noteOff(int ch, int note);
void control(int ch, int cc, int val);
frame tick() {
inline frame tick() {
frame out{};
frame reverbBus{};
for(auto& channel : channels) {
out += channel.tick();
frame channelOut = channel.tick();
out += channelOut;
reverbBus += channel.settings.reverb * channelOut;
}
out = reverb.tick(out);
out += reverb.tick(reverbBus);
out *= 0.125f;
return out;
}

@ -19,6 +19,8 @@ public:
float oscDetune;
float osc2Pitch;
float noiseMix;
Filter::Settings filter;
ADSR::Envelope ampEnv;
@ -29,6 +31,8 @@ public:
float lfoStep;
float lfoPitchMod;
float lfoFltMod;
float reverb;
} Settings;
private:
@ -42,12 +46,13 @@ private:
public:
int note;
float gain;
float pan;
float detune;
void reset();
void assign(Settings const * settings);
void noteOn(int note, float detune = 0, float pan = 0.5);
void noteOn(int note, float detune = 0, float gain = 1.0, float pan = 0.5);
void noteOff();
inline bool isIdle() { return adsrAmp.isIdle(); }
@ -58,9 +63,10 @@ public:
float out = 0;
out += (1 - settings->oscMix) * osc1.tick(osc1CV);
out += settings->oscMix * osc2.tick(osc2CV);
out += settings->noiseMix * ((1.f / 3.f) * (whiteNoise() + whiteNoise() + whiteNoise()) - out);
const float keyTrackVal = settings->keyTrack * (note - 72) / 12.f;
out = filter.tick(out, settings->modEnvFltGain * adsrMod.tick() + keyTrackVal + fltMod);
out *= adsrAmp.tick();
out *= gain * adsrAmp.tick();
return out;
}
};

@ -22,6 +22,8 @@ private:
OSC2_PIT_SLIDER,
OSC_MIX_SLIDER,
NOISE_MIX_SLIDER,
FLT_TYPE_SLIDER,
FLT_SLOPE_SLIDER,
FLT_FREQ_SLIDER,
@ -43,7 +45,9 @@ private:
LFO_FREQ_SLIDER,
LFO_PITCH_SLIDER,
LFO_FILTER_SLIDER
LFO_FILTER_SLIDER,
REVERB_SLIDER
};
wxSlider* addCCSlider(wxWindow* parent, wxSizer* sizer, wxWindowID id, const wxString& label, uint8_t value);
@ -59,6 +63,8 @@ private:
void OnOsc2PitScroll(wxScrollEvent& event);
void OnOscMixScroll(wxScrollEvent& event);
void OnNoiseMixScroll(wxScrollEvent& event);
void OnFltTypeScroll(wxScrollEvent& event);
void OnFltSlopeScroll(wxScrollEvent& event);
void OnFltFreqScroll(wxScrollEvent& event);
@ -82,6 +88,8 @@ private:
void OnLFOPitchScroll(wxScrollEvent& event);
void OnLFOFilterScroll(wxScrollEvent& event);
void OnReverbScroll(wxScrollEvent& event);
wxDECLARE_EVENT_TABLE();
};

@ -1,44 +0,0 @@
#include <cstdio>
#include <cmath>
#include "synth/dsp/filter.h"
#include "synth/dsp/util.h"
void dumpLUT(const char * filename, const char * identifier, float *lut, size_t size) {
FILE * f = fopen(filename, "w");
fprintf(f, "float %s[] = {\n", identifier);
for(size_t i = 0; i < size; ++i) {
if(i % 8 == 0) {
fputs(" ", f);
}
fprintf(f, "%13.7ff", (double) lut[i]);
if(i < size - 1) {
fputs(", ", f);
}
if(i % 8 == 7) {
putc('\n', f);
}
}
fputs("};\n", f);
fclose(f);
}
int main(int argc, char** argv) {
float kLUT[K_LUT_SIZE];
for(int i = 0; i < K_LUT_SIZE; ++i) {
kLUT[i] = tan(std::max(M_PI_4, M_PI_2 * FILTER_K_SCALE * exp2(FILTER_CV_MAX * i / (K_LUT_SIZE - 1.0))));
}
dumpLUT("src/synth/dsp/filterlut.cpp", "kLUT", kLUT, K_LUT_SIZE);
float noteLUT[NOTE_LUT_SIZE];
for(int i = 0; i < NOTE_LUT_SIZE; ++i) {
noteLUT[i] = 440 * powf(2.f, (i - 69.f) / 12.0f);
}
dumpLUT("src/synth/dsp/notelut.cpp", "noteLUT", noteLUT, NOTE_LUT_SIZE);
float centLUT[CENT_LUT_SIZE];
for(int i = 0; i < CENT_LUT_SIZE; ++i) {
centLUT[i] = pow(2.f, i / ((CENT_LUT_SIZE - 1) * 12.0f));
}
dumpLUT("src/synth/dsp/centlut.cpp", "centLUT", centLUT, CENT_LUT_SIZE);
}

@ -5,31 +5,31 @@
#include "synth/channel.h"
float midiToNote(int note) {
inline float midiToNote(int note) {
return note + 24;
}
float timeToStep(float t) {
return (1.0f / SAMPLE_RATE) / t;
inline float timeToStep(float t) {
return SAMPLE_RATE_INV / t;
}
float ccToA(int x) {
inline float ccToA(int x) {
return 5.0 * exp(9.2 * (x / 127.0) - 9.2);
}
float ccToDR(int x) {
inline float ccToDR(int x) {
return 5.0 * exp(7.0 * (x / 127.0) - 7.0);
}
float ccToLFOStep(int x) {
return PIx2 * 0.1f * expf((1 + x) * 6.907755278982137f / 128.0f) / SAMPLE_RATE;
inline float ccToLFOStep(int x) {
return (float) PIx2 * 0.1f * expf((1 + x) * 6.907755278982137f / 128.0f) * SAMPLE_RATE_INV;
}
float ccToLFOPitchMod(int x) {
inline float ccToLFOPitchMod(int x) {
return 6.f * x * x / 16129.f;
}
float ccToLFOFltMod(int x) {
inline float ccToLFOFltMod(int x) {
return (float) FILTER_CV_MAX * (x - 64) / 126.f;
}
@ -41,6 +41,7 @@ void Channel::loadPreset(const Preset * preset) {
settings.oscDetune = preset->oscDetune / 254.f;
settings.osc2Pitch = floorf(preset->osc2Pitch * 13.f / 128.f);
settings.oscMix = preset->oscMix / 127.f;
settings.noiseMix = preset->noiseMix / 127.f;
settings.filter.type = Filter::Type(preset->filter.type);
settings.filter.slope = Filter::Slope(preset->filter.slope);
@ -62,6 +63,8 @@ void Channel::loadPreset(const Preset * preset) {
settings.lfoStep = ccToLFOStep(preset->lfoFreq);
settings.lfoPitchMod = ccToLFOPitchMod(preset->lfoPitchMod);
settings.lfoFltMod = ccToLFOFltMod(preset->lfoFltMod);
settings.reverb = preset->reverb / 127.f;
}
void Channel::noteOn(int note, int velocity) {
@ -69,7 +72,7 @@ void Channel::noteOn(int note, int velocity) {
for(int i = -range; i <= range; i += 4) {
Voice* const voice = voiceManager->get(number);
voice->assign(&settings);
voice->noteOn(midiToNote(note), i * settings.oscDetune, range ? 0.5f + 0.5f * i / range : 0.5f);
voice->noteOn(midiToNote(note), i * settings.oscDetune, 1.f / sqrtf(settings.unison), range ? 0.5f + 0.5f * i / range : 0.5f);
}
}
@ -181,6 +184,14 @@ void Channel::control(int code, int value) {
settings.filter.slope = Filter::Slope(floorf(2.f * value / 128.f));
break;
case CC_RVB_SND:
settings.reverb = value / 127.f;
break;
case CC_NOI_MIX:
settings.noiseMix = value / 127.f;
break;
// LFO delay
// Reverb Time
// Reverb Brightness

@ -9,6 +9,8 @@ const Preset DEFAULT_PRESET = {
.oscDetune = 10,
.osc2Pitch = 0,
.noiseMix = 0,
.filter = {
.type = 0,
.slope = 22,
@ -34,5 +36,7 @@ const Preset DEFAULT_PRESET = {
.keyTrack = 127,
.lfoFreq = 64,
.lfoPitchMod = 16,
.lfoFltMod = 64
.lfoFltMod = 64,
.reverb = 32
};

@ -14,8 +14,9 @@ void Voice::assign(Settings const * settings) {
filter.assign(&settings->filter);
}
void Voice::noteOn(int note, float detune, float pan) {
void Voice::noteOn(int note, float detune, float gain, float pan) {
this->note = note;
this->gain = gain;
this->detune = detune;
this->pan = pan;
adsrAmp.noteOn();

@ -38,6 +38,9 @@ Voice * VoiceManager::get(channel_t channel) {
*/
VoiceData& voiceData = voices[0];
if(!voiceData.voice.isIdle()) {
printf("Out of voices\n");
}
voiceData.channel = channel;
voiceData.serial = serial++;
voiceData.voice.reset();

@ -3,12 +3,16 @@
#include <cmath>
#include "synth/globals.h"
#include "synth/dsp/util.h"
#include "synthapp.h"
#include "synthframe.h"
using namespace std;
uint64_t synthNanos = 0;
uint64_t synthSamples = 0;
// PortAudio callback for audio I/O
bool firstPACallback = true;
static int paCallback(
@ -50,11 +54,21 @@ static int paCallback(
float *out = (float*) outputBuffer;
uint64_t started = nanos();
for(unsigned long i = 0; i < framesPerBuffer; i++) {
frame f = app->synth.tick();
*out++ = f.l;
*out++ = f.r;
}
uint64_t finished = nanos();
synthNanos += finished - started;
synthSamples += framesPerBuffer;
if(synthSamples > 5 * SAMPLE_RATE) {
printf("%llu ns\n", synthNanos / synthSamples);
synthNanos = 0;
synthSamples = 0;
}
return 0;
}

@ -37,7 +37,8 @@ SynthFrame::SynthFrame() : wxFrame(NULL, wxID_ANY, "Hello World") {
sizer->Add(new CCSlider(panel, OSC2_MODE_SLIDER, DEFAULT_PRESET.osc2Mode, "O2M"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, OSC_DET_SLIDER, DEFAULT_PRESET.oscDetune, "Det"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, OSC2_PIT_SLIDER, DEFAULT_PRESET.osc2Pitch, "2nd"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, OSC_MIX_SLIDER, DEFAULT_PRESET.oscMix, "Mix"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, OSC_MIX_SLIDER, DEFAULT_PRESET.oscMix, "OMx"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, NOISE_MIX_SLIDER, DEFAULT_PRESET.noiseMix, "NMx"), 1, wxEXPAND);
sizer->AddStretchSpacer();
sizer->Add(new CCSlider(panel, FLT_TYPE_SLIDER, DEFAULT_PRESET.filter.type, "FTy"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, FLT_SLOPE_SLIDER, DEFAULT_PRESET.filter.slope, "FSl"), 1, wxEXPAND);
@ -62,6 +63,8 @@ SynthFrame::SynthFrame() : wxFrame(NULL, wxID_ANY, "Hello World") {
sizer->Add(new CCSlider(panel, LFO_PITCH_SLIDER, DEFAULT_PRESET.lfoPitchMod, "Pit"), 1, wxEXPAND);
sizer->Add(new CCSlider(panel, LFO_FILTER_SLIDER, DEFAULT_PRESET.lfoFltMod, "Flt"), 1, wxEXPAND);
sizer->AddStretchSpacer();
sizer->Add(new CCSlider(panel, REVERB_SLIDER, DEFAULT_PRESET.reverb, "Rvb"), 1, wxEXPAND);
sizer->AddStretchSpacer();
this->FitInside();
@ -106,7 +109,12 @@ void SynthFrame::OnOsc2PitScroll(wxScrollEvent& event) {
void SynthFrame::OnOscMixScroll(wxScrollEvent& event) {
SynthApp& app = wxGetApp();
app.synth.control(0, CC_OSC_MIX, event.GetPosition());
}
}
void SynthFrame::OnNoiseMixScroll(wxScrollEvent& event) {
SynthApp& app = wxGetApp();
app.synth.control(0, CC_NOI_MIX, event.GetPosition());
}
void SynthFrame::OnFltTypeScroll(wxScrollEvent& event) {
SynthApp& app = wxGetApp();
@ -193,19 +201,21 @@ void SynthFrame::OnLFOFilterScroll(wxScrollEvent& event) {
app.synth.control(0, CC_LFO_FLT, event.GetPosition());
}
void SynthFrame::OnReverbScroll(wxScrollEvent& event) {
SynthApp& app = wxGetApp();
app.synth.control(0, CC_RVB_SND, event.GetPosition());
}
wxBEGIN_EVENT_TABLE(SynthFrame, wxFrame)
EVT_COMMAND_SCROLL(SynthFrame::UNISON_SLIDER, SynthFrame::OnUnisonScroll)
//#define CC_OSC1MDE 28 // Oscillator 1 Mode
//#define CC_OSC2MDE 29 // Oscillator 2 Mode
EVT_COMMAND_SCROLL(SynthFrame::OSC1_MODE_SLIDER, SynthFrame::OnOsc1ModeScroll)
EVT_COMMAND_SCROLL(SynthFrame::OSC2_MODE_SLIDER, SynthFrame::OnOsc2ModeScroll)
EVT_COMMAND_SCROLL(SynthFrame::OSC_DET_SLIDER, SynthFrame::OnOscDetScroll)
EVT_COMMAND_SCROLL(SynthFrame::OSC2_PIT_SLIDER, SynthFrame::OnOsc2PitScroll)
EVT_COMMAND_SCROLL(SynthFrame::OSC_MIX_SLIDER, SynthFrame::OnOscMixScroll)
EVT_COMMAND_SCROLL(SynthFrame::NOISE_MIX_SLIDER, SynthFrame::OnNoiseMixScroll)
EVT_COMMAND_SCROLL(SynthFrame::FLT_TYPE_SLIDER, SynthFrame::OnFltTypeScroll)
EVT_COMMAND_SCROLL(SynthFrame::FLT_SLOPE_SLIDER, SynthFrame::OnFltSlopeScroll)
@ -230,4 +240,6 @@ EVT_COMMAND_SCROLL(SynthFrame::LFO_FREQ_SLIDER, SynthFrame::OnLFOFreqScroll)
EVT_COMMAND_SCROLL(SynthFrame::LFO_PITCH_SLIDER, SynthFrame::OnLFOPitchScroll)
EVT_COMMAND_SCROLL(SynthFrame::LFO_FILTER_SLIDER, SynthFrame::OnLFOFilterScroll)
EVT_COMMAND_SCROLL(SynthFrame::REVERB_SLIDER, SynthFrame::OnReverbScroll)
wxEND_EVENT_TABLE()
Loading…
Cancel
Save