tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RateTransposer.cpp (8416B)


      1 ////////////////////////////////////////////////////////////////////////////////
      2 /// 
      3 /// Sample rate transposer. Changes sample rate by using linear interpolation 
      4 /// together with anti-alias filtering (first order interpolation with anti-
      5 /// alias filtering should be quite adequate for this application)
      6 ///
      7 /// Author        : Copyright (c) Olli Parviainen
      8 /// Author e-mail : oparviai 'at' iki.fi
      9 /// SoundTouch WWW: http://www.surina.net/soundtouch
     10 ///
     11 ////////////////////////////////////////////////////////////////////////////////
     12 //
     13 // License :
     14 //
     15 //  SoundTouch audio processing library
     16 //  Copyright (c) Olli Parviainen
     17 //
     18 //  This library is free software; you can redistribute it and/or
     19 //  modify it under the terms of the GNU Lesser General Public
     20 //  License as published by the Free Software Foundation; either
     21 //  version 2.1 of the License, or (at your option) any later version.
     22 //
     23 //  This library is distributed in the hope that it will be useful,
     24 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
     25 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     26 //  Lesser General Public License for more details.
     27 //
     28 //  You should have received a copy of the GNU Lesser General Public
     29 //  License along with this library; if not, write to the Free Software
     30 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     31 //
     32 ////////////////////////////////////////////////////////////////////////////////
     33 
     34 #include <memory.h>
     35 #include <assert.h>
     36 #include <stdlib.h>
     37 #include <stdio.h>
     38 #include "RateTransposer.h"
     39 #include "InterpolateLinear.h"
     40 #include "InterpolateCubic.h"
     41 #include "InterpolateShannon.h"
     42 #include "AAFilter.h"
     43 
     44 using namespace soundtouch;
     45 
     46 // Define default interpolation algorithm here
     47 TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
     48 
     49 
     50 // Constructor
     51 RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
     52 {
     53    bUseAAFilter = 
     54 #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
     55        true;
     56 #else
     57        // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
     58        false;
     59 #endif
     60 
     61    // Instantiates the anti-alias filter
     62    pAAFilter = new AAFilter(64);
     63    pTransposer = TransposerBase::newInstance();
     64    clear();
     65 }
     66 
     67 
     68 RateTransposer::~RateTransposer()
     69 {
     70    delete pAAFilter;
     71    delete pTransposer;
     72 }
     73 
     74 
     75 /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
     76 void RateTransposer::enableAAFilter(bool newMode)
     77 {
     78 #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
     79    // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
     80    bUseAAFilter = newMode;
     81    clear();
     82 #endif
     83 }
     84 
     85 
     86 /// Returns nonzero if anti-alias filter is enabled.
     87 bool RateTransposer::isAAFilterEnabled() const
     88 {
     89    return bUseAAFilter;
     90 }
     91 
     92 
     93 AAFilter *RateTransposer::getAAFilter()
     94 {
     95    return pAAFilter;
     96 }
     97 
     98 
     99 // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower 
    100 // iRate, larger faster iRates.
    101 void RateTransposer::setRate(double newRate)
    102 {
    103    double fCutoff;
    104 
    105    pTransposer->setRate(newRate);
    106 
    107    // design a new anti-alias filter
    108    if (newRate > 1.0) 
    109    {
    110        fCutoff = 0.5 / newRate;
    111    } 
    112    else 
    113    {
    114        fCutoff = 0.5 * newRate;
    115    }
    116    pAAFilter->setCutoffFreq(fCutoff);
    117 }
    118 
    119 
    120 // Adds 'nSamples' pcs of samples from the 'samples' memory position into
    121 // the input of the object.
    122 void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
    123 {
    124    processSamples(samples, nSamples);
    125 }
    126 
    127 
    128 // Transposes sample rate by applying anti-alias filter to prevent folding. 
    129 // Returns amount of samples returned in the "dest" buffer.
    130 // The maximum amount of samples that can be returned at a time is set by
    131 // the 'set_returnBuffer_size' function.
    132 void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
    133 {
    134    uint count;
    135 
    136    if (nSamples == 0) return;
    137 
    138    // Store samples to input buffer
    139    inputBuffer.putSamples(src, nSamples);
    140 
    141    // If anti-alias filter is turned off, simply transpose without applying
    142    // the filter
    143    if (bUseAAFilter == false) 
    144    {
    145        count = pTransposer->transpose(outputBuffer, inputBuffer);
    146        return;
    147    }
    148 
    149    assert(pAAFilter);
    150 
    151    // Transpose with anti-alias filter
    152    if (pTransposer->rate < 1.0f) 
    153    {
    154        // If the parameter 'Rate' value is smaller than 1, first transpose
    155        // the samples and then apply the anti-alias filter to remove aliasing.
    156 
    157        // Transpose the samples, store the result to end of "midBuffer"
    158        pTransposer->transpose(midBuffer, inputBuffer);
    159 
    160        // Apply the anti-alias filter for transposed samples in midBuffer
    161        pAAFilter->evaluate(outputBuffer, midBuffer);
    162    } 
    163    else  
    164    {
    165        // If the parameter 'Rate' value is larger than 1, first apply the
    166        // anti-alias filter to remove high frequencies (prevent them from folding
    167        // over the lover frequencies), then transpose.
    168 
    169        // Apply the anti-alias filter for samples in inputBuffer
    170        pAAFilter->evaluate(midBuffer, inputBuffer);
    171 
    172        // Transpose the AA-filtered samples in "midBuffer"
    173        pTransposer->transpose(outputBuffer, midBuffer);
    174    }
    175 }
    176 
    177 
    178 // Sets the number of channels, 1 = mono, 2 = stereo
    179 void RateTransposer::setChannels(int nChannels)
    180 {
    181    if (!verifyNumberOfChannels(nChannels) ||
    182        (pTransposer->numChannels == nChannels)) return;
    183 
    184    pTransposer->setChannels(nChannels);
    185    inputBuffer.setChannels(nChannels);
    186    midBuffer.setChannels(nChannels);
    187    outputBuffer.setChannels(nChannels);
    188 }
    189 
    190 
    191 // Clears all the samples in the object
    192 void RateTransposer::clear()
    193 {
    194    outputBuffer.clear();
    195    midBuffer.clear();
    196    inputBuffer.clear();
    197    pTransposer->resetRegisters();
    198 
    199    // prefill buffer to avoid losing first samples at beginning of stream
    200    int prefill = getLatency();
    201    inputBuffer.addSilent(prefill);
    202 }
    203 
    204 
    205 // Returns nonzero if there aren't any samples available for outputting.
    206 int RateTransposer::isEmpty() const
    207 {
    208    int res;
    209 
    210    res = FIFOProcessor::isEmpty();
    211    if (res == 0) return 0;
    212    return inputBuffer.isEmpty();
    213 }
    214 
    215 
    216 /// Return approximate initial input-output latency
    217 int RateTransposer::getLatency() const
    218 {
    219    return pTransposer->getLatency() +
    220        ((bUseAAFilter) ? (pAAFilter->getLength() / 2) : 0);
    221 }
    222 
    223 
    224 //////////////////////////////////////////////////////////////////////////////
    225 //
    226 // TransposerBase - Base class for interpolation
    227 // 
    228 
    229 // static function to set interpolation algorithm
    230 void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
    231 {
    232    TransposerBase::algorithm = a;
    233 }
    234 
    235 
    236 // Transposes the sample rate of the given samples using linear interpolation. 
    237 // Returns the number of samples returned in the "dest" buffer
    238 int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
    239 {
    240    int numSrcSamples = src.numSamples();
    241    int sizeDemand = (int)((double)numSrcSamples / rate) + 8;
    242    int numOutput;
    243    SAMPLETYPE *psrc = src.ptrBegin();
    244    SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
    245 
    246 #ifndef USE_MULTICH_ALWAYS
    247    if (numChannels == 1)
    248    {
    249        numOutput = transposeMono(pdest, psrc, numSrcSamples);
    250    }
    251    else if (numChannels == 2) 
    252    {
    253        numOutput = transposeStereo(pdest, psrc, numSrcSamples);
    254    } 
    255    else 
    256 #endif // USE_MULTICH_ALWAYS
    257    {
    258        assert(numChannels > 0);
    259        numOutput = transposeMulti(pdest, psrc, numSrcSamples);
    260    }
    261    dest.putSamples(numOutput);
    262    src.receiveSamples(numSrcSamples);
    263    return numOutput;
    264 }
    265 
    266 
    267 TransposerBase::TransposerBase()
    268 {
    269    numChannels = 0;
    270    rate = 1.0f;
    271 }
    272 
    273 
    274 TransposerBase::~TransposerBase()
    275 {
    276 }
    277 
    278 
    279 void TransposerBase::setChannels(int channels)
    280 {
    281    numChannels = channels;
    282    resetRegisters();
    283 }
    284 
    285 
    286 void TransposerBase::setRate(double newRate)
    287 {
    288    rate = newRate;
    289 }
    290 
    291 
    292 // static factory function
    293 TransposerBase *TransposerBase::newInstance()
    294 {
    295 #ifdef SOUNDTOUCH_INTEGER_SAMPLES
    296    // Notice: For integer arithmetic support only linear algorithm (due to simplest calculus)
    297    return ::new InterpolateLinearInteger;
    298 #else
    299    switch (algorithm)
    300    {
    301        case LINEAR:
    302            return new InterpolateLinearFloat;
    303 
    304        case CUBIC:
    305            return new InterpolateCubic;
    306 
    307        case SHANNON:
    308            return new InterpolateShannon;
    309 
    310        default:
    311            assert(false);
    312            return NULL;
    313    }
    314 #endif
    315 }