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: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
14 // File revision : $Revision: 4 $
15 //
16 // $Id: RateTransposer.cpp 225 2015-07-26 14:45:48Z 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 "RateTransposer.h"
46 #include "InterpolateLinear.h"
47 #include "InterpolateCubic.h"
48 #include "InterpolateShannon.h"
49 #include "AAFilter.h"
50
51 using namespace soundtouch;
52
53 // Define default interpolation algorithm here
54 TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
55
56
57 // Constructor
RateTransposer()58 RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
59 {
60 bUseAAFilter = true;
61
62 // Instantiates the anti-alias filter
63 pAAFilter = new AAFilter(64);
64 pTransposer = TransposerBase::newInstance();
65 }
66
67
68
~RateTransposer()69 RateTransposer::~RateTransposer()
70 {
71 delete pAAFilter;
72 delete pTransposer;
73 }
74
75
76
77 /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
enableAAFilter(bool newMode)78 void RateTransposer::enableAAFilter(bool newMode)
79 {
80 bUseAAFilter = newMode;
81 }
82
83
84 /// Returns nonzero if anti-alias filter is enabled.
isAAFilterEnabled() const85 bool RateTransposer::isAAFilterEnabled() const
86 {
87 return bUseAAFilter;
88 }
89
90
getAAFilter()91 AAFilter *RateTransposer::getAAFilter()
92 {
93 return pAAFilter;
94 }
95
96
97
98 // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
99 // iRate, larger faster iRates.
setRate(double newRate)100 void RateTransposer::setRate(double newRate)
101 {
102 double fCutoff;
103
104 pTransposer->setRate(newRate);
105
106 // design a new anti-alias filter
107 if (newRate > 1.0)
108 {
109 fCutoff = 0.5 / newRate;
110 }
111 else
112 {
113 fCutoff = 0.5 * newRate;
114 }
115 pAAFilter->setCutoffFreq(fCutoff);
116 }
117
118
119 // Adds 'nSamples' pcs of samples from the 'samples' memory position into
120 // the input of the object.
putSamples(const SAMPLETYPE * samples,uint nSamples)121 void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
122 {
123 processSamples(samples, nSamples);
124 }
125
126
127 // Transposes sample rate by applying anti-alias filter to prevent folding.
128 // Returns amount of samples returned in the "dest" buffer.
129 // The maximum amount of samples that can be returned at a time is set by
130 // the 'set_returnBuffer_size' function.
processSamples(const SAMPLETYPE * src,uint nSamples)131 void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
132 {
133 uint count;
134
135 if (nSamples == 0) return;
136
137 // Store samples to input buffer
138 inputBuffer.putSamples(src, nSamples);
139
140 // If anti-alias filter is turned off, simply transpose without applying
141 // the filter
142 if (bUseAAFilter == false)
143 {
144 count = pTransposer->transpose(outputBuffer, inputBuffer);
145 return;
146 }
147
148 assert(pAAFilter);
149
150 // Transpose with anti-alias filter
151 if (pTransposer->rate < 1.0f)
152 {
153 // If the parameter 'Rate' value is smaller than 1, first transpose
154 // the samples and then apply the anti-alias filter to remove aliasing.
155
156 // Transpose the samples, store the result to end of "midBuffer"
157 pTransposer->transpose(midBuffer, inputBuffer);
158
159 // Apply the anti-alias filter for transposed samples in midBuffer
160 pAAFilter->evaluate(outputBuffer, midBuffer);
161 }
162 else
163 {
164 // If the parameter 'Rate' value is larger than 1, first apply the
165 // anti-alias filter to remove high frequencies (prevent them from folding
166 // over the lover frequencies), then transpose.
167
168 // Apply the anti-alias filter for samples in inputBuffer
169 pAAFilter->evaluate(midBuffer, inputBuffer);
170
171 // Transpose the AA-filtered samples in "midBuffer"
172 pTransposer->transpose(outputBuffer, midBuffer);
173 }
174 }
175
176
177 // Sets the number of channels, 1 = mono, 2 = stereo
setChannels(int nChannels)178 void RateTransposer::setChannels(int nChannels)
179 {
180 assert(nChannels > 0);
181
182 if (pTransposer->numChannels == nChannels) return;
183 pTransposer->setChannels(nChannels);
184
185 inputBuffer.setChannels(nChannels);
186 midBuffer.setChannels(nChannels);
187 outputBuffer.setChannels(nChannels);
188 }
189
190
191 // Clears all the samples in the object
clear()192 void RateTransposer::clear()
193 {
194 outputBuffer.clear();
195 midBuffer.clear();
196 inputBuffer.clear();
197 }
198
199
200 // Returns nonzero if there aren't any samples available for outputting.
isEmpty() const201 int RateTransposer::isEmpty() const
202 {
203 int res;
204
205 res = FIFOProcessor::isEmpty();
206 if (res == 0) return 0;
207 return inputBuffer.isEmpty();
208 }
209
210
211 //////////////////////////////////////////////////////////////////////////////
212 //
213 // TransposerBase - Base class for interpolation
214 //
215
216 // static function to set interpolation algorithm
setAlgorithm(TransposerBase::ALGORITHM a)217 void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
218 {
219 TransposerBase::algorithm = a;
220 }
221
222
223 // Transposes the sample rate of the given samples using linear interpolation.
224 // Returns the number of samples returned in the "dest" buffer
transpose(FIFOSampleBuffer & dest,FIFOSampleBuffer & src)225 int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
226 {
227 int numSrcSamples = src.numSamples();
228 int sizeDemand = (int)((double)numSrcSamples / rate) + 8;
229 int numOutput;
230 SAMPLETYPE *psrc = src.ptrBegin();
231 SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
232
233 #ifndef USE_MULTICH_ALWAYS
234 if (numChannels == 1)
235 {
236 numOutput = transposeMono(pdest, psrc, numSrcSamples);
237 }
238 else if (numChannels == 2)
239 {
240 numOutput = transposeStereo(pdest, psrc, numSrcSamples);
241 }
242 else
243 #endif // USE_MULTICH_ALWAYS
244 {
245 assert(numChannels > 0);
246 numOutput = transposeMulti(pdest, psrc, numSrcSamples);
247 }
248 dest.putSamples(numOutput);
249 src.receiveSamples(numSrcSamples);
250 return numOutput;
251 }
252
253
TransposerBase()254 TransposerBase::TransposerBase()
255 {
256 numChannels = 0;
257 rate = 1.0f;
258 }
259
260
~TransposerBase()261 TransposerBase::~TransposerBase()
262 {
263 }
264
265
setChannels(int channels)266 void TransposerBase::setChannels(int channels)
267 {
268 numChannels = channels;
269 resetRegisters();
270 }
271
272
setRate(double newRate)273 void TransposerBase::setRate(double newRate)
274 {
275 rate = newRate;
276 }
277
278
279 // static factory function
newInstance()280 TransposerBase *TransposerBase::newInstance()
281 {
282 #ifdef SOUNDTOUCH_INTEGER_SAMPLES
283 // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus)
284 return ::new InterpolateLinearInteger;
285 #else
286 switch (algorithm)
287 {
288 case LINEAR:
289 return new InterpolateLinearFloat;
290
291 case CUBIC:
292 return new InterpolateCubic;
293
294 case SHANNON:
295 return new InterpolateShannon;
296
297 default:
298 assert(false);
299 return NULL;
300 }
301 #endif
302 }
303