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.

129 lines
4.0KB

  1. /*
  2. ==============================================================================
  3. This file was auto-generated by the Jucer!
  4. It contains the basic startup code for a Juce application.
  5. ==============================================================================
  6. */
  7. /** A demo synth sound that's just a basic sine wave.. */
  8. class SineWaveSound : public SynthesiserSound
  9. {
  10. public:
  11. SineWaveSound() {}
  12. bool appliesToNote (int /*midiNoteNumber*/) override { return true; }
  13. bool appliesToChannel (int /*midiChannel*/) override { return true; }
  14. };
  15. //==============================================================================
  16. /** A simple demo synth voice that just plays a sine wave.. */
  17. class SineWaveVoice : public SynthesiserVoice
  18. {
  19. public:
  20. SineWaveVoice()
  21. : currentAngle (0), angleDelta (0), level (0), tailOff (0)
  22. {
  23. }
  24. bool canPlaySound (SynthesiserSound* sound) override
  25. {
  26. return dynamic_cast<SineWaveSound*> (sound) != nullptr;
  27. }
  28. void startNote (int midiNoteNumber, float velocity,
  29. SynthesiserSound* /*sound*/,
  30. int /*currentPitchWheelPosition*/) override
  31. {
  32. currentAngle = 0.0;
  33. level = velocity * 0.15;
  34. tailOff = 0.0;
  35. double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
  36. double cyclesPerSample = cyclesPerSecond / getSampleRate();
  37. angleDelta = cyclesPerSample * 2.0 * double_Pi;
  38. }
  39. void stopNote (float /*velocity*/, bool allowTailOff) override
  40. {
  41. if (allowTailOff)
  42. {
  43. // start a tail-off by setting this flag. The render callback will pick up on
  44. // this and do a fade out, calling clearCurrentNote() when it's finished.
  45. if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
  46. // stopNote method could be called more than once.
  47. tailOff = 1.0;
  48. }
  49. else
  50. {
  51. // we're being told to stop playing immediately, so reset everything..
  52. clearCurrentNote();
  53. angleDelta = 0.0;
  54. }
  55. }
  56. void pitchWheelMoved (int /*newValue*/) override
  57. {
  58. // not implemented for the purposes of this demo!
  59. }
  60. void controllerMoved (int /*controllerNumber*/, int /*newValue*/) override
  61. {
  62. // not implemented for the purposes of this demo!
  63. }
  64. void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override
  65. {
  66. if (angleDelta != 0.0)
  67. {
  68. if (tailOff > 0)
  69. {
  70. while (--numSamples >= 0)
  71. {
  72. const float currentSample = (float) (sin (currentAngle) * level * tailOff);
  73. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  74. outputBuffer.addSample (i, startSample, currentSample);
  75. currentAngle += angleDelta;
  76. ++startSample;
  77. tailOff *= 0.99;
  78. if (tailOff <= 0.005)
  79. {
  80. // tells the synth that this voice has stopped
  81. clearCurrentNote();
  82. angleDelta = 0.0;
  83. break;
  84. }
  85. }
  86. }
  87. else
  88. {
  89. while (--numSamples >= 0)
  90. {
  91. const float currentSample = (float) (sin (currentAngle) * level);
  92. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  93. outputBuffer.addSample (i, startSample, currentSample);
  94. currentAngle += angleDelta;
  95. ++startSample;
  96. }
  97. }
  98. }
  99. }
  100. private:
  101. double currentAngle, angleDelta, level, tailOff;
  102. };