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.

166 lines
5.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. #include "StringSynthesiser.h"
  20. #include "StringComponent.h"
  21. //==============================================================================
  22. class StringDemoComponent : public AudioAppComponent
  23. {
  24. public:
  25. StringDemoComponent()
  26. {
  27. createStringComponents();
  28. setSize (800, 560);
  29. // specify the number of input and output channels that we want to open
  30. setAudioChannels (0, 2);
  31. }
  32. ~StringDemoComponent()
  33. {
  34. shutdownAudio();
  35. }
  36. //==============================================================================
  37. void prepareToPlay (int /*samplesPerBlockExpected*/, double sampleRate) override
  38. {
  39. generateStringSynths (sampleRate);
  40. }
  41. void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
  42. {
  43. bufferToFill.clearActiveBufferRegion();
  44. for (int channel = 0; channel < bufferToFill.buffer->getNumChannels(); ++channel)
  45. {
  46. float* const channelData = bufferToFill.buffer->getWritePointer (channel, bufferToFill.startSample);
  47. if (channel == 0)
  48. {
  49. for (auto synth : stringSynths)
  50. synth->generateAndAddData (channelData, bufferToFill.numSamples);
  51. }
  52. else
  53. {
  54. memcpy (channelData,
  55. bufferToFill.buffer->getReadPointer (0),
  56. bufferToFill.numSamples * sizeof (float));
  57. }
  58. }
  59. }
  60. void releaseResources() override
  61. {
  62. stringSynths.clear();
  63. }
  64. //==============================================================================
  65. void paint (Graphics& g) override
  66. {
  67. }
  68. void resized() override
  69. {
  70. int xPos = 20;
  71. int yPos = 20;
  72. int yDistance = 50;
  73. for (auto stringLine : stringLines)
  74. {
  75. stringLine->setTopLeftPosition (xPos, yPos);
  76. yPos += yDistance;
  77. addAndMakeVisible (stringLine);
  78. }
  79. }
  80. private:
  81. void mouseDown (const MouseEvent& e) override
  82. {
  83. mouseDrag (e);
  84. }
  85. void mouseDrag (const MouseEvent& e) override
  86. {
  87. for (int i = 0; i < stringLines.size(); ++i)
  88. {
  89. auto* stringLine = stringLines.getUnchecked(i);
  90. if (stringLine->getBounds().contains (e.getPosition()))
  91. {
  92. float position = (e.position.x - stringLine->getX()) / stringLine->getWidth();
  93. stringLine->stringPlucked (position);
  94. stringSynths.getUnchecked(i)->stringPlucked (position);
  95. }
  96. }
  97. }
  98. //==============================================================================
  99. struct StringParameters
  100. {
  101. StringParameters (int midiNote)
  102. : frequencyInHz (MidiMessage::getMidiNoteInHertz (midiNote)),
  103. lengthInPixels ((int) (760 / (frequencyInHz / MidiMessage::getMidiNoteInHertz (42))))
  104. {
  105. }
  106. double frequencyInHz;
  107. int lengthInPixels;
  108. };
  109. static std::vector<StringParameters> getDefaultStringParameters()
  110. {
  111. return { 42, 44, 46, 49, 51, 54, 56, 58, 61, 63, 66, 68, 70 };
  112. }
  113. void createStringComponents()
  114. {
  115. for (auto stringParams : getDefaultStringParameters())
  116. {
  117. stringLines.add (new StringComponent (stringParams.lengthInPixels,
  118. Colour::fromHSV (Random().nextFloat(), 0.6f, 0.9f, 1.0f)));
  119. }
  120. }
  121. void generateStringSynths (double sampleRate)
  122. {
  123. stringSynths.clear();
  124. for (auto stringParams : getDefaultStringParameters())
  125. {
  126. stringSynths.add (new StringSynthesiser (sampleRate, stringParams.frequencyInHz));
  127. }
  128. }
  129. //==============================================================================
  130. OwnedArray<StringComponent> stringLines;
  131. OwnedArray<StringSynthesiser> stringSynths;
  132. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringDemoComponent)
  133. };