The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

251 lines
8.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #pragma once
  20. #include "../JuceLibraryCode/JuceHeader.h"
  21. /**
  22. Base class for oscillators
  23. */
  24. class Oscillator : public SynthesiserVoice
  25. {
  26. public:
  27. Oscillator()
  28. {
  29. amplitude.reset (getSampleRate(), 0.1);
  30. phaseIncrement.reset (getSampleRate(), 0.1);
  31. }
  32. void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int) override
  33. {
  34. frequency = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
  35. phaseIncrement.setValue (((2.0 * double_Pi) * frequency) / sampleRate);
  36. amplitude.setValue (velocity);
  37. // Store the initial note and work out the maximum frequency deviations for pitch bend
  38. initialNote = midiNoteNumber;
  39. maxFreq = MidiMessage::getMidiNoteInHertz (initialNote + 4) - frequency;
  40. minFreq = frequency - MidiMessage::getMidiNoteInHertz (initialNote - 4);
  41. }
  42. void stopNote (float, bool) override
  43. {
  44. clearCurrentNote();
  45. amplitude.setValue (0.0);
  46. }
  47. void pitchWheelMoved (int newValue) override
  48. {
  49. // Change the phase increment based on pitch bend amount
  50. auto frequencyOffset = ((newValue > 0 ? maxFreq : minFreq) * (newValue / 127.0));
  51. phaseIncrement.setValue (((2.0 * double_Pi) * (frequency + frequencyOffset)) / sampleRate);
  52. }
  53. void controllerMoved (int, int) override
  54. {
  55. }
  56. void channelPressureChanged (int newChannelPressureValue) override
  57. {
  58. // Set the amplitude based on pressure value
  59. amplitude.setValue (newChannelPressureValue / 127.0);
  60. }
  61. void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override
  62. {
  63. while (--numSamples >= 0)
  64. {
  65. auto output = getSample() * amplitude.getNextValue();
  66. for (auto i = outputBuffer.getNumChannels(); --i >= 0;)
  67. outputBuffer.addSample (i, startSample, static_cast<float> (output));
  68. ++startSample;
  69. }
  70. }
  71. /** Returns the next sample */
  72. double getSample()
  73. {
  74. auto output = renderWaveShape (phasePos);
  75. phasePos += phaseIncrement.getNextValue();
  76. if (phasePos > (2.0 * double_Pi))
  77. phasePos -= (2.0 * double_Pi);
  78. return output;
  79. }
  80. /** Subclasses should override this to say whether they can play the given sound */
  81. virtual bool canPlaySound (SynthesiserSound*) override = 0;
  82. /** Subclasses should override this to render a waveshape */
  83. virtual double renderWaveShape (const double currentPhase) = 0;
  84. private:
  85. LinearSmoothedValue<double> amplitude, phaseIncrement;
  86. double frequency = 0;
  87. double phasePos = 0.0f;
  88. double sampleRate = 44100.0;
  89. int initialNote = 0;
  90. double maxFreq = 0, minFreq = 0;
  91. //==============================================================================
  92. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oscillator)
  93. };
  94. //==============================================================================
  95. /**
  96. Sine sound struct - applies to MIDI channel 1
  97. */
  98. struct SineSound : public SynthesiserSound
  99. {
  100. SineSound () {}
  101. bool appliesToNote (int) override { return true; }
  102. bool appliesToChannel (int midiChannel) override { return (midiChannel == 1); }
  103. //==============================================================================
  104. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SineSound)
  105. };
  106. /**
  107. Sine voice struct that renders a sin waveshape
  108. */
  109. struct SineVoice : public Oscillator
  110. {
  111. SineVoice() {};
  112. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<SineSound*> (sound) != nullptr; }
  113. double renderWaveShape (const double currentPhase) override { return sin (currentPhase); }
  114. //==============================================================================
  115. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SineVoice)
  116. };
  117. //==============================================================================
  118. /**
  119. Square sound struct - applies to MIDI channel 2
  120. */
  121. struct SquareSound : public SynthesiserSound
  122. {
  123. SquareSound() {}
  124. bool appliesToNote (int) override { return true; }
  125. bool appliesToChannel (int midiChannel) override { return (midiChannel == 2); }
  126. //==============================================================================
  127. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SquareSound)
  128. };
  129. /**
  130. Square voice struct that renders a square waveshape
  131. */
  132. struct SquareVoice : public Oscillator
  133. {
  134. SquareVoice() {};
  135. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<SquareSound*> (sound) != nullptr; }
  136. double renderWaveShape (const double currentPhase) override { return (currentPhase < double_Pi ? 0.0 : 1.0); }
  137. //==============================================================================
  138. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SquareVoice)
  139. };
  140. //==============================================================================
  141. /**
  142. Sawtooth sound - applies to MIDI channel 3
  143. */
  144. struct SawSound : public SynthesiserSound
  145. {
  146. SawSound() {}
  147. bool appliesToNote (int) override { return true; }
  148. bool appliesToChannel (int midiChannel) override { return (midiChannel == 3); }
  149. //==============================================================================
  150. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SawSound)
  151. };
  152. /**
  153. Sawtooth voice that renders a sawtooth waveshape
  154. */
  155. struct SawVoice : public Oscillator
  156. {
  157. SawVoice() {}
  158. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<SawSound*> (sound) != nullptr; }
  159. double renderWaveShape (const double currentPhase) override { return (1.0 / double_Pi) * currentPhase - 1.0; }
  160. //==============================================================================
  161. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SawVoice)
  162. };
  163. //==============================================================================
  164. /**
  165. Triangle sound - applies to MIDI channel 4
  166. */
  167. struct TriangleSound : public SynthesiserSound
  168. {
  169. TriangleSound() {}
  170. bool appliesToNote (int) override { return true; }
  171. bool appliesToChannel (int midiChannel) override { return (midiChannel == 4); }
  172. //==============================================================================
  173. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TriangleSound)
  174. };
  175. /**
  176. Triangle voice that renders a triangle waveshape
  177. */
  178. struct TriangleVoice : public Oscillator
  179. {
  180. TriangleVoice() {}
  181. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<TriangleSound*> (sound) != nullptr; }
  182. double renderWaveShape (const double currentPhase) override
  183. {
  184. return (currentPhase < double_Pi ? -1.0 + (2.0 / double_Pi) * currentPhase
  185. : 3.0 - (2.0 / double_Pi) * currentPhase);
  186. }
  187. //==============================================================================
  188. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TriangleVoice)
  189. };