PageRenderTime 63ms CodeModel.GetById 11ms app.highlight 44ms RepoModel.GetById 1ms app.codeStats 1ms

/external/pysoundtouch14/libsoundtouch/RateTransposer.cpp

http://echo-nest-remix.googlecode.com/
C++ | 624 lines | 350 code | 127 blank | 147 comment | 42 complexity | f8e5f8acbeb7398469a036ec4b323baa MD5 | raw file
  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// Last changed  : $Date: 2009-01-11 13:34:24 +0200 (Sun, 11 Jan 2009) $
 14// File revision : $Revision: 4 $
 15//
 16// $Id: RateTransposer.cpp 45 2009-01-11 11:34:24Z oparviai $
 17//
 18////////////////////////////////////////////////////////////////////////////////
 19//
 20// License :
 21//
 22//  SoundTouch audio processing library
 23//  Copyright (c) Olli Parviainen
 24//
 25//  This library is free software; you can redistribute it and/or
 26//  modify it under the terms of the GNU Lesser General Public
 27//  License as published by the Free Software Foundation; either
 28//  version 2.1 of the License, or (at your option) any later version.
 29//
 30//  This library is distributed in the hope that it will be useful,
 31//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 32//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 33//  Lesser General Public License for more details.
 34//
 35//  You should have received a copy of the GNU Lesser General Public
 36//  License along with this library; if not, write to the Free Software
 37//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 38//
 39////////////////////////////////////////////////////////////////////////////////
 40
 41#include <memory.h>

 42#include <assert.h>

 43#include <stdlib.h>

 44#include <stdio.h>

 45#include <stdexcept>

 46#include "RateTransposer.h"

 47#include "AAFilter.h"

 48
 49using namespace std;
 50using namespace soundtouch;
 51
 52
 53/// A linear samplerate transposer class that uses integer arithmetics.
 54/// for the transposing.
 55class RateTransposerInteger : public RateTransposer
 56{
 57protected:
 58    int iSlopeCount;
 59    int iRate;
 60    SAMPLETYPE sPrevSampleL, sPrevSampleR;
 61
 62    virtual void resetRegisters();
 63
 64    virtual uint transposeStereo(SAMPLETYPE *dest, 
 65                         const SAMPLETYPE *src, 
 66                         uint numSamples);
 67    virtual uint transposeMono(SAMPLETYPE *dest, 
 68                       const SAMPLETYPE *src, 
 69                       uint numSamples);
 70
 71public:
 72    RateTransposerInteger();
 73    virtual ~RateTransposerInteger();
 74
 75    /// Sets new target rate. Normal rate = 1.0, smaller values represent slower 
 76    /// rate, larger faster rates.
 77    virtual void setRate(float newRate);
 78
 79};
 80
 81
 82/// A linear samplerate transposer class that uses floating point arithmetics
 83/// for the transposing.
 84class RateTransposerFloat : public RateTransposer
 85{
 86protected:
 87    float fSlopeCount;
 88    SAMPLETYPE sPrevSampleL, sPrevSampleR;
 89
 90    virtual void resetRegisters();
 91
 92    virtual uint transposeStereo(SAMPLETYPE *dest, 
 93                         const SAMPLETYPE *src, 
 94                         uint numSamples);
 95    virtual uint transposeMono(SAMPLETYPE *dest, 
 96                       const SAMPLETYPE *src, 
 97                       uint numSamples);
 98
 99public:
100    RateTransposerFloat();
101    virtual ~RateTransposerFloat();
102};
103
104
105
106
107// Operator 'new' is overloaded so that it automatically creates a suitable instance 
108// depending on if we've a MMX/SSE/etc-capable CPU available or not.
109void * RateTransposer::operator new(size_t s)
110{
111    throw runtime_error("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
112    return NULL;
113}
114
115
116RateTransposer *RateTransposer::newInstance()
117{
118#ifdef INTEGER_SAMPLES

119    return ::new RateTransposerInteger;
120#else

121    return ::new RateTransposerFloat;
122#endif

123}
124
125
126// Constructor
127RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
128{
129    numChannels = 2;
130    bUseAAFilter = TRUE;
131    fRate = 0;
132
133    // Instantiates the anti-alias filter with default tap length
134    // of 32
135    pAAFilter = new AAFilter(32);
136}
137
138
139
140RateTransposer::~RateTransposer()
141{
142    delete pAAFilter;
143}
144
145
146
147/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
148void RateTransposer::enableAAFilter(BOOL newMode)
149{
150    bUseAAFilter = newMode;
151}
152
153
154/// Returns nonzero if anti-alias filter is enabled.
155BOOL RateTransposer::isAAFilterEnabled() const
156{
157    return bUseAAFilter;
158}
159
160
161AAFilter *RateTransposer::getAAFilter() const
162{
163    return pAAFilter;
164}
165
166
167
168// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower 
169// iRate, larger faster iRates.
170void RateTransposer::setRate(float newRate)
171{
172    double fCutoff;
173    fRate = newRate;
174
175    // design a new anti-alias filter
176    if (newRate > 1.0f) 
177    {
178        fCutoff = 0.5f / newRate;
179    } 
180    else 
181    {
182        fCutoff = 0.5f * newRate;
183    }
184    pAAFilter->setCutoffFreq(fCutoff);
185}
186
187
188// Outputs as many samples of the 'outputBuffer' as possible, and if there's
189// any room left, outputs also as many of the incoming samples as possible.
190// The goal is to drive the outputBuffer empty.
191//
192// It's allowed for 'output' and 'input' parameters to point to the same
193// memory position.
194/*
195void RateTransposer::flushStoreBuffer()
196{
197    if (storeBuffer.isEmpty()) return;
198
199    outputBuffer.moveSamples(storeBuffer);
200}
201*/
202
203
204// Adds 'nSamples' pcs of samples from the 'samples' memory position into
205// the input of the object.
206void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
207{
208    processSamples(samples, nSamples);
209}
210
211
212
213// Transposes up the sample rate, causing the observed playback 'rate' of the
214// sound to decrease
215void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples)
216{
217    uint count, sizeTemp, num;
218
219    // If the parameter 'uRate' value is smaller than 'SCALE', first transpose
220    // the samples and then apply the anti-alias filter to remove aliasing.
221
222    // First check that there's enough room in 'storeBuffer' 
223    // (+16 is to reserve some slack in the destination buffer)
224
225    sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
226    // Transpose the samples, store the result into the end of "storeBuffer"
227    count = transpose(storeBuffer.ptrEnd(sizeTemp), src, nSamples);
228    storeBuffer.putSamples(count);
229
230    // Apply the anti-alias filter to samples in "store output", output the
231    // result to "dest"
232    num = storeBuffer.numSamples();
233    count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), 
234        storeBuffer.ptrBegin(), num, (uint)numChannels);
235    outputBuffer.putSamples(count);
236
237    // Remove the processed samples from "storeBuffer"
238    storeBuffer.receiveSamples(count);
239}
240
241
242// Transposes down the sample rate, causing the observed playback 'rate' of the
243// sound to increase
244void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
245{
246    uint count, sizeTemp;
247
248    // If the parameter 'uRate' value is larger than 'SCALE', first apply the
249    // anti-alias filter to remove high frequencies (prevent them from folding
250    // over the lover frequencies), then transpose. */
251
252    // Add the new samples to the end of the storeBuffer */
253    storeBuffer.putSamples(src, nSamples);
254
255    // Anti-alias filter the samples to prevent folding and output the filtered 
256    // data to tempBuffer. Note : because of the FIR filter length, the
257    // filtering routine takes in 'filter_length' more samples than it outputs.
258    assert(tempBuffer.isEmpty());
259    sizeTemp = storeBuffer.numSamples();
260
261    count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), 
262        storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels);
263
264    // Remove the filtered samples from 'storeBuffer'
265    storeBuffer.receiveSamples(count);
266
267    // Transpose the samples (+16 is to reserve some slack in the destination buffer)
268    sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
269    count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
270    outputBuffer.putSamples(count);
271}
272
273
274// Transposes sample rate by applying anti-alias filter to prevent folding. 
275// Returns amount of samples returned in the "dest" buffer.
276// The maximum amount of samples that can be returned at a time is set by
277// the 'set_returnBuffer_size' function.
278void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
279{
280    uint count;
281    uint sizeReq;
282
283    if (nSamples == 0) return;
284    assert(pAAFilter);
285
286    // If anti-alias filter is turned off, simply transpose without applying
287    // the filter
288    if (bUseAAFilter == FALSE) 
289    {
290        sizeReq = (uint)((float)nSamples / fRate + 1.0f);
291        count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples);
292        outputBuffer.putSamples(count);
293        return;
294    }
295
296    // Transpose with anti-alias filter
297    if (fRate < 1.0f) 
298    {
299        upsample(src, nSamples);
300    } 
301    else  
302    {
303        downsample(src, nSamples);
304    }
305}
306
307
308// Transposes the sample rate of the given samples using linear interpolation. 
309// Returns the number of samples returned in the "dest" buffer
310inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
311{
312    if (numChannels == 2) 
313    {
314        return transposeStereo(dest, src, nSamples);
315    } 
316    else 
317    {
318        return transposeMono(dest, src, nSamples);
319    }
320}
321
322
323// Sets the number of channels, 1 = mono, 2 = stereo
324void RateTransposer::setChannels(int nChannels)
325{
326    assert(nChannels > 0);
327    if (numChannels == nChannels) return;
328
329    assert(nChannels == 1 || nChannels == 2);
330    numChannels = nChannels;
331
332    storeBuffer.setChannels(numChannels);
333    tempBuffer.setChannels(numChannels);
334    outputBuffer.setChannels(numChannels);
335
336    // Inits the linear interpolation registers
337    resetRegisters();
338}
339
340
341// Clears all the samples in the object
342void RateTransposer::clear()
343{
344    outputBuffer.clear();
345    storeBuffer.clear();
346}
347
348
349// Returns nonzero if there aren't any samples available for outputting.
350int RateTransposer::isEmpty() const
351{
352    int res;
353
354    res = FIFOProcessor::isEmpty();
355    if (res == 0) return 0;
356    return storeBuffer.isEmpty();
357}
358
359
360//////////////////////////////////////////////////////////////////////////////
361//
362// RateTransposerInteger - integer arithmetic implementation
363// 
364
365/// fixed-point interpolation routine precision
366#define SCALE    65536

367
368// Constructor
369RateTransposerInteger::RateTransposerInteger() : RateTransposer()
370{
371    // Notice: use local function calling syntax for sake of clarity, 
372    // to indicate the fact that C++ constructor can't call virtual functions.
373    RateTransposerInteger::resetRegisters();
374    RateTransposerInteger::setRate(1.0f);
375}
376
377
378RateTransposerInteger::~RateTransposerInteger()
379{
380}
381
382
383void RateTransposerInteger::resetRegisters()
384{
385    iSlopeCount = 0;
386    sPrevSampleL = 
387    sPrevSampleR = 0;
388}
389
390
391
392// Transposes the sample rate of the given samples using linear interpolation. 
393// 'Mono' version of the routine. Returns the number of samples returned in 
394// the "dest" buffer
395uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
396{
397    unsigned int i, used;
398    LONG_SAMPLETYPE temp, vol1;
399
400    used = 0;    
401    i = 0;
402
403    // Process the last sample saved from the previous call first...
404    while (iSlopeCount <= SCALE) 
405    {
406        vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
407        temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
408        dest[i] = (SAMPLETYPE)(temp / SCALE);
409        i++;
410        iSlopeCount += iRate;
411    }
412    // now always (iSlopeCount > SCALE)
413    iSlopeCount -= SCALE;
414
415    while (1)
416    {
417        while (iSlopeCount > SCALE) 
418        {
419            iSlopeCount -= SCALE;
420            used ++;
421            if (used >= nSamples - 1) goto end;
422        }
423        vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
424        temp = src[used] * vol1 + iSlopeCount * src[used + 1];
425        dest[i] = (SAMPLETYPE)(temp / SCALE);
426
427        i++;
428        iSlopeCount += iRate;
429    }
430end:
431    // Store the last sample for the next round
432    sPrevSampleL = src[nSamples - 1];
433
434    return i;
435}
436
437
438// Transposes the sample rate of the given samples using linear interpolation. 
439// 'Stereo' version of the routine. Returns the number of samples returned in 
440// the "dest" buffer
441uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
442{
443    unsigned int srcPos, i, used;
444    LONG_SAMPLETYPE temp, vol1;
445
446    if (nSamples == 0) return 0;  // no samples, no work
447
448    used = 0;    
449    i = 0;
450
451    // Process the last sample saved from the sPrevSampleLious call first...
452    while (iSlopeCount <= SCALE) 
453    {
454        vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
455        temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
456        dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
457        temp = vol1 * sPrevSampleR + iSlopeCount * src[1];
458        dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
459        i++;
460        iSlopeCount += iRate;
461    }
462    // now always (iSlopeCount > SCALE)
463    iSlopeCount -= SCALE;
464
465    while (1)
466    {
467        while (iSlopeCount > SCALE) 
468        {
469            iSlopeCount -= SCALE;
470            used ++;
471            if (used >= nSamples - 1) goto end;
472        }
473        srcPos = 2 * used;
474        vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
475        temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2];
476        dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
477        temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3];
478        dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
479
480        i++;
481        iSlopeCount += iRate;
482    }
483end:
484    // Store the last sample for the next round
485    sPrevSampleL = src[2 * nSamples - 2];
486    sPrevSampleR = src[2 * nSamples - 1];
487
488    return i;
489}
490
491
492// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower 
493// iRate, larger faster iRates.
494void RateTransposerInteger::setRate(float newRate)
495{
496    iRate = (int)(newRate * SCALE + 0.5f);
497    RateTransposer::setRate(newRate);
498}
499
500
501//////////////////////////////////////////////////////////////////////////////
502//
503// RateTransposerFloat - floating point arithmetic implementation
504// 
505//////////////////////////////////////////////////////////////////////////////
506
507// Constructor
508RateTransposerFloat::RateTransposerFloat() : RateTransposer()
509{
510    // Notice: use local function calling syntax for sake of clarity, 
511    // to indicate the fact that C++ constructor can't call virtual functions.
512    RateTransposerFloat::resetRegisters();
513    RateTransposerFloat::setRate(1.0f);
514}
515
516
517RateTransposerFloat::~RateTransposerFloat()
518{
519}
520
521
522void RateTransposerFloat::resetRegisters()
523{
524    fSlopeCount = 0;
525    sPrevSampleL = 
526    sPrevSampleR = 0;
527}
528
529
530
531// Transposes the sample rate of the given samples using linear interpolation. 
532// 'Mono' version of the routine. Returns the number of samples returned in 
533// the "dest" buffer
534uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
535{
536    unsigned int i, used;
537
538    used = 0;    
539    i = 0;
540
541    // Process the last sample saved from the previous call first...
542    while (fSlopeCount <= 1.0f ) 
543    {
544        dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
545        i++;
546        fSlopeCount += fRate;
547    }
548    fSlopeCount -= 1.0f;
549
550    if (nSamples == 1) goto end;
551
552    while (1)
553    {
554        while (fSlopeCount > 1.0f) 
555        {
556            fSlopeCount -= 1.0f;
557            used ++;
558            if (used >= nSamples - 1) goto end;
559        }
560        
561        //if(i>= nSamples -1) goto end;
562        
563        dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]);
564        i++;
565        fSlopeCount += fRate;
566    }
567end:
568    // Store the last sample for the next round
569    sPrevSampleL = src[nSamples - 1];
570
571    return i;
572}
573
574
575// Transposes the sample rate of the given samples using linear interpolation. 
576// 'Mono' version of the routine. Returns the number of samples returned in 
577// the "dest" buffer
578uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
579{
580    unsigned int srcPos, i, used;
581
582    if (nSamples == 0) return 0;  // no samples, no work
583
584    used = 0;    
585    i = 0;
586
587    // Process the last sample saved from the sPrevSampleLious call first...
588    while (fSlopeCount <= 1.0f) 
589    {
590        dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
591        dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]);
592        i++;
593        fSlopeCount += fRate;
594    }
595    // now always (iSlopeCount > 1.0f)
596    fSlopeCount -= 1.0f;
597
598    if (nSamples == 1) goto end;
599
600    while (1)
601    {
602        while (fSlopeCount > 1.0f) 
603        {
604            fSlopeCount -= 1.0f;
605            used ++;
606            if (used >= nSamples - 1) goto end;
607        }
608        srcPos = 2 * used;
609
610        dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos] 
611            + fSlopeCount * src[srcPos + 2]);
612        dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1] 
613            + fSlopeCount * src[srcPos + 3]);
614
615        i++;
616        fSlopeCount += fRate;
617    }
618end:
619    // Store the last sample for the next round
620    sPrevSampleL = src[2 * nSamples - 2];
621    sPrevSampleR = src[2 * nSamples - 1];
622
623    return i;
624}