|
|
|
@ -3,7 +3,7 @@ |
|
|
|
|
#include "synth/globals.h" |
|
|
|
|
#include "synth/cc.h" |
|
|
|
|
|
|
|
|
|
#include "synth/part.h" |
|
|
|
|
#include "synth/channel.h" |
|
|
|
|
|
|
|
|
|
float timeToStep(float t) { |
|
|
|
|
return (1.0 / SAMPLE_RATE) / t; |
|
|
|
@ -25,7 +25,7 @@ float ccToLFOPitchMod(int x) { |
|
|
|
|
return 0.01 * exp(x * 7.090076835776092 / 127.0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Part::loadPreset(const Preset * preset) { |
|
|
|
|
void Channel::loadPreset(const Preset * preset) { |
|
|
|
|
settings.osc1Mode = Oscillator::Mode(preset->osc1Mode); |
|
|
|
|
settings.osc2Mode = Oscillator::Mode(preset->osc2Mode); |
|
|
|
|
settings.oscMix = preset->oscMix / 127.0; |
|
|
|
@ -54,42 +54,22 @@ void Part::loadPreset(const Preset * preset) { |
|
|
|
|
settings.lfoFltMod = preset->lfoFltMod / 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(); |
|
|
|
|
void Channel::noteOn(int note, int velocity) { |
|
|
|
|
Voice* const voice = voiceManager->get(number); |
|
|
|
|
voice->assign(&settings); |
|
|
|
|
voice->noteOn(); |
|
|
|
|
if(notes.count(note)) { |
|
|
|
|
notes.at(note).insert(voice); |
|
|
|
|
} else { |
|
|
|
|
notes.emplace(note, std::set<Voice *>{voice}); |
|
|
|
|
} |
|
|
|
|
voice->noteOn(note); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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 Channel::noteOff(int note) { |
|
|
|
|
Voice** voices = voiceManager->getChannelVoices(number); |
|
|
|
|
for(Voice** voice = voices; *voice != NULL; ++voice) { |
|
|
|
|
if((*voice)->note == note) { |
|
|
|
|
(*voice)->noteOff(); |
|
|
|
|
}
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Part::control(int code, int value) { |
|
|
|
|
void Channel::control(int code, int value) { |
|
|
|
|
switch(code) { |
|
|
|
|
case CC_VOLUME: // Volume (Standard MIDI)
|
|
|
|
|
volume = value / 127.0; |