You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

139 lines
4.3 KiB

#include <iostream>
#include "synth/globals.h"
#include "synth/cc.h"
#include "synth/part.h"
float timeToStep(float t) {
return (1.0 / SAMPLE_RATE) / t;
}
float ccToA(int x) {
return 5.0 * exp(9.2 * (x / 127.0) - 9.2);
}
float ccToDR(int x) {
return 5.0 * exp(7.0 * (x / 127.0) - 7.0);
}
void Part::loadPreset(const Preset * preset) {
settings.osc1Mode = Oscillator::Mode(preset->osc1Mode);
settings.osc2Mode = Oscillator::Mode(preset->osc2Mode);
settings.oscMix = preset->oscMix / 127.0;
settings.oscDetune = (preset->oscDetune - 64.0) / 100.0;
settings.filter.type = Filter::Type(preset->filter.type);
settings.filter.slope = Filter::Slope(preset->filter.slope);
settings.filter.freq = preset->filter.freq / 127.0;
settings.filter.Q = preset->filter.Q / 31.75;
settings.ampEnv.attackStep = timeToStep(ccToA(preset->ampEnv.attack));
settings.ampEnv.decayStep = timeToStep(ccToDR(preset->ampEnv.decay));
settings.ampEnv.sustain = preset->ampEnv.sustain / 127.0;
settings.ampEnv.releaseStep = timeToStep(ccToDR(preset->ampEnv.release));
settings.modEnv.attackStep = timeToStep(ccToA(preset->modEnv.attack));
settings.modEnv.decayStep = timeToStep(ccToDR(preset->modEnv.decay));
settings.modEnv.sustain = preset->modEnv.sustain / 127.0;
settings.modEnv.releaseStep = timeToStep(ccToDR(preset->modEnv.release));
settings.modEnvFltGain = preset->modEnvFltGain / 127.0;
settings.keyTrack = preset->keyTrack / 127.0;
}
void Part::noteOn(int note, int velocity) {
// Garbage collection - free up idle voices
std::erase_if(notes, [this](auto& note) {
std::erase_if(note.second, [this](auto& voice) {
if(voice->isIdle()) {
voiceManager->free(voice);
return true;
}
return false;
});
return note.second.empty();
});
Voice * const voice = voiceManager->allocate();
voice->assign(&settings);
voice->noteOn();
if(notes.count(note)) {
notes.at(note).insert(voice);
} else {
notes.emplace(note, std::set<Voice *>{voice});
}
}
void Part::noteOff(int note) {
if(notes.count(note)) {
auto& voices = notes.at(note);
for (auto i = voices.rbegin(); i != voices.rend(); ++i ) {
if((*i)->keyed) {
(*i)->noteOff();
break;
}
}
}
}
void Part::control(int code, int value) {
switch(code) {
case CC_VOLUME: // Volume (Standard MIDI)
volume = value / 127.0;
break;
case CC_FLT_ATK: // Filter Attack Time
settings.modEnv.attackStep = timeToStep(ccToA(value));
break;
case CC_FLT_DEC: // Filter Decay Time
settings.modEnv.decayStep = timeToStep(ccToDR(value));
break;
case CC_FLT_SUS: // Filter Sustain
settings.modEnv.sustain = value / 127.0;
break;
case CC_FLT_REL: // Filter Release Time
settings.modEnv.releaseStep = timeToStep(ccToDR(value));
break;
case CC_FLT_Q: // Timbre / Harmonic Content (Standard MIDI)
settings.filter.Q = value / 31.75;
std::cout << "Q=" << settings.filter.Q << std::endl;
break;
case CC_AMP_REL: // Release Time (Standard MIDI)
settings.ampEnv.releaseStep = timeToStep(ccToDR(value));
break;
case CC_AMP_ATK: // Attack Time (Standard MIDI)
settings.ampEnv.attackStep = timeToStep(ccToA(value));
break;
case CC_FLT_FRQ: // Brightness (Standard MIDI)
settings.filter.freq = value / 127.0;
break;
case CC_AMP_DEC: // Decay Time
settings.ampEnv.decayStep = timeToStep(ccToDR(value));
break;
case CC_AMP_SUS: // Sustain
settings.ampEnv.sustain = value / 127.0;
break;
case CC_OSC_DET: // Detune (Standard MIDI)
settings.oscDetune = (value - 64.0) / 100.0;
break;
case CC_MOD_FLT: // Mod Envelope Filter Gain
settings.modEnvFltGain = value / 127.0;
break;
case CC_KEY_TRK: // Filter Key Tracking
settings.keyTrack = value / 127.0;
break;
}
}