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.

185 lines
6.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. AudioSourcePlayer::AudioSourcePlayer()
  19. : source (nullptr),
  20. sampleRate (0),
  21. bufferSize (0),
  22. tempBuffer (2, 8),
  23. lastGain (1.0f),
  24. gain (1.0f)
  25. {
  26. }
  27. AudioSourcePlayer::~AudioSourcePlayer()
  28. {
  29. setSource (nullptr);
  30. }
  31. void AudioSourcePlayer::setSource (AudioSource* newSource)
  32. {
  33. if (source != newSource)
  34. {
  35. AudioSource* const oldSource = source;
  36. if (newSource != nullptr && bufferSize > 0 && sampleRate > 0)
  37. newSource->prepareToPlay (bufferSize, sampleRate);
  38. {
  39. const ScopedLock sl (readLock);
  40. source = newSource;
  41. }
  42. if (oldSource != nullptr)
  43. oldSource->releaseResources();
  44. }
  45. }
  46. void AudioSourcePlayer::setGain (const float newGain) noexcept
  47. {
  48. gain = newGain;
  49. }
  50. void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,
  51. int totalNumInputChannels,
  52. float** outputChannelData,
  53. int totalNumOutputChannels,
  54. int numSamples)
  55. {
  56. // these should have been prepared by audioDeviceAboutToStart()...
  57. jassert (sampleRate > 0 && bufferSize > 0);
  58. const ScopedLock sl (readLock);
  59. if (source != nullptr)
  60. {
  61. int numActiveChans = 0, numInputs = 0, numOutputs = 0;
  62. // messy stuff needed to compact the channels down into an array
  63. // of non-zero pointers..
  64. for (int i = 0; i < totalNumInputChannels; ++i)
  65. {
  66. if (inputChannelData[i] != nullptr)
  67. {
  68. inputChans [numInputs++] = inputChannelData[i];
  69. if (numInputs >= numElementsInArray (inputChans))
  70. break;
  71. }
  72. }
  73. for (int i = 0; i < totalNumOutputChannels; ++i)
  74. {
  75. if (outputChannelData[i] != nullptr)
  76. {
  77. outputChans [numOutputs++] = outputChannelData[i];
  78. if (numOutputs >= numElementsInArray (outputChans))
  79. break;
  80. }
  81. }
  82. if (numInputs > numOutputs)
  83. {
  84. // if there aren't enough output channels for the number of
  85. // inputs, we need to create some temporary extra ones (can't
  86. // use the input data in case it gets written to)
  87. tempBuffer.setSize (numInputs - numOutputs, numSamples,
  88. false, false, true);
  89. for (int i = 0; i < numOutputs; ++i)
  90. {
  91. channels[numActiveChans] = outputChans[i];
  92. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples);
  93. ++numActiveChans;
  94. }
  95. for (int i = numOutputs; i < numInputs; ++i)
  96. {
  97. channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0);
  98. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples);
  99. ++numActiveChans;
  100. }
  101. }
  102. else
  103. {
  104. for (int i = 0; i < numInputs; ++i)
  105. {
  106. channels[numActiveChans] = outputChans[i];
  107. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples);
  108. ++numActiveChans;
  109. }
  110. for (int i = numInputs; i < numOutputs; ++i)
  111. {
  112. channels[numActiveChans] = outputChans[i];
  113. zeromem (channels[numActiveChans], sizeof (float) * (size_t) numSamples);
  114. ++numActiveChans;
  115. }
  116. }
  117. AudioSampleBuffer buffer (channels, numActiveChans, numSamples);
  118. AudioSourceChannelInfo info (&buffer, 0, numSamples);
  119. source->getNextAudioBlock (info);
  120. for (int i = info.buffer->getNumChannels(); --i >= 0;)
  121. buffer.applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
  122. lastGain = gain;
  123. }
  124. else
  125. {
  126. for (int i = 0; i < totalNumOutputChannels; ++i)
  127. if (outputChannelData[i] != nullptr)
  128. zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
  129. }
  130. }
  131. void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device)
  132. {
  133. prepareToPlay (device->getCurrentSampleRate(),
  134. device->getCurrentBufferSizeSamples());
  135. }
  136. void AudioSourcePlayer::prepareToPlay (double newSampleRate, int newBufferSize)
  137. {
  138. sampleRate = newSampleRate;
  139. bufferSize = newBufferSize;
  140. zeromem (channels, sizeof (channels));
  141. if (source != nullptr)
  142. source->prepareToPlay (bufferSize, sampleRate);
  143. }
  144. void AudioSourcePlayer::audioDeviceStopped()
  145. {
  146. if (source != nullptr)
  147. source->releaseResources();
  148. sampleRate = 0.0;
  149. bufferSize = 0;
  150. tempBuffer.setSize (2, 8);
  151. }