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.

229 lines
7.2KB

  1. #ifndef OSCILLATORS_H_INCLUDED
  2. #define OSCILLATORS_H_INCLUDED
  3. #include "../JuceLibraryCode/JuceHeader.h"
  4. /**
  5. Base class for oscillators
  6. */
  7. class Oscillator : public SynthesiserVoice
  8. {
  9. public:
  10. Oscillator()
  11. {
  12. amplitude.reset (getSampleRate(), 0.1);
  13. phaseIncrement.reset (getSampleRate(), 0.1);
  14. }
  15. void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int) override
  16. {
  17. frequency = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
  18. phaseIncrement.setValue (((2.0 * double_Pi) * frequency) / sampleRate);
  19. amplitude.setValue (velocity);
  20. // Store the initial note and work out the maximum frequency deviations for pitch bend
  21. initialNote = midiNoteNumber;
  22. maxFreq = MidiMessage::getMidiNoteInHertz (initialNote + 4) - frequency;
  23. minFreq = frequency - MidiMessage::getMidiNoteInHertz (initialNote - 4);
  24. }
  25. void stopNote (float, bool) override
  26. {
  27. clearCurrentNote();
  28. amplitude.setValue (0.0);
  29. }
  30. void pitchWheelMoved (int newValue) override
  31. {
  32. // Change the phase increment based on pitch bend amount
  33. double frequencyOffset = ((newValue > 0 ? maxFreq : minFreq) * (newValue / 127.0));
  34. phaseIncrement.setValue (((2.0 * double_Pi) * (frequency + frequencyOffset)) / sampleRate);
  35. }
  36. void controllerMoved (int, int) override
  37. {
  38. }
  39. void channelPressureChanged (int newChannelPressureValue) override
  40. {
  41. // Set the amplitude based on pressure value
  42. amplitude.setValue (newChannelPressureValue / 127.0);
  43. }
  44. void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override
  45. {
  46. while (--numSamples >= 0)
  47. {
  48. double output = getSample() * amplitude.getNextValue();
  49. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  50. outputBuffer.addSample (i, startSample, static_cast<float> (output));
  51. ++startSample;
  52. }
  53. }
  54. /** Returns the next sample */
  55. double getSample()
  56. {
  57. double output = renderWaveShape (phasePos);
  58. phasePos += phaseIncrement.getNextValue();
  59. if (phasePos > (2.0 * double_Pi))
  60. phasePos -= (2.0 * double_Pi);
  61. return output;
  62. }
  63. /** Subclasses should override this to say whether they can play the given sound */
  64. virtual bool canPlaySound (SynthesiserSound*) override = 0;
  65. /** Subclasses should override this to render a waveshape */
  66. virtual double renderWaveShape (double currentPhase) = 0;
  67. private:
  68. LinearSmoothedValue<double> amplitude, phaseIncrement;
  69. double frequency = 0;
  70. double phasePos = 0.0f;
  71. double sampleRate = 44100.0;
  72. int initialNote = 0;
  73. double maxFreq = 0, minFreq = 0;
  74. //==============================================================================
  75. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oscillator)
  76. };
  77. //==============================================================================
  78. /**
  79. Sine sound struct - applies to MIDI channel 1
  80. */
  81. struct SineSound : public SynthesiserSound
  82. {
  83. SineSound () {}
  84. bool appliesToNote (int) override { return true; }
  85. bool appliesToChannel (int midiChannel) override { return (midiChannel == 1); }
  86. //==============================================================================
  87. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SineSound)
  88. };
  89. /**
  90. Sine voice struct that renders a sin waveshape
  91. */
  92. struct SineVoice : public Oscillator
  93. {
  94. SineVoice() {};
  95. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<SineSound*> (sound) != nullptr; }
  96. double renderWaveShape (const double currentPhase) override { return sin (currentPhase); }
  97. //==============================================================================
  98. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SineVoice)
  99. };
  100. //==============================================================================
  101. /**
  102. Square sound struct - applies to MIDI channel 2
  103. */
  104. struct SquareSound : public SynthesiserSound
  105. {
  106. SquareSound() {}
  107. bool appliesToNote (int) override { return true; }
  108. bool appliesToChannel (int midiChannel) override { return (midiChannel == 2); }
  109. //==============================================================================
  110. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SquareSound)
  111. };
  112. /**
  113. Square voice struct that renders a square waveshape
  114. */
  115. struct SquareVoice : public Oscillator
  116. {
  117. SquareVoice() {};
  118. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<SquareSound*> (sound) != nullptr; }
  119. double renderWaveShape (const double currentPhase) override { return (currentPhase < double_Pi ? 0.0 : 1.0); }
  120. //==============================================================================
  121. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SquareVoice)
  122. };
  123. //==============================================================================
  124. /**
  125. Sawtooth sound - applies to MIDI channel 3
  126. */
  127. struct SawSound : public SynthesiserSound
  128. {
  129. SawSound() {}
  130. bool appliesToNote (int) override { return true; }
  131. bool appliesToChannel (int midiChannel) override { return (midiChannel == 3); }
  132. //==============================================================================
  133. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SawSound)
  134. };
  135. /**
  136. Sawtooth voice that renders a sawtooth waveshape
  137. */
  138. struct SawVoice : public Oscillator
  139. {
  140. SawVoice() {}
  141. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<SawSound*> (sound) != nullptr; }
  142. double renderWaveShape (const double currentPhase) override { return (1.0 / double_Pi) * currentPhase - 1.0; }
  143. //==============================================================================
  144. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SawVoice)
  145. };
  146. //==============================================================================
  147. /**
  148. Triangle sound - applies to MIDI channel 4
  149. */
  150. struct TriangleSound : public SynthesiserSound
  151. {
  152. TriangleSound() {}
  153. bool appliesToNote (int) override { return true; }
  154. bool appliesToChannel (int midiChannel) override { return (midiChannel == 4); }
  155. //==============================================================================
  156. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TriangleSound)
  157. };
  158. /**
  159. Triangle voice that renders a triangle waveshape
  160. */
  161. struct TriangleVoice : public Oscillator
  162. {
  163. TriangleVoice() {}
  164. bool canPlaySound (SynthesiserSound* sound) override { return dynamic_cast<TriangleSound*> (sound) != nullptr; }
  165. double renderWaveShape (const double currentPhase) override
  166. {
  167. return (currentPhase < double_Pi ? -1.0 + (2.0 / double_Pi) * currentPhase
  168. : 3.0 - (2.0 / double_Pi) * currentPhase);
  169. }
  170. //==============================================================================
  171. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TriangleVoice)
  172. };
  173. #endif // OSCILLATORS_H_INCLUDED