/[pcsx2_0.9.7]/trunk/3rdparty/SoundTouch/RateTransposer.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/SoundTouch/RateTransposer.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 5 months ago) by william
File size: 18115 byte(s)
exported r3113 from ./upstream/trunk
1 william 10 ////////////////////////////////////////////////////////////////////////////////
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: 2009-10-31 16:37:24 +0200 (Sat, 31 Oct 2009) $
14     // File revision : $Revision: 4 $
15     //
16     // $Id: RateTransposer.cpp 74 2009-10-31 14:37:24Z 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 <stdexcept>
46     #include "RateTransposer.h"
47     #include "AAFilter.h"
48    
49     using namespace std;
50     using namespace soundtouch;
51    
52    
53     /// A linear samplerate transposer class that uses integer arithmetics.
54     /// for the transposing.
55     class RateTransposerInteger : public RateTransposer
56     {
57     protected:
58     int iSlopeCount;
59     int iRate;
60     SAMPLETYPE sPrevSampleL, sPrevSampleR;
61    
62     virtual void resetRegisters();
63    
64     virtual uint transposeStereo(SAMPLETYPE *dest,
65     const SAMPLETYPE *src,
66     uint numSamples);
67     virtual uint transposeMono(SAMPLETYPE *dest,
68     const SAMPLETYPE *src,
69     uint numSamples);
70    
71     public:
72     RateTransposerInteger();
73     virtual ~RateTransposerInteger();
74    
75     /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
76     /// rate, larger faster rates.
77     virtual void setRate(float newRate);
78    
79     };
80    
81    
82     /// A linear samplerate transposer class that uses floating point arithmetics
83     /// for the transposing.
84     class RateTransposerFloat : public RateTransposer
85     {
86     protected:
87     float fSlopeCount;
88     SAMPLETYPE sPrevSampleL, sPrevSampleR;
89    
90     virtual void resetRegisters();
91    
92     virtual uint transposeStereo(SAMPLETYPE *dest,
93     const SAMPLETYPE *src,
94     uint numSamples);
95     virtual uint transposeMono(SAMPLETYPE *dest,
96     const SAMPLETYPE *src,
97     uint numSamples);
98    
99     public:
100     RateTransposerFloat();
101     virtual ~RateTransposerFloat();
102     };
103    
104    
105    
106    
107     // Operator 'new' is overloaded so that it automatically creates a suitable instance
108     // depending on if we've a MMX/SSE/etc-capable CPU available or not.
109     void * RateTransposer::operator new(size_t s)
110     {
111     throw runtime_error("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
112     return NULL;
113     }
114    
115    
116     RateTransposer *RateTransposer::newInstance()
117     {
118     #ifdef INTEGER_SAMPLES
119     return ::new RateTransposerInteger;
120     #else
121     return ::new RateTransposerFloat;
122     #endif
123     }
124    
125    
126     // Constructor
127     RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
128     {
129     numChannels = 2;
130     bUseAAFilter = TRUE;
131     fRate = 0;
132    
133     // Instantiates the anti-alias filter with default tap length
134     // of 32
135     pAAFilter = new AAFilter(32);
136     }
137    
138    
139    
140     RateTransposer::~RateTransposer()
141     {
142     delete pAAFilter;
143     }
144    
145    
146    
147     /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
148     void RateTransposer::enableAAFilter(BOOL newMode)
149     {
150     bUseAAFilter = newMode;
151     }
152    
153    
154     /// Returns nonzero if anti-alias filter is enabled.
155     BOOL RateTransposer::isAAFilterEnabled() const
156     {
157     return bUseAAFilter;
158     }
159    
160    
161     AAFilter *RateTransposer::getAAFilter()
162     {
163     return pAAFilter;
164     }
165    
166    
167    
168     // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
169     // iRate, larger faster iRates.
170     void RateTransposer::setRate(float newRate)
171     {
172     double fCutoff;
173    
174     fRate = newRate;
175    
176     // design a new anti-alias filter
177     if (newRate > 1.0f)
178     {
179     fCutoff = 0.5f / newRate;
180     }
181     else
182     {
183     fCutoff = 0.5f * newRate;
184     }
185     pAAFilter->setCutoffFreq(fCutoff);
186     }
187    
188    
189     // Outputs as many samples of the 'outputBuffer' as possible, and if there's
190     // any room left, outputs also as many of the incoming samples as possible.
191     // The goal is to drive the outputBuffer empty.
192     //
193     // It's allowed for 'output' and 'input' parameters to point to the same
194     // memory position.
195     /*
196     void RateTransposer::flushStoreBuffer()
197     {
198     if (storeBuffer.isEmpty()) return;
199    
200     outputBuffer.moveSamples(storeBuffer);
201     }
202     */
203    
204    
205     // Adds 'nSamples' pcs of samples from the 'samples' memory position into
206     // the input of the object.
207     void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
208     {
209     processSamples(samples, nSamples);
210     }
211    
212    
213    
214     // Transposes up the sample rate, causing the observed playback 'rate' of the
215     // sound to decrease
216     void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples)
217     {
218     uint count, sizeTemp, num;
219    
220     // If the parameter 'uRate' value is smaller than 'SCALE', first transpose
221     // the samples and then apply the anti-alias filter to remove aliasing.
222    
223     // First check that there's enough room in 'storeBuffer'
224     // (+16 is to reserve some slack in the destination buffer)
225     sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
226    
227     // Transpose the samples, store the result into the end of "storeBuffer"
228     count = transpose(storeBuffer.ptrEnd(sizeTemp), src, nSamples);
229     storeBuffer.putSamples(count);
230    
231     // Apply the anti-alias filter to samples in "store output", output the
232     // result to "dest"
233     num = storeBuffer.numSamples();
234     count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
235     storeBuffer.ptrBegin(), num, (uint)numChannels);
236     outputBuffer.putSamples(count);
237    
238     // Remove the processed samples from "storeBuffer"
239     storeBuffer.receiveSamples(count);
240     }
241    
242    
243     // Transposes down the sample rate, causing the observed playback 'rate' of the
244     // sound to increase
245     void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
246     {
247     uint count, sizeTemp;
248    
249     // If the parameter 'uRate' value is larger than 'SCALE', first apply the
250     // anti-alias filter to remove high frequencies (prevent them from folding
251     // over the lover frequencies), then transpose.
252    
253     // Add the new samples to the end of the storeBuffer
254     storeBuffer.putSamples(src, nSamples);
255    
256     // Anti-alias filter the samples to prevent folding and output the filtered
257     // data to tempBuffer. Note : because of the FIR filter length, the
258     // filtering routine takes in 'filter_length' more samples than it outputs.
259     assert(tempBuffer.isEmpty());
260     sizeTemp = storeBuffer.numSamples();
261    
262     count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
263     storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels);
264    
265     if (count == 0) return;
266    
267     // Remove the filtered samples from 'storeBuffer'
268     storeBuffer.receiveSamples(count);
269    
270     // Transpose the samples (+16 is to reserve some slack in the destination buffer)
271     sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
272     count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
273     outputBuffer.putSamples(count);
274     }
275    
276    
277     // Transposes sample rate by applying anti-alias filter to prevent folding.
278     // Returns amount of samples returned in the "dest" buffer.
279     // The maximum amount of samples that can be returned at a time is set by
280     // the 'set_returnBuffer_size' function.
281     void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
282     {
283     uint count;
284     uint sizeReq;
285    
286     if (nSamples == 0) return;
287     assert(pAAFilter);
288    
289     // If anti-alias filter is turned off, simply transpose without applying
290     // the filter
291     if (bUseAAFilter == FALSE)
292     {
293     sizeReq = (uint)((float)nSamples / fRate + 1.0f);
294     count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples);
295     outputBuffer.putSamples(count);
296     return;
297     }
298    
299     // Transpose with anti-alias filter
300     if (fRate < 1.0f)
301     {
302     upsample(src, nSamples);
303     }
304     else
305     {
306     downsample(src, nSamples);
307     }
308     }
309    
310    
311     // Transposes the sample rate of the given samples using linear interpolation.
312     // Returns the number of samples returned in the "dest" buffer
313     inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
314     {
315     if (numChannels == 2)
316     {
317     return transposeStereo(dest, src, nSamples);
318     }
319     else
320     {
321     return transposeMono(dest, src, nSamples);
322     }
323     }
324    
325    
326     // Sets the number of channels, 1 = mono, 2 = stereo
327     void RateTransposer::setChannels(int nChannels)
328     {
329     assert(nChannels > 0);
330     if (numChannels == nChannels) return;
331    
332     assert(nChannels == 1 || nChannels == 2);
333     numChannels = nChannels;
334    
335     storeBuffer.setChannels(numChannels);
336     tempBuffer.setChannels(numChannels);
337     outputBuffer.setChannels(numChannels);
338    
339     // Inits the linear interpolation registers
340     resetRegisters();
341     }
342    
343    
344     // Clears all the samples in the object
345     void RateTransposer::clear()
346     {
347     outputBuffer.clear();
348     storeBuffer.clear();
349     }
350    
351    
352     // Returns nonzero if there aren't any samples available for outputting.
353     int RateTransposer::isEmpty() const
354     {
355     int res;
356    
357     res = FIFOProcessor::isEmpty();
358     if (res == 0) return 0;
359     return storeBuffer.isEmpty();
360     }
361    
362    
363     //////////////////////////////////////////////////////////////////////////////
364     //
365     // RateTransposerInteger - integer arithmetic implementation
366     //
367    
368     /// fixed-point interpolation routine precision
369     #define SCALE 65536
370    
371     // Constructor
372     RateTransposerInteger::RateTransposerInteger() : RateTransposer()
373     {
374     // Notice: use local function calling syntax for sake of clarity,
375     // to indicate the fact that C++ constructor can't call virtual functions.
376     RateTransposerInteger::resetRegisters();
377     RateTransposerInteger::setRate(1.0f);
378     }
379    
380    
381     RateTransposerInteger::~RateTransposerInteger()
382     {
383     }
384    
385    
386     void RateTransposerInteger::resetRegisters()
387     {
388     iSlopeCount = 0;
389     sPrevSampleL =
390     sPrevSampleR = 0;
391     }
392    
393    
394    
395     // Transposes the sample rate of the given samples using linear interpolation.
396     // 'Mono' version of the routine. Returns the number of samples returned in
397     // the "dest" buffer
398     uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
399     {
400     unsigned int i, used;
401     LONG_SAMPLETYPE temp, vol1;
402    
403     if (nSamples == 0) return 0; // no samples, no work
404    
405     used = 0;
406     i = 0;
407    
408     // Process the last sample saved from the previous call first...
409     while (iSlopeCount <= SCALE)
410     {
411     vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
412     temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
413     dest[i] = (SAMPLETYPE)(temp / SCALE);
414     i++;
415     iSlopeCount += iRate;
416     }
417     // now always (iSlopeCount > SCALE)
418     iSlopeCount -= SCALE;
419    
420     while (1)
421     {
422     while (iSlopeCount > SCALE)
423     {
424     iSlopeCount -= SCALE;
425     used ++;
426     if (used >= nSamples - 1) goto end;
427     }
428     vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
429     temp = src[used] * vol1 + iSlopeCount * src[used + 1];
430     dest[i] = (SAMPLETYPE)(temp / SCALE);
431    
432     i++;
433     iSlopeCount += iRate;
434     }
435     end:
436     // Store the last sample for the next round
437     sPrevSampleL = src[nSamples - 1];
438    
439     return i;
440     }
441    
442    
443     // Transposes the sample rate of the given samples using linear interpolation.
444     // 'Stereo' version of the routine. Returns the number of samples returned in
445     // the "dest" buffer
446     uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
447     {
448     unsigned int srcPos, i, used;
449     LONG_SAMPLETYPE temp, vol1;
450    
451     if (nSamples == 0) return 0; // no samples, no work
452    
453     used = 0;
454     i = 0;
455    
456     // Process the last sample saved from the sPrevSampleLious call first...
457     while (iSlopeCount <= SCALE)
458     {
459     vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
460     temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
461     dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
462     temp = vol1 * sPrevSampleR + iSlopeCount * src[1];
463     dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
464     i++;
465     iSlopeCount += iRate;
466     }
467     // now always (iSlopeCount > SCALE)
468     iSlopeCount -= SCALE;
469    
470     while (1)
471     {
472     while (iSlopeCount > SCALE)
473     {
474     iSlopeCount -= SCALE;
475     used ++;
476     if (used >= nSamples - 1) goto end;
477     }
478     srcPos = 2 * used;
479     vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
480     temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2];
481     dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
482     temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3];
483     dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
484    
485     i++;
486     iSlopeCount += iRate;
487     }
488     end:
489     // Store the last sample for the next round
490     sPrevSampleL = src[2 * nSamples - 2];
491     sPrevSampleR = src[2 * nSamples - 1];
492    
493     return i;
494     }
495    
496    
497     // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
498     // iRate, larger faster iRates.
499     void RateTransposerInteger::setRate(float newRate)
500     {
501     iRate = (int)(newRate * SCALE + 0.5f);
502     RateTransposer::setRate(newRate);
503     }
504    
505    
506     //////////////////////////////////////////////////////////////////////////////
507     //
508     // RateTransposerFloat - floating point arithmetic implementation
509     //
510     //////////////////////////////////////////////////////////////////////////////
511    
512     // Constructor
513     RateTransposerFloat::RateTransposerFloat() : RateTransposer()
514     {
515     // Notice: use local function calling syntax for sake of clarity,
516     // to indicate the fact that C++ constructor can't call virtual functions.
517     RateTransposerFloat::resetRegisters();
518     RateTransposerFloat::setRate(1.0f);
519     }
520    
521    
522     RateTransposerFloat::~RateTransposerFloat()
523     {
524     }
525    
526    
527     void RateTransposerFloat::resetRegisters()
528     {
529     fSlopeCount = 0;
530     sPrevSampleL =
531     sPrevSampleR = 0;
532     }
533    
534    
535    
536     // Transposes the sample rate of the given samples using linear interpolation.
537     // 'Mono' version of the routine. Returns the number of samples returned in
538     // the "dest" buffer
539     uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
540     {
541     unsigned int i, used;
542    
543     used = 0;
544     i = 0;
545    
546     // Process the last sample saved from the previous call first...
547     while (fSlopeCount <= 1.0f)
548     {
549     dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
550     i++;
551     fSlopeCount += fRate;
552     }
553     fSlopeCount -= 1.0f;
554    
555     if (nSamples > 1)
556     {
557     while (1)
558     {
559     while (fSlopeCount > 1.0f)
560     {
561     fSlopeCount -= 1.0f;
562     used ++;
563     if (used >= nSamples - 1) goto end;
564     }
565     dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]);
566     i++;
567     fSlopeCount += fRate;
568     }
569     }
570     end:
571     // Store the last sample for the next round
572     sPrevSampleL = src[nSamples - 1];
573    
574     return i;
575     }
576    
577    
578     // Transposes the sample rate of the given samples using linear interpolation.
579     // 'Mono' version of the routine. Returns the number of samples returned in
580     // the "dest" buffer
581     uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
582     {
583     unsigned int srcPos, i, used;
584    
585     if (nSamples == 0) return 0; // no samples, no work
586    
587     used = 0;
588     i = 0;
589    
590     // Process the last sample saved from the sPrevSampleLious call first...
591     while (fSlopeCount <= 1.0f)
592     {
593     dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
594     dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]);
595     i++;
596     fSlopeCount += fRate;
597     }
598     // now always (iSlopeCount > 1.0f)
599     fSlopeCount -= 1.0f;
600    
601     if (nSamples > 1)
602     {
603     while (1)
604     {
605     while (fSlopeCount > 1.0f)
606     {
607     fSlopeCount -= 1.0f;
608     used ++;
609     if (used >= nSamples - 1) goto end;
610     }
611     srcPos = 2 * used;
612    
613     dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos]
614     + fSlopeCount * src[srcPos + 2]);
615     dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1]
616     + fSlopeCount * src[srcPos + 3]);
617    
618     i++;
619     fSlopeCount += fRate;
620     }
621     }
622     end:
623     // Store the last sample for the next round
624     sPrevSampleL = src[2 * nSamples - 2];
625     sPrevSampleR = src[2 * nSamples - 1];
626    
627     return i;
628     }

  ViewVC Help
Powered by ViewVC 1.1.22