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.

187 lines
5.9KB

  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. for (int i = 0; i < buffer.getNumChannels(); ++i)
  83. {
  84. const int remappedChan = getRemappedInputChannel (i);
  85. if (remappedChan >= 0 && remappedChan < numChans)
  86. {
  87. buffer.copyFrom (i, 0, *bufferToFill.buffer,
  88. remappedChan,
  89. bufferToFill.startSample,
  90. bufferToFill.numSamples);
  91. }
  92. else
  93. {
  94. buffer.clear (i, 0, bufferToFill.numSamples);
  95. }
  96. }
  97. remappedInfo.numSamples = bufferToFill.numSamples;
  98. source->getNextAudioBlock (remappedInfo);
  99. bufferToFill.clearActiveBufferRegion();
  100. for (int i = 0; i < requiredNumberOfChannels; ++i)
  101. {
  102. const int remappedChan = getRemappedOutputChannel (i);
  103. if (remappedChan >= 0 && remappedChan < numChans)
  104. {
  105. bufferToFill.buffer->addFrom (remappedChan, bufferToFill.startSample,
  106. buffer, i, 0, bufferToFill.numSamples);
  107. }
  108. }
  109. }
  110. //==============================================================================
  111. XmlElement* ChannelRemappingAudioSource::createXml() const
  112. {
  113. XmlElement* e = new XmlElement ("MAPPINGS");
  114. String ins, outs;
  115. const ScopedLock sl (lock);
  116. for (int i = 0; i < remappedInputs.size(); ++i)
  117. ins << remappedInputs.getUnchecked(i) << ' ';
  118. for (int i = 0; i < remappedOutputs.size(); ++i)
  119. outs << remappedOutputs.getUnchecked(i) << ' ';
  120. e->setAttribute ("inputs", ins.trimEnd());
  121. e->setAttribute ("outputs", outs.trimEnd());
  122. return e;
  123. }
  124. void ChannelRemappingAudioSource::restoreFromXml (const XmlElement& e)
  125. {
  126. if (e.hasTagName ("MAPPINGS"))
  127. {
  128. const ScopedLock sl (lock);
  129. clearAllMappings();
  130. StringArray ins, outs;
  131. ins.addTokens (e.getStringAttribute ("inputs"), false);
  132. outs.addTokens (e.getStringAttribute ("outputs"), false);
  133. for (int i = 0; i < ins.size(); ++i)
  134. remappedInputs.add (ins[i].getIntValue());
  135. for (int i = 0; i < outs.size(); ++i)
  136. remappedOutputs.add (outs[i].getIntValue());
  137. }
  138. }