#include #include "globals.h" #include "cc.h" #include "channel.h" inline int midiToNote(int note) { return note - 24; } inline float timeToStep(float t) { return (float) SAMPLE_RATE_INV / t; } inline float ccToA(int x) { return 5.0 * exp(9.2 * (x / 127.0) - 9.2); } inline float ccToDR(int x) { return 5.0 * exp(7.0 * (x / 127.0) - 7.0); } inline float ccToLFOStep(int x) { return (float) 0.1f * expf((1 + x) * 6.907755278982137f / 128.0f) * (float) SAMPLE_RATE_INV; } inline float ccToLFOPitchMod(int x) { return 6.f * x * x / 16129.f; } inline float ccToLFOFltMod(int x) { return (float) FILTER_CV_MAX * (x - 64) / 126.f; } void Channel::loadPreset(const Preset * preset) { settings.unison = 2 + 2 * floorf(preset->unison * 4.f / 128.f); settings.osc1Mode = Oscillator::Mode(preset->osc1Mode); settings.osc2Mode = Oscillator::Mode(preset->osc2Mode); 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 = FilterStereo::Type(floorf(4.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; settings.ampEnv.attackStep = timeToStep(ccToA(preset->ampEnv.attack)); settings.ampEnv.decayStep = timeToStep(ccToDR(preset->ampEnv.decay)); settings.ampEnv.sustain = preset->ampEnv.sustain / 127.f; 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.f; settings.modEnv.releaseStep = timeToStep(ccToDR(preset->modEnv.release)); settings.modEnvFltGain = (float) FILTER_CV_MAX * preset->modEnvFltGain / 127.f; settings.keyTrack = preset->keyTrack / 127.f; 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) { //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); } void Channel::noteOff(int note) { Voice** voices = voiceManager->getChannelVoices(number); for(Voice** voice = voices; *voice != NULL; ++voice) { if((*voice)->note == midiToNote(note)) { //printf("off: midi=%d note=%d\n", note, midiToNote(note)); (*voice)->noteOff(); } } } void Channel::control(int code, int value) { switch(code) { case CC_VOLUME: // Volume (Standard MIDI) volume = value / 127.f; 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.f; 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.res = value / 31.75f; 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 = (float) FILTER_CV_MAX * value / 127.f; break; case CC_AMP_DEC: // Decay Time settings.ampEnv.decayStep = timeToStep(ccToDR(value)); break; case CC_AMP_SUS: // Sustain settings.ampEnv.sustain = value / 127.f; break; case CC_OSC_DET: // Detune (Standard MIDI) settings.oscDetune = value / 254.f; break; case CC_OSC2PIT: // Oscillator 2 Pitch settings.osc2Pitch = floorf(value * (13.f / 128.f)); break; case CC_MOD_FLT: // Mod Envelope Filter Gain settings.modEnvFltGain = (float) FILTER_CV_MAX * value / 127.f; break; case CC_KEY_TRK: // Filter Key Tracking settings.keyTrack = value / 127.f; break; case CC_LFO_FRQ: // LFO Frequency settings.lfoStep = ccToLFOStep(value); break; case CC_LFO_PIT: // LFO Pitch Modulation settings.lfoPitchMod = ccToLFOPitchMod(value); break; case CC_LFO_FLT: // LFO Filter Modulation settings.lfoFltMod = ccToLFOFltMod(value); break; case CC_UNISON: // Unison Amount settings.unison = 2 + 2 * floorf(value * 4.f / 128.f); break; case CC_OSC_MIX: // Oscillator 1/2 Mix settings.oscMix = value / 127.f; break; case CC_OSC1MDE: // Oscillator 1 Mode settings.osc1Mode = Oscillator::Mode(floorf(3.f * value / 128.f)); break; case CC_OSC2MDE: // Oscillator 2 Mode settings.osc2Mode = Oscillator::Mode(floorf(3.f * value / 128.f)); break; case CC_FLT_TYP: // Filter Type settings.filter.type = FilterStereo::Type(floorf(4.f * value / 128.f)); break; case CC_FLT_SLP: // Filter Slope settings.filter.slope = FilterStereo::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 // Reverb Density } }