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.

184 lines
6.0KB

  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. AudioSourceChannelInfo info;
  62. int i, numActiveChans = 0, numInputs = 0, numOutputs = 0;
  63. // messy stuff needed to compact the channels down into an array
  64. // of non-zero pointers..
  65. for (i = 0; i < totalNumInputChannels; ++i)
  66. {
  67. if (inputChannelData[i] != nullptr)
  68. {
  69. inputChans [numInputs++] = inputChannelData[i];
  70. if (numInputs >= numElementsInArray (inputChans))
  71. break;
  72. }
  73. }
  74. for (i = 0; i < totalNumOutputChannels; ++i)
  75. {
  76. if (outputChannelData[i] != nullptr)
  77. {
  78. outputChans [numOutputs++] = outputChannelData[i];
  79. if (numOutputs >= numElementsInArray (outputChans))
  80. break;
  81. }
  82. }
  83. if (numInputs > numOutputs)
  84. {
  85. // if there aren't enough output channels for the number of
  86. // inputs, we need to create some temporary extra ones (can't
  87. // use the input data in case it gets written to)
  88. tempBuffer.setSize (numInputs - numOutputs, numSamples,
  89. false, false, true);
  90. for (i = 0; i < numOutputs; ++i)
  91. {
  92. channels[numActiveChans] = outputChans[i];
  93. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
  94. ++numActiveChans;
  95. }
  96. for (i = numOutputs; i < numInputs; ++i)
  97. {
  98. channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0);
  99. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
  100. ++numActiveChans;
  101. }
  102. }
  103. else
  104. {
  105. for (i = 0; i < numInputs; ++i)
  106. {
  107. channels[numActiveChans] = outputChans[i];
  108. memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
  109. ++numActiveChans;
  110. }
  111. for (i = numInputs; i < numOutputs; ++i)
  112. {
  113. channels[numActiveChans] = outputChans[i];
  114. zeromem (channels[numActiveChans], sizeof (float) * numSamples);
  115. ++numActiveChans;
  116. }
  117. }
  118. AudioSampleBuffer buffer (channels, numActiveChans, numSamples);
  119. info.buffer = &buffer;
  120. info.startSample = 0;
  121. info.numSamples = numSamples;
  122. source->getNextAudioBlock (info);
  123. for (i = info.buffer->getNumChannels(); --i >= 0;)
  124. info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
  125. lastGain = gain;
  126. }
  127. else
  128. {
  129. for (int i = 0; i < totalNumOutputChannels; ++i)
  130. if (outputChannelData[i] != nullptr)
  131. zeromem (outputChannelData[i], sizeof (float) * numSamples);
  132. }
  133. }
  134. void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device)
  135. {
  136. sampleRate = device->getCurrentSampleRate();
  137. bufferSize = device->getCurrentBufferSizeSamples();
  138. zeromem (channels, sizeof (channels));
  139. if (source != nullptr)
  140. source->prepareToPlay (bufferSize, sampleRate);
  141. }
  142. void AudioSourcePlayer::audioDeviceStopped()
  143. {
  144. if (source != nullptr)
  145. source->releaseResources();
  146. sampleRate = 0.0;
  147. bufferSize = 0;
  148. tempBuffer.setSize (2, 8);
  149. }