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.

191 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. ChannelRemappingAudioSource::ChannelRemappingAudioSource (AudioSource* const source_,
  19. const bool deleteSourceWhenDeleted)
  20. : source (source_, deleteSourceWhenDeleted),
  21. requiredNumberOfChannels (2),
  22. buffer (2, 16)
  23. {
  24. remappedInfo.buffer = &buffer;
  25. remappedInfo.startSample = 0;
  26. }
  27. ChannelRemappingAudioSource::~ChannelRemappingAudioSource() {}
  28. //==============================================================================
  29. void ChannelRemappingAudioSource::setNumberOfChannelsToProduce (const int requiredNumberOfChannels_)
  30. {
  31. const ScopedLock sl (lock);
  32. requiredNumberOfChannels = requiredNumberOfChannels_;
  33. }
  34. void ChannelRemappingAudioSource::clearAllMappings()
  35. {
  36. const ScopedLock sl (lock);
  37. remappedInputs.clear();
  38. remappedOutputs.clear();
  39. }
  40. void ChannelRemappingAudioSource::setInputChannelMapping (const int destIndex, const int sourceIndex)
  41. {
  42. const ScopedLock sl (lock);
  43. while (remappedInputs.size() < destIndex)
  44. remappedInputs.add (-1);
  45. remappedInputs.set (destIndex, sourceIndex);
  46. }
  47. void ChannelRemappingAudioSource::setOutputChannelMapping (const int sourceIndex, const int destIndex)
  48. {
  49. const ScopedLock sl (lock);
  50. while (remappedOutputs.size() < sourceIndex)
  51. remappedOutputs.add (-1);
  52. remappedOutputs.set (sourceIndex, destIndex);
  53. }
  54. int ChannelRemappingAudioSource::getRemappedInputChannel (const int inputChannelIndex) const
  55. {
  56. const ScopedLock sl (lock);
  57. if (inputChannelIndex >= 0 && inputChannelIndex < remappedInputs.size())
  58. return remappedInputs.getUnchecked (inputChannelIndex);
  59. return -1;
  60. }
  61. int ChannelRemappingAudioSource::getRemappedOutputChannel (const int outputChannelIndex) const
  62. {
  63. const ScopedLock sl (lock);
  64. if (outputChannelIndex >= 0 && outputChannelIndex < remappedOutputs.size())
  65. return remappedOutputs .getUnchecked (outputChannelIndex);
  66. return -1;
  67. }
  68. //==============================================================================
  69. void ChannelRemappingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
  70. {
  71. source->prepareToPlay (samplesPerBlockExpected, sampleRate);
  72. }
  73. void ChannelRemappingAudioSource::releaseResources()
  74. {
  75. source->releaseResources();
  76. }
  77. void ChannelRemappingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
  78. {
  79. const ScopedLock sl (lock);
  80. buffer.setSize (requiredNumberOfChannels, bufferToFill.numSamples, false, false, true);
  81. const int numChans = bufferToFill.buffer->getNumChannels();
  82. int i;
  83. for (i = 0; i < buffer.getNumChannels(); ++i)
  84. {
  85. const int remappedChan = getRemappedInputChannel (i);
  86. if (remappedChan >= 0 && remappedChan < numChans)
  87. {
  88. buffer.copyFrom (i, 0, *bufferToFill.buffer,
  89. remappedChan,
  90. bufferToFill.startSample,
  91. bufferToFill.numSamples);
  92. }
  93. else
  94. {
  95. buffer.clear (i, 0, bufferToFill.numSamples);
  96. }
  97. }
  98. remappedInfo.numSamples = bufferToFill.numSamples;
  99. source->getNextAudioBlock (remappedInfo);
  100. bufferToFill.clearActiveBufferRegion();
  101. for (i = 0; i < requiredNumberOfChannels; ++i)
  102. {
  103. const int remappedChan = getRemappedOutputChannel (i);
  104. if (remappedChan >= 0 && remappedChan < numChans)
  105. {
  106. bufferToFill.buffer->addFrom (remappedChan, bufferToFill.startSample,
  107. buffer, i, 0, bufferToFill.numSamples);
  108. }
  109. }
  110. }
  111. //==============================================================================
  112. XmlElement* ChannelRemappingAudioSource::createXml() const
  113. {
  114. XmlElement* e = new XmlElement ("MAPPINGS");
  115. String ins, outs;
  116. int i;
  117. const ScopedLock sl (lock);
  118. for (i = 0; i < remappedInputs.size(); ++i)
  119. ins << remappedInputs.getUnchecked(i) << ' ';
  120. for (i = 0; i < remappedOutputs.size(); ++i)
  121. outs << remappedOutputs.getUnchecked(i) << ' ';
  122. e->setAttribute ("inputs", ins.trimEnd());
  123. e->setAttribute ("outputs", outs.trimEnd());
  124. return e;
  125. }
  126. void ChannelRemappingAudioSource::restoreFromXml (const XmlElement& e)
  127. {
  128. if (e.hasTagName ("MAPPINGS"))
  129. {
  130. const ScopedLock sl (lock);
  131. clearAllMappings();
  132. StringArray ins, outs;
  133. ins.addTokens (e.getStringAttribute ("inputs"), false);
  134. outs.addTokens (e.getStringAttribute ("outputs"), false);
  135. int i;
  136. for (i = 0; i < ins.size(); ++i)
  137. remappedInputs.add (ins[i].getIntValue());
  138. for (i = 0; i < outs.size(); ++i)
  139. remappedOutputs.add (outs[i].getIntValue());
  140. }
  141. }