![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
00001 /* 00002 ------------------------------------------------------------------------------- 00003 This file is part of the Plink, Plonk, Plank libraries 00004 by Martin Robinson 00005 00006 http://code.google.com/p/pl-nk/ 00007 00008 Copyright University of the West of England, Bristol 2011-14 00009 All rights reserved. 00010 00011 Redistribution and use in source and binary forms, with or without 00012 modification, are permitted provided that the following conditions are met: 00013 00014 * Redistributions of source code must retain the above copyright 00015 notice, this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright 00017 notice, this list of conditions and the following disclaimer in the 00018 documentation and/or other materials provided with the distribution. 00019 * Neither the name of University of the West of England, Bristol nor 00020 the names of its contributors may be used to endorse or promote products 00021 derived from this software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00026 DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 This software makes use of third party libraries. For more information see: 00035 doc/license.txt included in the distribution. 00036 ------------------------------------------------------------------------------- 00037 */ 00038 00039 #ifndef PLONK_OVERLAPMIXCHANNEL_H 00040 #define PLONK_OVERLAPMIXCHANNEL_H 00041 00042 #include "../channel/plonk_ChannelInternalCore.h" 00043 #include "../plonk_GraphForwardDeclarations.h" 00044 00045 00047 template<class SampleType> 00048 class OverlapMixChannelInternal 00049 : public ProxyOwnerChannelInternal<SampleType, ChannelInternalCore::Data> 00050 { 00051 public: 00052 typedef ChannelInternalCore::Data Data; 00053 typedef ChannelBase<SampleType> ChannelType; 00054 typedef ObjectArray<ChannelType> ChannelArrayType; 00055 typedef OverlapMixChannelInternal<SampleType> OverlapMixInternal; 00056 typedef ProxyOwnerChannelInternal<SampleType,Data> Internal; 00057 typedef ChannelInternalBase<SampleType> InternalBase; 00058 typedef UnitBase<SampleType> UnitType; 00059 typedef InputDictionary Inputs; 00060 typedef NumericalArray<SampleType> Buffer; 00061 typedef ObjectArray<Buffer> BufferArray; 00062 00063 OverlapMixChannelInternal (Inputs const& inputs, 00064 Data const& data, 00065 BlockSize const& blockSize, 00066 SampleRate const& sampleRate, 00067 ChannelArrayType& channels) throw() 00068 : Internal (inputs.getMaxNumChannels(), inputs, data, blockSize, sampleRate, channels), 00069 overlapMix (ChannelInternalCore::getInputAs<DoubleVariable> (IOKey::OverlapMix)), 00070 tempBuffers (BufferArray::withSize (inputs.getMaxNumChannels())), 00071 tempBufferPos (0), 00072 tempBufferStartOffset (0), 00073 nextInputTimeStamp (TimeStamp::getZero()) 00074 { 00075 } 00076 00077 Text getName() const throw() 00078 { 00079 return "Overlap Mix"; 00080 } 00081 00082 IntArray getInputKeys() const throw() 00083 { 00084 const IntArray keys (IOKey::Generic); 00085 return keys; 00086 } 00087 00088 void initChannel (const int channel) throw() 00089 { 00090 const UnitType& input = this->getInputAsUnit (IOKey::Generic); 00091 const SampleType sourceValue = input.getValue (channel); 00092 00093 if ((channel % this->getNumChannels()) == 0) 00094 { 00095 // all need to be the same input BS and SR 00096 this->setBlockSize (input.getBlockSize (0)); 00097 this->setSampleRate (input.getSampleRate (0)); 00098 00099 for (int i = 0; i < this->getNumChannels(); ++i) 00100 { 00101 tempBuffers.atUnchecked (i).setSize (this->getBlockSize().getValue() * 2, false); 00102 tempBuffers.atUnchecked (i).zero(); 00103 tempBufferPos = 0; 00104 tempBufferStartOffset = 0; 00105 } 00106 } 00107 00108 this->initProxyValue (channel, sourceValue); 00109 } 00110 00111 void process (ProcessInfo& info, const int /*channel*/) throw() 00112 { 00113 /* Be careful optimising this with the new NumericalArray vector stuff */ 00114 00115 UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00116 00117 const int numChannels = this->getNumChannels(); 00118 const int outputBufferLength = this->getOutputBuffer (0).length(); 00119 const int overlapLength = int (this->overlapMix.getValue() * outputBufferLength + 0.5); 00120 int i, channel, channelBufferPos; 00121 00122 if (overlapLength < outputBufferLength) 00123 { 00124 const TimeStamp infoTimeStamp = info.getTimeStamp(); 00125 00126 for (channel = 0; channel < numChannels; ++channel) 00127 { 00128 channelBufferPos = tempBufferPos; 00129 00130 SampleType* const outputSamples = this->getOutputSamples (channel); 00131 SampleType* const tempBufferSamples = this->tempBuffers.atUnchecked (channel).getArray(); 00132 00133 // copy remaining overlap from last time to the output 00134 for (i = 0; i < outputBufferLength; ++i) 00135 outputSamples[i] = tempBufferSamples[channelBufferPos++]; 00136 00137 tempBuffers.atUnchecked (channel).zero(); 00138 } 00139 00140 // build the overlapping material in the temp buffer 00141 tempBufferPos = tempBufferStartOffset; 00142 00143 while (tempBufferPos < outputBufferLength) 00144 { 00145 const int tempBufferStartPos = tempBufferPos; 00146 00147 info.setTimeStamp (nextInputTimeStamp); 00148 00149 for (channel = 0; channel < numChannels; ++channel) 00150 { 00151 channelBufferPos = tempBufferPos; 00152 00153 SampleType* const tempBufferSamples = this->tempBuffers.atUnchecked (channel).getArray(); 00154 00155 const Buffer& inputBuffer (inputUnit.process (info, channel)); 00156 const SampleType* const inputSamples = inputBuffer.getArray(); 00157 const int inputBufferLength = inputBuffer.length(); 00158 00159 plonk_assert (inputBufferLength == outputBufferLength); 00160 00161 for (i = 0; i < inputBufferLength; ++i) 00162 tempBufferSamples[channelBufferPos++] += inputSamples[i]; 00163 00164 channelBufferPos = tempBufferStartPos + overlapLength; 00165 } 00166 00167 tempBufferPos = channelBufferPos; 00168 nextInputTimeStamp = inputUnit.getNextTimeStamp (0); 00169 } 00170 00171 // in case the overlap is not an integer divsion of the block size 00172 tempBufferStartOffset = tempBufferPos - outputBufferLength; 00173 00174 // accumulate the first part of the temp buffer to the output 00175 // leaving the rest there for next time 00176 tempBufferPos = 0; 00177 00178 for (channel = 0; channel < numChannels; ++channel) 00179 { 00180 channelBufferPos = tempBufferPos; 00181 00182 SampleType* const outputSamples = this->getOutputSamples (channel); 00183 SampleType* const tempBufferSamples = this->tempBuffers.atUnchecked (channel).getArray(); 00184 00185 for (i = 0; i < outputBufferLength; ++i) 00186 outputSamples[i] += tempBufferSamples[channelBufferPos++]; 00187 } 00188 00189 tempBufferPos = channelBufferPos; 00190 00191 info.setTimeStamp (infoTimeStamp); // reset for the parent graph 00192 } 00193 else 00194 { 00195 for (channel = 0; channel < numChannels; ++channel) 00196 { 00197 SampleType* const outputSamples = this->getOutputSamples (channel); 00198 const Buffer& inputBuffer (inputUnit.process (info, channel)); 00199 const SampleType* const inputSamples = inputBuffer.getArray(); 00200 00201 plonk_assert (outputBufferLength == inputBuffer.length()); 00202 00203 Buffer::copyData (outputSamples, inputSamples, outputBufferLength); 00204 } 00205 } 00206 } 00207 00208 private: 00209 DoubleVariable overlapMix; 00210 BufferArray tempBuffers; 00211 int tempBufferPos; 00212 int tempBufferStartOffset; 00213 TimeStamp nextInputTimeStamp; 00214 }; 00215 00216 //------------------------------------------------------------------------------ 00217 00229 template<class SampleType> 00230 class OverlapMixUnit 00231 { 00232 public: 00233 typedef OverlapMixChannelInternal<SampleType> OverlapMixInternal; 00234 typedef typename OverlapMixInternal::Data Data; 00235 typedef ChannelBase<SampleType> ChannelType; 00236 typedef ChannelInternal<SampleType,Data> Internal; 00237 typedef UnitBase<SampleType> UnitType; 00238 typedef InputDictionary Inputs; 00239 00240 static inline UnitInfos getInfo() throw() 00241 { 00242 const double minOverlap = TypeUtility<double>::getTypeEpsilon(); 00243 00244 return UnitInfo ("OverlapMix", "Mixes down incoming overlapped blocks into a continuous signal.", 00245 00246 // output 00247 ChannelCount::VariableChannelCount, 00248 IOKey::Generic, Measure::None, IOInfo::NoDefault, IOLimit::None, IOKey::End, 00249 00250 // inputs 00251 IOKey::Generic, Measure::None, IOInfo::NoDefault, IOLimit::None, 00252 IOKey::OverlapMix, Measure::Factor, 0.5, IOLimit::Clipped, Measure::Factor, minOverlap, 1.0, 00253 IOKey::End); 00254 } 00255 00257 static UnitType ar (UnitType const& input, 00258 DoubleVariable const& overlap = Math<DoubleVariable>::get0_5()) throw() 00259 { 00260 plonk_assert (overlap.getValue() >= TypeUtility<double>::getTypeEpsilon()); 00261 plonk_assert (overlap.getValue() <= 1.0); 00262 00263 Inputs inputs; 00264 inputs.put (IOKey::Generic, input); 00265 inputs.put (IOKey::OverlapMix, overlap); 00266 00267 Data data = { -1.0, -1.0 }; 00268 00269 return UnitType::template proxiesFromInputs<OverlapMixInternal> (inputs, 00270 data, 00271 BlockSize::noPreference(), 00272 SampleRate::noPreference()); 00273 } 00274 00275 00276 }; 00277 00278 typedef OverlapMixUnit<PLONK_TYPE_DEFAULT> OverlapMix; 00279 00280 00281 #endif // PLONK_OVERLAPMIXCHANNEL_H