Line data Source code
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: 2014-04-06 15:57:21 +0000 (Sun, 06 Apr 2014) $
14 : // File revision : $Revision: 4 $
15 : //
16 : // $Id: RateTransposer.cpp 195 2014-04-06 15:57:21Z 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
58 0 : RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
59 : {
60 0 : bUseAAFilter = true;
61 :
62 : // Instantiates the anti-alias filter
63 0 : pAAFilter = new AAFilter(64);
64 0 : pTransposer = TransposerBase::newInstance();
65 0 : }
66 :
67 :
68 :
69 0 : RateTransposer::~RateTransposer()
70 : {
71 0 : delete pAAFilter;
72 0 : delete pTransposer;
73 0 : }
74 :
75 :
76 :
77 : /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
78 0 : void RateTransposer::enableAAFilter(bool newMode)
79 : {
80 0 : bUseAAFilter = newMode;
81 0 : }
82 :
83 :
84 : /// Returns nonzero if anti-alias filter is enabled.
85 0 : bool RateTransposer::isAAFilterEnabled() const
86 : {
87 0 : return bUseAAFilter;
88 : }
89 :
90 :
91 0 : AAFilter *RateTransposer::getAAFilter()
92 : {
93 0 : return pAAFilter;
94 : }
95 :
96 :
97 :
98 : // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
99 : // iRate, larger faster iRates.
100 0 : void RateTransposer::setRate(float newRate)
101 : {
102 : double fCutoff;
103 :
104 0 : pTransposer->setRate(newRate);
105 :
106 : // design a new anti-alias filter
107 0 : if (newRate > 1.0f)
108 : {
109 0 : fCutoff = 0.5f / newRate;
110 : }
111 : else
112 : {
113 0 : fCutoff = 0.5f * newRate;
114 : }
115 0 : pAAFilter->setCutoffFreq(fCutoff);
116 0 : }
117 :
118 :
119 : // Adds 'nSamples' pcs of samples from the 'samples' memory position into
120 : // the input of the object.
121 0 : void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
122 : {
123 0 : processSamples(samples, nSamples);
124 0 : }
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.
131 0 : void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
132 : {
133 : uint count;
134 :
135 0 : if (nSamples == 0) return;
136 :
137 : // Store samples to input buffer
138 0 : inputBuffer.putSamples(src, nSamples);
139 :
140 : // If anti-alias filter is turned off, simply transpose without applying
141 : // the filter
142 0 : if (bUseAAFilter == false)
143 : {
144 0 : count = pTransposer->transpose(outputBuffer, inputBuffer);
145 0 : return;
146 : }
147 :
148 0 : assert(pAAFilter);
149 :
150 : // Transpose with anti-alias filter
151 0 : 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 0 : pTransposer->transpose(midBuffer, inputBuffer);
158 :
159 : // Apply the anti-alias filter for transposed samples in midBuffer
160 0 : 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 0 : pAAFilter->evaluate(midBuffer, inputBuffer);
170 :
171 : // Transpose the AA-filtered samples in "midBuffer"
172 0 : pTransposer->transpose(outputBuffer, midBuffer);
173 : }
174 : }
175 :
176 :
177 : // Sets the number of channels, 1 = mono, 2 = stereo
178 0 : void RateTransposer::setChannels(int nChannels)
179 : {
180 0 : assert(nChannels > 0);
181 :
182 0 : if (pTransposer->numChannels == nChannels) return;
183 0 : pTransposer->setChannels(nChannels);
184 :
185 0 : inputBuffer.setChannels(nChannels);
186 0 : midBuffer.setChannels(nChannels);
187 0 : outputBuffer.setChannels(nChannels);
188 : }
189 :
190 :
191 : // Clears all the samples in the object
192 0 : void RateTransposer::clear()
193 : {
194 0 : outputBuffer.clear();
195 0 : midBuffer.clear();
196 0 : inputBuffer.clear();
197 0 : }
198 :
199 :
200 : // Returns nonzero if there aren't any samples available for outputting.
201 0 : int RateTransposer::isEmpty() const
202 : {
203 : int res;
204 :
205 0 : res = FIFOProcessor::isEmpty();
206 0 : if (res == 0) return 0;
207 0 : return inputBuffer.isEmpty();
208 : }
209 :
210 :
211 : //////////////////////////////////////////////////////////////////////////////
212 : //
213 : // TransposerBase - Base class for interpolation
214 : //
215 :
216 : // static function to set interpolation algorithm
217 0 : void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
218 : {
219 0 : TransposerBase::algorithm = a;
220 0 : }
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
225 0 : int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
226 : {
227 0 : int numSrcSamples = src.numSamples();
228 0 : int sizeDemand = (int)((float)numSrcSamples / rate) + 8;
229 : int numOutput;
230 0 : SAMPLETYPE *psrc = src.ptrBegin();
231 0 : SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
232 :
233 : #ifndef USE_MULTICH_ALWAYS
234 0 : if (numChannels == 1)
235 : {
236 0 : numOutput = transposeMono(pdest, psrc, numSrcSamples);
237 : }
238 0 : else if (numChannels == 2)
239 : {
240 0 : numOutput = transposeStereo(pdest, psrc, numSrcSamples);
241 : }
242 : else
243 : #endif // USE_MULTICH_ALWAYS
244 : {
245 0 : assert(numChannels > 0);
246 0 : numOutput = transposeMulti(pdest, psrc, numSrcSamples);
247 : }
248 0 : dest.putSamples(numOutput);
249 0 : src.receiveSamples(numSrcSamples);
250 0 : return numOutput;
251 : }
252 :
253 :
254 0 : TransposerBase::TransposerBase()
255 : {
256 0 : numChannels = 0;
257 0 : rate = 1.0f;
258 0 : }
259 :
260 :
261 0 : TransposerBase::~TransposerBase()
262 : {
263 0 : }
264 :
265 :
266 0 : void TransposerBase::setChannels(int channels)
267 : {
268 0 : numChannels = channels;
269 0 : resetRegisters();
270 0 : }
271 :
272 :
273 0 : void TransposerBase::setRate(float newRate)
274 : {
275 0 : rate = newRate;
276 0 : }
277 :
278 :
279 : // static factory function
280 0 : 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 0 : switch (algorithm)
287 : {
288 : case LINEAR:
289 0 : return new InterpolateLinearFloat;
290 :
291 : case CUBIC:
292 0 : return new InterpolateCubic;
293 :
294 : case SHANNON:
295 0 : return new InterpolateShannon;
296 :
297 : default:
298 0 : assert(false);
299 : return NULL;
300 : }
301 : #endif
302 : }
|