📄 ratetransposer.cpp
字号:
/***************************************************************************** * * Sample rate transposer. Changes sample rate by using linear interpolation * together with anti-alias filtering (first order interpolation with anti- * alias filtering should be quite adequate for this application) * * Author : Copyright (c) Olli Parviainen * Author e-mail : oparviai @ iki.fi * File created : 13-Jan-2002 * * Last changed : $Date: 2004/10/26 19:09:37 $ * File revision : $Revision: 1.3 $ * * $Id: RateTransposer.cpp,v 1.3 2004/10/26 19:09:37 vjohnson Exp $ * * License : * * SoundTouch sound processing library * Copyright (c) Olli Parviainen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *****************************************************************************/#include <memory.h>#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <limits.h>#include "RateTransposer.h"#include "AAFilter.h"using namespace soundtouch;/// A linear samplerate transposer class that uses integer arithmetics./// for the transposing.class RateTransposerInteger : public RateTransposer{protected: int iSlopeCount; uint uRate; soundtouch::SAMPLETYPE sPrevSampleL, sPrevSampleR; virtual void resetRegisters(); virtual uint transposeStereo(soundtouch::SAMPLETYPE *dest, const soundtouch::SAMPLETYPE *src, uint numSamples); virtual uint transposeMono(soundtouch::SAMPLETYPE *dest, const soundtouch::SAMPLETYPE *src, uint numSamples);public: RateTransposerInteger(); virtual ~RateTransposerInteger(); /// Sets new target rate. Normal rate = 1.0, smaller values represent slower /// rate, larger faster rates. virtual void setRate(float newRate);};/// A linear samplerate transposer class that uses floating point arithmetics/// for the transposing.class RateTransposerFloat : public RateTransposer{protected: float fSlopeCount; float fRateStep; soundtouch::SAMPLETYPE sPrevSampleL, sPrevSampleR; virtual void resetRegisters(); virtual uint transposeStereo(soundtouch::SAMPLETYPE *dest, const soundtouch::SAMPLETYPE *src, uint numSamples); virtual uint transposeMono(soundtouch::SAMPLETYPE *dest, const soundtouch::SAMPLETYPE *src, uint numSamples);public: RateTransposerFloat(); virtual ~RateTransposerFloat();};#ifndef min#define min(a,b) ((a > b) ? b : a)#define max(a,b) ((a < b) ? b : a)#endif// Operator 'new' is overloaded so that it automatically creates a suitable instance // depending on if we've a MMX/SSE/etc-capable CPU available or not.void * RateTransposer::operator new(size_t s){ // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead! assert(FALSE); return NULL;}RateTransposer *RateTransposer::newInstance(){#ifdef INTEGER_SAMPLES return ::new RateTransposerInteger;#else return ::new RateTransposerFloat;#endif}// ConstructorRateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer){ uChannels = 2; bUseAAFilter = TRUE; // Instantiates the anti-alias filter with default tap length // of 32 pAAFilter = new AAFilter(32);}RateTransposer::~RateTransposer(){ delete pAAFilter;}/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enablevoid RateTransposer::enableAAFilter(const BOOL newMode){ bUseAAFilter = newMode;}/// Returns nonzero if anti-alias filter is enabled.BOOL RateTransposer::isAAFilterEnabled() const{ return bUseAAFilter;}AAFilter *RateTransposer::getAAFilter() const{ return pAAFilter;}// Sets new target uRate. Normal uRate = 1.0, smaller values represent slower // uRate, larger faster uRates.void RateTransposer::setRate(float newRate){ float fCutoff; fRate = newRate; // design a new anti-alias filter if (newRate > 1.0f) { fCutoff = 0.5f / newRate; } else { fCutoff = 0.5f * newRate; } pAAFilter->setCutoffFreq(fCutoff);}// Outputs as many samples of the 'outputBuffer' as possible, and if there's// any room left, outputs also as many of the incoming samples as possible.// The goal is to drive the outputBuffer empty.//// It's allowed for 'output' and 'input' parameters to point to the same// memory position.void RateTransposer::flushStoreBuffer(){ if (storeBuffer.isEmpty()) return; outputBuffer.moveSamples(storeBuffer);}// Adds 'numSamples' pcs of samples from the 'samples' memory position into// the input of the object.void RateTransposer::putSamples(const SAMPLETYPE *samples, uint numSamples){ processSamples(samples, numSamples);}// Transposes up the sample rate, causing the observed playback 'rate' of the// sound to decreasevoid RateTransposer::upsample(const SAMPLETYPE *src, uint numSamples){ int count, sizeTemp, num; // If the parameter 'uRate' value is smaller than 'SCALE', first transpose // the samples and then apply the anti-alias filter to remove aliasing. // First check that there's enough room in 'storeBuffer' // (+16 is to reserve some slack in the destination buffer) sizeTemp = (int)((float)numSamples / fRate + 16.0f); // Transpose the samples, store the result into the end of "storeBuffer" count = transpose(storeBuffer.ptrEnd(sizeTemp), src, numSamples); storeBuffer.putSamples(count); // Apply the anti-alias filter to samples in "store output", output the // result to "dest" num = storeBuffer.numSamples(); count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), storeBuffer.ptrBegin(), num, uChannels); outputBuffer.putSamples(count); // Remove the processed samples from "storeBuffer" storeBuffer.receiveSamples(count);}// Transposes down the sample rate, causing the observed playback 'rate' of the// sound to increasevoid RateTransposer::downsample(const SAMPLETYPE *src, uint numSamples){ int count, sizeTemp; // If the parameter 'uRate' value is larger than 'SCALE', first apply the // anti-alias filter to remove high frequencies (prevent them from folding // over the lover frequencies), then transpose. */ // Add the new samples to the end of the storeBuffer */ storeBuffer.putSamples(src, numSamples); // Anti-alias filter the samples to prevent folding and output the filtered // data to tempBuffer. Note : because of the FIR filter length, the // filtering routine takes in 'filter_length' more samples than it outputs. assert(tempBuffer.isEmpty()); sizeTemp = storeBuffer.numSamples(); count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), storeBuffer.ptrBegin(), sizeTemp, uChannels); // Remove the filtered samples from 'storeBuffer' storeBuffer.receiveSamples(count); // Transpose the samples (+16 is to reserve some slack in the destination buffer) sizeTemp = (int)((float)numSamples / fRate + 16.0f); count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count); outputBuffer.putSamples(count);}// Transposes sample rate by applying anti-alias filter to prevent folding. // Returns amount of samples returned in the "dest" buffer.// The maximum amount of samples that can be returned at a time is set by// the 'set_returnBuffer_size' function.void RateTransposer::processSamples(const SAMPLETYPE *src, uint numSamples){ uint count; uint sizeReq; if (numSamples == 0) return; assert(pAAFilter); // If anti-alias filter is turned off, simply transpose without applying // the filter if (bUseAAFilter == FALSE) { sizeReq = (int)((float)numSamples / fRate + 1.0f); count = transpose(outputBuffer.ptrEnd(sizeReq), src, numSamples); outputBuffer.putSamples(count); return; } // Transpose with anti-alias filter if (fRate < 1.0f) { upsample(src, numSamples); } else { downsample(src, numSamples); }}// Transposes the sample rate of the given samples using linear interpolation. // Returns the number of samples returned in the "dest" buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -