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.

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