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.

168 lines
5.3KB

  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. #include "../JuceLibraryCode/JuceHeader.h"
  20. //==============================================================================
  21. class MainContentComponent : public AudioAppComponent
  22. {
  23. public:
  24. //==============================================================================
  25. MainContentComponent()
  26. : phase (0.0f),
  27. phaseDelta (0.0f),
  28. frequency (5000.0f),
  29. amplitude (0.2f),
  30. sampleRate (0.0),
  31. expectedSamplesPerBlock (0)
  32. {
  33. setSize (800, 600);
  34. // Specify the number of input and output channels that we want to open.
  35. setAudioChannels (0, 2);
  36. }
  37. ~MainContentComponent()
  38. {
  39. shutdownAudio();
  40. }
  41. //==============================================================================
  42. void prepareToPlay (int samplesPerBlockExpected, double newSampleRate) override
  43. {
  44. sampleRate = newSampleRate;
  45. expectedSamplesPerBlock = samplesPerBlockExpected;
  46. }
  47. /* This method generates the actual audio samples.
  48. In this example the buffer is filled with a sine wave whose frequency and
  49. amplitude are controlled by the mouse position.
  50. */
  51. void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
  52. {
  53. bufferToFill.clearActiveBufferRegion();
  54. const float originalPhase = phase;
  55. for (int chan = 0; chan < bufferToFill.buffer->getNumChannels(); ++chan)
  56. {
  57. phase = originalPhase;
  58. float* const channelData = bufferToFill.buffer->getWritePointer (chan, bufferToFill.startSample);
  59. for (int i = 0; i < bufferToFill.numSamples ; ++i)
  60. {
  61. channelData[i] = amplitude * std::sin (phase);
  62. // increment the phase step for the next sample
  63. phase = std::fmod (phase + phaseDelta, float_Pi * 2.0f);
  64. }
  65. }
  66. }
  67. void releaseResources() override
  68. {
  69. // This gets automatically called when audio device parameters change
  70. // or device is restarted.
  71. }
  72. //==============================================================================
  73. void paint (Graphics& g) override
  74. {
  75. // (Our component is opaque, so we must completely fill the background with a solid colour)
  76. g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
  77. const float centreY = getHeight() / 2.0f;
  78. const float radius = amplitude * 200.0f;
  79. // Draw an ellipse based on the mouse position and audio volume
  80. g.setColour (Colours::lightgreen);
  81. g.fillEllipse (lastMousePosition.x - radius / 2.0f,
  82. lastMousePosition.y - radius / 2.0f,
  83. radius, radius);
  84. // Draw a representative sine wave.
  85. Path wavePath;
  86. wavePath.startNewSubPath (0, centreY);
  87. for (float x = 1.0f; x < getWidth(); ++x)
  88. wavePath.lineTo (x, centreY + amplitude * getHeight() * 2.0f
  89. * std::sin (x * frequency * 0.0001f));
  90. g.setColour (getLookAndFeel().findColour (Slider::thumbColourId));
  91. g.strokePath (wavePath, PathStrokeType (2.0f));
  92. }
  93. // Mouse handling..
  94. void mouseDown (const MouseEvent& e) override
  95. {
  96. mouseDrag (e);
  97. }
  98. void mouseDrag (const MouseEvent& e) override
  99. {
  100. lastMousePosition = e.position;
  101. frequency = (getHeight() - e.y) * 10.0f;
  102. amplitude = jmin (0.9f, 0.2f * e.position.x / getWidth());
  103. phaseDelta = (float) (2.0 * double_Pi * frequency / sampleRate);
  104. repaint();
  105. }
  106. void mouseUp (const MouseEvent&) override
  107. {
  108. amplitude = 0.0f;
  109. repaint();
  110. }
  111. void resized() override
  112. {
  113. // This is called when the MainContentComponent is resized.
  114. // If you add any child components, this is where you should
  115. // update their positions.
  116. }
  117. private:
  118. //==============================================================================
  119. float phase;
  120. float phaseDelta;
  121. float frequency;
  122. float amplitude;
  123. double sampleRate;
  124. int expectedSamplesPerBlock;
  125. Point<float> lastMousePosition;
  126. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
  127. };
  128. Component* createMainContentComponent() { return new MainContentComponent(); };