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 }