MythTV  0.26-pre
RateTransposer.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 //
00013 // Last changed  : $Date$
00014 // File revision : $Revision$
00015 //
00016 // $Id$
00017 //
00019 //
00020 // License :
00021 //
00022 //  SoundTouch audio processing library
00023 //  Copyright (c) Olli Parviainen
00024 //
00025 //  This library is free software; you can redistribute it and/or
00026 //  modify it under the terms of the GNU Lesser General Public
00027 //  License as published by the Free Software Foundation; either
00028 //  version 2.1 of the License, or (at your option) any later version.
00029 //
00030 //  This library is distributed in the hope that it will be useful,
00031 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00032 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033 //  Lesser General Public License for more details.
00034 //
00035 //  You should have received a copy of the GNU Lesser General Public
00036 //  License along with this library; if not, write to the Free Software
00037 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00038 //
00040 
00041 #include <memory.h>
00042 #include <assert.h>
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <limits.h>
00046 #include "RateTransposer.h"
00047 #include "AAFilter.h"
00048 
00049 using namespace soundtouch;
00050 
00051 
00054 class RateTransposerInteger : public RateTransposer
00055 {
00056 protected:
00057     int iSlopeCount;
00058     uint uRate;
00059     SAMPLETYPE sPrevSampleL, sPrevSampleR;
00060 
00061     virtual void resetRegisters();
00062 
00063     virtual uint transposeStereo(SAMPLETYPE *dest, 
00064                          const SAMPLETYPE *src, 
00065                          uint numSamples);
00066     virtual uint transposeMono(SAMPLETYPE *dest, 
00067                        const SAMPLETYPE *src, 
00068                        uint numSamples);
00069 
00070 public:
00071     RateTransposerInteger();
00072     virtual ~RateTransposerInteger();
00073 
00076     virtual void setRate(float newRate);
00077 
00078 };
00079 
00080 
00083 class RateTransposerFloat : public RateTransposer
00084 {
00085 protected:
00086     float fSlopeCount;
00087     float fRateStep;
00088     SAMPLETYPE sPrevSampleL, sPrevSampleR;
00089 
00090     virtual void resetRegisters();
00091 
00092     virtual uint transposeStereo(SAMPLETYPE *dest, 
00093                          const SAMPLETYPE *src, 
00094                          uint numSamples);
00095     virtual uint transposeMono(SAMPLETYPE *dest, 
00096                        const SAMPLETYPE *src, 
00097                        uint numSamples);
00098 
00099 public:
00100     RateTransposerFloat();
00101     virtual ~RateTransposerFloat();
00102 };
00103 
00104 
00105 
00106 #ifndef min
00107 #define min(a,b) ((a > b) ? b : a)
00108 #define max(a,b) ((a < b) ? b : a)
00109 #endif
00110 
00111 
00112 // Operator 'new' is overloaded so that it automatically creates a suitable instance 
00113 // depending on if we've a MMX/SSE/etc-capable CPU available or not.
00114 void * RateTransposer::operator new(size_t s)
00115 {
00116     // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
00117     assert(FALSE);  
00118     return NULL;
00119 }
00120 
00121 
00122 RateTransposer *RateTransposer::newInstance()
00123 {
00124 #ifdef INTEGER_SAMPLES
00125     return ::new RateTransposerInteger;
00126 #else
00127     return ::new RateTransposerFloat;
00128 #endif
00129 }
00130 
00131 
00132 // Constructor
00133 RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
00134 {
00135     fRate = 1.0f;
00136     uChannels = 2;
00137     bUseAAFilter = TRUE;
00138 
00139     // Instantiates the anti-alias filter with default tap length
00140     // of 32
00141     pAAFilter = new AAFilter(32);
00142 }
00143 
00144 
00145 
00146 RateTransposer::~RateTransposer()
00147 {
00148     delete pAAFilter;
00149 }
00150 
00151 
00152 
00154 void RateTransposer::enableAAFilter(const BOOL newMode)
00155 {
00156     bUseAAFilter = newMode;
00157 }
00158 
00159 
00161 BOOL RateTransposer::isAAFilterEnabled() const
00162 {
00163     return bUseAAFilter;
00164 }
00165 
00166 
00167 AAFilter *RateTransposer::getAAFilter() const
00168 {
00169     return pAAFilter;
00170 }
00171 
00172 
00173 
00174 // Sets new target uRate. Normal uRate = 1.0, smaller values represent slower 
00175 // uRate, larger faster uRates.
00176 void RateTransposer::setRate(float newRate)
00177 {
00178     float fCutoff;
00179 
00180     fRate = newRate;
00181 
00182     // design a new anti-alias filter
00183     if (newRate > 1.0f) 
00184     {
00185         fCutoff = 0.5f / newRate;
00186     } 
00187     else 
00188     {
00189         fCutoff = 0.5f * newRate;
00190     }
00191     pAAFilter->setCutoffFreq(fCutoff);
00192 }
00193 
00194 
00195 // Outputs as many samples of the 'outputBuffer' as possible, and if there's
00196 // any room left, outputs also as many of the incoming samples as possible.
00197 // The goal is to drive the outputBuffer empty.
00198 //
00199 // It's allowed for 'output' and 'input' parameters to point to the same
00200 // memory position.
00201 void RateTransposer::flushStoreBuffer()
00202 {
00203     if (storeBuffer.isEmpty()) return;
00204 
00205     outputBuffer.moveSamples(storeBuffer);
00206 }
00207 
00208 
00209 // Adds 'numSamples' pcs of samples from the 'samples' memory position into
00210 // the input of the object.
00211 void RateTransposer::putSamples(const SAMPLETYPE *samples, uint numSamples)
00212 {
00213     processSamples(samples, numSamples);
00214 }
00215 
00216 
00217 
00218 // Transposes up the sample rate, causing the observed playback 'rate' of the
00219 // sound to decrease
00220 void RateTransposer::upsample(const SAMPLETYPE *src, uint numSamples)
00221 {
00222     int count, sizeTemp, num;
00223 
00224     // If the parameter 'uRate' value is smaller than 'SCALE', first transpose
00225     // the samples and then apply the anti-alias filter to remove aliasing.
00226 
00227     // First check that there's enough room in 'storeBuffer' 
00228     // (+16 is to reserve some slack in the destination buffer)
00229     sizeTemp = (int)((float)numSamples / fRate + 16.0f);
00230 
00231     // Transpose the samples, store the result into the end of "storeBuffer"
00232     count = transpose(storeBuffer.ptrEnd(sizeTemp), src, numSamples);
00233     storeBuffer.putSamples(count);
00234 
00235     // Apply the anti-alias filter to samples in "store output", output the
00236     // result to "dest"
00237     num = storeBuffer.numSamples();
00238     count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), 
00239         storeBuffer.ptrBegin(), num, uChannels);
00240     outputBuffer.putSamples(count);
00241 
00242     // Remove the processed samples from "storeBuffer"
00243     storeBuffer.receiveSamples(count);
00244 }
00245 
00246 
00247 // Transposes down the sample rate, causing the observed playback 'rate' of the
00248 // sound to increase
00249 void RateTransposer::downsample(const SAMPLETYPE *src, uint numSamples)
00250 {
00251     int count, sizeTemp;
00252 
00253     // If the parameter 'uRate' value is larger than 'SCALE', first apply the
00254     // anti-alias filter to remove high frequencies (prevent them from folding
00255     // over the lover frequencies), then transpose. */
00256 
00257     // Add the new samples to the end of the storeBuffer */
00258     storeBuffer.putSamples(src, numSamples);
00259 
00260     // Anti-alias filter the samples to prevent folding and output the filtered 
00261     // data to tempBuffer. Note : because of the FIR filter length, the
00262     // filtering routine takes in 'filter_length' more samples than it outputs.
00263     assert(tempBuffer.isEmpty());
00264     sizeTemp = storeBuffer.numSamples();
00265 
00266     count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), 
00267         storeBuffer.ptrBegin(), sizeTemp, uChannels);
00268 
00269     // Remove the filtered samples from 'storeBuffer'
00270     storeBuffer.receiveSamples(count);
00271 
00272     // Transpose the samples (+16 is to reserve some slack in the destination buffer)
00273     sizeTemp = (int)((float)numSamples / fRate + 16.0f);
00274     count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
00275     outputBuffer.putSamples(count);
00276 }
00277 
00278 
00279 // Transposes sample rate by applying anti-alias filter to prevent folding. 
00280 // Returns amount of samples returned in the "dest" buffer.
00281 // The maximum amount of samples that can be returned at a time is set by
00282 // the 'set_returnBuffer_size' function.
00283 void RateTransposer::processSamples(const SAMPLETYPE *src, uint numSamples)
00284 {
00285     uint count;
00286     uint sizeReq;
00287 
00288     if (numSamples == 0) return;
00289     assert(pAAFilter);
00290 
00291     // If anti-alias filter is turned off, simply transpose without applying
00292     // the filter
00293     if (bUseAAFilter == FALSE) 
00294     {
00295         sizeReq = (int)((float)numSamples / fRate + 1.0f);
00296         count = transpose(outputBuffer.ptrEnd(sizeReq), src, numSamples);
00297         outputBuffer.putSamples(count);
00298         return;
00299     }
00300 
00301     // Transpose with anti-alias filter
00302     if (fRate < 1.0f) 
00303     {
00304         upsample(src, numSamples);
00305     } 
00306     else  
00307     {
00308         downsample(src, numSamples);
00309     }
00310 }
00311 
00312 
00313 // Transposes the sample rate of the given samples using linear interpolation. 
00314 // Returns the number of samples returned in the "dest" buffer
00315 inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
00316 {
00317     if (uChannels == 2) 
00318     {
00319         return transposeStereo(dest, src, numSamples);
00320     } 
00321     else 
00322     {
00323         return transposeMono(dest, src, numSamples);
00324     }
00325 }
00326 
00327 
00328 // Sets the number of channels, 1 = mono, 2 = stereo
00329 void RateTransposer::setChannels(const uint numchannels)
00330 {
00331     if (uChannels == numchannels) return;
00332 
00333 #ifdef MULTICHANNEL
00334     assert(numchannels >= 1 && numchannels <= MULTICHANNEL);
00335 #else
00336     assert(numchannels == 1 || numchannels == 2);
00337 #endif
00338     uChannels = numchannels;
00339 
00340     storeBuffer.setChannels(uChannels);
00341     tempBuffer.setChannels(uChannels);
00342     outputBuffer.setChannels(uChannels);
00343 
00344     // Inits the linear interpolation registers
00345     resetRegisters();
00346 }
00347 
00348 
00349 // Clears all the samples in the object
00350 void RateTransposer::clear()
00351 {
00352     outputBuffer.clear();
00353     storeBuffer.clear();
00354 }
00355 
00356 
00357 // Returns nonzero if there aren't any samples available for outputting.
00358 int RateTransposer::isEmpty() const
00359 {
00360     int res;
00361 
00362     res = FIFOProcessor::isEmpty();
00363     if (res == 0) return 0;
00364     return storeBuffer.isEmpty();
00365 }
00366 
00367 
00369 //
00370 // RateTransposerInteger - integer arithmetic implementation
00371 // 
00372 
00374 #define SCALE    65536
00375 
00376 // Constructor
00377 RateTransposerInteger::RateTransposerInteger() : RateTransposer()
00378 {
00379     // call these here as these are virtual functions; calling these
00380     // from the base class constructor wouldn't execute the overloaded
00381     // versions (<master yoda>peculiar C++ can be</my>).
00382     resetRegisters();
00383     setRate(1.0f);
00384 }
00385 
00386 
00387 RateTransposerInteger::~RateTransposerInteger()
00388 {
00389 }
00390 
00391 
00392 void RateTransposerInteger::resetRegisters()
00393 {
00394     iSlopeCount = 0;
00395     sPrevSampleL = 
00396     sPrevSampleR = 0;
00397 }
00398 
00399 
00400 
00401 // Transposes the sample rate of the given samples using linear interpolation. 
00402 // 'Mono' version of the routine. Returns the number of samples returned in 
00403 // the "dest" buffer
00404 uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
00405 {
00406     unsigned int i, used;
00407     LONG_SAMPLETYPE temp, vol1;
00408 
00409     used = 0;    
00410     i = 0;
00411 
00412     // Process the last sample saved from the previous call first...
00413     while (iSlopeCount <= SCALE) 
00414     {
00415         vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
00416         temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
00417         dest[i] = (SAMPLETYPE)(temp / SCALE);
00418         i++;
00419         iSlopeCount += uRate;
00420     }
00421     // now always (iSlopeCount > SCALE)
00422     iSlopeCount -= SCALE;
00423 
00424     while (1)
00425     {
00426         while (iSlopeCount > SCALE) 
00427         {
00428             iSlopeCount -= SCALE;
00429             used ++;
00430             if (used >= numSamples - 1) goto end;
00431         }
00432         vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
00433         temp = src[used] * vol1 + iSlopeCount * src[used + 1];
00434         dest[i] = (SAMPLETYPE)(temp / SCALE);
00435 
00436         i++;
00437         iSlopeCount += uRate;
00438     }
00439 end:
00440     // Store the last sample for the next round
00441     sPrevSampleL = src[numSamples - 1];
00442 
00443     return i;
00444 }
00445 
00446 
00447 // Transposes the sample rate of the given samples using linear interpolation. 
00448 // 'Stereo' version of the routine. Returns the number of samples returned in 
00449 // the "dest" buffer
00450 uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
00451 {
00452     unsigned int srcPos, i, used;
00453     LONG_SAMPLETYPE temp, vol1;
00454 
00455     if (numSamples == 0) return 0;  // no samples, no work
00456 
00457     used = 0;    
00458     i = 0;
00459 
00460     // Process the last sample saved from the sPrevSampleLious call first...
00461     while (iSlopeCount <= SCALE) 
00462     {
00463         vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
00464         temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
00465         dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
00466         temp = vol1 * sPrevSampleR + iSlopeCount * src[1];
00467         dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
00468         i++;
00469         iSlopeCount += uRate;
00470     }
00471     // now always (iSlopeCount > SCALE)
00472     iSlopeCount -= SCALE;
00473 
00474     while (1)
00475     {
00476         while (iSlopeCount > SCALE) 
00477         {
00478             iSlopeCount -= SCALE;
00479             used ++;
00480             if (used >= numSamples - 1) goto end;
00481         }
00482         srcPos = 2 * used;
00483         vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
00484         temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2];
00485         dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
00486         temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3];
00487         dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
00488 
00489         i++;
00490         iSlopeCount += uRate;
00491     }
00492 end:
00493     // Store the last sample for the next round
00494     sPrevSampleL = src[2 * numSamples - 2];
00495     sPrevSampleR = src[2 * numSamples - 1];
00496 
00497     return i;
00498 }
00499 
00500 
00501 // Sets new target uRate. Normal uRate = 1.0, smaller values represent slower 
00502 // uRate, larger faster uRates.
00503 void RateTransposerInteger::setRate(float newRate)
00504 {
00505     uRate = (int)(newRate * SCALE + 0.5f);
00506     RateTransposer::setRate(newRate);
00507 }
00508 
00509 
00511 //
00512 // RateTransposerFloat - floating point arithmetic implementation
00513 // 
00515 
00516 // Constructor
00517 RateTransposerFloat::RateTransposerFloat() : RateTransposer()
00518 {
00519     // call these here as these are virtual functions; calling these
00520     // from the base class constructor wouldn't execute the overloaded
00521     // versions (<master yoda>peculiar C++ can be</my>).
00522     resetRegisters();
00523     setRate(1.0f);
00524 }
00525 
00526 
00527 RateTransposerFloat::~RateTransposerFloat()
00528 {
00529 }
00530 
00531 
00532 void RateTransposerFloat::resetRegisters()
00533 {
00534     fSlopeCount = 0;
00535     sPrevSampleL = 
00536     sPrevSampleR = 0;
00537 }
00538 
00539 
00540 
00541 // Transposes the sample rate of the given samples using linear interpolation. 
00542 // 'Mono' version of the routine. Returns the number of samples returned in 
00543 // the "dest" buffer
00544 uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
00545 {
00546     unsigned int i, used;
00547 
00548     used = 0;    
00549     i = 0;
00550 
00551     // Process the last sample saved from the previous call first...
00552     while (fSlopeCount <= 1.0f) 
00553     {
00554         dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
00555         i++;
00556         fSlopeCount += fRate;
00557     }
00558     fSlopeCount -= 1.0f;
00559 
00560     if (numSamples == 1) goto end;
00561 
00562     while (1)
00563     {
00564         while (fSlopeCount > 1.0f) 
00565         {
00566             fSlopeCount -= 1.0f;
00567             used ++;
00568             if (used >= numSamples - 1) goto end;
00569         }
00570         dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]);
00571         i++;
00572         fSlopeCount += fRate;
00573     }
00574 end:
00575     // Store the last sample for the next round
00576     sPrevSampleL = src[numSamples - 1];
00577 
00578     return i;
00579 }
00580 
00581 
00582 // Transposes the sample rate of the given samples using linear interpolation. 
00583 // 'Mono' version of the routine. Returns the number of samples returned in 
00584 // the "dest" buffer
00585 uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
00586 {
00587     unsigned int srcPos, i, used;
00588 
00589     if (numSamples == 0) return 0;  // no samples, no work
00590 
00591     used = 0;    
00592     i = 0;
00593 
00594     // Process the last sample saved from the sPrevSampleLious call first...
00595     while (fSlopeCount <= 1.0f) 
00596     {
00597         dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
00598         dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]);
00599         i++;
00600         fSlopeCount += fRate;
00601     }
00602     // now always (iSlopeCount > 1.0f)
00603     fSlopeCount -= 1.0f;
00604 
00605     if (numSamples == 1) goto end;
00606 
00607     while (1)
00608     {
00609         while (fSlopeCount > 1.0f) 
00610         {
00611             fSlopeCount -= 1.0f;
00612             used ++;
00613             if (used >= numSamples - 1) goto end;
00614         }
00615         srcPos = 2 * used;
00616 
00617         dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos] 
00618             + fSlopeCount * src[srcPos + 2]);
00619         dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1] 
00620             + fSlopeCount * src[srcPos + 3]);
00621 
00622         i++;
00623         fSlopeCount += fRate;
00624     }
00625 end:
00626     // Store the last sample for the next round
00627     sPrevSampleL = src[2 * numSamples - 2];
00628     sPrevSampleR = src[2 * numSamples - 1];
00629 
00630     return i;
00631 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends