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

Annotation of /trunk/3rdparty/SoundTouch/SoundTouch.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: 14820 byte(s)
exported r3113 from ./upstream/trunk
1 william 10 //////////////////////////////////////////////////////////////////////////////
2     ///
3     /// SoundTouch - main class for tempo/pitch/rate adjusting routines.
4     ///
5     /// Notes:
6     /// - Initialize the SoundTouch object instance by setting up the sound stream
7     /// parameters with functions 'setSampleRate' and 'setChannels', then set
8     /// desired tempo/pitch/rate settings with the corresponding functions.
9     ///
10     /// - The SoundTouch class behaves like a first-in-first-out pipeline: The
11     /// samples that are to be processed are fed into one of the pipe by calling
12     /// function 'putSamples', while the ready processed samples can be read
13     /// from the other end of the pipeline with function 'receiveSamples'.
14     ///
15     /// - The SoundTouch processing classes require certain sized 'batches' of
16     /// samples in order to process the sound. For this reason the classes buffer
17     /// incoming samples until there are enough of samples available for
18     /// processing, then they carry out the processing step and consequently
19     /// make the processed samples available for outputting.
20     ///
21     /// - For the above reason, the processing routines introduce a certain
22     /// 'latency' between the input and output, so that the samples input to
23     /// SoundTouch may not be immediately available in the output, and neither
24     /// the amount of outputtable samples may not immediately be in direct
25     /// relationship with the amount of previously input samples.
26     ///
27     /// - The tempo/pitch/rate control parameters can be altered during processing.
28     /// Please notice though that they aren't currently protected by semaphores,
29     /// so in multi-thread application external semaphore protection may be
30     /// required.
31     ///
32     /// - This class utilizes classes 'TDStretch' for tempo change (without modifying
33     /// pitch) and 'RateTransposer' for changing the playback rate (that is, both
34     /// tempo and pitch in the same ratio) of the sound. The third available control
35     /// 'pitch' (change pitch but maintain tempo) is produced by a combination of
36     /// combining the two other controls.
37     ///
38     /// Author : Copyright (c) Olli Parviainen
39     /// Author e-mail : oparviai 'at' iki.fi
40     /// SoundTouch WWW: http://www.surina.net/soundtouch
41     ///
42     ////////////////////////////////////////////////////////////////////////////////
43     //
44     // Last changed : $Date: 2009-05-19 07:57:30 +0300 (Tue, 19 May 2009) $
45     // File revision : $Revision: 4 $
46     //
47     // $Id: SoundTouch.cpp 73 2009-05-19 04:57:30Z oparviai $
48     //
49     ////////////////////////////////////////////////////////////////////////////////
50     //
51     // License :
52     //
53     // SoundTouch audio processing library
54     // Copyright (c) Olli Parviainen
55     //
56     // This library is free software; you can redistribute it and/or
57     // modify it under the terms of the GNU Lesser General Public
58     // License as published by the Free Software Foundation; either
59     // version 2.1 of the License, or (at your option) any later version.
60     //
61     // This library is distributed in the hope that it will be useful,
62     // but WITHOUT ANY WARRANTY; without even the implied warranty of
63     // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
64     // Lesser General Public License for more details.
65     //
66     // You should have received a copy of the GNU Lesser General Public
67     // License along with this library; if not, write to the Free Software
68     // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
69     //
70     ////////////////////////////////////////////////////////////////////////////////
71    
72     #include <assert.h>
73     #include <stdlib.h>
74     #include <memory.h>
75     #include <math.h>
76     #include <stdexcept>
77     #include <stdio.h>
78    
79     #include "SoundTouch.h"
80     #include "TDStretch.h"
81     #include "RateTransposer.h"
82     #include "cpu_detect.h"
83    
84     using namespace soundtouch;
85    
86     /// test if two floating point numbers are equal
87     #define TEST_FLOAT_EQUAL(a, b) (fabs(a - b) < 1e-10)
88    
89    
90     /// Print library version string for autoconf
91     extern "C" void soundtouch_ac_test()
92     {
93     printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION);
94     }
95    
96    
97     SoundTouch::SoundTouch()
98     {
99     // Initialize rate transposer and tempo changer instances
100    
101     pRateTransposer = RateTransposer::newInstance();
102     pTDStretch = TDStretch::newInstance();
103    
104     setOutPipe(pTDStretch);
105    
106     rate = tempo = 0;
107    
108     virtualPitch =
109     virtualRate =
110     virtualTempo = 1.0;
111    
112     calcEffectiveRateAndTempo();
113    
114     channels = 0;
115     bSrateSet = FALSE;
116     }
117    
118    
119    
120     SoundTouch::~SoundTouch()
121     {
122     delete pRateTransposer;
123     delete pTDStretch;
124     }
125    
126    
127    
128     /// Get SoundTouch library version string
129     const char *SoundTouch::getVersionString()
130     {
131     static const char *_version = SOUNDTOUCH_VERSION;
132    
133     return _version;
134     }
135    
136    
137     /// Get SoundTouch library version Id
138     uint SoundTouch::getVersionId()
139     {
140     return SOUNDTOUCH_VERSION_ID;
141     }
142    
143    
144     // Sets the number of channels, 1 = mono, 2 = stereo
145     void SoundTouch::setChannels(uint numChannels)
146     {
147     if (numChannels != 1 && numChannels != 2)
148     {
149     throw std::runtime_error("Illegal number of channels");
150     }
151     channels = numChannels;
152     pRateTransposer->setChannels((int)numChannels);
153     pTDStretch->setChannels((int)numChannels);
154     }
155    
156    
157    
158     // Sets new rate control value. Normal rate = 1.0, smaller values
159     // represent slower rate, larger faster rates.
160     void SoundTouch::setRate(float newRate)
161     {
162     virtualRate = newRate;
163     calcEffectiveRateAndTempo();
164     }
165    
166    
167    
168     // Sets new rate control value as a difference in percents compared
169     // to the original rate (-50 .. +100 %)
170     void SoundTouch::setRateChange(float newRate)
171     {
172     virtualRate = 1.0f + 0.01f * newRate;
173     calcEffectiveRateAndTempo();
174     }
175    
176    
177    
178     // Sets new tempo control value. Normal tempo = 1.0, smaller values
179     // represent slower tempo, larger faster tempo.
180     void SoundTouch::setTempo(float newTempo)
181     {
182     virtualTempo = newTempo;
183     calcEffectiveRateAndTempo();
184     }
185    
186    
187    
188     // Sets new tempo control value as a difference in percents compared
189     // to the original tempo (-50 .. +100 %)
190     void SoundTouch::setTempoChange(float newTempo)
191     {
192     virtualTempo = 1.0f + 0.01f * newTempo;
193     calcEffectiveRateAndTempo();
194     }
195    
196    
197    
198     // Sets new pitch control value. Original pitch = 1.0, smaller values
199     // represent lower pitches, larger values higher pitch.
200     void SoundTouch::setPitch(float newPitch)
201     {
202     virtualPitch = newPitch;
203     calcEffectiveRateAndTempo();
204     }
205    
206    
207    
208     // Sets pitch change in octaves compared to the original pitch
209     // (-1.00 .. +1.00)
210     void SoundTouch::setPitchOctaves(float newPitch)
211     {
212     virtualPitch = (float)exp(0.69314718056f * newPitch);
213     calcEffectiveRateAndTempo();
214     }
215    
216    
217    
218     // Sets pitch change in semi-tones compared to the original pitch
219     // (-12 .. +12)
220     void SoundTouch::setPitchSemiTones(int newPitch)
221     {
222     setPitchOctaves((float)newPitch / 12.0f);
223     }
224    
225    
226    
227     void SoundTouch::setPitchSemiTones(float newPitch)
228     {
229     setPitchOctaves(newPitch / 12.0f);
230     }
231    
232    
233     // Calculates 'effective' rate and tempo values from the
234     // nominal control values.
235     void SoundTouch::calcEffectiveRateAndTempo()
236     {
237     float oldTempo = tempo;
238     float oldRate = rate;
239    
240     tempo = virtualTempo / virtualPitch;
241     rate = virtualPitch * virtualRate;
242    
243     if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate);
244     if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
245    
246     #ifndef PREVENT_CLICK_AT_RATE_CROSSOVER
247     if (rate <= 1.0f)
248     {
249     if (output != pTDStretch)
250     {
251     FIFOSamplePipe *tempoOut;
252    
253     assert(output == pRateTransposer);
254     // move samples in the current output buffer to the output of pTDStretch
255     tempoOut = pTDStretch->getOutput();
256     tempoOut->moveSamples(*output);
257     // move samples in pitch transposer's store buffer to tempo changer's input
258     pTDStretch->moveSamples(*pRateTransposer->getStore());
259    
260     output = pTDStretch;
261     }
262     }
263     else
264     #endif
265     {
266     if (output != pRateTransposer)
267     {
268     FIFOSamplePipe *transOut;
269    
270     assert(output == pTDStretch);
271     // move samples in the current output buffer to the output of pRateTransposer
272     transOut = pRateTransposer->getOutput();
273     transOut->moveSamples(*output);
274     // move samples in tempo changer's input to pitch transposer's input
275     pRateTransposer->moveSamples(*pTDStretch->getInput());
276    
277     output = pRateTransposer;
278     }
279     }
280     }
281    
282    
283     // Sets sample rate.
284     void SoundTouch::setSampleRate(uint srate)
285     {
286     bSrateSet = TRUE;
287     // set sample rate, leave other tempo changer parameters as they are.
288     pTDStretch->setParameters((int)srate);
289     }
290    
291    
292     // Adds 'numSamples' pcs of samples from the 'samples' memory position into
293     // the input of the object.
294     void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
295     {
296     if (bSrateSet == FALSE)
297     {
298     throw std::runtime_error("SoundTouch : Sample rate not defined");
299     }
300     else if (channels == 0)
301     {
302     throw std::runtime_error("SoundTouch : Number of channels not defined");
303     }
304    
305     // Transpose the rate of the new samples if necessary
306     /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
307     if (rate == 1.0f)
308     {
309     // The rate value is same as the original, simply evaluate the tempo changer.
310     assert(output == pTDStretch);
311     if (pRateTransposer->isEmpty() == 0)
312     {
313     // yet flush the last samples in the pitch transposer buffer
314     // (may happen if 'rate' changes from a non-zero value to zero)
315     pTDStretch->moveSamples(*pRateTransposer);
316     }
317     pTDStretch->putSamples(samples, nSamples);
318     }
319     */
320     #ifndef PREVENT_CLICK_AT_RATE_CROSSOVER
321     else if (rate <= 1.0f)
322     {
323     // transpose the rate down, output the transposed sound to tempo changer buffer
324     assert(output == pTDStretch);
325     pRateTransposer->putSamples(samples, nSamples);
326     pTDStretch->moveSamples(*pRateTransposer);
327     }
328     else
329     #endif
330     {
331     // evaluate the tempo changer, then transpose the rate up,
332     assert(output == pRateTransposer);
333     pTDStretch->putSamples(samples, nSamples);
334     pRateTransposer->moveSamples(*pTDStretch);
335     }
336     }
337    
338    
339     // Flushes the last samples from the processing pipeline to the output.
340     // Clears also the internal processing buffers.
341     //
342     // Note: This function is meant for extracting the last samples of a sound
343     // stream. This function may introduce additional blank samples in the end
344     // of the sound stream, and thus it's not recommended to call this function
345     // in the middle of a sound stream.
346     void SoundTouch::flush()
347     {
348     int i;
349     uint nOut;
350     SAMPLETYPE buff[128];
351    
352     nOut = numSamples();
353    
354     memset(buff, 0, 128 * sizeof(SAMPLETYPE));
355     // "Push" the last active samples out from the processing pipeline by
356     // feeding blank samples into the processing pipeline until new,
357     // processed samples appear in the output (not however, more than
358     // 8ksamples in any case)
359     for (i = 0; i < 128; i ++)
360     {
361     putSamples(buff, 64);
362     if (numSamples() != nOut) break; // new samples have appeared in the output!
363     }
364    
365     // Clear working buffers
366     pRateTransposer->clear();
367     pTDStretch->clearInput();
368     // yet leave the 'tempoChanger' output intouched as that's where the
369     // flushed samples are!
370     }
371    
372    
373     // Changes a setting controlling the processing system behaviour. See the
374     // 'SETTING_...' defines for available setting ID's.
375     BOOL SoundTouch::setSetting(int settingId, int value)
376     {
377     int sampleRate, sequenceMs, seekWindowMs, overlapMs;
378    
379     // read current tdstretch routine parameters
380     pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
381    
382     switch (settingId)
383     {
384     case SETTING_USE_AA_FILTER :
385     // enables / disabless anti-alias filter
386     pRateTransposer->enableAAFilter((value != 0) ? TRUE : FALSE);
387     return TRUE;
388    
389     case SETTING_AA_FILTER_LENGTH :
390     // sets anti-alias filter length
391     pRateTransposer->getAAFilter()->setLength(value);
392     return TRUE;
393    
394     case SETTING_USE_QUICKSEEK :
395     // enables / disables tempo routine quick seeking algorithm
396     pTDStretch->enableQuickSeek((value != 0) ? TRUE : FALSE);
397     return TRUE;
398    
399     case SETTING_SEQUENCE_MS:
400     // change time-stretch sequence duration parameter
401     pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs);
402     return TRUE;
403    
404     case SETTING_SEEKWINDOW_MS:
405     // change time-stretch seek window length parameter
406     pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs);
407     return TRUE;
408    
409     case SETTING_OVERLAP_MS:
410     // change time-stretch overlap length parameter
411     pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value);
412     return TRUE;
413    
414     default :
415     return FALSE;
416     }
417     }
418    
419    
420     // Reads a setting controlling the processing system behaviour. See the
421     // 'SETTING_...' defines for available setting ID's.
422     //
423     // Returns the setting value.
424     int SoundTouch::getSetting(int settingId) const
425     {
426     int temp;
427    
428     switch (settingId)
429     {
430     case SETTING_USE_AA_FILTER :
431     return (uint)pRateTransposer->isAAFilterEnabled();
432    
433     case SETTING_AA_FILTER_LENGTH :
434     return pRateTransposer->getAAFilter()->getLength();
435    
436     case SETTING_USE_QUICKSEEK :
437     return (uint) pTDStretch->isQuickSeekEnabled();
438    
439     case SETTING_SEQUENCE_MS:
440     pTDStretch->getParameters(NULL, &temp, NULL, NULL);
441     return temp;
442    
443     case SETTING_SEEKWINDOW_MS:
444     pTDStretch->getParameters(NULL, NULL, &temp, NULL);
445     return temp;
446    
447     case SETTING_OVERLAP_MS:
448     pTDStretch->getParameters(NULL, NULL, NULL, &temp);
449     return temp;
450    
451     default :
452     return 0;
453     }
454     }
455    
456    
457     // Clears all the samples in the object's output and internal processing
458     // buffers.
459     void SoundTouch::clear()
460     {
461     pRateTransposer->clear();
462     pTDStretch->clear();
463     }
464    
465    
466    
467     /// Returns number of samples currently unprocessed.
468     uint SoundTouch::numUnprocessedSamples() const
469     {
470     FIFOSamplePipe * psp;
471     if (pTDStretch)
472     {
473     psp = pTDStretch->getInput();
474     if (psp)
475     {
476     return psp->numSamples();
477     }
478     }
479     return 0;
480     }

  ViewVC Help
Powered by ViewVC 1.1.22