DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
6.0KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "DistrhoPlugin.hpp"
  17. #include <cmath>
  18. #include <cstring>
  19. START_NAMESPACE_DISTRHO
  20. // -----------------------------------------------------------------------------------------------------------
  21. /**
  22. Plugin that demonstrates sending notes from the editor in DPF.
  23. */
  24. class SendNoteExamplePlugin : public Plugin
  25. {
  26. public:
  27. SendNoteExamplePlugin()
  28. : Plugin(0, 0, 0)
  29. {
  30. std::memset(fNotesPlayed, 0, sizeof(fNotesPlayed));
  31. std::memset(fOscillatorPhases, 0, sizeof(fOscillatorPhases));
  32. }
  33. protected:
  34. /* --------------------------------------------------------------------------------------------------------
  35. * Information */
  36. /**
  37. Get the plugin label.
  38. This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
  39. */
  40. const char* getLabel() const override
  41. {
  42. return "SendNote";
  43. }
  44. /**
  45. Get an extensive comment/description about the plugin.
  46. */
  47. const char* getDescription() const override
  48. {
  49. return "Plugin that demonstrates sending notes from the editor in DPF.";
  50. }
  51. /**
  52. Get the plugin author/maker.
  53. */
  54. const char* getMaker() const override
  55. {
  56. return "DISTRHO";
  57. }
  58. /**
  59. Get the plugin homepage.
  60. */
  61. const char* getHomePage() const override
  62. {
  63. return "https://github.com/DISTRHO/DPF";
  64. }
  65. /**
  66. Get the plugin license name (a single line of text).
  67. For commercial plugins this should return some short copyright information.
  68. */
  69. const char* getLicense() const override
  70. {
  71. return "ISC";
  72. }
  73. /**
  74. Get the plugin version, in hexadecimal.
  75. */
  76. uint32_t getVersion() const override
  77. {
  78. return d_version(1, 0, 0);
  79. }
  80. /**
  81. Get the plugin unique Id.
  82. This value is used by LADSPA, DSSI and VST plugin formats.
  83. */
  84. int64_t getUniqueId() const override
  85. {
  86. return d_cconst('d', 'S', 'N', 'o');
  87. }
  88. /* --------------------------------------------------------------------------------------------------------
  89. * Init and Internal data, unused in this plugin */
  90. void initParameter(uint32_t, Parameter&) override {}
  91. float getParameterValue(uint32_t) const override { return 0.0f;}
  92. void setParameterValue(uint32_t, float) override {}
  93. /* --------------------------------------------------------------------------------------------------------
  94. * Audio/MIDI Processing */
  95. /**
  96. Run/process function for plugins with MIDI input.
  97. This synthesizes the MIDI voices with a sum of sine waves.
  98. */
  99. void run(const float**, float** outputs, uint32_t frames,
  100. const MidiEvent* midiEvents, uint32_t midiEventCount) override
  101. {
  102. for (uint32_t i = 0; i < midiEventCount; ++i)
  103. {
  104. if (midiEvents[i].size <= 3)
  105. {
  106. uint8_t status = midiEvents[i].data[0];
  107. uint8_t note = midiEvents[i].data[1] & 127;
  108. uint8_t velocity = midiEvents[i].data[2] & 127;
  109. switch (status & 0xf0)
  110. {
  111. case 0x90:
  112. if (velocity != 0)
  113. {
  114. fNotesPlayed[note] = velocity;
  115. break;
  116. }
  117. /* fall through */
  118. case 0x80:
  119. fNotesPlayed[note] = 0;
  120. fOscillatorPhases[note] = 0;
  121. break;
  122. }
  123. }
  124. }
  125. float* const output = outputs[0];
  126. std::memset(output, 0, frames * sizeof(float));
  127. for (uint32_t noteNumber = 0; noteNumber < 128; ++noteNumber)
  128. {
  129. if (fNotesPlayed[noteNumber] == 0)
  130. continue;
  131. float notePitch = 8.17579891564 * std::exp(0.0577622650 * noteNumber);
  132. float phase = fOscillatorPhases[noteNumber];
  133. float timeStep = notePitch / getSampleRate();
  134. float k2pi = 2.0 * M_PI;
  135. float gain = 0.1;
  136. for (uint32_t i = 0; i < frames; ++i)
  137. {
  138. output[i] += gain * std::sin(k2pi * phase);
  139. phase += timeStep;
  140. phase -= (int)phase;
  141. }
  142. fOscillatorPhases[noteNumber] = phase;
  143. }
  144. }
  145. // -------------------------------------------------------------------------------------------------------
  146. private:
  147. uint8_t fNotesPlayed[128];
  148. float fOscillatorPhases[128];
  149. /**
  150. Set our plugin class as non-copyable and add a leak detector just in case.
  151. */
  152. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SendNoteExamplePlugin)
  153. };
  154. /* ------------------------------------------------------------------------------------------------------------
  155. * Plugin entry point, called by DPF to create a new plugin instance. */
  156. Plugin* createPlugin()
  157. {
  158. return new SendNoteExamplePlugin();
  159. }
  160. // -----------------------------------------------------------------------------------------------------------
  161. END_NAMESPACE_DISTRHO