![]() |
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_RESAMPLECHANNEL_H 00040 #define PLONK_RESAMPLECHANNEL_H 00041 00042 #include "../channel/plonk_ChannelInternalCore.h" 00043 #include "../plonk_GraphForwardDeclarations.h" 00044 00045 00047 template<class SampleType, Interp::TypeCode InterpTypeCode> 00048 class ResampleChannelInternal 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 ResampleChannelInternal<SampleType,InterpTypeCode> ResampleInternal; 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 typedef typename TypeUtility<SampleType>::IndexType IndexType; 00063 00064 typedef typename TypeUtility<SampleType>::IndexType RateType; 00065 typedef UnitBase<RateType> RateUnitType; 00066 typedef NumericalArray<RateType> RateBufferType; 00067 00068 typedef InterpSelect<SampleType,IndexType,InterpTypeCode> InterpSelectType; 00069 typedef typename InterpSelectType::InterpType InterpType; 00070 typedef typename InterpType::ExtensionBuffer ExtensionBuffer; 00071 00072 ResampleChannelInternal (Inputs const& inputs, 00073 Data const& data, 00074 BlockSize const& blockSize, 00075 SampleRate const& sampleRate, 00076 ChannelArrayType& channels) throw() 00077 : Internal (inputs.getMaxNumChannels(), inputs, data, blockSize, sampleRate, channels), 00078 tempBuffers (BufferArray::withSize (inputs.getMaxNumChannels())), 00079 tempBufferPos (0), 00080 nextInputTimeStamp (TimeStamp::getZero()) 00081 { 00082 plonk_assert (sampleRate.getValue() > 0.0); // no need to resample a DC signal 00083 00084 // should check the input is all the same sample rate too... 00085 } 00086 00087 Text getName() const throw() 00088 { 00089 return "Resample"; 00090 } 00091 00092 IntArray getInputKeys() const throw() 00093 { 00094 const IntArray keys (IOKey::Generic, IOKey::Rate); 00095 return keys; 00096 } 00097 00098 /* 00099 void initChannel (const int channel) throw() 00100 { 00101 if ((channel % this->getNumChannels()) == 0) 00102 { 00103 const AudioFileReader& file = this->getInputAsAudioFileReader (IOKey::AudioFileReader); 00104 00105 double fileSampleRate = file.getSampleRate(); 00106 00107 if (fileSampleRate <= 0.0) 00108 fileSampleRate = file.getDefaultSampleRate(); 00109 00110 this->setSampleRate (SampleRate::decide (fileSampleRate, this->getSampleRate())); 00111 buffer.setSize (this->getBlockSize().getValue() * file.getNumChannels(), false); 00112 } 00113 00114 this->initProxyValue (channel, 0); 00115 } 00116 */ 00117 void initChannel (const int channel) throw() 00118 { 00119 const UnitType& input = this->getInputAsUnit (IOKey::Generic); 00120 const SampleType sourceValue = input.getValue (channel); 00121 const RateUnitType& rateUnit = ChannelInternalCore::getInputAs<RateUnitType> (IOKey::Rate); 00122 plonk_assert (input.getOverlap (channel) == Math<DoubleVariable>::get1()); 00123 plonk_assert (rateUnit.getOverlap (channel) == Math<DoubleVariable>::get1()); 00124 00125 if (rateUnit.getBlockSize (channel).getValue() != this->getBlockSize().getValue()) 00126 this->ratePositions.setSize (this->getNumChannels(), false); 00127 00128 if ((channel % this->getNumChannels()) == 0) 00129 { 00130 // larger for interpolation 00131 resizeTempBuffer (input.getBlockSize (0).getValue() + InterpType::getExtension()); 00132 tempBufferPos = tempBufferPosMax; 00133 } 00134 00135 tempBuffers.atUnchecked (channel).zero(); 00136 tempBuffers.atUnchecked (channel).put (tempBufferPos, sourceValue); 00137 00138 this->initProxyValue (channel, sourceValue); 00139 } 00140 00141 inline void resizeTempBuffer (const int inputBufferLength) throw() 00142 { 00143 if (inputBufferLength != tempBuffers.atUnchecked (0).length()) 00144 { 00145 for (int i = 0; i < tempBuffers.length(); ++i) 00146 { 00147 Buffer& tempBuffer = tempBuffers.atUnchecked (i); 00148 tempBuffer.setSize (inputBufferLength, false); 00149 } 00150 00151 tempBufferUsableLength = IndexType (inputBufferLength) - InterpType::getExtensionAsIndex(); 00152 tempBufferPosMax = tempBufferUsableLength + InterpType::getOffsetAsIndex(); 00153 } 00154 } 00155 00156 inline void getNextInputBuffer (ProcessInfo& info) throw() 00157 { 00158 const int extension = InterpType::getExtension(); 00159 const int numChannels = this->getNumChannels(); 00160 00161 info.setTimeStamp (nextInputTimeStamp); 00162 00163 UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00164 00165 tempBufferPos -= tempBufferUsableLength; 00166 00167 for (int channel = 0; channel < numChannels; ++channel) 00168 { 00169 const Buffer& inputBuffer (inputUnit.process (info, channel)); 00170 const SampleType* const inputSamples = inputBuffer.getArray(); 00171 const int inputBufferLength = inputBuffer.length(); 00172 00173 ExtensionBuffer interpolationValues; 00174 Buffer::copyData (interpolationValues.buffer, 00175 tempBuffers.atUnchecked (channel).getArray() + tempBuffers.atUnchecked (channel).length() - extension, 00176 extension); 00177 00178 resizeTempBuffer (inputBufferLength + extension); 00179 00180 Buffer::copyData (tempBuffers.atUnchecked (channel).getArray(), 00181 interpolationValues.buffer, 00182 extension); 00183 00184 Buffer::copyData (tempBuffers.atUnchecked (channel).getArray() + extension, 00185 inputSamples, 00186 inputBufferLength); 00187 } 00188 00189 nextInputTimeStamp = inputUnit.getNextTimeStamp (0); 00190 } 00191 00192 void process (ProcessInfo& info, const int /*channel*/) throw() 00193 { 00194 const Data& data = this->getState(); 00195 00196 UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00197 const IndexType inputSampleRate = IndexType (inputUnit.getSampleRate (0)); // should be the same sample rate for each input channel 00198 00199 RateUnitType& rateUnit = ChannelInternalCore::getInputAs<RateUnitType> (IOKey::Rate); 00200 00201 const int outputBufferLength = this->getOutputBuffer (0).length(); 00202 const int numChannels = this->getNumChannels(); 00203 00204 if (inputSampleRate <= 0.0) 00205 { 00206 for (int channel = 0; channel < numChannels; ++channel) 00207 { 00208 const SampleType inputValue = inputUnit.process (info, channel).atUnchecked (0); 00209 SampleType* const outputSamples = this->getOutputSamples (channel); 00210 NumericalArrayFiller<SampleType>::fill (outputSamples, inputValue, outputBufferLength); 00211 } 00212 } 00213 else 00214 { 00215 const TimeStamp infoTimeStamp = info.getTimeStamp(); 00216 00217 const RateBufferType& rateBuffer (rateUnit.process (info, 0)); 00218 const int rateBufferLength = rateBuffer.length(); 00219 00220 if (rateBufferLength == 1) 00221 { 00222 const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateBuffer.getArray() [0]); 00223 00224 if (tempBufferIncrement == Math<IndexType>::get0()) 00225 { 00226 for (int channel = 0; channel < numChannels; ++channel) 00227 { 00228 SampleType* tempBufferSamples = this->tempBuffers.atUnchecked (channel).getArray(); 00229 const SampleType dcOutput = InterpType::lookup (tempBufferSamples, tempBufferPos); 00230 SampleType* const outputSamples = this->getOutputSamples (channel); 00231 NumericalArrayFiller<SampleType>::fill (outputSamples, dcOutput, outputBufferLength); 00232 } 00233 } 00234 else 00235 { 00236 int outputSamplePosition = 0; 00237 00238 while (outputSamplePosition < outputBufferLength) 00239 { 00240 if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00241 getNextInputBuffer (info); 00242 00243 int channelSamplePosition; 00244 IndexType channelBufferPos; 00245 00246 for (int channel = 0; channel < numChannels; ++channel) 00247 { 00248 channelSamplePosition = outputSamplePosition; 00249 channelBufferPos = tempBufferPos; 00250 00251 const SampleType* const tempBufferSamples = tempBuffers.atUnchecked (channel).getArray(); 00252 SampleType* const outputSamples = this->getOutputSamples (channel); 00253 00254 for (channelSamplePosition = outputSamplePosition; 00255 (channelSamplePosition < outputBufferLength) && (channelBufferPos < tempBufferPosMax); 00256 ++channelSamplePosition) 00257 { 00258 outputSamples[channelSamplePosition] = InterpType::lookup (tempBufferSamples, channelBufferPos); 00259 channelBufferPos += tempBufferIncrement; 00260 } 00261 } 00262 00263 outputSamplePosition = channelSamplePosition; 00264 tempBufferPos = channelBufferPos; 00265 } 00266 } 00267 } 00268 else if (rateBufferLength == outputBufferLength) 00269 { 00270 int outputSamplePosition = 0; 00271 00272 while (outputSamplePosition < outputBufferLength) 00273 { 00274 if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00275 getNextInputBuffer (info); 00276 00277 int channelSamplePosition; 00278 IndexType channelBufferPos; 00279 00280 for (int channel = 0; channel < numChannels; ++channel) 00281 { 00282 channelSamplePosition = outputSamplePosition; 00283 channelBufferPos = tempBufferPos; 00284 00285 const SampleType* const tempBufferSamples = tempBuffers.atUnchecked (channel).getArray(); 00286 SampleType* const outputSamples = this->getOutputSamples (channel); 00287 const SampleType* const rateSamples = rateBuffer.getArray(); 00288 00289 for (channelSamplePosition = outputSamplePosition; 00290 (channelSamplePosition < outputBufferLength) && (channelBufferPos < tempBufferPosMax); 00291 ++channelSamplePosition) 00292 { 00293 outputSamples[channelSamplePosition] = InterpType::lookup (tempBufferSamples, channelBufferPos); 00294 const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateSamples[channelSamplePosition]); 00295 channelBufferPos += tempBufferIncrement; 00296 } 00297 } 00298 00299 outputSamplePosition = channelSamplePosition; 00300 tempBufferPos = channelBufferPos; 00301 } 00302 } 00303 else 00304 { 00305 int outputSamplePosition = 0; 00306 this->ratePositions.zero(); 00307 double* const ratePositionArray = this->ratePositions.getArray(); 00308 00309 while (outputSamplePosition < outputBufferLength) 00310 { 00311 if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00312 getNextInputBuffer (info); 00313 00314 int channelSamplePosition; 00315 IndexType channelBufferPos = tempBufferPos; 00316 00317 for (int channel = 0; channel < numChannels; ++channel) 00318 { 00319 channelSamplePosition = outputSamplePosition; 00320 00321 const SampleType* const tempBufferSamples = tempBuffers.atUnchecked (channel).getArray(); 00322 SampleType* const outputSamples = this->getOutputSamples (channel); 00323 const SampleType* const rateSamples = rateBuffer.getArray(); 00324 00325 const double rateIncrement = double (rateBufferLength) / double (outputBufferLength); 00326 00327 for (channelSamplePosition = outputSamplePosition; 00328 (channelSamplePosition < outputBufferLength) && (channelBufferPos < tempBufferPosMax); 00329 ++channelSamplePosition) 00330 { 00331 outputSamples[channelSamplePosition] = InterpType::lookup (tempBufferSamples, channelBufferPos); 00332 const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateSamples[int (ratePositionArray[channel])]); 00333 channelBufferPos += tempBufferIncrement; 00334 ratePositionArray[channel] += rateIncrement; 00335 } 00336 } 00337 00338 outputSamplePosition = channelSamplePosition; 00339 tempBufferPos = channelBufferPos; 00340 } 00341 } 00342 00343 info.setTimeStamp (infoTimeStamp); // reset for the parent graph 00344 } 00345 } 00346 00347 private: 00348 BufferArray tempBuffers; 00349 IndexType tempBufferPos; 00350 IndexType tempBufferPosMax; 00351 IndexType tempBufferUsableLength; 00352 TimeStamp nextInputTimeStamp; 00353 DoubleArray ratePositions; 00354 }; 00355 00357 //template<class SampleType, Interp::TypeCode InterpTypeCode> 00358 //class ResampleChannelInternal 00359 //: public ChannelInternal<SampleType, ChannelInternalCore::Data> 00360 //{ 00361 //public: 00362 // typedef ChannelInternalCore::Data Data; 00363 // typedef ChannelBase<SampleType> ChannelType; 00364 // typedef ResampleChannelInternal<SampleType,InterpTypeCode> ResampleInternal; 00365 // typedef ChannelInternal<SampleType,Data> Internal; 00366 // typedef ChannelInternalBase<SampleType> InternalBase; 00367 // typedef UnitBase<SampleType> UnitType; 00368 // typedef InputDictionary Inputs; 00369 // typedef NumericalArray<SampleType> Buffer; 00370 // typedef typename TypeUtility<SampleType>::IndexType IndexType; 00371 // 00372 // typedef typename TypeUtility<SampleType>::IndexType RateType; 00373 // typedef UnitBase<RateType> RateUnitType; 00374 // typedef NumericalArray<RateType> RateBufferType; 00375 // 00376 // typedef InterpSelect<SampleType,IndexType,InterpTypeCode> InterpSelect; 00377 // typedef typename InterpSelect::InterpType InterpType; 00378 // typedef typename InterpType::ExtensionBuffer ExtensionBuffer; 00379 // 00380 // ResampleChannelInternal (Inputs const& inputs, 00381 // Data const& data, 00382 // BlockSize const& blockSize, 00383 // SampleRate const& sampleRate) throw() 00384 // : Internal (inputs, data, blockSize, sampleRate), 00385 // tempBufferPos (0), 00386 // nextInputTimeStamp (TimeStamp::getZero()) 00387 // { 00388 // plonk_assert (sampleRate.getValue() > 0.0); // no need to resample a DC signal 00389 // } 00390 // 00391 // Text getName() const throw() 00392 // { 00393 // return "Resample"; 00394 // } 00395 // 00396 // IntArray getInputKeys() const throw() 00397 // { 00398 // const IntArray keys (IOKey::Generic, IOKey::Rate); 00399 // return keys; 00400 // } 00401 // 00402 // InternalBase* getChannel (const int index) throw() 00403 // { 00404 // const Inputs channelInputs = this->getInputs().getChannel (index); 00405 // return new ResampleInternal (channelInputs, 00406 // this->getState(), 00407 // this->getBlockSize(), 00408 // this->getSampleRate()); 00409 // } 00410 // 00411 // void initChannel (const int channel) throw() 00412 // { 00413 // const UnitType& input = this->getInputAsUnit (IOKey::Generic); 00414 // 00415 //#ifdef PLONK_DEBUG 00416 // const RateUnitType& rateUnit = ChannelInternalCore::getInputAs<RateUnitType> (IOKey::Rate); 00417 // plonk_assert (input.getOverlap (channel) == Math<DoubleVariable>::get1()); 00418 // plonk_assert (rateUnit.getOverlap (channel) == Math<DoubleVariable>::get1()); 00419 //#endif 00420 // 00421 // const SampleType sourceValue = input.getValue (channel); 00422 // this->initValue (sourceValue); 00423 // 00424 // // larger for interpolation 00425 // resizeTempBuffer (input.getBlockSize (channel).getValue() + InterpType::getExtension()); 00426 // tempBuffer.zero(); // was a bug on interpolation here.. 00427 // tempBufferPos = tempBufferPosMax; 00428 // 00429 // tempBuffer.put (tempBufferPos, sourceValue); 00430 // } 00431 // 00432 // inline void resizeTempBuffer (const int inputBufferLength) throw() 00433 // { 00434 // if (inputBufferLength != tempBuffer.length()) 00435 // { 00436 // tempBuffer.setSize (inputBufferLength, false); 00437 // tempBufferUsableLength = IndexType (inputBufferLength) - InterpType::getExtensionAsIndex(); 00438 // tempBufferPosMax = tempBufferUsableLength + InterpType::getOffsetAsIndex(); 00439 // } 00440 // } 00441 // 00442 // inline void getNextInputBuffer (ProcessInfo& info, const int channel, SampleType* &tempBufferSamples, int& tempBufferLength) throw() 00443 // { 00444 // const int extension = InterpType::getExtension(); 00445 // 00446 // UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00447 // 00448 // 00449 // // bug here for multiple channels ?? 00450 // // as a result, might need to make the timestamp access virtual or shared between proxies and proxyowners? 00451 // // won't help as the first channel getting the next buffer obliterates the remaining channels for the previous buffer 00452 // 00453 // info.setTimeStamp (nextInputTimeStamp); 00454 // const Buffer& inputBuffer (inputUnit.process (info, channel)); 00455 // nextInputTimeStamp = inputUnit.getNextTimeStamp (channel); 00456 // 00457 // const SampleType* const inputSamples = inputBuffer.getArray(); 00458 // const int inputBufferLength = inputBuffer.length(); 00459 // 00460 // ExtensionBuffer interpolationValues; 00461 // Buffer::copyData (interpolationValues.buffer, 00462 // tempBufferSamples + tempBufferLength - extension, 00463 // extension); 00464 // 00465 // tempBufferPos -= tempBufferUsableLength; // move this before resize 00466 // tempBufferLength = inputBufferLength + extension; // larger for interpolation 00467 // resizeTempBuffer (tempBufferLength); 00468 // tempBufferSamples = this->tempBuffer.getArray(); 00469 // 00470 // Buffer::copyData (tempBufferSamples, 00471 // interpolationValues.buffer, 00472 // extension); 00473 // 00474 // Buffer::copyData (tempBufferSamples + extension, 00475 // inputSamples, 00476 // inputBufferLength); 00477 // } 00478 // 00479 // void process (ProcessInfo& info, const int channel) throw() 00480 // { 00481 // const Data& data = this->getState(); 00482 // 00483 // UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00484 // const IndexType inputSampleRate = IndexType (inputUnit.getSampleRate (channel)); 00485 // 00486 // RateUnitType& rateUnit = ChannelInternalCore::getInputAs<RateUnitType> (IOKey::Rate); 00487 // 00488 // const int outputBufferLength = this->getOutputBuffer().length(); 00489 // SampleType* outputSamples = this->getOutputSamples(); 00490 // 00491 // if (inputSampleRate <= 0.0) 00492 // { 00493 // const SampleType inputValue = inputUnit.process (info, channel).atUnchecked (0); 00494 // NumericalArrayFiller<SampleType>::fill (outputSamples, inputValue, outputBufferLength); 00495 // } 00496 // else 00497 // { 00498 // const TimeStamp infoTimeStamp = info.getTimeStamp(); 00499 // SampleType* const outputSamplesEnd = outputSamples + outputBufferLength; 00500 // 00501 // const RateBufferType& rateBuffer (rateUnit.process (info, channel)); 00502 // const RateType* rateSamples = rateBuffer.getArray(); 00503 // const int rateBufferLength = rateBuffer.length(); 00504 // 00505 // if (rateBufferLength == 1) 00506 // { 00507 // const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateSamples[0]); 00508 // 00509 // if (tempBufferIncrement == Math<IndexType>::get0()) 00510 // { 00511 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00512 // const SampleType dcOutput = InterpType::lookup (tempBufferSamples, tempBufferPos); 00513 // NumericalArrayFiller<SampleType>::fill (outputSamples, dcOutput, outputBufferLength); 00514 // } 00515 // else 00516 // { 00517 // while (outputSamples < outputSamplesEnd) 00518 // { 00519 // int tempBufferLength = this->tempBuffer.length(); 00520 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00521 // 00522 // if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00523 // getNextInputBuffer (info, channel, tempBufferSamples, tempBufferLength); 00524 // 00525 // while ((outputSamples < outputSamplesEnd) && (tempBufferPos < tempBufferPosMax)) 00526 // { 00527 // *outputSamples++ = InterpType::lookup (tempBufferSamples, tempBufferPos); 00528 // tempBufferPos += tempBufferIncrement; 00529 // } 00530 // } 00531 // } 00532 // } 00533 // else if (rateBufferLength == outputBufferLength) 00534 // { 00535 // while (outputSamples < outputSamplesEnd) 00536 // { 00537 // int tempBufferLength = this->tempBuffer.length(); 00538 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00539 // 00540 // if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00541 // getNextInputBuffer (info, channel, tempBufferSamples, tempBufferLength); 00542 // 00543 // while ((outputSamples < outputSamplesEnd) && (tempBufferPos < tempBufferPosMax)) 00544 // { 00545 // *outputSamples++ = InterpType::lookup (tempBufferSamples, tempBufferPos); 00546 // const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * *rateSamples++); 00547 // tempBufferPos += tempBufferIncrement; 00548 // } 00549 // } 00550 // } 00551 // else 00552 // { 00553 // while (outputSamples < outputSamplesEnd) 00554 // { 00555 // int tempBufferLength = this->tempBuffer.length(); 00556 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00557 // 00558 // if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00559 // getNextInputBuffer (info, channel, tempBufferSamples, tempBufferLength); 00560 // 00561 // double ratePosition = 0.0; 00562 // const double rateIncrement = double (rateBufferLength) / double (outputBufferLength); 00563 // 00564 // while ((outputSamples < outputSamplesEnd) && (tempBufferPos < tempBufferPosMax)) 00565 // { 00566 // *outputSamples++ = InterpType::lookup (tempBufferSamples, tempBufferPos); 00567 // const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateSamples[int (ratePosition)]); 00568 // tempBufferPos += tempBufferIncrement; 00569 // ratePosition += rateIncrement; 00570 // } 00571 // } 00572 // } 00573 // 00574 // info.setTimeStamp (infoTimeStamp); // reset for the parent graph 00575 // } 00576 // } 00577 // 00578 //private: 00579 // Buffer tempBuffer; 00580 // IndexType tempBufferPos; 00581 // IndexType tempBufferPosMax; 00582 // IndexType tempBufferUsableLength; 00583 // TimeStamp nextInputTimeStamp; 00584 //}; 00585 00586 //------------------------------------------------------------------------------ 00587 00601 template<class SampleType, Interp::TypeCode InterpTypeCode> 00602 class ResampleUnit 00603 { 00604 public: 00605 typedef ResampleChannelInternal<SampleType,InterpTypeCode> ResampleInternal; 00606 typedef typename ResampleInternal::Data Data; 00607 typedef ChannelBase<SampleType> ChannelType; 00608 typedef ChannelInternal<SampleType,Data> Internal; 00609 typedef UnitBase<SampleType> UnitType; 00610 typedef InputDictionary Inputs; 00611 00612 typedef typename ResampleInternal::RateType RateType; 00613 typedef typename ResampleInternal::RateUnitType RateUnitType; 00614 typedef typename ResampleInternal::RateBufferType RateBufferType; 00615 00616 static inline UnitInfos getInfo() throw() 00617 { 00618 const double blockSize = (double)BlockSize::getDefault().getValue(); 00619 const double sampleRate = SampleRate::getDefault().getValue(); 00620 00621 return UnitInfo ("Resample", "Resamples signals in terms of block size and/or sample rate.", 00622 00623 // output 00624 ChannelCount::VariableChannelCount, 00625 IOKey::Generic, Measure::None, IOInfo::NoDefault, IOLimit::None, IOKey::End, 00626 00627 // inputs 00628 IOKey::Generic, Measure::None, IOInfo::NoDefault, IOLimit::None, 00629 IOKey::Rate, Measure::Factor, 1.0, IOLimit::Minimum, Measure::Factor, 0.0, 00630 IOKey::BlockSize, Measure::Samples, blockSize, IOLimit::Minimum, Measure::Samples, 1.0, 00631 IOKey::SampleRate, Measure::Hertz, sampleRate, IOLimit::Minimum, Measure::Hertz, 0.0, 00632 IOKey::End); 00633 } 00634 00635 // /** Create an audio rate sample rate converter. */ 00636 // static UnitType ar (UnitType const& input, 00637 // RateUnitType const& rate = Math<RateUnitType>::get1(), 00638 // BlockSize const& preferredBlockSize = BlockSize::getDefault(), 00639 // SampleRate const& preferredSampleRate = SampleRate::getDefault()) throw() 00640 // { 00641 // plonk_assert (preferredSampleRate.getValue() > 0.0); // no need to resample a DC signal 00642 // 00643 // Inputs inputs; 00644 // inputs.put (IOKey::Generic, input); 00645 // inputs.put (IOKey::Rate, rate); 00646 // 00647 // Data data = { -1.0, -1.0 }; 00648 // 00649 // return UnitType::template createFromInputs<ResampleInternal> (inputs, 00650 // data, 00651 // preferredBlockSize, 00652 // preferredSampleRate); 00653 // } 00654 00656 static UnitType ar (UnitType const& input, 00657 RateUnitType const& rate = Math<RateUnitType>::get1(), 00658 BlockSize const& preferredBlockSize = BlockSize::getDefault(), 00659 SampleRate const& preferredSampleRate = SampleRate::getDefault()) throw() 00660 { 00661 plonk_assert (preferredSampleRate.getValue() > 0.0); // no need to resample a DC signal 00662 plonk_assert (rate.getNumChannels() == 1); 00663 00664 bool needsResample = false; 00665 00666 if (rate != Math<RateUnitType>::get1()) 00667 { 00668 needsResample = true; 00669 } 00670 else 00671 { 00672 for (int i = 0; i < input.getNumChannels(); ++i) 00673 { 00674 if (input.getSampleRate (i) != preferredSampleRate) 00675 { 00676 needsResample = true; 00677 break; 00678 } 00679 } 00680 } 00681 00682 if (!needsResample) 00683 return input; 00684 00685 00686 Inputs inputs; 00687 inputs.put (IOKey::Generic, input); 00688 inputs.put (IOKey::Rate, rate); 00689 00690 Data data = { -1.0, -1.0 }; 00691 00692 return UnitType::template proxiesFromInputs<ResampleInternal> (inputs, 00693 data, 00694 preferredBlockSize, 00695 preferredSampleRate); 00696 } 00697 00698 static inline UnitType kr (UnitType const& input, RateUnitType const& rate) throw() 00699 { 00700 return ar (input, 00701 rate, 00702 BlockSize::getControlRateBlockSize(), 00703 SampleRate::getControlRate()); 00704 } 00705 00706 static inline UnitType kr (UnitType const& input) throw() 00707 { 00708 return ar (input, 00709 Math<RateUnitType>::get1(), 00710 BlockSize::getControlRateBlockSize(), 00711 SampleRate::getControlRate()); 00712 } 00713 00714 }; 00715 00717 //template<class SampleType, Interp::TypeCode InterpTypeCode> 00718 //class ResampleChannelInternal 00719 //: public ProxyOwnerChannelInternal<SampleType, ChannelInternalCore::Data> 00720 //{ 00721 //public: 00722 // typedef ChannelInternalCore::Data Data; 00723 // typedef ChannelBase<SampleType> ChannelType; 00724 // typedef ObjectArray<ChannelType> ChannelArrayType; 00725 // typedef ResampleChannelInternal<SampleType,InterpTypeCode> ResampleInternal; 00726 // typedef ProxyOwnerChannelInternal<SampleType,Data> Internal; 00727 // typedef UnitBase<SampleType> UnitType; 00728 // typedef InputDictionary Inputs; 00729 // typedef NumericalArray<SampleType> Buffer; 00730 // typedef typename TypeUtility<SampleType>::IndexType IndexType; 00731 // 00732 // typedef typename TypeUtility<SampleType>::IndexType RateType; 00733 // typedef UnitBase<RateType> RateUnitType; 00734 // typedef NumericalArray<RateType> RateBufferType; 00735 // 00736 // typedef InterpSelect<SampleType,IndexType,InterpTypeCode> InterpSelect; 00737 // typedef typename InterpSelect::InterpType InterpType; 00738 // typedef typename InterpType::ExtensionBuffer ExtensionBuffer; 00739 // 00740 // struct InputBufferPositionData 00741 // { 00742 // IndexType tempBufferPos; 00743 // IndexType tempBufferPosMax; 00744 // IndexType tempBufferUsableLength; 00745 // TimeStamp nextInputTimeStamp; 00746 // }; 00747 // 00748 // struct InputBufferData 00749 // { 00750 // Buffer tempBuffer; 00751 // InputBufferPositionData position; 00752 // }; 00753 // 00754 // typedef ObjectArray<InputBufferData> InputBufferDataArray; 00755 // 00756 // ResampleChannelInternal (Inputs const& inputs, 00757 // Data const& data, 00758 // BlockSize const& blockSize, 00759 // SampleRate const& sampleRate, 00760 // ChannelArrayType& channels) throw() 00761 // : Internal (inputs.getMaxNumChannels(), inputs, data, blockSize, sampleRate, channels) 00762 // { 00763 // plonk_assert (sampleRate.getValue() > 0.0); // no need to resample a DC signal 00764 // 00765 // buffers.setSize (this->getNumChannels()); 00766 // 00767 // for (int i = 0; i < buffers.length(); ++i) 00768 // Memory::zero (buffers[i].position); 00769 // } 00770 // 00771 // Text getName() const throw() 00772 // { 00773 // return "Resample"; 00774 // } 00775 // 00776 // IntArray getInputKeys() const throw() 00777 // { 00778 // const IntArray keys (IOKey::Generic, IOKey::Rate); 00779 // return keys; 00780 // } 00781 // 00782 // void initChannel (const int channel) throw() 00783 // { 00784 // const UnitType& input = this->getInputAsUnit (IOKey::Generic); 00785 // 00786 //#ifdef PLONK_DEBUG 00787 // const RateUnitType& rateUnit = ChannelInternalCore::getInputAs<RateUnitType> (IOKey::Rate); 00788 // plonk_assert (input.getOverlap (channel) == Math<DoubleVariable>::get1()); 00789 // plonk_assert (rateUnit.getOverlap (channel) == Math<DoubleVariable>::get1()); 00790 //#endif 00791 // 00792 // const SampleType sourceValue = input.getValue (channel); 00793 // this->initProxyValue (channel, sourceValue); 00794 // 00795 // resizeTempBuffer (channel, input.getBlockSize (channel).getValue() + InterpType::getExtension()); 00796 // buffers[channel].tempBuffer.zero(); 00797 // 00798 // const int tempBufferPos (buffers[channel].position.tempBufferPosMax); 00799 // buffers[channel].position.tempBufferPos = IndexType (tempBufferPos); 00800 // buffers[channel].tempBuffer.put (tempBufferPos, sourceValue); 00801 // } 00802 // 00803 // inline void resizeTempBuffer (const int channel, const int inputBufferLength) throw() 00804 // { 00805 // if (inputBufferLength != tempBuffer.length()) 00806 // { 00807 // buffers[channel].tempBuffer.setSize (inputBufferLength, false); 00808 // 00809 // const IndexType tempBufferUsableLength = IndexType (inputBufferLength) - InterpType::getExtensionAsIndex(); 00810 // buffers[channel].position.tempBufferUsableLength = tempBufferUsableLength; 00811 // buffers[channel].position.tempBufferPosMax = tempBufferUsableLength + InterpType::getOffsetAsIndex(); 00812 // } 00813 // } 00814 // 00815 // inline void getNextInputBuffer (ProcessInfo& info, const int channel, SampleType* &tempBufferSamples, int& tempBufferLength) throw() 00816 // { 00817 // const int extension = InterpType::getExtension(); 00818 // 00819 // UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00820 // 00821 // info.setTimeStamp (buffers[channel].position.nextInputTimeStamp); 00822 // const Buffer& inputBuffer (inputUnit.process (info, channel)); 00823 // buffers[channel].position.nextInputTimeStamp = inputUnit.getNextTimeStamp (channel); 00824 // 00825 // const SampleType* const inputSamples = inputBuffer.getArray(); 00826 // const int inputBufferLength = inputBuffer.length(); 00827 // 00828 // ExtensionBuffer interpolationValues; 00829 // Buffer::copyData (interpolationValues.buffer, 00830 // tempBufferSamples + tempBufferLength - extension, 00831 // extension); 00832 // 00833 // tempBufferPos -= tempBufferUsableLength; // move this before resize 00834 // tempBufferLength = inputBufferLength + extension; // larger for interpolation 00835 // resizeTempBuffer (channel, tempBufferLength); 00836 // tempBufferSamples = buffers[channel].tempBuffer.getArray(); 00837 // 00838 // Buffer::copyData (tempBufferSamples, 00839 // interpolationValues.buffer, 00840 // extension); 00841 // 00842 // Buffer::copyData (tempBufferSamples + extension, 00843 // inputSamples, 00844 // inputBufferLength); 00845 // } 00846 // 00847 // void process (ProcessInfo& info, const int /*channel*/) throw() 00848 // { 00849 // const Data& data = this->getState(); 00850 // 00851 // UnitType& inputUnit (this->getInputAsUnit (IOKey::Generic)); 00852 // RateUnitType& rateUnit = ChannelInternalCore::getInputAs<RateUnitType> (IOKey::Rate); 00853 // 00854 // 00855 // const IndexType inputSampleRate = IndexType (inputUnit.getSampleRate (channel)); 00856 // 00857 // const int outputBufferLength = this->getOutputBuffer().length(); 00858 // SampleType* outputSamples = this->getOutputSamples(); 00859 // 00860 // if (inputSampleRate <= 0.0) 00861 // { 00862 // const SampleType inputValue = inputUnit.process (info, channel).atUnchecked (0); 00863 // NumericalArrayFiller<SampleType>::fill (outputSamples, inputValue, outputBufferLength); 00864 // } 00865 // else 00866 // { 00867 // const TimeStamp infoTimeStamp = info.getTimeStamp(); 00868 // SampleType* const outputSamplesEnd = outputSamples + outputBufferLength; 00869 // 00870 // const RateBufferType& rateBuffer (rateUnit.process (info, channel)); 00871 // const RateType* rateSamples = rateBuffer.getArray(); 00872 // const int rateBufferLength = rateBuffer.length(); 00873 // 00874 // if (rateBufferLength == 1) 00875 // { 00876 // const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateSamples[0]); 00877 // 00878 // if (tempBufferIncrement == Math<IndexType>::get0()) 00879 // { 00880 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00881 // const SampleType dcOutput = InterpType::lookup (tempBufferSamples, tempBufferPos); 00882 // NumericalArrayFiller<SampleType>::fill (outputSamples, dcOutput, outputBufferLength); 00883 // } 00884 // else 00885 // { 00886 // while (outputSamples < outputSamplesEnd) 00887 // { 00888 // int tempBufferLength = this->tempBuffer.length(); 00889 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00890 // 00891 // if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00892 // getNextInputBuffer (info, channel, tempBufferSamples, tempBufferLength); 00893 // 00894 // while ((outputSamples < outputSamplesEnd) && (tempBufferPos < tempBufferPosMax)) 00895 // { 00896 // *outputSamples++ = InterpType::lookup (tempBufferSamples, tempBufferPos); 00897 // tempBufferPos += tempBufferIncrement; 00898 // } 00899 // } 00900 // } 00901 // } 00902 // else if (rateBufferLength == outputBufferLength) 00903 // { 00904 // while (outputSamples < outputSamplesEnd) 00905 // { 00906 // int tempBufferLength = this->tempBuffer.length(); 00907 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00908 // 00909 // if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00910 // getNextInputBuffer (info, channel, tempBufferSamples, tempBufferLength); 00911 // 00912 // while ((outputSamples < outputSamplesEnd) && (tempBufferPos < tempBufferPosMax)) 00913 // { 00914 // *outputSamples++ = InterpType::lookup (tempBufferSamples, tempBufferPos); 00915 // const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * *rateSamples++); 00916 // tempBufferPos += tempBufferIncrement; 00917 // } 00918 // } 00919 // } 00920 // else 00921 // { 00922 // while (outputSamples < outputSamplesEnd) 00923 // { 00924 // int tempBufferLength = this->tempBuffer.length(); 00925 // SampleType* tempBufferSamples = this->tempBuffer.getArray(); 00926 // 00927 // if (tempBufferPos >= tempBufferPosMax) // ran out of buffer 00928 // getNextInputBuffer (info, channel, tempBufferSamples, tempBufferLength); 00929 // 00930 // double ratePosition = 0.0; 00931 // const double rateIncrement = double (rateBufferLength) / double (outputBufferLength); 00932 // 00933 // while ((outputSamples < outputSamplesEnd) && (tempBufferPos < tempBufferPosMax)) 00934 // { 00935 // *outputSamples++ = InterpType::lookup (tempBufferSamples, tempBufferPos); 00936 // const IndexType tempBufferIncrement (inputSampleRate * IndexType (data.sampleDuration) * rateSamples[int (ratePosition)]); 00937 // tempBufferPos += tempBufferIncrement; 00938 // ratePosition += rateIncrement; 00939 // } 00940 // } 00941 // } 00942 // 00943 // info.setTimeStamp (infoTimeStamp); // reset for the parent graph 00944 // } 00945 // } 00946 // 00947 //private: 00948 // InputBufferDataArray buffers; 00949 //}; 00950 // 00952 // 00954 // 00955 // @par Factory functions: 00956 // - ar (input, rate=1, preferredBlockSize=default, preferredSampleRate=default) 00957 // - kr (input, rate=1) 00958 // 00959 // @par Inputs: 00960 // - input: (unit, multi) the unit to resample 00961 // - rate: (unit, multi) a modulatable rate multiplier (e.g., for varispeed playback) 00962 // - preferredBlockSize: the preferred output block size 00963 // - preferredSampleRate: the preferred output sample rate 00964 // 00965 // @ingroup ConverterUnits */ 00966 //template<class SampleType, Interp::TypeCode InterpTypeCode> 00967 //class ResampleUnit 00968 //{ 00969 //public: 00970 // typedef ResampleChannelInternal<SampleType,InterpTypeCode> ResampleInternal; 00971 // typedef typename ResampleInternal::Data Data; 00972 // typedef ChannelBase<SampleType> ChannelType; 00973 // typedef ChannelInternal<SampleType,Data> Internal; 00974 // typedef UnitBase<SampleType> UnitType; 00975 // typedef InputDictionary Inputs; 00976 // 00977 // typedef typename ResampleInternal::RateType RateType; 00978 // typedef typename ResampleInternal::RateUnitType RateUnitType; 00979 // typedef typename ResampleInternal::RateBufferType RateBufferType; 00980 // 00981 // static inline UnitInfos getInfo() throw() 00982 // { 00983 // const double blockSize = (double)BlockSize::getDefault().getValue(); 00984 // const double sampleRate = SampleRate::getDefault().getValue(); 00985 // 00986 // return UnitInfo ("Resample", "Resamples signals in terms of block size and/or sample rate.", 00987 // 00988 // // output 00989 // ChannelCount::VariableChannelCount, 00990 // IOKey::Generic, Measure::None, IOInfo::NoDefault, IOLimit::None, IOKey::End, 00991 // 00992 // // inputs 00993 // IOKey::Generic, Measure::None, IOInfo::NoDefault, IOLimit::None, 00994 // IOKey::Rate, Measure::Factor, 1.0, IOLimit::Minimum, Measure::Factor, 0.0, 00995 // IOKey::BlockSize, Measure::Samples, blockSize, IOLimit::Minimum, Measure::Samples, 1.0, 00996 // IOKey::SampleRate, Measure::Hertz, sampleRate, IOLimit::Minimum, Measure::Hertz, 0.0, 00997 // IOKey::End); 00998 // } 00999 // 01000 // /** Create an audio rate sample rate converter. */ 01001 // static UnitType ar (UnitType const& input, 01002 // RateUnitType const& rate = Math<RateUnitType>::get1(), 01003 // BlockSize const& preferredBlockSize = BlockSize::getDefault(), 01004 // SampleRate const& preferredSampleRate = SampleRate::getDefault()) throw() 01005 // { 01006 // plonk_assert (preferredSampleRate.getValue() > 0.0); // no need to resample a DC signal 01007 // 01008 // Inputs inputs; 01009 // inputs.put (IOKey::Generic, input); 01010 // inputs.put (IOKey::Rate, rate); 01011 // 01012 // Data data = { -1.0, -1.0 }; 01013 // 01014 // return UnitType::template createFromInputs<ResampleInternal> (inputs, 01015 // data, 01016 // preferredBlockSize, 01017 // preferredSampleRate); 01018 // } 01019 // 01020 // static inline UnitType kr (UnitType const& input, 01021 // RateUnitType const& rate = Math<RateUnitType>::get1()) throw() 01022 // { 01023 // return ar (input, 01024 // rate, 01025 // BlockSize::getControlRateBlockSize(), 01026 // SampleRate::getControlRate()); 01027 // } 01028 // 01029 //}; 01030 01031 01032 typedef ResampleUnit<PLONK_TYPE_DEFAULT,Interp::Linear> ResampleLinear; 01033 typedef ResampleUnit<PLONK_TYPE_DEFAULT,Interp::Lagrange3> ResampleLagrange3; 01034 01035 01036 #endif // PLONK_RESAMPLECHANNEL_H 01037 01038