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.

271 lines
8.7KB

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