media/libsoundtouch/src/RateTransposer.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial