1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libsoundtouch/src/RateTransposer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,302 @@ 1.4 +//////////////////////////////////////////////////////////////////////////////// 1.5 +/// 1.6 +/// Sample rate transposer. Changes sample rate by using linear interpolation 1.7 +/// together with anti-alias filtering (first order interpolation with anti- 1.8 +/// alias filtering should be quite adequate for this application) 1.9 +/// 1.10 +/// Author : Copyright (c) Olli Parviainen 1.11 +/// Author e-mail : oparviai 'at' iki.fi 1.12 +/// SoundTouch WWW: http://www.surina.net/soundtouch 1.13 +/// 1.14 +//////////////////////////////////////////////////////////////////////////////// 1.15 +// 1.16 +// Last changed : $Date: 2014-04-06 10:57:21 -0500 (Sun, 06 Apr 2014) $ 1.17 +// File revision : $Revision: 4 $ 1.18 +// 1.19 +// $Id: RateTransposer.cpp 195 2014-04-06 15:57:21Z oparviai $ 1.20 +// 1.21 +//////////////////////////////////////////////////////////////////////////////// 1.22 +// 1.23 +// License : 1.24 +// 1.25 +// SoundTouch audio processing library 1.26 +// Copyright (c) Olli Parviainen 1.27 +// 1.28 +// This library is free software; you can redistribute it and/or 1.29 +// modify it under the terms of the GNU Lesser General Public 1.30 +// License as published by the Free Software Foundation; either 1.31 +// version 2.1 of the License, or (at your option) any later version. 1.32 +// 1.33 +// This library is distributed in the hope that it will be useful, 1.34 +// but WITHOUT ANY WARRANTY; without even the implied warranty of 1.35 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.36 +// Lesser General Public License for more details. 1.37 +// 1.38 +// You should have received a copy of the GNU Lesser General Public 1.39 +// License along with this library; if not, write to the Free Software 1.40 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.41 +// 1.42 +//////////////////////////////////////////////////////////////////////////////// 1.43 + 1.44 +#include <memory.h> 1.45 +#include <assert.h> 1.46 +#include <stdlib.h> 1.47 +#include <stdio.h> 1.48 +#include "RateTransposer.h" 1.49 +#include "InterpolateLinear.h" 1.50 +#include "InterpolateCubic.h" 1.51 +#include "InterpolateShannon.h" 1.52 +#include "AAFilter.h" 1.53 + 1.54 +using namespace soundtouch; 1.55 + 1.56 +// Define default interpolation algorithm here 1.57 +TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC; 1.58 + 1.59 + 1.60 +// Constructor 1.61 +RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer) 1.62 +{ 1.63 + bUseAAFilter = true; 1.64 + 1.65 + // Instantiates the anti-alias filter 1.66 + pAAFilter = new AAFilter(64); 1.67 + pTransposer = TransposerBase::newInstance(); 1.68 +} 1.69 + 1.70 + 1.71 + 1.72 +RateTransposer::~RateTransposer() 1.73 +{ 1.74 + delete pAAFilter; 1.75 + delete pTransposer; 1.76 +} 1.77 + 1.78 + 1.79 + 1.80 +/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable 1.81 +void RateTransposer::enableAAFilter(bool newMode) 1.82 +{ 1.83 + bUseAAFilter = newMode; 1.84 +} 1.85 + 1.86 + 1.87 +/// Returns nonzero if anti-alias filter is enabled. 1.88 +bool RateTransposer::isAAFilterEnabled() const 1.89 +{ 1.90 + return bUseAAFilter; 1.91 +} 1.92 + 1.93 + 1.94 +AAFilter *RateTransposer::getAAFilter() 1.95 +{ 1.96 + return pAAFilter; 1.97 +} 1.98 + 1.99 + 1.100 + 1.101 +// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower 1.102 +// iRate, larger faster iRates. 1.103 +void RateTransposer::setRate(float newRate) 1.104 +{ 1.105 + double fCutoff; 1.106 + 1.107 + pTransposer->setRate(newRate); 1.108 + 1.109 + // design a new anti-alias filter 1.110 + if (newRate > 1.0f) 1.111 + { 1.112 + fCutoff = 0.5f / newRate; 1.113 + } 1.114 + else 1.115 + { 1.116 + fCutoff = 0.5f * newRate; 1.117 + } 1.118 + pAAFilter->setCutoffFreq(fCutoff); 1.119 +} 1.120 + 1.121 + 1.122 +// Adds 'nSamples' pcs of samples from the 'samples' memory position into 1.123 +// the input of the object. 1.124 +void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples) 1.125 +{ 1.126 + processSamples(samples, nSamples); 1.127 +} 1.128 + 1.129 + 1.130 +// Transposes sample rate by applying anti-alias filter to prevent folding. 1.131 +// Returns amount of samples returned in the "dest" buffer. 1.132 +// The maximum amount of samples that can be returned at a time is set by 1.133 +// the 'set_returnBuffer_size' function. 1.134 +void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) 1.135 +{ 1.136 + uint count; 1.137 + 1.138 + if (nSamples == 0) return; 1.139 + 1.140 + // Store samples to input buffer 1.141 + inputBuffer.putSamples(src, nSamples); 1.142 + 1.143 + // If anti-alias filter is turned off, simply transpose without applying 1.144 + // the filter 1.145 + if (bUseAAFilter == false) 1.146 + { 1.147 + count = pTransposer->transpose(outputBuffer, inputBuffer); 1.148 + return; 1.149 + } 1.150 + 1.151 + assert(pAAFilter); 1.152 + 1.153 + // Transpose with anti-alias filter 1.154 + if (pTransposer->rate < 1.0f) 1.155 + { 1.156 + // If the parameter 'Rate' value is smaller than 1, first transpose 1.157 + // the samples and then apply the anti-alias filter to remove aliasing. 1.158 + 1.159 + // Transpose the samples, store the result to end of "midBuffer" 1.160 + pTransposer->transpose(midBuffer, inputBuffer); 1.161 + 1.162 + // Apply the anti-alias filter for transposed samples in midBuffer 1.163 + pAAFilter->evaluate(outputBuffer, midBuffer); 1.164 + } 1.165 + else 1.166 + { 1.167 + // If the parameter 'Rate' value is larger than 1, first apply the 1.168 + // anti-alias filter to remove high frequencies (prevent them from folding 1.169 + // over the lover frequencies), then transpose. 1.170 + 1.171 + // Apply the anti-alias filter for samples in inputBuffer 1.172 + pAAFilter->evaluate(midBuffer, inputBuffer); 1.173 + 1.174 + // Transpose the AA-filtered samples in "midBuffer" 1.175 + pTransposer->transpose(outputBuffer, midBuffer); 1.176 + } 1.177 +} 1.178 + 1.179 + 1.180 +// Sets the number of channels, 1 = mono, 2 = stereo 1.181 +void RateTransposer::setChannels(int nChannels) 1.182 +{ 1.183 + assert(nChannels > 0); 1.184 + 1.185 + if (pTransposer->numChannels == nChannels) return; 1.186 + pTransposer->setChannels(nChannels); 1.187 + 1.188 + inputBuffer.setChannels(nChannels); 1.189 + midBuffer.setChannels(nChannels); 1.190 + outputBuffer.setChannels(nChannels); 1.191 +} 1.192 + 1.193 + 1.194 +// Clears all the samples in the object 1.195 +void RateTransposer::clear() 1.196 +{ 1.197 + outputBuffer.clear(); 1.198 + midBuffer.clear(); 1.199 + inputBuffer.clear(); 1.200 +} 1.201 + 1.202 + 1.203 +// Returns nonzero if there aren't any samples available for outputting. 1.204 +int RateTransposer::isEmpty() const 1.205 +{ 1.206 + int res; 1.207 + 1.208 + res = FIFOProcessor::isEmpty(); 1.209 + if (res == 0) return 0; 1.210 + return inputBuffer.isEmpty(); 1.211 +} 1.212 + 1.213 + 1.214 +////////////////////////////////////////////////////////////////////////////// 1.215 +// 1.216 +// TransposerBase - Base class for interpolation 1.217 +// 1.218 + 1.219 +// static function to set interpolation algorithm 1.220 +void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a) 1.221 +{ 1.222 + TransposerBase::algorithm = a; 1.223 +} 1.224 + 1.225 + 1.226 +// Transposes the sample rate of the given samples using linear interpolation. 1.227 +// Returns the number of samples returned in the "dest" buffer 1.228 +int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) 1.229 +{ 1.230 + int numSrcSamples = src.numSamples(); 1.231 + int sizeDemand = (int)((float)numSrcSamples / rate) + 8; 1.232 + int numOutput; 1.233 + SAMPLETYPE *psrc = src.ptrBegin(); 1.234 + SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand); 1.235 + 1.236 +#ifndef USE_MULTICH_ALWAYS 1.237 + if (numChannels == 1) 1.238 + { 1.239 + numOutput = transposeMono(pdest, psrc, numSrcSamples); 1.240 + } 1.241 + else if (numChannels == 2) 1.242 + { 1.243 + numOutput = transposeStereo(pdest, psrc, numSrcSamples); 1.244 + } 1.245 + else 1.246 +#endif // USE_MULTICH_ALWAYS 1.247 + { 1.248 + assert(numChannels > 0); 1.249 + numOutput = transposeMulti(pdest, psrc, numSrcSamples); 1.250 + } 1.251 + dest.putSamples(numOutput); 1.252 + src.receiveSamples(numSrcSamples); 1.253 + return numOutput; 1.254 +} 1.255 + 1.256 + 1.257 +TransposerBase::TransposerBase() 1.258 +{ 1.259 + numChannels = 0; 1.260 + rate = 1.0f; 1.261 +} 1.262 + 1.263 + 1.264 +TransposerBase::~TransposerBase() 1.265 +{ 1.266 +} 1.267 + 1.268 + 1.269 +void TransposerBase::setChannels(int channels) 1.270 +{ 1.271 + numChannels = channels; 1.272 + resetRegisters(); 1.273 +} 1.274 + 1.275 + 1.276 +void TransposerBase::setRate(float newRate) 1.277 +{ 1.278 + rate = newRate; 1.279 +} 1.280 + 1.281 + 1.282 +// static factory function 1.283 +TransposerBase *TransposerBase::newInstance() 1.284 +{ 1.285 +#ifdef SOUNDTOUCH_INTEGER_SAMPLES 1.286 + // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus) 1.287 + return ::new InterpolateLinearInteger; 1.288 +#else 1.289 + switch (algorithm) 1.290 + { 1.291 + case LINEAR: 1.292 + return new InterpolateLinearFloat; 1.293 + 1.294 + case CUBIC: 1.295 + return new InterpolateCubic; 1.296 + 1.297 + case SHANNON: 1.298 + return new InterpolateShannon; 1.299 + 1.300 + default: 1.301 + assert(false); 1.302 + return NULL; 1.303 + } 1.304 +#endif 1.305 +}