pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_ResampleChannel.h
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 
 All Classes Functions Typedefs Enumerations Enumerator Properties