/* * DISTRHO Kars Plugin, based on karplong by Chris Cannam. * Copyright (C) 2015 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this * permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "DistrhoPluginKars.hpp" START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- DistrhoPluginKars::DistrhoPluginKars() : Plugin(paramCount, 0, 0), // 0 programs, 0 states fSustain(false), fSampleRate(getSampleRate()), fBlockStart(0) { for (int i=kMaxNotes; --i >= 0;) { fNotes[i].index = i; fNotes[i].setSampleRate(fSampleRate); } } // ----------------------------------------------------------------------- // Init void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter) { if (index != 0) return; parameter.hints = kParameterIsAutomable|kParameterIsBoolean; parameter.name = "Sustain"; parameter.symbol = "sustain"; parameter.ranges.def = 0.0f; parameter.ranges.min = 0.0f; parameter.ranges.max = 1.0f; } // ----------------------------------------------------------------------- // Internal data float DistrhoPluginKars::getParameterValue(uint32_t index) const { if (index != 0) return 0.0f; return fSustain ? 1.0f : 0.0f; } void DistrhoPluginKars::setParameterValue(uint32_t index, float value) { if (index != 0) return; fSustain = value > 0.5f; } // ----------------------------------------------------------------------- // Process void DistrhoPluginKars::activate() { fBlockStart = 0; for (int i=kMaxNotes; --i >= 0;) { fNotes[i].on = kNoteNull; fNotes[i].off = kNoteNull; fNotes[i].velocity = 0; } } void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) { uint8_t note, velo; float* out = outputs[0]; for (uint32_t count, pos=0, curEventIndex=0; pos= midiEvents[curEventIndex].frame; ++curEventIndex) { if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) continue; const uint8_t* data = midiEvents[curEventIndex].data; const uint8_t status = data[0] & 0xF0; switch (status) { case 0x90: note = data[1]; velo = data[2]; DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes if (velo > 0) { fNotes[note].on = fBlockStart + midiEvents[curEventIndex].frame; fNotes[note].off = kNoteNull; fNotes[note].velocity = velo; break; } // nobreak case 0x80: note = data[1]; DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes fNotes[note].off = fBlockStart + midiEvents[curEventIndex].frame; break; } } if (curEventIndex < midiEventCount && midiEvents[curEventIndex].frame < frames) count = midiEvents[curEventIndex].frame - pos; else count = frames - pos; std::memset(out+pos, 0, sizeof(float)*count); //for (uint32_t i=0; i= 0;) { if (fNotes[i].on != kNoteNull) addSamples(out, i, pos, count); } pos += count; } fBlockStart += frames; } void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t offset, uint32_t count) { const uint32_t start = fBlockStart + offset; Note& note(fNotes[voice]); if (start < note.on) return; if (start == note.on) { for (int i=note.sizei; --i >= 0;) note.wavetable[i] = (float(rand()) / float(RAND_MAX)) * 2.0f - 1.0f; } const float vgain = float(note.velocity) / 127.0f; bool decay; float gain, sample; uint32_t index, size; for (uint32_t i=0, s=start-note.on; i index) { note.on = kNoteNull; break; } gain = gain * float(index - size) / float(index); } size = uint32_t(note.sizei); decay = s > size; index = s % size; sample = note.wavetable[index]; if (decay) { if (index == 0) sample += note.wavetable[size-1]; else sample += note.wavetable[index-1]; note.wavetable[index] = sample/2; } out[offset+i] += gain * sample; } } // ----------------------------------------------------------------------- Plugin* createPlugin() { return new DistrhoPluginKars(); } // ----------------------------------------------------------------------- END_NAMESPACE_DISTRHO