diff --git a/plugins/Nekobi/DistrhoPluginNekobi.cpp b/plugins/Nekobi/DistrhoPluginNekobi.cpp index 9c5e24c..d423739 100644 --- a/plugins/Nekobi/DistrhoPluginNekobi.cpp +++ b/plugins/Nekobi/DistrhoPluginNekobi.cpp @@ -1,387 +1,387 @@ -/* - * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. - * Copyright (C) 2004 Sean Bolton and others - * Copyright (C) 2013-2022 Filipe Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * For a full copy of the GNU General Public License see the LICENSE file. - */ - -#include "DistrhoPluginNekobi.hpp" - - -#include "nekobee-src/nekobee_synth.c" -#include "nekobee-src/nekobee_voice.c" -#include "nekobee-src/nekobee_voice_render.c" - -// ----------------------------------------------------------------------- -// nekobee_handle_raw_event - -void nekobee_handle_raw_event(nekobee_synth_t* const synth, const uint8_t size, const uint8_t* const data) -{ - if (size != 3) - return; - - switch (data[0] & 0xf0) - { - case 0x80: - nekobee_synth_note_off(synth, data[1], data[2]); - break; - case 0x90: - if (data[2] > 0) - nekobee_synth_note_on(synth, data[1], data[2]); - else - nekobee_synth_note_off(synth, data[1], 64); /* shouldn't happen, but... */ - break; - case 0xB0: - nekobee_synth_control_change(synth, data[1], data[2]); - break; - default: - break; - } -} - - -START_NAMESPACE_DISTRHO - -// ----------------------------------------------------------------------- - -DistrhoPluginNekobi::DistrhoPluginNekobi() - : Plugin(paramCount, 0, 0) // 0 programs, 0 states -{ - nekobee_init_tables(); - - // init synth - fSynth.sample_rate = getSampleRate(); - fSynth.deltat = 1.0f / (float)getSampleRate(); - fSynth.nugget_remains = 0; - - fSynth.note_id = 0; - fSynth.monophonic = XSYNTH_MONO_MODE_ONCE; - fSynth.glide = 0; - fSynth.last_noteon_pitch = 0.0f; - fSynth.vcf_accent = 0.0f; - fSynth.vca_accent = 0.0f; - - for (int i=0; i<8; ++i) - fSynth.held_keys[i] = -1; - - fSynth.voice = nekobee_voice_new(); - - fSynth.channel_pressure = 0; - fSynth.pitch_wheel_sensitivity = 0; - fSynth.pitch_wheel = 0; - - for (int i=0; i<128; ++i) - { - fSynth.key_pressure[i] = 0; - fSynth.cc[i] = 0; - } - fSynth.cc[7] = 127; // full volume - - fSynth.mod_wheel = 1.0f; - fSynth.pitch_bend = 1.0f; - fSynth.cc_volume = 1.0f; - - // Default values - fParams.waveform = 0.0f; - fParams.tuning = 0.0f; - fParams.cutoff = 25.0f; - fParams.resonance = 25.0f; - fParams.envMod = 50.0f; - fParams.decay = 75.0f; - fParams.accent = 25.0f; - fParams.volume = 75.0f; - - // Internal stuff - fSynth.waveform = 0.0f; - fSynth.tuning = 1.0f; - fSynth.cutoff = 5.0f; - fSynth.resonance = 0.8f; - fSynth.envmod = 0.3f; - fSynth.decay = 0.0002f; - fSynth.accent = 0.3f; - fSynth.volume = 0.75f; - - // reset - deactivate(); -} - -DistrhoPluginNekobi::~DistrhoPluginNekobi() -{ - std::free(fSynth.voice); -} - -// ----------------------------------------------------------------------- -// Init - -void DistrhoPluginNekobi::initAudioPort(bool input, uint32_t index, AudioPort& port) -{ - port.groupId = kPortGroupMono; - - Plugin::initAudioPort(input, index, port); -} - -void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter) -{ - switch (index) - { - case paramWaveform: - parameter.hints = kParameterIsAutomatable|kParameterIsInteger; - parameter.name = "Waveform"; - parameter.symbol = "waveform"; - parameter.ranges.def = 0.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 1.0f; - parameter.enumValues.count = 2; - parameter.enumValues.restrictedMode = true; - parameter.midiCC = 70; //Sound Variation - { - ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[2]; - enumValues[0].value = 0.0f; - enumValues[0].label = "Square"; - enumValues[1].value = 1.0f; - enumValues[1].label = "Triangle"; - parameter.enumValues.values = enumValues; - } - break; - case paramTuning: - parameter.hints = kParameterIsAutomatable; // was 0.5 <-> 2.0, log - parameter.name = "Tuning"; - parameter.symbol = "tuning"; - parameter.ranges.def = 0.0f; - parameter.ranges.min = -12.0f; - parameter.ranges.max = 12.0f; - parameter.midiCC = 75; - break; - case paramCutoff: - parameter.hints = kParameterIsAutomatable; // modified x2.5 - parameter.name = "Cutoff"; - parameter.symbol = "cutoff"; - parameter.unit = "%"; - parameter.ranges.def = 25.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 100.0f; - parameter.midiCC = 74; - break; - case paramResonance: - parameter.hints = kParameterIsAutomatable; // modified x100 - parameter.name = "VCF Resonance"; - parameter.symbol = "resonance"; - parameter.unit = "%"; - parameter.ranges.def = 25.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 95.0f; - parameter.midiCC = 71; - break; - case paramEnvMod: - parameter.hints = kParameterIsAutomatable; // modified x100 - parameter.name = "Env Mod"; - parameter.symbol = "env_mod"; - parameter.unit = "%"; - parameter.ranges.def = 50.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 100.0f; - parameter.midiCC = 1; //Mod Wheel - break; - case paramDecay: - parameter.hints = kParameterIsAutomatable; // was 0.000009 <-> 0.0005, log - parameter.name = "Decay"; - parameter.symbol = "decay"; - parameter.unit = "%"; - parameter.ranges.def = 75.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 100.0f; - parameter.midiCC = 72; - break; - case paramAccent: - parameter.hints = kParameterIsAutomatable; // modified x100 - parameter.name = "Accent"; - parameter.symbol = "accent"; - parameter.unit = "%"; - parameter.ranges.def = 25.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 100.0f; - parameter.midiCC = 76; - break; - case paramVolume: - parameter.hints = kParameterIsAutomatable; // modified x100 - parameter.name = "Volume"; - parameter.symbol = "volume"; - parameter.unit = "%"; - parameter.ranges.def = 75.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 100.0f; - parameter.midiCC = 7; //Volume - break; - } -} - -// ----------------------------------------------------------------------- -// Internal data - -float DistrhoPluginNekobi::getParameterValue(uint32_t index) const -{ - switch (index) - { - case paramWaveform: - return fParams.waveform; - case paramTuning: - return fParams.tuning; - case paramCutoff: - return fParams.cutoff; - case paramResonance: - return fParams.resonance; - case paramEnvMod: - return fParams.envMod; - case paramDecay: - return fParams.decay; - case paramAccent: - return fParams.accent; - case paramVolume: - return fParams.volume; - } - - return 0.0f; -} - -void DistrhoPluginNekobi::setParameterValue(uint32_t index, float value) -{ - switch (index) - { - case paramWaveform: - fParams.waveform = value; - fSynth.waveform = value; - DISTRHO_SAFE_ASSERT(fSynth.waveform == 0.0f || fSynth.waveform == 1.0f); - break; - case paramTuning: - fParams.tuning = value; - fSynth.tuning = exp2f( value / 12.0f ); - DISTRHO_SAFE_ASSERT(fSynth.tuning >= 0.5f && fSynth.tuning <= 2.0f); - break; - case paramCutoff: - fParams.cutoff = value; - fSynth.cutoff = value/2.5f; - DISTRHO_SAFE_ASSERT(fSynth.cutoff >= 0.0f && fSynth.cutoff <= 40.0f); - break; - case paramResonance: - fParams.resonance = value; - fSynth.resonance = value/100.0f; - DISTRHO_SAFE_ASSERT(fSynth.resonance >= 0.0f && fSynth.resonance <= 0.95f); - break; - case paramEnvMod: - fParams.envMod = value; - fSynth.envmod = value/100.0f; - DISTRHO_SAFE_ASSERT(fSynth.envmod >= 0.0f && fSynth.envmod <= 1.0f); - break; - case paramDecay: - fParams.decay = value; - fSynth.decay = value/100.0f * 0.000491f + 0.000009f; // FIXME: log? - DISTRHO_SAFE_ASSERT(fSynth.decay >= 0.000009f && fSynth.decay <= 0.0005f); - break; - case paramAccent: - fParams.accent = value; - fSynth.accent = value/100.0f; - DISTRHO_SAFE_ASSERT(fSynth.accent >= 0.0f && fSynth.accent <= 1.0f); - break; - case paramVolume: - fParams.volume = value; - fSynth.volume = value/100.0f; - DISTRHO_SAFE_ASSERT(fSynth.volume >= 0.0f && fSynth.volume <= 1.0f); - break; - } -} - -// ----------------------------------------------------------------------- -// Process - -void DistrhoPluginNekobi::activate() -{ - fSynth.nugget_remains = 0; - fSynth.note_id = 0; - - if (fSynth.voice != nullptr) - nekobee_synth_all_voices_off(&fSynth); -} - -void DistrhoPluginNekobi::deactivate() -{ - if (fSynth.voice != nullptr) - nekobee_synth_all_voices_off(&fSynth); -} - -void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) -{ - uint32_t framesDone = 0; - uint32_t curEventIndex = 0; - uint32_t burstSize; - - float* out = outputs[0]; - - if (fSynth.voice == nullptr) - { - std::memset(out, 0, sizeof(float)*frames); - return; - } - - while (framesDone < frames) - { - if (fSynth.nugget_remains == 0) - fSynth.nugget_remains = XSYNTH_NUGGET_SIZE; - - /* process any ready events */ - for (; curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame; ++curEventIndex) - { - if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) - continue; - - nekobee_handle_raw_event(&fSynth, midiEvents[curEventIndex].size, midiEvents[curEventIndex].data); - } - - /* calculate the sample count (burstSize) for the next nekobee_voice_render() call to be the smallest of: - * - control calculation quantization size (XSYNTH_NUGGET_SIZE, in samples) - * - the number of samples remaining in an already-begun nugget (synth->nugget_remains) - * - the number of samples until the next event is ready - * - the number of samples left in this run - */ - burstSize = XSYNTH_NUGGET_SIZE; - - /* we're still in the middle of a nugget, so reduce the burst size - * to end when the nugget ends */ - if (fSynth.nugget_remains < burstSize) - burstSize = fSynth.nugget_remains; - - /* reduce burst size to end when next event is ready */ - if (curEventIndex < midiEventCount && midiEvents[curEventIndex].frame - framesDone < burstSize) - burstSize = midiEvents[curEventIndex].frame - framesDone; - - /* reduce burst size to end at end of this run */ - if (frames - framesDone < burstSize) - burstSize = frames - framesDone; - - /* render the burst */ - nekobee_synth_render_voices(&fSynth, out + framesDone, burstSize, (burstSize == fSynth.nugget_remains)); - framesDone += burstSize; - fSynth.nugget_remains -= burstSize; - } -} - -// ----------------------------------------------------------------------- - -Plugin* createPlugin() -{ - return new DistrhoPluginNekobi(); -} - -// ----------------------------------------------------------------------- - -END_NAMESPACE_DISTRHO +/* + * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. + * Copyright (C) 2004 Sean Bolton and others + * Copyright (C) 2013-2022 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the LICENSE file. + */ + +#include "DistrhoPluginNekobi.hpp" + + +#include "nekobee-src/nekobee_synth.c" +#include "nekobee-src/nekobee_voice.c" +#include "nekobee-src/nekobee_voice_render.c" + +// ----------------------------------------------------------------------- +// nekobee_handle_raw_event + +void nekobee_handle_raw_event(nekobee_synth_t* const synth, const uint8_t size, const uint8_t* const data) +{ + if (size != 3) + return; + + switch (data[0] & 0xf0) + { + case 0x80: + nekobee_synth_note_off(synth, data[1], data[2]); + break; + case 0x90: + if (data[2] > 0) + nekobee_synth_note_on(synth, data[1], data[2]); + else + nekobee_synth_note_off(synth, data[1], 64); /* shouldn't happen, but... */ + break; + case 0xB0: + nekobee_synth_control_change(synth, data[1], data[2]); + break; + default: + break; + } +} + + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +DistrhoPluginNekobi::DistrhoPluginNekobi() + : Plugin(paramCount, 0, 0) // 0 programs, 0 states +{ + nekobee_init_tables(); + + // init synth + fSynth.sample_rate = getSampleRate(); + fSynth.deltat = 1.0f / (float)getSampleRate(); + fSynth.nugget_remains = 0; + + fSynth.note_id = 0; + fSynth.monophonic = XSYNTH_MONO_MODE_ONCE; + fSynth.glide = 0; + fSynth.last_noteon_pitch = 0.0f; + fSynth.vcf_accent = 0.0f; + fSynth.vca_accent = 0.0f; + + for (int i=0; i<8; ++i) + fSynth.held_keys[i] = -1; + + fSynth.voice = nekobee_voice_new(); + + fSynth.channel_pressure = 0; + fSynth.pitch_wheel_sensitivity = 0; + fSynth.pitch_wheel = 0; + + for (int i=0; i<128; ++i) + { + fSynth.key_pressure[i] = 0; + fSynth.cc[i] = 0; + } + fSynth.cc[7] = 127; // full volume + + fSynth.mod_wheel = 1.0f; + fSynth.pitch_bend = 1.0f; + fSynth.cc_volume = 1.0f; + + // Default values + fParams.waveform = 0.0f; + fParams.tuning = 0.0f; + fParams.cutoff = 25.0f; + fParams.resonance = 25.0f; + fParams.envMod = 50.0f; + fParams.decay = 75.0f; + fParams.accent = 25.0f; + fParams.volume = 75.0f; + + // Internal stuff + fSynth.waveform = 0.0f; + fSynth.tuning = 1.0f; + fSynth.cutoff = 5.0f; + fSynth.resonance = 0.8f; + fSynth.envmod = 0.3f; + fSynth.decay = 0.0002f; + fSynth.accent = 0.3f; + fSynth.volume = 0.75f; + + // reset + deactivate(); +} + +DistrhoPluginNekobi::~DistrhoPluginNekobi() +{ + std::free(fSynth.voice); +} + +// ----------------------------------------------------------------------- +// Init + +void DistrhoPluginNekobi::initAudioPort(bool input, uint32_t index, AudioPort& port) +{ + port.groupId = kPortGroupMono; + + Plugin::initAudioPort(input, index, port); +} + +void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter) +{ + switch (index) + { + case paramWaveform: + parameter.hints = kParameterIsAutomatable|kParameterIsInteger; + parameter.name = "Waveform"; + parameter.symbol = "waveform"; + parameter.ranges.def = 0.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + parameter.enumValues.count = 2; + parameter.enumValues.restrictedMode = true; + parameter.midiCC = 70; //Sound Variation + { + ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[2]; + enumValues[0].value = 0.0f; + enumValues[0].label = "Square"; + enumValues[1].value = 1.0f; + enumValues[1].label = "Triangle"; + parameter.enumValues.values = enumValues; + } + break; + case paramTuning: + parameter.hints = kParameterIsAutomatable; // was 0.5 <-> 2.0, log + parameter.name = "Tuning"; + parameter.symbol = "tuning"; + parameter.ranges.def = 0.0f; + parameter.ranges.min = -12.0f; + parameter.ranges.max = 12.0f; + parameter.midiCC = 75; + break; + case paramCutoff: + parameter.hints = kParameterIsAutomatable; + parameter.name = "Cutoff"; + parameter.symbol = "cutoff"; + parameter.unit = "%"; + parameter.ranges.def = 63.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 127.0f; + parameter.midiCC = 74; + break; + case paramResonance: + parameter.hints = kParameterIsAutomatable; // modified x100 + parameter.name = "VCF Resonance"; + parameter.symbol = "resonance"; + parameter.unit = "%"; + parameter.ranges.def = 25.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 95.0f; + parameter.midiCC = 71; + break; + case paramEnvMod: + parameter.hints = kParameterIsAutomatable; // modified x100 + parameter.name = "Env Mod"; + parameter.symbol = "env_mod"; + parameter.unit = "%"; + parameter.ranges.def = 50.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 100.0f; + parameter.midiCC = 1; //Mod Wheel + break; + case paramDecay: + parameter.hints = kParameterIsAutomatable; // was 0.000009 <-> 0.0005, log + parameter.name = "Decay"; + parameter.symbol = "decay"; + parameter.unit = "%"; + parameter.ranges.def = 75.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 100.0f; + parameter.midiCC = 72; + break; + case paramAccent: + parameter.hints = kParameterIsAutomatable; // modified x100 + parameter.name = "Accent"; + parameter.symbol = "accent"; + parameter.unit = "%"; + parameter.ranges.def = 25.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 100.0f; + parameter.midiCC = 76; + break; + case paramVolume: + parameter.hints = kParameterIsAutomatable; // modified x100 + parameter.name = "Volume"; + parameter.symbol = "volume"; + parameter.unit = "%"; + parameter.ranges.def = 75.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 100.0f; + parameter.midiCC = 7; //Volume + break; + } +} + +// ----------------------------------------------------------------------- +// Internal data + +float DistrhoPluginNekobi::getParameterValue(uint32_t index) const +{ + switch (index) + { + case paramWaveform: + return fParams.waveform; + case paramTuning: + return fParams.tuning; + case paramCutoff: + return fParams.cutoff; + case paramResonance: + return fParams.resonance; + case paramEnvMod: + return fParams.envMod; + case paramDecay: + return fParams.decay; + case paramAccent: + return fParams.accent; + case paramVolume: + return fParams.volume; + } + + return 0.0f; +} + +void DistrhoPluginNekobi::setParameterValue(uint32_t index, float value) +{ + switch (index) + { + case paramWaveform: + fParams.waveform = value; + fSynth.waveform = value; + DISTRHO_SAFE_ASSERT(fSynth.waveform == 0.0f || fSynth.waveform == 1.0f); + break; + case paramTuning: + fParams.tuning = value; + fSynth.tuning = exp2f( value / 12.0f ); + DISTRHO_SAFE_ASSERT(fSynth.tuning >= 0.5f && fSynth.tuning <= 2.0f); + break; + case paramCutoff: + fParams.cutoff = value; + fSynth.cutoff = value; + DISTRHO_SAFE_ASSERT(fSynth.cutoff >= 0.0f && fSynth.cutoff <= 127.0f); + break; + case paramResonance: + fParams.resonance = value; + fSynth.resonance = value/100.0f; + DISTRHO_SAFE_ASSERT(fSynth.resonance >= 0.0f && fSynth.resonance <= 0.95f); + break; + case paramEnvMod: + fParams.envMod = value; + fSynth.envmod = value/100.0f; + DISTRHO_SAFE_ASSERT(fSynth.envmod >= 0.0f && fSynth.envmod <= 1.0f); + break; + case paramDecay: + fParams.decay = value; + fSynth.decay = value/100.0f * 0.000491f + 0.000009f; // FIXME: log? + DISTRHO_SAFE_ASSERT(fSynth.decay >= 0.000009f && fSynth.decay <= 0.0005f); + break; + case paramAccent: + fParams.accent = value; + fSynth.accent = value/100.0f; + DISTRHO_SAFE_ASSERT(fSynth.accent >= 0.0f && fSynth.accent <= 1.0f); + break; + case paramVolume: + fParams.volume = value; + fSynth.volume = value/100.0f; + DISTRHO_SAFE_ASSERT(fSynth.volume >= 0.0f && fSynth.volume <= 1.0f); + break; + } +} + +// ----------------------------------------------------------------------- +// Process + +void DistrhoPluginNekobi::activate() +{ + fSynth.nugget_remains = 0; + fSynth.note_id = 0; + + if (fSynth.voice != nullptr) + nekobee_synth_all_voices_off(&fSynth); +} + +void DistrhoPluginNekobi::deactivate() +{ + if (fSynth.voice != nullptr) + nekobee_synth_all_voices_off(&fSynth); +} + +void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) +{ + uint32_t framesDone = 0; + uint32_t curEventIndex = 0; + uint32_t burstSize; + + float* out = outputs[0]; + + if (fSynth.voice == nullptr) + { + std::memset(out, 0, sizeof(float)*frames); + return; + } + + while (framesDone < frames) + { + if (fSynth.nugget_remains == 0) + fSynth.nugget_remains = XSYNTH_NUGGET_SIZE; + + /* process any ready events */ + for (; curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame; ++curEventIndex) + { + if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) + continue; + + nekobee_handle_raw_event(&fSynth, midiEvents[curEventIndex].size, midiEvents[curEventIndex].data); + } + + /* calculate the sample count (burstSize) for the next nekobee_voice_render() call to be the smallest of: + * - control calculation quantization size (XSYNTH_NUGGET_SIZE, in samples) + * - the number of samples remaining in an already-begun nugget (synth->nugget_remains) + * - the number of samples until the next event is ready + * - the number of samples left in this run + */ + burstSize = XSYNTH_NUGGET_SIZE; + + /* we're still in the middle of a nugget, so reduce the burst size + * to end when the nugget ends */ + if (fSynth.nugget_remains < burstSize) + burstSize = fSynth.nugget_remains; + + /* reduce burst size to end when next event is ready */ + if (curEventIndex < midiEventCount && midiEvents[curEventIndex].frame - framesDone < burstSize) + burstSize = midiEvents[curEventIndex].frame - framesDone; + + /* reduce burst size to end at end of this run */ + if (frames - framesDone < burstSize) + burstSize = frames - framesDone; + + /* render the burst */ + nekobee_synth_render_voices(&fSynth, out + framesDone, burstSize, (burstSize == fSynth.nugget_remains)); + framesDone += burstSize; + fSynth.nugget_remains -= burstSize; + } +} + +// ----------------------------------------------------------------------- + +Plugin* createPlugin() +{ + return new DistrhoPluginNekobi(); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/plugins/Nekobi/DistrhoUINekobi.cpp b/plugins/Nekobi/DistrhoUINekobi.cpp index d308217..e48c6d7 100644 --- a/plugins/Nekobi/DistrhoUINekobi.cpp +++ b/plugins/Nekobi/DistrhoUINekobi.cpp @@ -63,9 +63,9 @@ DistrhoUINekobi::DistrhoUINekobi() fKnobCutoff = new ImageKnob(this, knobImage, ImageKnob::Vertical); fKnobCutoff->setId(DistrhoPluginNekobi::paramCutoff); fKnobCutoff->setAbsolutePos(185, 43); - fKnobCutoff->setRange(0.0f, 100.0f); - fKnobCutoff->setDefault(25.0f); - fKnobCutoff->setValue(25.0f); + fKnobCutoff->setRange(0.0f, 127.0f); + fKnobCutoff->setDefault(50.0f); + fKnobCutoff->setValue(50.0f); fKnobCutoff->setRotationAngle(305); fKnobCutoff->setCallback(this); diff --git a/plugins/Nekobi/nekobee-src/nekobee_voice_render.c b/plugins/Nekobi/nekobee-src/nekobee_voice_render.c index b3339c6..bb3ac03 100644 --- a/plugins/Nekobi/nekobee-src/nekobee_voice_render.c +++ b/plugins/Nekobi/nekobee-src/nekobee_voice_render.c @@ -96,17 +96,30 @@ void vco(nekobee_synth_t *synth, uint32_t count) { osc->delay = delay; } +void vcf(nekobee_synth_t *synth, uint32_t count) { + // run a 4-pole ladder filter over a block + // this is a crude implementation that only approximates the complex + // behaviour of the "real" ladder filter + + nekobee_voice_t *voice = synth->voice; + printf("cutoff set to %f\n", synth->cutoff); + (void)voice; + (void)count; + +} + void nekobee_voice_render(nekobee_synth_t *synth, float *out, uint32_t count) { // generate "count" samples into the buffer at out vco(synth, count); + + vcf(synth, count); for(uint32_t i=0; ivoice->osc_audio[i]; } + + return; - (void)synth; - (void)out; - (void)count; }