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.

188 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. BEGIN_JUCE_NAMESPACE
  19. //==============================================================================
  20. AudioSourcePlayer::AudioSourcePlayer()
  21. : source (nullptr),
  22. sampleRate (0),
  23. bufferSize (0),
  24. tempBuffer (2, 8),
  25. lastGain (1.0f),
  26. gain (1.0f)
  27. {
  28. }
  29. AudioSourcePlayer::~AudioSourcePlayer()
  30. {
  31. setSource (nullptr);
  32. }
  33. void AudioSourcePlayer::setSource (AudioSource* newSource)
  34. {
  35. if (source != newSource)
  36. {
  37. AudioSource* const oldSource = source;
  38. if (newSource != nullptr && bufferSize > 0 && sampleRate > 0)
  39. newSource->prepareToPlay (bufferSize, sampleRate);
  40. {
  41. const ScopedLock sl (readLock);
  42. source = newSource;
  43. }
  44. if (oldSource != nullptr)
  45. oldSource->releaseResources();
  46. }
  47. }
  48. void AudioSourcePlayer::setGain (const float newGain) noexcept
  49. {
  50. gain = newGain;
  51. }
  52. void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,
  53. int totalNumInputChannels,
  54. float** outputChannelData,
  55. int totalNumOutputChannels,
  56. int numSamples)
  57. {
  58. // these should have been prepared by audioDeviceAboutToStart()...
  59. jassert (sampleRate > 0 && bufferSize > 0);
  60. const ScopedLock sl (readLock);
  61. if (source != nullptr)
  62. {
  63. AudioSourceChannelInfo info;
  64. int i, numActiveChans = 0, numInputs = 0, numOutputs = 0;
  65. // messy stuff needed to compact the channels down into an array
  66. // of non-zero pointers..
  67. for (i = 0; i < totalNumInputChannels; ++i)
  68. {
  69. if (inputChannelData[i] != nullptr)
  70. {
  71. inputChans [numInputs++] = inputChannelData[i];
  72. if (numInputs >= numElementsInArray (inputChans))
  73. break;
  74. }
  75. }
  76. for (i = 0; i < totalNumOutputChannels; ++i)
  77. {
  78. if (outputChannelData[i] != nullptr)
  79. {
  80. outputChans [numOutputs++] = outputChannelData[i];
  81. if (numOutputs >= numElementsInArray (outputChans))
  82. break;
  83. }
  84. }
  85. if (numInputs > numOutputs)
  86. {
  87. // if there aren't enough output channels for the number of
  88. // inputs, we need to create some temporary extra ones (can't
  89. // use the input data in case it gets written to)
  90. tempBuffer.setSize (numInputs - numOutputs, numSamples,
  91. false, false, true);
  92. for (i = 0; i < numOutputs; ++i)
  93. {
  94. channels[numActiveChans] = outputChans[i];
  95. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
  96. ++numActiveChans;
  97. }
  98. for (i = numOutputs; i < numInputs; ++i)
  99. {
  100. channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0);
  101. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
  102. ++numActiveChans;
  103. }
  104. }
  105. else
  106. {
  107. for (i = 0; i < numInputs; ++i)
  108. {
  109. channels[numActiveChans] = outputChans[i];
  110. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
  111. ++numActiveChans;
  112. }
  113. for (i = numInputs; i < numOutputs; ++i)
  114. {
  115. channels[numActiveChans] = outputChans[i];
  116. zeromem (channels[numActiveChans], sizeof (float) * numSamples);
  117. ++numActiveChans;
  118. }
  119. }
  120. AudioSampleBuffer buffer (channels, numActiveChans, numSamples);
  121. info.buffer = &buffer;
  122. info.startSample = 0;
  123. info.numSamples = numSamples;
  124. source->getNextAudioBlock (info);
  125. for (i = info.buffer->getNumChannels(); --i >= 0;)
  126. info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
  127. lastGain = gain;
  128. }
  129. else
  130. {
  131. for (int i = 0; i < totalNumOutputChannels; ++i)
  132. if (outputChannelData[i] != nullptr)
  133. zeromem (outputChannelData[i], sizeof (float) * numSamples);
  134. }
  135. }
  136. void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device)
  137. {
  138. sampleRate = device->getCurrentSampleRate();
  139. bufferSize = device->getCurrentBufferSizeSamples();
  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. }
  152. END_JUCE_NAMESPACE