/* * DISTRHO Plugin Framework (DPF) * Copyright (C) 2012-2024 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 "DistrhoPlugin.hpp" #include #include START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------------------------------------------- /** Plugin that demonstrates sending notes from the editor in DPF. */ class SendNoteExamplePlugin : public Plugin { public: SendNoteExamplePlugin() : Plugin(0, 0, 0) { std::memset(fNotesPlayed, 0, sizeof(fNotesPlayed)); std::memset(fOscillatorPhases, 0, sizeof(fOscillatorPhases)); } protected: /* -------------------------------------------------------------------------------------------------------- * Information */ /** Get the plugin label. This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters. */ const char* getLabel() const override { return "SendNote"; } /** Get an extensive comment/description about the plugin. */ const char* getDescription() const override { return "Plugin that demonstrates sending notes from the editor in DPF."; } /** Get the plugin author/maker. */ const char* getMaker() const override { return "DISTRHO"; } /** Get the plugin homepage. */ const char* getHomePage() const override { return "https://github.com/DISTRHO/DPF"; } /** Get the plugin license name (a single line of text). For commercial plugins this should return some short copyright information. */ const char* getLicense() const override { return "ISC"; } /** Get the plugin version, in hexadecimal. */ uint32_t getVersion() const override { return d_version(1, 0, 0); } /* -------------------------------------------------------------------------------------------------------- * Init */ /** Initialize the audio port @a index.@n This function will be called once, shortly after the plugin is created. */ void initAudioPort(bool input, uint32_t index, AudioPort& port) override { // treat meter audio ports as stereo port.groupId = kPortGroupMono; // everything else is as default Plugin::initAudioPort(input, index, port); } /* -------------------------------------------------------------------------------------------------------- * Audio/MIDI Processing */ /** Run/process function for plugins with MIDI input. This synthesizes the MIDI voices with a sum of sine waves. */ void run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override { for (uint32_t i = 0; i < midiEventCount; ++i) { if (midiEvents[i].size <= 3) { uint8_t status = midiEvents[i].data[0]; uint8_t note = midiEvents[i].data[1] & 127; uint8_t velocity = midiEvents[i].data[2] & 127; switch (status & 0xf0) { case 0x90: if (velocity != 0) { fNotesPlayed[note] = velocity; break; } /* fall through */ case 0x80: fNotesPlayed[note] = 0; fOscillatorPhases[note] = 0; break; } } } float* const output = outputs[0]; std::memset(output, 0, frames * sizeof(float)); for (uint32_t noteNumber = 0; noteNumber < 128; ++noteNumber) { if (fNotesPlayed[noteNumber] == 0) continue; float notePitch = 8.17579891564 * std::exp(0.0577622650 * noteNumber); float phase = fOscillatorPhases[noteNumber]; float timeStep = notePitch / getSampleRate(); float k2pi = 2.0 * M_PI; float gain = 0.1; for (uint32_t i = 0; i < frames; ++i) { output[i] += gain * std::sin(k2pi * phase); phase += timeStep; phase -= (int)phase; } fOscillatorPhases[noteNumber] = phase; } } // ------------------------------------------------------------------------------------------------------- private: uint8_t fNotesPlayed[128]; float fOscillatorPhases[128]; /** Set our plugin class as non-copyable and add a leak detector just in case. */ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SendNoteExamplePlugin) }; /* ------------------------------------------------------------------------------------------------------------ * Plugin entry point, called by DPF to create a new plugin instance. */ Plugin* createPlugin() { return new SendNoteExamplePlugin(); } // ----------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO