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.

278 lines
9.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. // This is an AudioTransportSource which will own it's assigned source
  21. struct AudioSourceOwningTransportSource : public AudioTransportSource
  22. {
  23. AudioSourceOwningTransportSource (PositionableAudioSource* s, double sr) : source (s)
  24. {
  25. AudioTransportSource::setSource (s, 0, nullptr, sr);
  26. }
  27. ~AudioSourceOwningTransportSource()
  28. {
  29. setSource (nullptr);
  30. }
  31. private:
  32. std::unique_ptr<PositionableAudioSource> source;
  33. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSourceOwningTransportSource)
  34. };
  35. //==============================================================================
  36. // An AudioSourcePlayer which will remove itself from the AudioDeviceManager's
  37. // callback list once it finishes playing its source
  38. struct AutoRemovingTransportSource : public AudioTransportSource,
  39. private Timer
  40. {
  41. AutoRemovingTransportSource (MixerAudioSource& mixerToUse, AudioTransportSource* ts, bool ownSource,
  42. int samplesPerBlock, double requiredSampleRate)
  43. : mixer (mixerToUse), transportSource (ts, ownSource)
  44. {
  45. jassert (ts != nullptr);
  46. setSource (transportSource);
  47. prepareToPlay (samplesPerBlock, requiredSampleRate);
  48. start();
  49. mixer.addInputSource (this, true);
  50. startTimerHz (10);
  51. }
  52. ~AutoRemovingTransportSource() override
  53. {
  54. setSource (nullptr);
  55. }
  56. void timerCallback() override
  57. {
  58. if (! transportSource->isPlaying())
  59. mixer.removeInputSource (this);
  60. }
  61. private:
  62. MixerAudioSource& mixer;
  63. OptionalScopedPointer<AudioTransportSource> transportSource;
  64. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AutoRemovingTransportSource)
  65. };
  66. // An AudioSource which simply outputs a buffer
  67. class AudioBufferSource : public PositionableAudioSource
  68. {
  69. public:
  70. AudioBufferSource (AudioBuffer<float>* audioBuffer, bool ownBuffer, bool playOnAllChannels)
  71. : buffer (audioBuffer, ownBuffer),
  72. playAcrossAllChannels (playOnAllChannels)
  73. {}
  74. //==============================================================================
  75. void setNextReadPosition (int64 newPosition) override
  76. {
  77. jassert (newPosition >= 0);
  78. if (looping)
  79. newPosition = newPosition % static_cast<int64> (buffer->getNumSamples());
  80. position = jmin (buffer->getNumSamples(), static_cast<int> (newPosition));
  81. }
  82. int64 getNextReadPosition() const override { return static_cast<int64> (position); }
  83. int64 getTotalLength() const override { return static_cast<int64> (buffer->getNumSamples()); }
  84. bool isLooping() const override { return looping; }
  85. void setLooping (bool shouldLoop) override { looping = shouldLoop; }
  86. //==============================================================================
  87. void prepareToPlay (int, double) override {}
  88. void releaseResources() override {}
  89. void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
  90. {
  91. bufferToFill.clearActiveBufferRegion();
  92. const int bufferSize = buffer->getNumSamples();
  93. const int samplesNeeded = bufferToFill.numSamples;
  94. const int samplesToCopy = jmin (bufferSize - position, samplesNeeded);
  95. if (samplesToCopy > 0)
  96. {
  97. int maxInChannels = buffer->getNumChannels();
  98. int maxOutChannels = bufferToFill.buffer->getNumChannels();
  99. if (! playAcrossAllChannels)
  100. maxOutChannels = jmin (maxOutChannels, maxInChannels);
  101. for (int i = 0; i < maxOutChannels; ++i)
  102. bufferToFill.buffer->copyFrom (i, bufferToFill.startSample, *buffer,
  103. i % maxInChannels, position, samplesToCopy);
  104. }
  105. position += samplesNeeded;
  106. if (looping)
  107. position %= bufferSize;
  108. }
  109. private:
  110. //==============================================================================
  111. OptionalScopedPointer<AudioBuffer<float>> buffer;
  112. int position = 0;
  113. bool looping = false, playAcrossAllChannels;
  114. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioBufferSource)
  115. };
  116. SoundPlayer::SoundPlayer()
  117. : sampleRate (44100.0), bufferSize (512)
  118. {
  119. formatManager.registerBasicFormats();
  120. player.setSource (&mixer);
  121. }
  122. SoundPlayer::~SoundPlayer()
  123. {
  124. mixer.removeAllInputs();
  125. player.setSource (nullptr);
  126. }
  127. void SoundPlayer::play (const File& file)
  128. {
  129. if (file.existsAsFile())
  130. play (formatManager.createReaderFor (file), true);
  131. }
  132. void SoundPlayer::play (const void* resourceData, size_t resourceSize)
  133. {
  134. if (resourceData != nullptr && resourceSize > 0)
  135. {
  136. auto mem = std::make_unique<MemoryInputStream> (resourceData, resourceSize, false);
  137. play (formatManager.createReaderFor (std::move (mem)), true);
  138. }
  139. }
  140. void SoundPlayer::play (AudioFormatReader* reader, bool deleteWhenFinished)
  141. {
  142. if (reader != nullptr)
  143. play (new AudioFormatReaderSource (reader, deleteWhenFinished), true, reader->sampleRate);
  144. }
  145. void SoundPlayer::play (AudioBuffer<float>* buffer, bool deleteWhenFinished, bool playOnAllOutputChannels)
  146. {
  147. if (buffer != nullptr)
  148. play (new AudioBufferSource (buffer, deleteWhenFinished, playOnAllOutputChannels), true);
  149. }
  150. void SoundPlayer::play (PositionableAudioSource* audioSource, bool deleteWhenFinished, double fileSampleRate)
  151. {
  152. if (audioSource != nullptr)
  153. {
  154. AudioTransportSource* transport = dynamic_cast<AudioTransportSource*> (audioSource);
  155. if (transport == nullptr)
  156. {
  157. if (deleteWhenFinished)
  158. {
  159. transport = new AudioSourceOwningTransportSource (audioSource, fileSampleRate);
  160. }
  161. else
  162. {
  163. transport = new AudioTransportSource();
  164. transport->setSource (audioSource, 0, nullptr, fileSampleRate);
  165. deleteWhenFinished = true;
  166. }
  167. }
  168. transport->start();
  169. transport->prepareToPlay (bufferSize, sampleRate);
  170. new AutoRemovingTransportSource (mixer, transport, deleteWhenFinished, bufferSize, sampleRate);
  171. }
  172. else
  173. {
  174. if (deleteWhenFinished)
  175. delete audioSource;
  176. }
  177. }
  178. void SoundPlayer::playTestSound()
  179. {
  180. auto soundLength = (int) sampleRate;
  181. double frequency = 440.0;
  182. float amplitude = 0.5f;
  183. auto phasePerSample = MathConstants<double>::twoPi / (sampleRate / frequency);
  184. auto* newSound = new AudioBuffer<float> (1, soundLength);
  185. for (int i = 0; i < soundLength; ++i)
  186. newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
  187. newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
  188. newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
  189. play (newSound, true, true);
  190. }
  191. //==============================================================================
  192. void SoundPlayer::audioDeviceIOCallback (const float** inputChannelData,
  193. int numInputChannels,
  194. float** outputChannelData,
  195. int numOutputChannels,
  196. int numSamples)
  197. {
  198. player.audioDeviceIOCallback (inputChannelData, numInputChannels,
  199. outputChannelData, numOutputChannels,
  200. numSamples);
  201. }
  202. void SoundPlayer::audioDeviceAboutToStart (AudioIODevice* device)
  203. {
  204. if (device != nullptr)
  205. {
  206. sampleRate = device->getCurrentSampleRate();
  207. bufferSize = device->getCurrentBufferSizeSamples();
  208. }
  209. player.audioDeviceAboutToStart (device);
  210. }
  211. void SoundPlayer::audioDeviceStopped()
  212. {
  213. player.audioDeviceStopped();
  214. }
  215. void SoundPlayer::audioDeviceError (const String& errorMessage)
  216. {
  217. player.audioDeviceError (errorMessage);
  218. }
  219. } // namespace juce