diff --git a/3rdparty/SoundTouch/AAFilter.cpp b/3rdparty/SoundTouch/AAFilter.cpp
index c73b2c60b8..860f7d5223 100644
--- a/3rdparty/SoundTouch/AAFilter.cpp
+++ b/3rdparty/SoundTouch/AAFilter.cpp
@@ -1,9 +1,9 @@
////////////////////////////////////////////////////////////////////////////////
///
/// FIR low-pass (anti-alias) filter with filter coefficient design routine and
-/// MMX optimization.
-///
-/// Anti-alias filter is used to prevent folding of high frequencies when
+/// MMX optimization.
+///
+/// Anti-alias filter is used to prevent folding of high frequencies when
/// transposing the sample rate with interpolation.
///
/// Author : Copyright (c) Olli Parviainen
@@ -12,7 +12,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-01-11 13:34:24 +0200 (Sun, 11 Jan 2009) $
+// Last changed : $Date: 2009-01-11 09:34:24 -0200 (dom, 11 jan 2009) $
// File revision : $Revision: 4 $
//
// $Id: AAFilter.cpp 45 2009-01-11 11:34:24Z oparviai $
@@ -112,21 +112,21 @@ void AAFilter::calculateCoeffs()
work = new double[length];
coeffs = new SAMPLETYPE[length];
- fc2 = 2.0 * cutoffFreq;
+ fc2 = 2.0 * cutoffFreq;
wc = PI * fc2;
tempCoeff = TWOPI / (double)length;
sum = 0;
- for (i = 0; i < length; i ++)
+ for (i = 0; i < length; i ++)
{
cntTemp = (double)i - (double)(length / 2);
temp = cntTemp * wc;
- if (temp != 0)
+ if (temp != 0)
{
h = fc2 * sin(temp) / temp; // sinc function
- }
- else
+ }
+ else
{
h = 1.0;
}
@@ -135,7 +135,7 @@ void AAFilter::calculateCoeffs()
temp = w * h;
work[i] = temp;
- // calc net sum of coefficients
+ // calc net sum of coefficients
sum += temp;
}
@@ -151,7 +151,7 @@ void AAFilter::calculateCoeffs()
// divided by 16384
scaleCoeff = 16384.0f / sum;
- for (i = 0; i < length; i ++)
+ for (i = 0; i < length; i ++)
{
// scale & round to nearest integer
temp = work[i] * scaleCoeff;
@@ -169,8 +169,8 @@ void AAFilter::calculateCoeffs()
}
-// Applies the filter to the given sequence of samples.
-// Note : The amount of outputted samples is by value of 'filter length'
+// Applies the filter to the given sequence of samples.
+// Note : The amount of outputted samples is by value of 'filter length'
// smaller than the amount of input samples.
uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
{
diff --git a/3rdparty/SoundTouch/AAFilter.h b/3rdparty/SoundTouch/AAFilter.h
index d92a3eac59..6b885e371c 100644
--- a/3rdparty/SoundTouch/AAFilter.h
+++ b/3rdparty/SoundTouch/AAFilter.h
@@ -1,10 +1,10 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
-/// while maintaining the original pitch by using a time domain WSOLA-like method
+/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
+/// while maintaining the original pitch by using a time domain WSOLA-like method
/// with several performance-increasing tweaks.
///
-/// Anti-alias filter is used to prevent folding of high frequencies when
+/// Anti-alias filter is used to prevent folding of high frequencies when
/// transposing the sample rate with interpolation.
///
/// Author : Copyright (c) Olli Parviainen
@@ -13,7 +13,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
+// Last changed : $Date: 2008-02-10 14:26:55 -0200 (dom, 10 fev 2008) $
// File revision : $Revision: 4 $
//
// $Id: AAFilter.h 11 2008-02-10 16:26:55Z oparviai $
@@ -67,8 +67,8 @@ public:
~AAFilter();
- /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling
- /// frequency (nyquist frequency = 0.5). The filter will cut off the
+ /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling
+ /// frequency (nyquist frequency = 0.5). The filter will cut off the
/// frequencies than that.
void setCutoffFreq(double newCutoffFreq);
@@ -77,12 +77,12 @@ public:
uint getLength() const;
- /// Applies the filter to the given sequence of samples.
- /// Note : The amount of outputted samples is by value of 'filter length'
+ /// Applies the filter to the given sequence of samples.
+ /// Note : The amount of outputted samples is by value of 'filter length'
/// smaller than the amount of input samples.
- uint evaluate(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples,
+ uint evaluate(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ uint numSamples,
uint numChannels) const;
};
diff --git a/3rdparty/SoundTouch/BPMDetect.cpp b/3rdparty/SoundTouch/BPMDetect.cpp
new file mode 100644
index 0000000000..34dbb4730a
--- /dev/null
+++ b/3rdparty/SoundTouch/BPMDetect.cpp
@@ -0,0 +1,370 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Beats-per-minute (BPM) detection routine.
+///
+/// The beat detection algorithm works as follows:
+/// - Use function 'inputSamples' to input a chunks of samples to the class for
+/// analysis. It's a good idea to enter a large sound file or stream in smallish
+/// chunks of around few kilosamples in order not to extinguish too much RAM memory.
+/// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden,
+/// which is basically ok as low (bass) frequencies mostly determine the beat rate.
+/// Simple averaging is used for anti-alias filtering because the resulting signal
+/// quality isn't of that high importance.
+/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
+/// taking absolute value that's smoothed by sliding average. Signal levels that
+/// are below a couple of times the general RMS amplitude level are cut away to
+/// leave only notable peaks there.
+/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
+/// autocorrelation function of the enveloped signal.
+/// - After whole sound data file has been analyzed as above, the bpm level is
+/// detected by function 'getBpm' that finds the highest peak of the autocorrelation
+/// function, calculates it's precise location and converts this reading to bpm's.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// Last changed : $Date: 2012-08-30 16:45:25 -0300 (qui, 30 ago 2012) $
+// File revision : $Revision: 4 $
+//
+// $Id: BPMDetect.cpp 149 2012-08-30 19:45:25Z oparviai $
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// License :
+//
+// SoundTouch audio processing library
+// Copyright (c) Olli Parviainen
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include
+#include
+#include "FIFOSampleBuffer.h"
+#include "PeakFinder.h"
+#include "BPMDetect.h"
+
+using namespace soundtouch;
+
+#define INPUT_BLOCK_SAMPLES 2048
+#define DECIMATED_BLOCK_SAMPLES 256
+
+/// decay constant for calculating RMS volume sliding average approximation
+/// (time constant is about 10 sec)
+const float avgdecay = 0.99986f;
+
+/// Normalization coefficient for calculating RMS sliding average approximation.
+const float avgnorm = (1 - avgdecay);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Enable following define to create bpm analysis file:
+
+// #define _CREATE_BPM_DEBUG_FILE
+
+#ifdef _CREATE_BPM_DEBUG_FILE
+
+ #define DEBUGFILE_NAME "c:\\temp\\soundtouch-bpm-debug.txt"
+
+ static void _SaveDebugData(const float *data, int minpos, int maxpos, double coeff)
+ {
+ FILE *fptr = fopen(DEBUGFILE_NAME, "wt");
+ int i;
+
+ if (fptr)
+ {
+ printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n");
+ for (i = minpos; i < maxpos; i ++)
+ {
+ fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]);
+ }
+ fclose(fptr);
+ }
+ }
+#else
+ #define _SaveDebugData(a,b,c,d)
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+BPMDetect::BPMDetect(int numChannels, int aSampleRate)
+{
+ this->sampleRate = aSampleRate;
+ this->channels = numChannels;
+
+ decimateSum = 0;
+ decimateCount = 0;
+
+ envelopeAccu = 0;
+
+ // Initialize RMS volume accumulator to RMS level of 1500 (out of 32768) that's
+ // safe initial RMS signal level value for song data. This value is then adapted
+ // to the actual level during processing.
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
+ // integer samples
+ RMSVolumeAccu = (1500 * 1500) / avgnorm;
+#else
+ // float samples, scaled to range [-1..+1[
+ RMSVolumeAccu = (0.045f * 0.045f) / avgnorm;
+#endif
+
+ // choose decimation factor so that result is approx. 1000 Hz
+ decimateBy = sampleRate / 1000;
+ assert(decimateBy > 0);
+ assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES);
+
+ // Calculate window length & starting item according to desired min & max bpms
+ windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
+ windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM);
+
+ assert(windowLen > windowStart);
+
+ // allocate new working objects
+ xcorr = new float[windowLen];
+ memset(xcorr, 0, windowLen * sizeof(float));
+
+ // allocate processing buffer
+ buffer = new FIFOSampleBuffer();
+ // we do processing in mono mode
+ buffer->setChannels(1);
+ buffer->clear();
+}
+
+
+
+BPMDetect::~BPMDetect()
+{
+ delete[] xcorr;
+ delete buffer;
+}
+
+
+
+/// convert to mono, low-pass filter & decimate to about 500 Hz.
+/// return number of outputted samples.
+///
+/// Decimation is used to remove the unnecessary frequencies and thus to reduce
+/// the amount of data needed to be processed as calculating autocorrelation
+/// function is a very-very heavy operation.
+///
+/// Anti-alias filtering is done simply by averaging the samples. This is really a
+/// poor-man's anti-alias filtering, but it's not so critical in this kind of application
+/// (it'd also be difficult to design a high-quality filter with steep cut-off at very
+/// narrow band)
+int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples)
+{
+ int count, outcount;
+ LONG_SAMPLETYPE out;
+
+ assert(channels > 0);
+ assert(decimateBy > 0);
+ outcount = 0;
+ for (count = 0; count < numsamples; count ++)
+ {
+ int j;
+
+ // convert to mono and accumulate
+ for (j = 0; j < channels; j ++)
+ {
+ decimateSum += src[j];
+ }
+ src += j;
+
+ decimateCount ++;
+ if (decimateCount >= decimateBy)
+ {
+ // Store every Nth sample only
+ out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels));
+ decimateSum = 0;
+ decimateCount = 0;
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
+ // check ranges for sure (shouldn't actually be necessary)
+ if (out > 32767)
+ {
+ out = 32767;
+ }
+ else if (out < -32768)
+ {
+ out = -32768;
+ }
+#endif // SOUNDTOUCH_INTEGER_SAMPLES
+ dest[outcount] = (SAMPLETYPE)out;
+ outcount ++;
+ }
+ }
+ return outcount;
+}
+
+
+
+// Calculates autocorrelation function of the sample history buffer
+void BPMDetect::updateXCorr(int process_samples)
+{
+ int offs;
+ SAMPLETYPE *pBuffer;
+
+ assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
+
+ pBuffer = buffer->ptrBegin();
+ for (offs = windowStart; offs < windowLen; offs ++)
+ {
+ LONG_SAMPLETYPE sum;
+ int i;
+
+ sum = 0;
+ for (i = 0; i < process_samples; i ++)
+ {
+ sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary
+ }
+// xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients
+ // if it's desired that the system adapts automatically to
+ // various bpms, e.g. in processing continouos music stream.
+ // The 'xcorr_decay' should be a value that's smaller than but
+ // close to one, and should also depend on 'process_samples' value.
+
+ xcorr[offs] += (float)sum;
+ }
+}
+
+
+// Calculates envelope of the sample data
+void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
+{
+ const static double decay = 0.7f; // decay constant for smoothing the envelope
+ const static double norm = (1 - decay);
+
+ int i;
+ LONG_SAMPLETYPE out;
+ double val;
+
+ for (i = 0; i < numsamples; i ++)
+ {
+ // calc average RMS volume
+ RMSVolumeAccu *= avgdecay;
+ val = (float)fabs((float)samples[i]);
+ RMSVolumeAccu += val * val;
+
+ // cut amplitudes that are below cutoff ~2 times RMS volume
+ // (we're interested in peak values, not the silent moments)
+ if (val < 0.5 * sqrt(RMSVolumeAccu * avgnorm))
+ {
+ val = 0;
+ }
+
+ // smooth amplitude envelope
+ envelopeAccu *= decay;
+ envelopeAccu += val;
+ out = (LONG_SAMPLETYPE)(envelopeAccu * norm);
+
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
+ // cut peaks (shouldn't be necessary though)
+ if (out > 32767) out = 32767;
+#endif // SOUNDTOUCH_INTEGER_SAMPLES
+ samples[i] = (SAMPLETYPE)out;
+ }
+}
+
+
+
+void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
+{
+ SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES];
+
+ // iterate so that max INPUT_BLOCK_SAMPLES processed per iteration
+ while (numSamples > 0)
+ {
+ int block;
+ int decSamples;
+
+ block = (numSamples > INPUT_BLOCK_SAMPLES) ? INPUT_BLOCK_SAMPLES : numSamples;
+
+ // decimate. note that converts to mono at the same time
+ decSamples = decimate(decimated, samples, block);
+ samples += block * channels;
+ numSamples -= block;
+
+ // envelope new samples and add them to buffer
+ calcEnvelope(decimated, decSamples);
+ buffer->putSamples(decimated, decSamples);
+ }
+
+ // when the buffer has enought samples for processing...
+ if ((int)buffer->numSamples() > windowLen)
+ {
+ int processLength;
+
+ // how many samples are processed
+ processLength = (int)buffer->numSamples() - windowLen;
+
+ // ... calculate autocorrelations for oldest samples...
+ updateXCorr(processLength);
+ // ... and remove them from the buffer
+ buffer->receiveSamples(processLength);
+ }
+}
+
+
+
+void BPMDetect::removeBias()
+{
+ int i;
+ float minval = 1e12f; // arbitrary large number
+
+ for (i = windowStart; i < windowLen; i ++)
+ {
+ if (xcorr[i] < minval)
+ {
+ minval = xcorr[i];
+ }
+ }
+
+ for (i = windowStart; i < windowLen; i ++)
+ {
+ xcorr[i] -= minval;
+ }
+}
+
+
+float BPMDetect::getBpm()
+{
+ double peakPos;
+ double coeff;
+ PeakFinder peakFinder;
+
+ coeff = 60.0 * ((double)sampleRate / (double)decimateBy);
+
+ // save bpm debug analysis data if debug data enabled
+ _SaveDebugData(xcorr, windowStart, windowLen, coeff);
+
+ // remove bias from xcorr data
+ removeBias();
+
+ // find peak position
+ peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen);
+
+ assert(decimateBy != 0);
+ if (peakPos < 1e-9) return 0.0; // detection failed.
+
+ // calculate BPM
+ return (float) (coeff / peakPos);
+}
diff --git a/3rdparty/SoundTouch/BPMDetect.h b/3rdparty/SoundTouch/BPMDetect.h
index 75289c6b9b..88628def06 100644
--- a/3rdparty/SoundTouch/BPMDetect.h
+++ b/3rdparty/SoundTouch/BPMDetect.h
@@ -14,10 +14,10 @@
/// taking absolute value that's smoothed by sliding average. Signal levels that
/// are below a couple of times the general RMS amplitude level are cut away to
/// leave only notable peaks there.
-/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
+/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
/// autocorrelation function of the enveloped signal.
-/// - After whole sound data file has been analyzed as above, the bpm level is
-/// detected by function 'getBpm' that finds the highest peak of the autocorrelation
+/// - After whole sound data file has been analyzed as above, the bpm level is
+/// detected by function 'getBpm' that finds the highest peak of the autocorrelation
/// function, calculates it's precise location and converts this reading to bpm's.
///
/// Author : Copyright (c) Olli Parviainen
@@ -26,10 +26,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $
+// Last changed : $Date: 2012-08-30 16:53:44 -0300 (qui, 30 ago 2012) $
// File revision : $Revision: 4 $
//
-// $Id: BPMDetect.h 63 2009-02-21 16:00:14Z oparviai $
+// $Id: BPMDetect.h 150 2012-08-30 19:53:44Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -67,7 +67,7 @@ namespace soundtouch
#define MIN_BPM 29
/// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit.
-#define MAX_BPM 230
+#define MAX_BPM 200
/// Class for calculating BPM rate for audio data.
@@ -76,12 +76,12 @@ class BPMDetect
protected:
/// Auto-correlation accumulator bins.
float *xcorr;
-
+
/// Amplitude envelope sliding average approximation level accumulator
- float envelopeAccu;
+ double envelopeAccu;
/// RMS volume sliding average approximation level accumulator
- float RMSVolumeAccu;
+ double RMSVolumeAccu;
/// Sample average counter.
int decimateCount;
@@ -104,12 +104,12 @@ protected:
/// Beginning of auto-correlation window: Autocorrelation isn't being updated for
/// the first these many correlation bins.
int windowStart;
-
+
/// FIFO-buffer for decimated processing samples.
soundtouch::FIFOSampleBuffer *buffer;
- /// Updates auto-correlation function for given number of decimated samples that
- /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe
+ /// Updates auto-correlation function for given number of decimated samples that
+ /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe
/// though).
void updateXCorr(int process_samples /// How many samples are processed.
);
@@ -128,6 +128,9 @@ protected:
int numsamples ///< Number of samples in buffer
);
+ /// remove constant bias from xcorr data
+ void removeBias();
+
public:
/// Constructor.
BPMDetect(int numChannels, ///< Number of channels in sample data.
@@ -139,9 +142,9 @@ public:
/// Inputs a block of samples for analyzing: Envelopes the samples and then
/// updates the autocorrelation estimation. When whole song data has been input
- /// in smaller blocks using this function, read the resulting bpm with 'getBpm'
- /// function.
- ///
+ /// in smaller blocks using this function, read the resulting bpm with 'getBpm'
+ /// function.
+ ///
/// Notice that data in 'samples' array can be disrupted in processing.
void inputSamples(const soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer
int numSamples ///< Number of samples in buffer
diff --git a/3rdparty/SoundTouch/FIFOSampleBuffer.cpp b/3rdparty/SoundTouch/FIFOSampleBuffer.cpp
index a395315ac7..80314d81f9 100644
--- a/3rdparty/SoundTouch/FIFOSampleBuffer.cpp
+++ b/3rdparty/SoundTouch/FIFOSampleBuffer.cpp
@@ -1,12 +1,12 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// A buffer class for temporarily storaging sound samples, operates as a
+/// A buffer class for temporarily storaging sound samples, operates as a
/// first-in-first-out pipe.
///
-/// Samples are added to the end of the sample buffer with the 'putSamples'
+/// Samples are added to the end of the sample buffer with the 'putSamples'
/// function, and are received from the beginning of the buffer by calling
-/// the 'receiveSamples' function. The class automatically removes the
-/// outputted samples from the buffer, as well as grows the buffer size
+/// the 'receiveSamples' function. The class automatically removes the
+/// outputted samples from the buffer, as well as grows the buffer size
/// whenever necessary.
///
/// Author : Copyright (c) Olli Parviainen
@@ -15,10 +15,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-27 19:24:42 +0200 (Fri, 27 Feb 2009) $
+// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $
// File revision : $Revision: 4 $
//
-// $Id: FIFOSampleBuffer.cpp 68 2009-02-27 17:24:42Z oparviai $
+// $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -47,7 +47,6 @@
#include
#include
#include
-#include
#include "FIFOSampleBuffer.h"
@@ -63,7 +62,7 @@ FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
samplesInBuffer = 0;
bufferPos = 0;
channels = (uint)numChannels;
- ensureCapacity(32); // allocate initial capacity
+ ensureCapacity(32); // allocate initial capacity
}
@@ -89,11 +88,11 @@ void FIFOSampleBuffer::setChannels(int numChannels)
// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
-// zeroes this pointer by copying samples from the 'bufferPos' pointer
+// zeroes this pointer by copying samples from the 'bufferPos' pointer
// location on to the beginning of the buffer.
void FIFOSampleBuffer::rewind()
{
- if (buffer && bufferPos)
+ if (buffer && bufferPos)
{
memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
bufferPos = 0;
@@ -101,7 +100,7 @@ void FIFOSampleBuffer::rewind()
}
-// Adds 'numSamples' pcs of samples from the 'samples' memory position to
+// Adds 'numSamples' pcs of samples from the 'samples' memory position to
// the sample buffer.
void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
{
@@ -114,7 +113,7 @@ void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
// samples.
//
// This function is used to update the number of samples in the sample buffer
-// when accessing the buffer directly with 'ptrEnd' function. Please be
+// when accessing the buffer directly with 'ptrEnd' function. Please be
// careful though!
void FIFOSampleBuffer::putSamples(uint nSamples)
{
@@ -126,31 +125,31 @@ void FIFOSampleBuffer::putSamples(uint nSamples)
}
-// Returns a pointer to the end of the used part of the sample buffer (i.e.
-// where the new samples are to be inserted). This function may be used for
-// inserting new samples into the sample buffer directly. Please be careful!
+// Returns a pointer to the end of the used part of the sample buffer (i.e.
+// where the new samples are to be inserted). This function may be used for
+// inserting new samples into the sample buffer directly. Please be careful!
//
// Parameter 'slackCapacity' tells the function how much free capacity (in
// terms of samples) there _at least_ should be, in order to the caller to
-// succesfully insert all the required samples to the buffer. When necessary,
+// succesfully insert all the required samples to the buffer. When necessary,
// the function grows the buffer size to comply with this requirement.
//
-// When using this function as means for inserting new samples, also remember
-// to increase the sample count afterwards, by calling the
+// When using this function as means for inserting new samples, also remember
+// to increase the sample count afterwards, by calling the
// 'putSamples(numSamples)' function.
-SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
+SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
{
ensureCapacity(samplesInBuffer + slackCapacity);
return buffer + samplesInBuffer * channels;
}
-// Returns a pointer to the beginning of the currently non-outputted samples.
-// This function is provided for accessing the output samples directly.
+// Returns a pointer to the beginning of the currently non-outputted samples.
+// This function is provided for accessing the output samples directly.
// Please be careful!
//
// When using this function to output samples, also remember to 'remove' the
-// outputted samples from the buffer by calling the
+// outputted samples from the buffer by calling the
// 'receiveSamples(numSamples)' function
SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
{
@@ -167,7 +166,7 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
{
SAMPLETYPE *tempUnaligned, *temp;
- if (capacityRequirement > getCapacity())
+ if (capacityRequirement > getCapacity())
{
// enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
@@ -175,10 +174,10 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
if (tempUnaligned == NULL)
{
- throw std::runtime_error("Couldn't allocate memory!\n");
+ ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
}
// Align the buffer to begin at 16byte cache line boundary for optimal performance
- temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16);
+ temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned);
if (samplesInBuffer)
{
memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
@@ -187,8 +186,8 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
buffer = temp;
bufferUnaligned = tempUnaligned;
bufferPos = 0;
- }
- else
+ }
+ else
{
// simply rewind the buffer (if necessary)
rewind();
@@ -260,3 +259,16 @@ void FIFOSampleBuffer::clear()
samplesInBuffer = 0;
bufferPos = 0;
}
+
+
+/// allow trimming (downwards) amount of samples in pipeline.
+/// Returns adjusted amount of samples
+uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
+{
+ if (numSamples < samplesInBuffer)
+ {
+ samplesInBuffer = numSamples;
+ }
+ return samplesInBuffer;
+}
+
diff --git a/3rdparty/SoundTouch/FIFOSampleBuffer.h b/3rdparty/SoundTouch/FIFOSampleBuffer.h
index ed31c8db63..5f1eb5f3da 100644
--- a/3rdparty/SoundTouch/FIFOSampleBuffer.h
+++ b/3rdparty/SoundTouch/FIFOSampleBuffer.h
@@ -1,12 +1,12 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// A buffer class for temporarily storaging sound samples, operates as a
+/// A buffer class for temporarily storaging sound samples, operates as a
/// first-in-first-out pipe.
///
-/// Samples are added to the end of the sample buffer with the 'putSamples'
+/// Samples are added to the end of the sample buffer with the 'putSamples'
/// function, and are received from the beginning of the buffer by calling
-/// the 'receiveSamples' function. The class automatically removes the
-/// output samples from the buffer as well as grows the storage size
+/// the 'receiveSamples' function. The class automatically removes the
+/// output samples from the buffer as well as grows the storage size
/// whenever necessary.
///
/// Author : Copyright (c) Olli Parviainen
@@ -15,10 +15,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $
+// Last changed : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $
// File revision : $Revision: 4 $
//
-// $Id: FIFOSampleBuffer.h 63 2009-02-21 16:00:14Z oparviai $
+// $Id: FIFOSampleBuffer.h 143 2012-06-13 19:29:53Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -54,7 +54,7 @@ namespace soundtouch
/// Sample buffer working in FIFO (first-in-first-out) principle. The class takes
/// care of storage size adjustment and data moving during input/output operations.
///
-/// Notice that in case of stereo audio, one sample is considered to consist of
+/// Notice that in case of stereo audio, one sample is considered to consist of
/// both channel data.
class FIFOSampleBuffer : public FIFOSamplePipe
{
@@ -75,12 +75,12 @@ private:
/// Channels, 1=mono, 2=stereo.
uint channels;
- /// Current position pointer to the buffer. This pointer is increased when samples are
+ /// Current position pointer to the buffer. This pointer is increased when samples are
/// removed from the pipe so that it's necessary to actually rewind buffer (move data)
/// only new data when is put to the pipe.
uint bufferPos;
- /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real
+ /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real
/// beginning of the buffer.
void rewind();
@@ -100,27 +100,27 @@ public:
/// destructor
~FIFOSampleBuffer();
- /// Returns a pointer to the beginning of the output samples.
- /// This function is provided for accessing the output samples directly.
+ /// Returns a pointer to the beginning of the output samples.
+ /// This function is provided for accessing the output samples directly.
/// Please be careful for not to corrupt the book-keeping!
///
/// When using this function to output samples, also remember to 'remove' the
- /// output samples from the buffer by calling the
+ /// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin();
- /// Returns a pointer to the end of the used part of the sample buffer (i.e.
- /// where the new samples are to be inserted). This function may be used for
+ /// Returns a pointer to the end of the used part of the sample buffer (i.e.
+ /// where the new samples are to be inserted). This function may be used for
/// inserting new samples into the sample buffer directly. Please be careful
/// not corrupt the book-keeping!
///
- /// When using this function as means for inserting new samples, also remember
- /// to increase the sample count afterwards, by calling the
+ /// When using this function as means for inserting new samples, also remember
+ /// to increase the sample count afterwards, by calling the
/// 'putSamples(numSamples)' function.
SAMPLETYPE *ptrEnd(
- uint slackCapacity ///< How much free capacity (in samples) there _at least_
- ///< should be so that the caller can succesfully insert the
- ///< desired samples to the buffer. If necessary, the function
+ uint slackCapacity ///< How much free capacity (in samples) there _at least_
+ ///< should be so that the caller can succesfully insert the
+ ///< desired samples to the buffer. If necessary, the function
///< grows the buffer size to comply with this requirement.
);
@@ -130,17 +130,17 @@ public:
uint numSamples ///< Number of samples to insert.
);
- /// Adjusts the book-keeping to increase number of samples in the buffer without
+ /// Adjusts the book-keeping to increase number of samples in the buffer without
/// copying any actual samples.
///
/// This function is used to update the number of samples in the sample buffer
- /// when accessing the buffer directly with 'ptrEnd' function. Please be
+ /// when accessing the buffer directly with 'ptrEnd' function. Please be
/// careful though!
virtual void putSamples(uint numSamples ///< Number of samples been inserted.
);
- /// Output samples from beginning of the sample buffer. Copies requested samples to
- /// output buffer and removes them from the sample buffer. If there are less than
+ /// Output samples from beginning of the sample buffer. Copies requested samples to
+ /// output buffer and removes them from the sample buffer. If there are less than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
@@ -148,8 +148,8 @@ public:
uint maxSamples ///< How many samples to receive at max.
);
- /// Adjusts book-keeping so that given number of samples are removed from beginning of the
- /// sample buffer without copying them anywhere.
+ /// Adjusts book-keeping so that given number of samples are removed from beginning of the
+ /// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
@@ -167,6 +167,10 @@ public:
/// Clears all the samples.
virtual void clear();
+
+ /// allow trimming (downwards) amount of samples in pipeline.
+ /// Returns adjusted amount of samples
+ uint adjustAmountOfSamples(uint numSamples);
};
}
diff --git a/3rdparty/SoundTouch/FIFOSamplePipe.h b/3rdparty/SoundTouch/FIFOSamplePipe.h
index 31dc40f93d..805e92597e 100644
--- a/3rdparty/SoundTouch/FIFOSamplePipe.h
+++ b/3rdparty/SoundTouch/FIFOSamplePipe.h
@@ -5,7 +5,7 @@
/// into one end of the pipe with the 'putSamples' function, and the processed
/// samples are received from the other end with the 'receiveSamples' function.
///
-/// 'FIFOProcessor' : A base class for classes the do signal processing with
+/// 'FIFOProcessor' : A base class for classes the do signal processing with
/// the samples while operating like a first-in-first-out pipe. When samples
/// are input with the 'putSamples' function, the class processes them
/// and moves the processed samples to the given 'output' pipe object, which
@@ -17,10 +17,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-04-13 16:18:48 +0300 (Mon, 13 Apr 2009) $
+// Last changed : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $
// File revision : $Revision: 4 $
//
-// $Id: FIFOSamplePipe.h 69 2009-04-13 13:18:48Z oparviai $
+// $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -63,12 +63,12 @@ public:
virtual ~FIFOSamplePipe() {}
- /// Returns a pointer to the beginning of the output samples.
- /// This function is provided for accessing the output samples directly.
+ /// Returns a pointer to the beginning of the output samples.
+ /// This function is provided for accessing the output samples directly.
/// Please be careful for not to corrupt the book-keeping!
///
/// When using this function to output samples, also remember to 'remove' the
- /// output samples from the buffer by calling the
+ /// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin() = 0;
@@ -89,8 +89,8 @@ public:
other.receiveSamples(oNumSamples);
};
- /// Output samples from beginning of the sample buffer. Copies requested samples to
- /// output buffer and removes them from the sample buffer. If there are less than
+ /// Output samples from beginning of the sample buffer. Copies requested samples to
+ /// output buffer and removes them from the sample buffer. If there are less than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
@@ -98,8 +98,8 @@ public:
uint maxSamples ///< How many samples to receive at max.
) = 0;
- /// Adjusts book-keeping so that given number of samples are removed from beginning of the
- /// sample buffer without copying them anywhere.
+ /// Adjusts book-keeping so that given number of samples are removed from beginning of the
+ /// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
@@ -114,16 +114,21 @@ public:
/// Clears all the samples.
virtual void clear() = 0;
+
+ /// allow trimming (downwards) amount of samples in pipeline.
+ /// Returns adjusted amount of samples
+ virtual uint adjustAmountOfSamples(uint numSamples) = 0;
+
};
-/// Base-class for sound processing routines working in FIFO principle. With this base
+/// Base-class for sound processing routines working in FIFO principle. With this base
/// class it's easy to implement sound processing stages that can be chained together,
-/// so that samples that are fed into beginning of the pipe automatically go through
+/// so that samples that are fed into beginning of the pipe automatically go through
/// all the processing stages.
///
-/// When samples are input to this class, they're first processed and then put to
+/// When samples are input to this class, they're first processed and then put to
/// the FIFO pipe that's defined as output of this class. This output pipe can be
/// either other processing stage or a FIFO sample buffer.
class FIFOProcessor :public FIFOSamplePipe
@@ -141,7 +146,7 @@ protected:
}
- /// Constructor. Doesn't define output pipe; it has to be set be
+ /// Constructor. Doesn't define output pipe; it has to be set be
/// 'setOutPipe' function.
FIFOProcessor()
{
@@ -163,12 +168,12 @@ protected:
}
- /// Returns a pointer to the beginning of the output samples.
- /// This function is provided for accessing the output samples directly.
+ /// Returns a pointer to the beginning of the output samples.
+ /// This function is provided for accessing the output samples directly.
/// Please be careful for not to corrupt the book-keeping!
///
/// When using this function to output samples, also remember to 'remove' the
- /// output samples from the buffer by calling the
+ /// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin()
{
@@ -177,8 +182,8 @@ protected:
public:
- /// Output samples from beginning of the sample buffer. Copies requested samples to
- /// output buffer and removes them from the sample buffer. If there are less than
+ /// Output samples from beginning of the sample buffer. Copies requested samples to
+ /// output buffer and removes them from the sample buffer. If there are less than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
@@ -190,8 +195,8 @@ public:
}
- /// Adjusts book-keeping so that given number of samples are removed from beginning of the
- /// sample buffer without copying them anywhere.
+ /// Adjusts book-keeping so that given number of samples are removed from beginning of the
+ /// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
@@ -214,6 +219,14 @@ public:
{
return output->isEmpty();
}
+
+ /// allow trimming (downwards) amount of samples in pipeline.
+ /// Returns adjusted amount of samples
+ virtual uint adjustAmountOfSamples(uint numSamples)
+ {
+ return output->adjustAmountOfSamples(numSamples);
+ }
+
};
}
diff --git a/3rdparty/SoundTouch/FIRFilter.cpp b/3rdparty/SoundTouch/FIRFilter.cpp
index 9f7351dce8..13a1896ce7 100644
--- a/3rdparty/SoundTouch/FIRFilter.cpp
+++ b/3rdparty/SoundTouch/FIRFilter.cpp
@@ -1,8 +1,8 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// General FIR digital filter routines with MMX optimization.
+/// General FIR digital filter routines with MMX optimization.
///
-/// Note : MMX optimized functions reside in a separate, platform-specific file,
+/// Note : MMX optimized functions reside in a separate, platform-specific file,
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
///
/// Author : Copyright (c) Olli Parviainen
@@ -11,10 +11,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $
+// Last changed : $Date: 2011-09-02 15:56:11 -0300 (sex, 02 set 2011) $
// File revision : $Revision: 4 $
//
-// $Id: FIRFilter.cpp 67 2009-02-25 17:13:51Z oparviai $
+// $Id: FIRFilter.cpp 131 2011-09-02 18:56:11Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -43,7 +43,6 @@
#include
#include
#include
-#include
#include "FIRFilter.h"
#include "cpu_detect.h"
@@ -75,7 +74,7 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
{
uint i, j, end;
LONG_SAMPLETYPE suml, sumr;
-#ifdef FLOAT_SAMPLES
+#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
@@ -88,14 +87,14 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
end = 2 * (numSamples - length);
- for (j = 0; j < end; j += 2)
+ for (j = 0; j < end; j += 2)
{
const SAMPLETYPE *ptr;
suml = sumr = 0;
ptr = src + j;
- for (i = 0; i < length; i += 4)
+ for (i = 0; i < length; i += 4)
{
// loop is unrolled by factor of 4 here for efficiency
suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
@@ -108,7 +107,7 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
ptr[2 * i + 7] * filterCoeffs[i + 3];
}
-#ifdef INTEGER_SAMPLES
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
suml >>= resultDivFactor;
sumr >>= resultDivFactor;
// saturate to 16 bit integer limits
@@ -118,7 +117,7 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
#else
suml *= dScaler;
sumr *= dScaler;
-#endif // INTEGER_SAMPLES
+#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)suml;
dest[j + 1] = (SAMPLETYPE)sumr;
}
@@ -133,7 +132,7 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint
{
uint i, j, end;
LONG_SAMPLETYPE sum;
-#ifdef FLOAT_SAMPLES
+#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
@@ -143,24 +142,24 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint
assert(length != 0);
end = numSamples - length;
- for (j = 0; j < end; j ++)
+ for (j = 0; j < end; j ++)
{
sum = 0;
- for (i = 0; i < length; i += 4)
+ for (i = 0; i < length; i += 4)
{
// loop is unrolled by factor of 4 here for efficiency
- sum += src[i + 0] * filterCoeffs[i + 0] +
- src[i + 1] * filterCoeffs[i + 1] +
- src[i + 2] * filterCoeffs[i + 2] +
+ sum += src[i + 0] * filterCoeffs[i + 0] +
+ src[i + 1] * filterCoeffs[i + 1] +
+ src[i + 2] * filterCoeffs[i + 2] +
src[i + 3] * filterCoeffs[i + 3];
}
-#ifdef INTEGER_SAMPLES
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
sum >>= resultDivFactor;
// saturate to 16 bit integer limits
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
#else
sum *= dScaler;
-#endif // INTEGER_SAMPLES
+#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)sum;
src ++;
}
@@ -174,7 +173,7 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint
void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
{
assert(newLength > 0);
- if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8");
+ if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
lengthDiv8 = newLength / 8;
length = lengthDiv8 * 8;
@@ -196,9 +195,9 @@ uint FIRFilter::getLength() const
-// Applies the filter to the given sequence of samples.
+// Applies the filter to the given sequence of samples.
//
-// Note : The amount of outputted samples is by value of 'filter_length'
+// Note : The amount of outputted samples is by value of 'filter_length'
// smaller than the amount of input samples.
uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
{
@@ -207,7 +206,7 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample
assert(length > 0);
assert(lengthDiv8 * 8 == length);
if (numSamples < length) return 0;
- if (numChannels == 2)
+ if (numChannels == 2)
{
return evaluateFilterStereo(dest, src, numSamples);
} else {
@@ -217,13 +216,13 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample
-// Operator 'new' is overloaded so that it automatically creates a suitable instance
+// Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX-capable CPU available or not.
void * FIRFilter::operator new(size_t s)
{
// Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
- throw std::runtime_error("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
- return NULL;
+ ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
+ return newInstance();
}
@@ -233,34 +232,25 @@ FIRFilter * FIRFilter::newInstance()
uExtensions = detectCPUextensions();
- // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
+ // Check if MMX/SSE instruction set extensions supported by CPU
-#ifdef ALLOW_MMX
+#ifdef SOUNDTOUCH_ALLOW_MMX
// MMX routines available only with integer sample types
if (uExtensions & SUPPORT_MMX)
{
return ::new FIRFilterMMX;
}
else
-#endif // ALLOW_MMX
+#endif // SOUNDTOUCH_ALLOW_MMX
-#ifdef ALLOW_SSE
+#ifdef SOUNDTOUCH_ALLOW_SSE
if (uExtensions & SUPPORT_SSE)
{
// SSE support
return ::new FIRFilterSSE;
}
else
-#endif // ALLOW_SSE
-
-#ifdef ALLOW_3DNOW
- if (uExtensions & SUPPORT_3DNOW)
- {
- // 3DNow! support
- return ::new FIRFilter3DNow;
- }
- else
-#endif // ALLOW_3DNOW
+#endif // SOUNDTOUCH_ALLOW_SSE
{
// ISA optimizations not supported, use plain C version
diff --git a/3rdparty/SoundTouch/FIRFilter.h b/3rdparty/SoundTouch/FIRFilter.h
index 2899c9bfd7..b593167452 100644
--- a/3rdparty/SoundTouch/FIRFilter.h
+++ b/3rdparty/SoundTouch/FIRFilter.h
@@ -1,8 +1,8 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// General FIR digital filter routines with MMX optimization.
+/// General FIR digital filter routines with MMX optimization.
///
-/// Note : MMX optimized functions reside in a separate, platform-specific file,
+/// Note : MMX optimized functions reside in a separate, platform-specific file,
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
///
/// Author : Copyright (c) Olli Parviainen
@@ -11,10 +11,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $
+// Last changed : $Date: 2011-02-13 17:13:57 -0200 (dom, 13 fev 2011) $
// File revision : $Revision: 4 $
//
-// $Id: FIRFilter.h 63 2009-02-21 16:00:14Z oparviai $
+// $Id: FIRFilter.h 104 2011-02-13 19:13:57Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -48,11 +48,11 @@
namespace soundtouch
{
-class FIRFilter
+class FIRFilter
{
protected:
// Number of FIR filter taps
- uint length;
+ uint length;
// Number of FIR filter taps divided by 8
uint lengthDiv8;
@@ -65,44 +65,44 @@ protected:
// Memory for filter coefficients
SAMPLETYPE *filterCoeffs;
- virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples) const;
- virtual uint evaluateFilterMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint evaluateFilterMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples) const;
public:
FIRFilter();
virtual ~FIRFilter();
- /// Operator 'new' is overloaded so that it automatically creates a suitable instance
+ /// Operator 'new' is overloaded so that it automatically creates a suitable instance
/// depending on if we've a MMX-capable CPU available or not.
static void * operator new(size_t s);
static FIRFilter *newInstance();
- /// Applies the filter to the given sequence of samples.
- /// Note : The amount of outputted samples is by value of 'filter_length'
+ /// Applies the filter to the given sequence of samples.
+ /// Note : The amount of outputted samples is by value of 'filter_length'
/// smaller than the amount of input samples.
///
/// \return Number of samples copied to 'dest'.
- uint evaluate(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples,
+ uint evaluate(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ uint numSamples,
uint numChannels) const;
uint getLength() const;
- virtual void setCoefficients(const SAMPLETYPE *coeffs,
- uint newLength,
+ virtual void setCoefficients(const SAMPLETYPE *coeffs,
+ uint newLength,
uint uResultDivFactor);
};
// Optional subclasses that implement CPU-specific optimizations:
-#ifdef ALLOW_MMX
+#ifdef SOUNDTOUCH_ALLOW_MMX
/// Class that implements MMX optimized functions exclusive for 16bit integer samples type.
class FIRFilterMMX : public FIRFilter
@@ -119,29 +119,10 @@ public:
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
};
-#endif // ALLOW_MMX
+#endif // SOUNDTOUCH_ALLOW_MMX
-#ifdef ALLOW_3DNOW
-
- /// Class that implements 3DNow! optimized functions exclusive for floating point samples type.
- class FIRFilter3DNow : public FIRFilter
- {
- protected:
- float *filterCoeffsUnalign;
- float *filterCoeffsAlign;
-
- virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
- public:
- FIRFilter3DNow();
- ~FIRFilter3DNow();
- virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
- };
-
-#endif // ALLOW_3DNOW
-
-
-#ifdef ALLOW_SSE
+#ifdef SOUNDTOUCH_ALLOW_SSE
/// Class that implements SSE optimized functions exclusive for floating point samples type.
class FIRFilterSSE : public FIRFilter
{
@@ -157,7 +138,7 @@ public:
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
};
-#endif // ALLOW_SSE
+#endif // SOUNDTOUCH_ALLOW_SSE
}
diff --git a/3rdparty/SoundTouch/Makefile.am b/3rdparty/SoundTouch/Makefile.am
index eb39bcc96f..709f0cbd23 100644
--- a/3rdparty/SoundTouch/Makefile.am
+++ b/3rdparty/SoundTouch/Makefile.am
@@ -1,42 +1,71 @@
## Process this file with automake to create Makefile.in
##
-## $Id: Makefile.am,v 1.3 2006/02/05 18:33:34 Olli Exp $
-##
-## Copyright (C) 2003 - David W. Durham
+## $Id: Makefile.am 138 2012-04-01 20:00:09Z oparviai $
##
## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
-##
+##
## SoundTouch is free software; you can redistribute it and/or modify it under the
## terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
-##
+##
## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
## A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-##
+##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the Free Software Foundation, Inc., 59 Temple
## Place - Suite 330, Boston, MA 02111-1307, USA
-AUTOMAKE_OPTIONS = foreign
-noinst_HEADERS=AAFilter.h cpu_detect.h FIRFilter.h RateTransposer.h TDStretch.h cpu_detect_x86_gcc.cpp
-noinst_LIBRARIES = libSoundTouch.a
+include $(top_srcdir)/config/am_include.mk
-libSoundTouch_a_CXXFLAGS = -msse -mmmx
-libSoundTouch_a_CFLAGS = -msse -mmmx
-#lib_LTLIBRARIES=libSoundTouch.la
-# the mmx_gcc.cpp and cpu_detect_x86_gcc.cpp may need to be conditionally included here from things discovered in configure.ac
-libSoundTouch_a_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp mmx_optimized.cpp sse_optimized.cpp \
-RateTransposer.cpp SoundTouch.cpp TDStretch.cpp WavFile.cpp cpu_detect_x86_gcc.cpp
+# set to something if you want other stuff to be included in the distribution tarball
+EXTRA_DIST=SoundTouch.dsp SoundTouch.dsw SoundTouch.sln SoundTouch.vcproj
+
+noinst_HEADERS=AAFilter.h cpu_detect.h cpu_detect_x86.cpp FIRFilter.h RateTransposer.h TDStretch.h PeakFinder.h
+
+lib_LTLIBRARIES=libSoundTouch.la
+#
+libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp RateTransposer.cpp SoundTouch.cpp TDStretch.cpp cpu_detect_x86.cpp BPMDetect.cpp PeakFinder.cpp
+
+
+# Compiler flags
+AM_CXXFLAGS=-O3 -fcheck-new -I../../include
+
+# Compile the files that need MMX and SSE individually.
+libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la
+noinst_LTLIBRARIES=libSoundTouchMMX.la libSoundTouchSSE.la
+libSoundTouchMMX_la_SOURCES=mmx_optimized.cpp
+libSoundTouchSSE_la_SOURCES=sse_optimized.cpp
+
+# We enable optimizations by default.
+# If MMX is supported compile with -mmmx.
+# Do not assume -msse is also supported.
+if HAVE_MMX
+libSoundTouchMMX_la_CXXFLAGS = -mmmx $(AM_CXXFLAGS)
+else
+libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS)
+endif
+
+# We enable optimizations by default.
+# If SSE is supported compile with -msse.
+if HAVE_SSE
+libSoundTouchSSE_la_CXXFLAGS = -msse $(AM_CXXFLAGS)
+else
+libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS)
+endif
+
+# Let the user disable optimizations if he wishes to.
+if !X86_OPTIMIZATIONS
+libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS)
+libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS)
+endif
-# ??? test for -fcheck-new in configure.ac
-# other compiler flags to add
-AM_CXXFLAGS=-O3 -msse -fcheck-new
-#-I../../include
# other linking flags to add
-#libSoundTouch_la_LIBADD=
-
+# noinst_LTLIBRARIES = libSoundTouchOpt.la
+# libSoundTouch_la_LIBADD = libSoundTouchOpt.la
+# libSoundTouchOpt_la_SOURCES = mmx_optimized.cpp sse_optimized.cpp
+# libSoundTouchOpt_la_CXXFLAGS = -O3 -msse -fcheck-new -I../../include
diff --git a/3rdparty/SoundTouch/PeakFinder.cpp b/3rdparty/SoundTouch/PeakFinder.cpp
new file mode 100644
index 0000000000..71203983f6
--- /dev/null
+++ b/3rdparty/SoundTouch/PeakFinder.cpp
@@ -0,0 +1,276 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Peak detection routine.
+///
+/// The routine detects highest value on an array of values and calculates the
+/// precise peak location as a mass-center of the 'hump' around the peak value.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// Last changed : $Date: 2012-12-28 17:52:47 -0200 (sex, 28 dez 2012) $
+// File revision : $Revision: 4 $
+//
+// $Id: PeakFinder.cpp 164 2012-12-28 19:52:47Z oparviai $
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// License :
+//
+// SoundTouch audio processing library
+// Copyright (c) Olli Parviainen
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+
+#include "PeakFinder.h"
+
+using namespace soundtouch;
+
+#define max(x, y) (((x) > (y)) ? (x) : (y))
+
+
+PeakFinder::PeakFinder()
+{
+ minPos = maxPos = 0;
+}
+
+
+// Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
+int PeakFinder::findTop(const float *data, int peakpos) const
+{
+ int i;
+ int start, end;
+ float refvalue;
+
+ refvalue = data[peakpos];
+
+ // seek within ±10 points
+ start = peakpos - 10;
+ if (start < minPos) start = minPos;
+ end = peakpos + 10;
+ if (end > maxPos) end = maxPos;
+
+ for (i = start; i <= end; i ++)
+ {
+ if (data[i] > refvalue)
+ {
+ peakpos = i;
+ refvalue = data[i];
+ }
+ }
+
+ // failure if max value is at edges of seek range => it's not peak, it's at slope.
+ if ((peakpos == start) || (peakpos == end)) return 0;
+
+ return peakpos;
+}
+
+
+// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding
+// to direction defined by 'direction' until next 'hump' after minimum value will
+// begin
+int PeakFinder::findGround(const float *data, int peakpos, int direction) const
+{
+ int lowpos;
+ int pos;
+ int climb_count;
+ float refvalue;
+ float delta;
+
+ climb_count = 0;
+ refvalue = data[peakpos];
+ lowpos = peakpos;
+
+ pos = peakpos;
+
+ while ((pos > minPos+1) && (pos < maxPos-1))
+ {
+ int prevpos;
+
+ prevpos = pos;
+ pos += direction;
+
+ // calculate derivate
+ delta = data[pos] - data[prevpos];
+ if (delta <= 0)
+ {
+ // going downhill, ok
+ if (climb_count)
+ {
+ climb_count --; // decrease climb count
+ }
+
+ // check if new minimum found
+ if (data[pos] < refvalue)
+ {
+ // new minimum found
+ lowpos = pos;
+ refvalue = data[pos];
+ }
+ }
+ else
+ {
+ // going uphill, increase climbing counter
+ climb_count ++;
+ if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit
+ }
+ }
+ return lowpos;
+}
+
+
+// Find offset where the value crosses the given level, when starting from 'peakpos' and
+// proceeds to direction defined in 'direction'
+int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const
+{
+ float peaklevel;
+ int pos;
+
+ peaklevel = data[peakpos];
+ assert(peaklevel >= level);
+ pos = peakpos;
+ while ((pos >= minPos) && (pos < maxPos))
+ {
+ if (data[pos + direction] < level) return pos; // crossing found
+ pos += direction;
+ }
+ return -1; // not found
+}
+
+
+// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos'
+double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const
+{
+ int i;
+ float sum;
+ float wsum;
+
+ sum = 0;
+ wsum = 0;
+ for (i = firstPos; i <= lastPos; i ++)
+ {
+ sum += (float)i * data[i];
+ wsum += data[i];
+ }
+
+ if (wsum < 1e-6) return 0;
+ return sum / wsum;
+}
+
+
+
+/// get exact center of peak near given position by calculating local mass of center
+double PeakFinder::getPeakCenter(const float *data, int peakpos) const
+{
+ float peakLevel; // peak level
+ int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level
+ float cutLevel; // cutting value
+ float groundLevel; // ground level of the peak
+ int gp1, gp2; // bottom positions of the peak 'hump'
+
+ // find ground positions.
+ gp1 = findGround(data, peakpos, -1);
+ gp2 = findGround(data, peakpos, 1);
+
+ groundLevel = 0.5f * (data[gp1] + data[gp2]);
+ peakLevel = data[peakpos];
+
+ // calculate 70%-level of the peak
+ cutLevel = 0.70f * peakLevel + 0.30f * groundLevel;
+ // find mid-level crossings
+ crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1);
+ crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1);
+
+ if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak..
+
+ // calculate mass center of the peak surroundings
+ return calcMassCenter(data, crosspos1, crosspos2);
+}
+
+
+
+double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
+{
+
+ int i;
+ int peakpos; // position of peak level
+ double highPeak, peak;
+
+ this->minPos = aminPos;
+ this->maxPos = amaxPos;
+
+ // find absolute peak
+ peakpos = minPos;
+ peak = data[minPos];
+ for (i = minPos + 1; i < maxPos; i ++)
+ {
+ if (data[i] > peak)
+ {
+ peak = data[i];
+ peakpos = i;
+ }
+ }
+
+ // Calculate exact location of the highest peak mass center
+ highPeak = getPeakCenter(data, peakpos);
+ peak = highPeak;
+
+ // Now check if the highest peak were in fact harmonic of the true base beat peak
+ // - sometimes the highest peak can be Nth harmonic of the true base peak yet
+ // just a slightly higher than the true base
+
+ for (i = 3; i < 10; i ++)
+ {
+ double peaktmp, harmonic;
+ int i1,i2;
+
+ harmonic = (double)i * 0.5;
+ peakpos = (int)(highPeak / harmonic + 0.5f);
+ if (peakpos < minPos) break;
+ peakpos = findTop(data, peakpos); // seek true local maximum index
+ if (peakpos == 0) continue; // no local max here
+
+ // calculate mass-center of possible harmonic peak
+ peaktmp = getPeakCenter(data, peakpos);
+
+ // accept harmonic peak if
+ // (a) it is found
+ // (b) is within ±4% of the expected harmonic interval
+ // (c) has at least half x-corr value of the max. peak
+
+ double diff = harmonic * peaktmp / highPeak;
+ if ((diff < 0.96) || (diff > 1.04)) continue; // peak too afar from expected
+
+ // now compare to highest detected peak
+ i1 = (int)(highPeak + 0.5);
+ i2 = (int)(peaktmp + 0.5);
+ if (data[i2] >= 0.4*data[i1])
+ {
+ // The harmonic is at least half as high primary peak,
+ // thus use the harmonic peak instead
+ peak = peaktmp;
+ }
+ }
+
+ return peak;
+}
diff --git a/3rdparty/SoundTouch/PeakFinder.h b/3rdparty/SoundTouch/PeakFinder.h
new file mode 100644
index 0000000000..c781643304
--- /dev/null
+++ b/3rdparty/SoundTouch/PeakFinder.h
@@ -0,0 +1,97 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// The routine detects highest value on an array of values and calculates the
+/// precise peak location as a mass-center of the 'hump' around the peak value.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// Last changed : $Date: 2011-12-30 18:33:46 -0200 (sex, 30 dez 2011) $
+// File revision : $Revision: 4 $
+//
+// $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// License :
+//
+// SoundTouch audio processing library
+// Copyright (c) Olli Parviainen
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _PeakFinder_H_
+#define _PeakFinder_H_
+
+namespace soundtouch
+{
+
+class PeakFinder
+{
+protected:
+ /// Min, max allowed peak positions within the data vector
+ int minPos, maxPos;
+
+ /// Calculates the mass center between given vector items.
+ double calcMassCenter(const float *data, ///< Data vector.
+ int firstPos, ///< Index of first vector item beloging to the peak.
+ int lastPos ///< Index of last vector item beloging to the peak.
+ ) const;
+
+ /// Finds the data vector index where the monotoniously decreasing signal crosses the
+ /// given level.
+ int findCrossingLevel(const float *data, ///< Data vector.
+ float level, ///< Goal crossing level.
+ int peakpos, ///< Peak position index within the data vector.
+ int direction /// Direction where to proceed from the peak: 1 = right, -1 = left.
+ ) const;
+
+ // Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
+ int findTop(const float *data, int peakpos) const;
+
+
+ /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right-
+ /// or left-hand side of the given peak position.
+ int findGround(const float *data, /// Data vector.
+ int peakpos, /// Peak position index within the data vector.
+ int direction /// Direction where to proceed from the peak: 1 = right, -1 = left.
+ ) const;
+
+ /// get exact center of peak near given position by calculating local mass of center
+ double getPeakCenter(const float *data, int peakpos) const;
+
+public:
+ /// Constructor.
+ PeakFinder();
+
+ /// Detect exact peak position of the data vector by finding the largest peak 'hump'
+ /// and calculating the mass-center location of the peak hump.
+ ///
+ /// \return The location of the largest base harmonic peak hump.
+ double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has
+ /// to be at least 'maxPos' items long.
+ int minPos, ///< Min allowed peak location within the vector data.
+ int maxPos ///< Max allowed peak location within the vector data.
+ );
+};
+
+}
+
+#endif // _PeakFinder_H_
diff --git a/3rdparty/SoundTouch/README.html b/3rdparty/SoundTouch/README.html
index 15a34c8648..5b2bcbb240 100644
--- a/3rdparty/SoundTouch/README.html
+++ b/3rdparty/SoundTouch/README.html
@@ -1,6 +1,7 @@
+ SoundTouch library README
@@ -9,32 +10,26 @@
content="Readme file for SoundTouch audio processing library">
- SoundTouch library README
-
+
-SoundTouch audio processing library v1.5.0
-
-SoundTouch library Copyright (c) Olli
-Parviainen 2002-2009
+SoundTouch audio processing library v1.7.1
+SoundTouch library Copyright © Olli Parviainen 2001-2012
1. Introduction
-SoundTouch is an open-source audio
-processing library that allows changing the sound tempo, pitch
-and playback rate parameters independently from each other, i.e.:
+SoundTouch is an open-source audio processing library that allows
+changing the sound tempo, pitch and playback rate parameters
+independently from each other, i.e.:
- - Sound tempo can be increased or decreased while
-maintaining the original pitch
- - Sound pitch can be increased or decreased while
-maintaining the original tempo
- - Change playback rate that affects both tempo
-and pitch at the same time
- - Choose any combination of tempo/pitch/rate
+ - Sound tempo can be increased or decreased while maintaining the
+original pitch
+ - Sound pitch can be increased or decreased while maintaining the
+original tempo
+ - Change playback rate that affects both tempo and pitch at the
+same time
+ - Choose any combination of tempo/pitch/rate
1.1 Contact information
Author email: oparviai 'at' iki.fi
@@ -42,50 +37,54 @@ and pitch at the same time
2. Compiling SoundTouch
Before compiling, notice that you can choose the sample data format
-if it's desirable to use floating point sample
-data instead of 16bit integers. See section "sample data format"
-for more information.
+if it's desirable to use floating point sample data instead of 16bit
+integers. See section "sample data format" for more information.
2.1. Building in Microsoft Windows
Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are
-supplied with the source code package.
- Please notice that SoundTouch
-library uses processor-specific optimizations for Pentium III and AMD
-processors. Visual Studio .NET and later versions supports the required
-instructions by default, but Visual Studio 6.0 requires a processor pack upgrade
-to be installed in order to support these optimizations. The processor pack upgrade can be downloaded from
-Microsoft site at this URL:
-http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx
-If the above URL is unavailable or removed, go
-to http://msdn.microsoft.com
-and perform a search with keywords "processor pack".
-To build the binaries with Visual C++
-compiler, either run "make-win.bat" script, or open the
-appropriate project files in source code directories with Visual
-Studio. The final executable will appear under the "SoundTouch\bin"
-directory. If using the Visual Studio IDE instead of the make-win.bat script, directories bin and
-lib may need to be created manually to the SoundTouch
-package root for the final executables. The make-win.bat script
-creates these directories automatically.
+supplied with the source code package.
+ Please notice that SoundTouch library uses processor-specific
+optimizations for Pentium III and AMD processors. Visual Studio .NET
+and later versions supports the required instructions by default, but
+Visual Studio 6.0 requires a processor pack upgrade to be installed in
+order to support these optimizations. The processor pack upgrade can be
+downloaded from Microsoft site at this URL:
+http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx
+If the above URL is unavailable or removed, go to http://msdn.microsoft.com and
+perform a search with keywords "processor pack".
+To build the binaries with Visual C++ compiler, either run
+"make-win.bat" script, or open the appropriate project files in source
+code directories with Visual Studio. The final executable will appear
+under the "SoundTouch\bin" directory. If using the Visual Studio IDE
+instead of the make-win.bat script, directories bin and lib may need to
+be created manually to the SoundTouch package root for the final
+executables. The make-win.bat script creates these directories
+automatically.
2.2. Building in Gnu platforms
-The SoundTouch library can be compiled in
-practically any platform supporting GNU compiler (GCC) tools.
-SoundTouch have been tested with gcc version 3.3.4., but it
-shouldn't be very specific about the gcc version. Assembler-level
-performance optimizations for GNU platform are currently available in
-x86 platforms only, they are automatically disabled and replaced with
-standard C routines in other processor platforms.
-To build and install the binaries, run the
-following commands in the SoundTouch/ directory:
+The SoundTouch library compiles in practically any platform
+supporting GNU compiler (GCC) tools. SoundTouch requires GCC version 4.3 or later.
+To build and install the binaries, run the following commands in
+/soundtouch directory:
+
+
+ ./bootstrap -
+ |
+ Creates "configure" file with
+local autoconf/automake toolset.
+ |
+
./configure -
|
- Configures the SoundTouch package for the local
-environment.
+ Configures the SoundTouch package for the local environment.
+Notice that "configure" file is not available before running the
+"./bootstrap" command as above.
+
|
@@ -93,8 +92,7 @@ environment.
make -
- Builds the SoundTouch library &
-SoundStretch utility.
+ Builds the SoundTouch library & SoundStretch utility.
|
@@ -102,175 +100,163 @@ SoundStretch utility.
make install -
- Installs the SoundTouch & BPM libraries
-to /usr/local/lib and SoundStretch utility to /usr/local/bin.
-Please notice that 'root' privileges may be required to install the
-binaries to the destination locations.
+ Installs the SoundTouch & BPM libraries to /usr/local/lib
+and SoundStretch utility to /usr/local/bin. Please notice that
+'root' privileges may be required to install the binaries to the
+destination locations.
|
2.2.1 Required GNU tools
- Bash shell, GNU C++ compiler, libtool, autoconf and automake tools are required
-for compiling
-the SoundTouch library. These are usually included with the GNU/Linux distribution, but if
-not, install these packages first. For example, in Ubuntu Linux these can be acquired and
-installed with the following command:
-sudo apt-get install automake autoconf libtool build-essential
+ Bash shell, GNU C++ compiler, libtool, autoconf and automake tools
+are required for compiling the SoundTouch library. These are usually
+included with the GNU/Linux distribution, but if not, install these
+packages first. For example, Ubuntu Linux can acquire and install
+these with the following command:
+sudo apt-get install automake autoconf libtool build-essential
2.2.2 Problems with GCC compiler compatibility
-At the release time the SoundTouch package has been tested to compile in
-GNU/Linux platform. However, in past it's happened that new gcc versions aren't
-necessarily compatible with the assembler settings used in the optimized
-routines. If you have problems getting the
-SoundTouch library compiled, try the workaround of disabling the optimizations
-by editing the file "include/STTypes.h" and removing the following
-definition there:
+At the release time the SoundTouch package has been tested to
+compile in GNU/Linux platform. However, If you have problems getting the
+SoundTouch library compiled, try disabling optimizations that are specific for
+x86 processors by running ./configure script with switch
- #define ALLOW_OPTIMIZATIONS 1
+--enable-x86-optimizations=no
-2.2.3 Problems with configure script or build process
-Incompatibilities between various GNU toolchain versions may cause errors when running the "configure" script or building the source
-codes, if your GNU tool versions are not compatible with the versions used for
-preparing the SoundTouch kit.
-To resolve the issue, regenerate the configure scripts with your local tool
-set by running
-the "./bootstrap" script included in the SoundTouch source code
-kit. After that, run the configure script and make as usually.
-2.2.4 Compiler issues with non-x86 processors
-SoundTouch library works also on non-x86 processors.
-However, in case that you get compiler errors when trying to compile for non-Intel processor, edit the file
-"source\SoundTouch\Makefile.am" and remove the "-msse2"
-flag on the AM_CXXFLAGS line:
-AM_CXXFLAGS=-O3 -fcheck-new -I../../include # Note: -msse2 flag removed!
-After that, run "./bootstrap" script, and then run configure
-and make again.
+
+Alternatively, if you don't use GNU Configure system, edit file "include/STTypes.h"
+directly and remove the following definition:
+ #define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
+
+
+2.2.3 Compiling Shared Library / DLL version
+
+ The GNU compilation does not automatically create a shared-library version of
+ SoundTouch (.so or .dll). If such is desired, then you can create it as follows
+ after running the usual compilation:
+
+ g++ -shared -static -DDLL_EXPORTS -I../../include -o SoundTouch.dll \
+ SoundTouchDLL.cpp ../SoundTouch/.libs/libSoundTouch.a
+sstrip SoundTouch.dll
+
+
+2.1. Building in Android
+Android compilation instructions are within the
+ source code package, see file "source/Android-lib/README-SoundTouch-Android.html"
+ in the package.
+
-3. About implementation & Usage tips
-3.1. Supported sample data formats
-The sample data format can be chosen
-between 16bit signed integer and 32bit floating point values, the
-default is 32bit floating point.
-
-
-In Windows environment, the sample data format is chosen
-in file "STTypes.h" by choosing one of the following
-defines:
+3. About implementation & Usage tips 3.1. Supported sample data formats
+
The sample data format can be chosen between 16bit signed integer
+and 32bit floating point values, the default is 32bit floating point.
+ In Windows environment, the sample data format is chosen in file
+"STTypes.h" by choosing one of the following defines:
- - #define INTEGER_SAMPLES
-for 16bit signed
-integer
- - #define FLOAT_SAMPLES for
-32bit floating point
+ - #define
+SOUNDTOUCH_INTEGER_SAMPLES for 16bit signed integer
+ - #define SOUNDTOUCH_FLOAT_SAMPLES for 32bit floating
+point
-
-In GNU environment, the floating sample format is used by default, but
-integer sample format can be chosen by giving the
-following switch to the configure script:
+
In GNU environment, the floating sample format is used by default,
+but integer sample format can be chosen by giving the following switch
+to the configure script:
-./configure --enable-integer-samples
+ ./configure --enable-integer-samples
-
-The sample data can have either single (mono)
-or double (stereo) audio channel. Stereo data is interleaved so
-that every other data value is for left channel and every second
-for right channel. Notice that while it'd be possible in theory
-to process stereo sound as two separate mono channels, this isn't
-recommended because processing the channels separately would
-result in losing the phase coherency between the channels, which
-consequently would ruin the stereo effect.
-Sample rates between 8000-48000H are
-supported.
+The sample data can have either single (mono) or double (stereo)
+audio channel. Stereo data is interleaved so that every other data
+value is for left channel and every second for right channel. Notice
+that while it'd be possible in theory to process stereo sound as two
+separate mono channels, this isn't recommended because processing the
+channels separately would result in losing the phase coherency between
+the channels, which consequently would ruin the stereo effect.
+Sample rates between 8000-48000H are supported.
3.2. Processing latency
-The processing and latency constraints of
-the SoundTouch library are:
+The processing and latency constraints of the SoundTouch library are:
- - Input/output processing latency for the
-SoundTouch processor is around 100 ms. This is when time-stretching is
-used. If the rate transposing effect alone is used, the latency
-requirement
-is much shorter, see section 'About algorithms'.
- - Processing CD-quality sound (16bit stereo
-sound with 44100H sample rate) in real-time or faster is possible
-starting from processors equivalent to Intel Pentium 133Mh or better,
-if using the "quick" processing algorithm. If not using the "quick"
-mode or
-if floating point sample data are being used, several times more CPU
-power is typically required.
+ - Input/output processing latency for the SoundTouch processor is
+around 100 ms. This is when time-stretching is used. If the rate
+transposing effect alone is used, the latency requirement is much
+shorter, see section 'About algorithms'.
+ - Processing CD-quality sound (16bit stereo sound with 44100H
+sample rate) in real-time or faster is possible starting from
+processors equivalent to Intel Pentium 133Mh or better, if using the
+"quick" processing algorithm. If not using the "quick" mode or if
+floating point sample data are being used, several times more CPU power
+is typically required.
3.3. About algorithms
-SoundTouch provides three seemingly
-independent effects: tempo, pitch and playback rate control.
-These three controls are implemented as combination of two primary
-effects, sample rate transposing and time-stretching.
-Sample rate transposing affects
-both the audio stream duration and pitch. It's implemented simply
-by converting the original audio sample stream to the desired
-duration by interpolating from the original audio samples. In SoundTouch, linear interpolation with anti-alias filtering is
-used. Theoretically a higher-order interpolation provide better
-result than 1st order linear interpolation, but in audio
-application linear interpolation together with anti-alias
-filtering performs subjectively about as well as higher-order
-filtering would.
-Time-stretching means changing
-the audio stream duration without affecting it's pitch. SoundTouch
-uses WSOLA-like time-stretching routines that operate in the time
-domain. Compared to sample rate transposing, time-stretching is a
-much heavier operation and also requires a longer processing
-"window" of sound samples used by the
-processing algorithm, thus increasing the algorithm input/output
-latency. Typical i/o latency for the SoundTouch
-time-stretch algorithm is around 100 ms.
-Sample rate transposing and time-stretching
-are then used together to produce the tempo, pitch and rate
-controls:
+SoundTouch provides three seemingly independent effects: tempo,
+pitch and playback rate control. These three controls are implemented
+as combination of two primary effects, sample rate transposing
+and time-stretching.
+Sample rate transposing affects both the audio stream
+duration and pitch. It's implemented simply by converting the original
+audio sample stream to the desired duration by interpolating from
+the original audio samples. In SoundTouch, linear interpolation with
+anti-alias filtering is used. Theoretically a higher-order
+interpolation provide better result than 1st order linear
+interpolation, but in audio application linear interpolation together
+with anti-alias filtering performs subjectively about as well as
+higher-order filtering would.
+Time-stretching means changing the audio stream duration
+without affecting it's pitch. SoundTouch uses WSOLA-like
+time-stretching routines that operate in the time domain. Compared to
+sample rate transposing, time-stretching is a much heavier operation
+and also requires a longer processing "window" of sound samples used by
+the processing algorithm, thus increasing the algorithm input/output
+latency. Typical i/o latency for the SoundTouch time-stretch algorithm
+is around 100 ms.
+Sample rate transposing and time-stretching are then used together
+to produce the tempo, pitch and rate controls:
- - 'Tempo' control is
-implemented purely by time-stretching.
- - 'Rate' control is implemented
-purely by sample rate transposing.
- - 'Pitch' control is
-implemented as a combination of time-stretching and sample rate
-transposing. For example, to increase pitch the audio stream is first
-time-stretched to longer duration (without affecting pitch) and then
-transposed back to original duration by sample rate transposing, which
-simultaneously reduces duration and increases pitch. The result is
-original duration but increased pitch.
+ - 'Tempo' control is implemented purely by
+time-stretching.
+ - 'Rate' control is implemented purely by sample
+rate transposing.
+ - 'Pitch' control is implemented as a
+combination of time-stretching and sample rate transposing. For
+example, to increase pitch the audio stream is first time-stretched to
+longer duration (without affecting pitch) and then transposed back to
+original duration by sample rate transposing, which simultaneously
+reduces duration and increases pitch. The result is original duration
+but increased pitch.
3.4 Tuning the algorithm parameters
-The time-stretch algorithm has few
-parameters that can be tuned to optimize sound quality for
-certain application. The current default parameters have been
-chosen by iterative if-then analysis (read: "trial and error")
-to obtain best subjective sound quality in pop/rock music
-processing, but in applications processing different kind of
-sound the default parameter set may result into a sub-optimal
-result.
-The time-stretch algorithm default
-parameter values are set by the following #defines in file "TDStretch.h":
+The time-stretch algorithm has few parameters that can be tuned to
+optimize sound quality for certain application. The current default
+parameters have been chosen by iterative if-then analysis (read: "trial
+and error") to obtain best subjective sound quality in pop/rock music
+processing, but in applications processing different kind of sound the
+default parameter set may result into a sub-optimal result.
+The time-stretch algorithm default parameter values are set by the
+following #defines in file "TDStretch.h":
- #define DEFAULT_SEQUENCE_MS AUTOMATIC
-#define DEFAULT_SEEKWINDOW_MS AUTOMATIC
-#define DEFAULT_OVERLAP_MS 8
+ #define DEFAULT_SEQUENCE_MS AUTOMATIC
#define DEFAULT_SEEKWINDOW_MS AUTOMATIC
#define DEFAULT_OVERLAP_MS 8
-These parameters affect to the time-stretch
-algorithm as follows:
+These parameters affect to the time-stretch algorithm as follows:
- - DEFAULT_SEQUENCE_MS: This is
-the default length of a single processing sequence in milliseconds
-which determines the how the original sound is chopped in
-the time-stretch algorithm. Larger values mean fewer sequences
-are used in processing. In principle a larger value sounds better when
-slowing down the tempo, but worse when increasing the tempo and vice
-versa.
+ - DEFAULT_SEQUENCE_MS: This is the default
+length of a single processing sequence in milliseconds which determines
+the how the original sound is chopped in the time-stretch algorithm.
+Larger values mean fewer sequences are used in processing. In principle
+a larger value sounds better when slowing down the tempo, but worse
+when increasing the tempo and vice versa.
- By default, this setting value is calculated automatically according to
- tempo value.
+By default, this setting value is calculated automatically according to
+tempo value.
- - DEFAULT_SEEKWINDOW_MS: The seeking window
+
- DEFAULT_SEEKWINDOW_MS: The seeking window
default length in milliseconds is for the algorithm that seeks the best
-possible overlapping location. This determines from how
-wide a sample "window" the algorithm can use to find an optimal mixing
-location when the sound sequences are to be linked back together.
+possible overlapping location. This determines from how wide a sample
+"window" the algorithm can use to find an optimal mixing location when
+the sound sequences are to be linked back together.
The bigger this window setting is, the higher the possibility to find a
better mixing position becomes, but at the same time large values may
@@ -279,474 +265,513 @@ chosen at more uneven intervals. If there's a disturbing artifact that
sounds as if a constant frequency was drifting around, try reducing
this setting.
- By default, this setting value is calculated automatically according to
- tempo value.
+By default, this setting value is calculated automatically according to
+tempo value.
- - DEFAULT_OVERLAP_MS: Overlap
-length in milliseconds. When the sound sequences are mixed back
-together to form again a continuous sound stream, this parameter
-defines how much the ends of the consecutive sequences will overlap with each other.
+ - DEFAULT_OVERLAP_MS: Overlap length in
+milliseconds. When the sound sequences are mixed back together to form
+again a continuous sound stream, this parameter defines how much the
+ends of the consecutive sequences will overlap with each other.
- This shouldn't be that critical parameter. If you reduce the
+This shouldn't be that critical parameter. If you reduce the
DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a
smaller value on this.
-Notice that these parameters can also be
-set during execution time with functions "TDStretch::setParameters()"
-and "SoundTouch::setSetting()".
-The table below summaries how the
-parameters can be adjusted for different applications:
+Notice that these parameters can also be set during execution time
+with functions "TDStretch::setParameters()" and "SoundTouch::setSetting()".
+The table below summaries how the parameters can be adjusted for
+different applications:
Parameter name |
- Default value
-magnitude |
- Larger value
-affects... |
- Smaller value
-affects... |
+ Default value magnitude |
+ Larger value affects... |
+ Smaller value affects... |
Effect to CPU burden |
SEQUENCE_MS
|
- Default value is relatively
-large, chosen for slowing down music tempo |
- Larger value is usually
-better for slowing down tempo. Growing the value decelerates the
-"echoing" artifact when slowing down the tempo. |
- Smaller value might be better
-for speeding up tempo. Reducing the value accelerates the "echoing"
-artifact when slowing down the tempo |
- Increasing the parameter
-value reduces computation burden |
+ Default value is relatively large, chosen for
+slowing down music tempo |
+ Larger value is usually better for slowing down
+tempo. Growing the value decelerates the "echoing" artifact when
+slowing down the tempo. |
+ Smaller value might be better for speeding up
+tempo. Reducing the value accelerates the "echoing" artifact when
+slowing down the tempo |
+ Increasing the parameter value reduces
+computation burden |
SEEKWINDOW_MS
|
- Default value is relatively
-large, chosen for slowing down music tempo |
- Larger value eases finding a
-good mixing position, but may cause a "drifting" artifact |
- Smaller reduce possibility to
-find a good mixing position, but reduce the "drifting" artifact. |
- Increasing the parameter
-value increases computation burden |
+ Default value is relatively large, chosen for
+slowing down music tempo |
+ Larger value eases finding a good mixing
+position, but may cause a "drifting" artifact |
+ Smaller reduce possibility to find a good mixing
+position, but reduce the "drifting" artifact. |
+ Increasing the parameter value increases
+computation burden |
OVERLAP_MS
|
- Default value is relatively
-large, chosen to suit with above parameters. |
+ Default value is relatively large, chosen to
+suit with above parameters. |
|
- If you reduce the "sequence
-ms" setting, you might wish to try a smaller value. |
- Increasing the parameter
-value increases computation burden |
+ If you reduce the "sequence ms" setting, you
+might wish to try a smaller value. |
+ Increasing the parameter value increases
+computation burden |
3.5 Performance Optimizations
General optimizations:
-The time-stretch routine has a 'quick' mode
-that substantially speeds up the algorithm but may degrade the
-sound quality by a small amount. This mode is activated by
-calling SoundTouch::setSetting() function with parameter id
-of SETTING_USE_QUICKSEEK and value "1", i.e.
+The time-stretch routine has a 'quick' mode that substantially
+speeds up the algorithm but may degrade the sound quality by a small
+amount. This mode is activated by calling SoundTouch::setSetting()
+function with parameter id of SETTING_USE_QUICKSEEK and value
+"1", i.e.
setSetting(SETTING_USE_QUICKSEEK, 1);
CPU-specific optimizations:
- - Intel MMX optimized routines are used with
-compatible CPUs when 16bit integer sample type is used. MMX optimizations are available both in Win32 and Gnu/x86 platforms.
-Compatible processors are Intel PentiumMMX and later; AMD K6-2, Athlon
-and later.
- - Intel SSE optimized routines are used with
-compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only.
-Processors compatible with SSE extension are Intel processors starting
-from Pentium-III, and AMD processors starting from Athlon XP.
- - AMD 3DNow! optimized routines are used with
-compatible CPUs when floating point sample type is used, but SSE
-extension isn't supported . 3DNow! optimizations are currently
-implemented for Win32 platform only. These optimizations are used in
-AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are
-used with AMD processor starting from Athlon XP.
+ - Intel MMX optimized routines are used with compatible CPUs when
+16bit integer sample type is used. MMX optimizations are available both
+in Win32 and Gnu/x86 platforms. Compatible processors are Intel
+PentiumMMX and later; AMD K6-2, Athlon and later.
+ - Intel SSE optimized routines are used with compatible CPUs when
+floating point sample type is used. SSE optimizations are currently
+implemented for Win32 platform only. Processors compatible with SSE
+extension are Intel processors starting from Pentium-III, and AMD
+processors starting from Athlon XP.
+ - AMD 3DNow! optimized routines are used with compatible CPUs when
+floating point sample type is used, but SSE extension isn't supported .
+3DNow! optimizations are currently implemented for Win32 platform only.
+These optimizations are used in AMD K6-2 and Athlon (classic) CPU's;
+better performing SSE routines are used with AMD processor starting
+from Athlon XP.
4. SoundStretch audio processing utility
SoundStretch audio processing utility
-Copyright (c) Olli Parviainen 2002-2009
-SoundStretch is a simple command-line
-application that can change tempo, pitch and playback rates of
-WAV sound files. This program is intended primarily to
-demonstrate how the "SoundTouch" library can be used to
-process sound in your own program, but it can as well be used for
-processing sound files.
+ Copyright (c) Olli Parviainen 2002-2012
+SoundStretch is a simple command-line application that can change
+tempo, pitch and playback rates of WAV sound files. This program is
+intended primarily to demonstrate how the "SoundTouch" library can be
+used to process sound in your own program, but it can as well be used
+for processing sound files.
4.1. SoundStretch Usage Instructions
SoundStretch Usage syntax:
soundstretch infilename outfilename [switches]
Where:
-
+
- "infilename"
+ "infilename"
|
- Name of the input sound
-data file (in .WAV audio file format). Give "stdin" as filename to use
- standard input pipe. |
+ Name of the input sound data file (in .WAV audio
+file format). Give "stdin" as filename to use standard input pipe. |
- "outfilename"
+ "outfilename"
|
- Name of the output sound
-file where the resulting sound is saved (in .WAV audio file format).
-This parameter may be omitted if you don't want to save the
-output
-(e.g. when only calculating BPM rate with '-bpm' switch). Give "stdout"
- as filename to use standard output pipe. |
+ Name of the output sound file where the
+resulting sound is saved (in .WAV audio file format). This parameter
+may be omitted if you don't want to save the output (e.g. when
+only calculating BPM rate with '-bpm' switch). Give "stdout" as
+filename to use standard output pipe. |
[switches]
|
- Are one or more control
-switches. |
+ Are one or more control switches. |
Available control switches are:
-
+
-tempo=n
|
- Change the sound tempo by n
-percents (n = -95.0 .. +5000.0 %) |
+ Change the sound tempo by n percents (n = -95.0
+.. +5000.0 %) |
-pitch=n
|
- Change the sound pitch by n
-semitones (n = -60.0 .. + 60.0 semitones) |
+ Change the sound pitch by n semitones (n = -60.0
+.. + 60.0 semitones) |
-rate=n
|
- Change the sound playback rate by
-n percents (n = -95.0 .. +5000.0 %) |
+ Change the sound playback rate by n percents (n
+= -95.0 .. +5000.0 %) |
-bpm=n
|
- Detect the Beats-Per-Minute (BPM) rate of the sound and adjust the tempo to meet 'n'
- BPMs. When this switch is
- applied, the "-tempo" switch is ignored. If "=n" is
-omitted, i.e. switch "-bpm" is used alone, then the BPM rate is
- estimated and displayed, but tempo not adjusted according to the BPM
-value. |
+ Detect the Beats-Per-Minute (BPM) rate of the
+sound and adjust the tempo to meet 'n' BPMs. When this switch is
+applied, the "-tempo" switch is ignored. If "=n" is omitted, i.e.
+switch "-bpm" is used alone, then the BPM rate is estimated and
+displayed, but tempo not adjusted according to the BPM value. |
-quick
|
- Use quicker tempo change
-algorithm. Gains speed but loses sound quality. |
+ Use quicker tempo change algorithm. Gains speed
+but loses sound quality. |
-naa
|
- Don't use anti-alias
-filtering in sample rate transposing. Gains speed but loses sound
-quality. |
+ Don't use anti-alias filtering in sample rate
+transposing. Gains speed but loses sound quality. |
-license
|
- Displays the program license
-text (LGPL) |
+ Displays the program license text (LGPL) |
Notes:
- - To use standard input/output pipes for processing, give "stdin"
- and "stdout" as input/output filenames correspondingly. The
- standard input/output pipes will still carry the audio data in .wav audio
- file format.
- - The numerical switches allow both integer (e.g. "-tempo=123") and decimal (e.g.
-"-tempo=123.45") numbers.
- - The "-naa" and/or "-quick" switches can be
-used to reduce CPU usage while compromising some sound quality
- - The BPM detection algorithm works by detecting
-repeating bass or drum patterns at low frequencies of <250Hz. A
- lower-than-expected BPM figure may be reported for music with uneven or
- complex bass patterns.
+ - To use standard input/output pipes for processing, give "stdin"
+and "stdout" as input/output filenames correspondingly. The standard
+input/output pipes will still carry the audio data in .wav audio file
+format.
+ - The numerical switches allow both integer (e.g. "-tempo=123")
+and decimal (e.g. "-tempo=123.45") numbers.
+ - The "-naa" and/or "-quick" switches can be used to reduce CPU
+usage while compromising some sound quality
+ - The BPM detection algorithm works by detecting repeating bass or
+drum patterns at low frequencies of <250Hz. A lower-than-expected
+BPM figure may be reported for music with uneven or complex bass
+patterns.
4.2. SoundStretch usage examples
Example 1
-The following command increases tempo of
-the sound file "originalfile.wav" by 12.5% and stores result to file "destinationfile.wav":
+The following command increases tempo of the sound file
+"originalfile.wav" by 12.5% and stores result to file
+"destinationfile.wav":
soundstretch originalfile.wav destinationfile.wav -tempo=12.5
Example 2
-The following command decreases the sound
-pitch (key) of the sound file "orig.wav" by two
-semitones and stores the result to file "dest.wav":
+The following command decreases the sound pitch (key) of the sound
+file "orig.wav" by two semitones and stores the result to file
+"dest.wav":
soundstretch orig.wav dest.wav -pitch=-2
Example 3
-The following command processes the file "orig.wav" by decreasing the sound tempo by 25.3% and
-increasing the sound pitch (key) by 1.5 semitones. Resulting .wav audio data is
-directed to standard output pipe:
+The following command processes the file "orig.wav" by decreasing
+the sound tempo by 25.3% and increasing the sound pitch (key) by 1.5
+semitones. Resulting .wav audio data is directed to standard output
+pipe:
soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5
Example 4
-The following command detects the BPM rate
-of the file "orig.wav" and adjusts the tempo to match
-100 beats per minute. Result is stored to file "dest.wav":
+The following command detects the BPM rate of the file "orig.wav"
+and adjusts the tempo to match 100 beats per minute. Result is stored
+to file "dest.wav":
soundstretch orig.wav dest.wav -bpm=100
Example 5
-The following command reads .wav sound data from standard input pipe and
-estimates the BPM rate:
+The following command reads .wav sound data from standard input pipe
+and estimates the BPM rate:
soundstretch stdin -bpm
5. Change History
5.1. SoundTouch library Change History
-
+1.7.1:
+
+ - Added files for Android compilation
+
+1.7.0:
+
+ - Sound quality improvements/li>
+
- Improved flush() to adjust output sound stream duration to match better with
+ ideal duration
+ - Rewrote x86 cpu feature check to resolve compatibility problems
+ - Configure script automatically checks if CPU supports mmx & sse compatibility for GNU platform, and
+ the script support now "--enable-x86-optimizations" switch to allow disabling x86-specific optimizations.
+ - Revised #define conditions for 32bit/64bit compatibility
+ - gnu autoconf/automake script compatibility fixes
+ - Tuned beat-per-minute detection algorithm
+
+1.6.0:
+
+ - Added automatic cutoff threshold adaptation to beat detection
+routine to better adapt BPM calculation to different types of music
+ - Retired 3DNow! optimization support as 3DNow! is nowadays
+obsoleted and assembler code is nuisance to maintain
+ - Retired "configure" file from source code package due to
+autoconf/automake versio conflicts, so that it is from now on to be
+generated by invoking "boostrap" script that uses locally available
+toolchain version for generating the "configure" file
+ - Resolved namespace/label naming conflicts with other libraries by
+replacing global labels such as INTEGER_SAMPLES with more specific
+SOUNDTOUCH_INTEGER_SAMPLES etc.
+
+ - Updated windows build scripts & project files for Visual
+Studio 2008 support
+ - Updated SoundTouch.dll API for .NET compatibility
+ - Added API for querying nominal processing input & output
+sample batch sizes
+
1.5.0:
-- Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality
-
-- Bugfixes:
-
- - Fixed negative array indexing in quick seek algorithm
- - FIR autoalias filter running too far in processing buffer
- - Check against zero sample count in rate transposing
- - Fix for x86-64 support: Removed pop/push instructions from the cpu detection algorithm.
- - Check against empty buffers in FIFOSampleBuffer
- - Other minor fixes & code cleanup
-
-
-
-- Fixes in compilation scripts for non-Intel platforms
-- Added Dynamic-Link-Library (DLL) version of SoundTouch library build,
- provided with Delphi/Pascal wrapper for calling the dll routines
-- Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a click artifact
- when crossing the nominal pitch from either positive to negative side or vice
- versa
-
+ - Added normalization to correlation calculation and improvement
+automatic seek/sequence parameter calculation to improve sound quality
+ - Bugfixes:
+
+ - Fixed negative array indexing in quick seek algorithm
+ - FIR autoalias filter running too far in processing buffer
+ - Check against zero sample count in rate transposing
+ - Fix for x86-64 support: Removed pop/push instructions from
+the cpu detection algorithm.
+ - Check against empty buffers in FIFOSampleBuffer
+ - Other minor fixes & code cleanup
+
+
+ - Fixes in compilation scripts for non-Intel platforms
+ - Added Dynamic-Link-Library (DLL) version of SoundTouch library
+build, provided with Delphi/Pascal wrapper for calling the dll routines
+
+ - Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a
+click artifact when crossing the nominal pitch from either positive to
+negative side or vice versa
-
1.4.1:
-- Fixed a buffer overflow bug in BPM detect algorithm routines if processing
- more than 2048 samples at one call
-
+ - Fixed a buffer overflow bug in BPM detect algorithm routines if
+processing more than 2048 samples at one call
-
1.4.0:
-- Improved sound quality by automatic calculation of time stretch algorithm
- processing parameters according to tempo setting
-- Moved BPM detection routines from SoundStretch application into SoundTouch
- library
-- Bugfixes: Usage of uninitialied variables, GNU build scripts, compiler errors
- due to 'const' keyword mismatch.
-- Source code cleanup
-
+ - Improved sound quality by automatic calculation of time stretch
+algorithm processing parameters according to tempo setting
+ - Moved BPM detection routines from SoundStretch application into
+SoundTouch library
+ - Bugfixes: Usage of uninitialied variables, GNU build scripts,
+compiler errors due to 'const' keyword mismatch.
+ - Source code cleanup
-
-v1.3.1:
-
+1.3.1:
-- Changed static class declaration to GCC 4.x compiler compatible syntax.
-- Enabled MMX/SSE-optimized routines also for GCC compilers. Earlier
-the MMX/SSE-optimized routines were written in compiler-specific inline
-assembler, now these routines are migrated to use compiler intrinsic
-syntax which allows compiling the same MMX/SSE-optimized source code with
-both Visual C++ and GCC compilers.
-- Set floating point as the default sample format and added switch to
-the GNU configure script for selecting the other sample format.
-
+ - Changed static class declaration to GCC 4.x compiler compatible
+syntax.
+ - Enabled MMX/SSE-optimized routines also for GCC compilers.
+Earlier the MMX/SSE-optimized routines were written in
+compiler-specific inline assembler, now these routines are migrated to
+use compiler intrinsic syntax which allows compiling the same
+MMX/SSE-optimized source code with both Visual C++ and GCC compilers.
+ - Set floating point as the default sample format and added switch
+to the GNU configure script for selecting the other sample format.
-
-v1.3.0:
-
+1.3.0:
- - Fixed tempo routine output duration inaccuracy due to rounding
+
- Fixed tempo routine output duration inaccuracy due to rounding
error
- - Implemented separate processing routines for integer and
+
- Implemented separate processing routines for integer and
floating arithmetic to allow improvements to floating point routines
(earlier used algorithms mostly optimized for integer arithmetic also
for floating point samples)
- - Fixed a bug that distorts sound if sample rate changes during the
-sound stream
- - Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized
+
- Fixed a bug that distorts sound if sample rate changes during
+the sound stream
+ - Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized
routines
- - Reduced redundant code pieces in MMX/SSE/3DNow! optimized
-routines vs. the standard C routines.
- - MMX routine incompatibility with new gcc compiler versions
- - Other miscellaneous bug fixes
+ - Reduced redundant code pieces in MMX/SSE/3DNow! optimized
+routines vs. the standard C routines.
+ - MMX routine incompatibility with new gcc compiler versions
+ - Other miscellaneous bug fixes
-v1.2.1:
+1.2.1:
- - Added automake/autoconf scripts for GNU
-platforms (in courtesy of David Durham)
- - Fixed SCALE overflow bug in rate transposer
-routine.
- - Fixed 64bit address space bugs.
- - Created a 'soundtouch' namespace for
-SAMPLETYPE definitions.
+ - Added automake/autoconf scripts for GNU platforms (in courtesy
+of David Durham)
+ - Fixed SCALE overflow bug in rate transposer routine.
+ - Fixed 64bit address space bugs.
+ - Created a 'soundtouch' namespace for SAMPLETYPE definitions.
-v1.2.0:
+1.2.0:
- - Added support for 32bit floating point sample
-data type with SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations currently not supported in GCC environment)
- - Replaced 'make-gcc' script for GNU environment
-by master Makefile
- - Added time-stretch routine configurability to
-SoundTouch main class
- - Bugfixes
+ - Added support for 32bit floating point sample data type with
+SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations
+currently not supported in GCC environment)
+ - Replaced 'make-gcc' script for GNU environment by master
+Makefile
+ - Added time-stretch routine configurability to SoundTouch main
+class
+ - Bugfixes
-v1.1.1:
+1.1.1:
- - Moved SoundTouch under lesser GPL license (LGPL). This allows using SoundTouch library in programs that aren't
-released under GPL license.
- - Changed MMX routine organiation so that MMX optimized routines are now implemented in classes that are derived from
-the basic classes having the standard non-mmx routines.
- - MMX routines to support gcc version 3.
- - Replaced windows makefiles by script using the .dsw files
+ - Moved SoundTouch under lesser GPL license (LGPL). This allows
+using SoundTouch library in programs that aren't released under GPL
+license.
+ - Changed MMX routine organiation so that MMX optimized routines
+are now implemented in classes that are derived from the basic classes
+having the standard non-mmx routines.
+ - MMX routines to support gcc version 3.
+ - Replaced windows makefiles by script using the .dsw files
-v1.01:
+1.0.1:
- - "mmx_gcc.cpp": Added "using namespace std" and
-removed "return 0" from a function with void return value to fix
-compiler errors when compiling the library in Solaris environment.
- - Moved file "FIFOSampleBuffer.h" to "include"
-directory to allow accessing the FIFOSampleBuffer class from external
-files.
+ - "mmx_gcc.cpp": Added "using namespace std" and removed "return
+0" from a function with void return value to fix compiler errors when
+compiling the library in Solaris environment.
+ - Moved file "FIFOSampleBuffer.h" to "include" directory to allow
+accessing the FIFOSampleBuffer class from external files.
-v1.0:
+1.0:
- - Initial release
+ - Initial release
-5.2. SoundStretch application Change
-History
-
+5.2. SoundStretch application Change History
+1.7.0:
+
+ - Bugfixes in Wavfile: exception string formatting, avoid getLengthMs() integer
+ precision overflow, support WAV files using 24/32bit sample format.
+
+ 1.5.0:
+
+ - Added "-speech" switch to activate algorithm parameters more
+suitable for speech processing than the default parameters tuned for
+music processing.
+
1.4.0:
-- Moved BPM detection routines from SoundStretch application into SoundTouch
- library
-- Allow using standard input/output pipes as audio processing input/output
- streams
-
+ - Moved BPM detection routines from SoundStretch application into
+SoundTouch library
+ - Allow using standard input/output pipes as audio processing
+input/output streams
-
-v1.3.0:
+1.3.0:
- - Simplified accessing WAV files with floating
-point sample format.
-
+ - Simplified accessing WAV files with floating point sample
+format.
-v1.2.1:
+1.2.1:
- - Fixed 64bit address space bugs.
+ - Fixed 64bit address space bugs.
-v1.2.0:
+1.2.0:
- - Added support for 32bit floating point sample
-data type
- - Restructured the BPM routines into separate
-library
- - Fixed big-endian conversion bugs in WAV file
-routines (hopefully :)
+ - Added support for 32bit floating point sample data type
+ - Restructured the BPM routines into separate library
+ - Fixed big-endian conversion bugs in WAV file routines (hopefully
+:)
-v1.1.1:
+1.1.1:
- - Fixed bugs in WAV file reading & added
-byte-order conversion for big-endian processors.
- - Moved SoundStretch source code under 'example'
-directory to highlight difference from SoundTouch stuff.
- - Replaced windows makefiles by script using the .dsw files
- - Output file name isn't required if output
-isn't desired (e.g. if using the switch '-bpm' in plain format only)
+ - Fixed bugs in WAV file reading & added byte-order conversion
+for big-endian processors.
+ - Moved SoundStretch source code under 'example' directory to
+highlight difference from SoundTouch stuff.
+ - Replaced windows makefiles by script using the .dsw files
+ - Output file name isn't required if output isn't desired (e.g. if
+using the switch '-bpm' in plain format only)
-v1.1:
+1.1:
- - Fixed "Release" settings in Microsoft Visual
-C++ project file (.dsp)
- - Added beats-per-minute (BPM) detection routine
-and command-line switch "-bpm"
+ - Fixed "Release" settings in Microsoft Visual C++ project file
+(.dsp)
+ - Added beats-per-minute (BPM) detection routine and command-line
+switch "-bpm"
-v1.01:
+1.01:
- - Initial release
+ - Initial release
-6. Acknowledgements
-Kudos for these people who have contributed to development or submitted
-bugfixes since
-SoundTouch v1.3.1:
+6. Acknowledgements
+Kudos for these people who have contributed to development or
+submitted bugfixes since SoundTouch v1.3.1:
- - Arthur A
- - Richard Ash
- - Stanislav Brabec
- - Christian Budde
- - Brian Cameron
- - Jason Champion
- - Patrick Colis
- - Justin Frankel
- - Jason Garland
- - Takashi Iwai
- - Paulo Pizarro
- - RJ Ryan
- - John Sheehy
+ - Arthur A
+ - Richard Ash
+ - Stanislav Brabec
+ - Christian Budde
+ - Jacek Caban
+ - Brian Cameron
+ - Jason Champion
+ - David Clark
+ - Patrick Colis
+ - Miquel Colon
+ - Justin Frankel
+ - Jason Garland
+ - Takashi Iwai
+ - Yuval Naveh
+ - Paulo Pizarro
+ - Blaise Potard
+ - RJ Ryan
+ - Patrick Colis
+ - Miquel Colon
+ - Sandro Cumerlato
+ - Justin Frankel
+ - Jason Garland
+ - Takashi Iwai
+ - Mathias Möhl
+ - Yuval Naveh
+ - Paulo Pizarro
+ - Blaise Potard
+ - RJ Ryan
+ - John Sheehy
+ - Tim Shuttleworth
+ - John Stumpo
+ - Tim Shuttleworth
+ - Katja Vetter
-Moral greetings to all other contributors and users also!
+Moral greetings to all other contributors and users also!
-7. LICENSE
+7. LICENSE
SoundTouch audio processing library
Copyright (c) Olli Parviainen
-This library is free software; you can
-redistribute it and/or modify it under the terms of the GNU
-Lesser General Public License version 2.1 as published by the Free Software
-Foundation.
-This library is distributed in the hope
-that it will be useful, but WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU Lesser General Public License for
-more details.
-You should have received a copy of the GNU
-Lesser General Public License along with this library; if not,
-write to the Free Software Foundation, Inc., 59 Temple Place,
-Suite 330, Boston, MA 02111-1307 USA
-
-
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License version 2.1
+as published by the Free Software Foundation.
+This library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+General Public License for more details.
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ RREADME.html file updated on 28-Dec-2012
diff --git a/3rdparty/SoundTouch/RateTransposer.cpp b/3rdparty/SoundTouch/RateTransposer.cpp
index 7d992f8ce2..19d4bf8ef2 100644
--- a/3rdparty/SoundTouch/RateTransposer.cpp
+++ b/3rdparty/SoundTouch/RateTransposer.cpp
@@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
-///
-/// Sample rate transposer. Changes sample rate by using linear interpolation
+///
+/// Sample rate transposer. Changes sample rate by using linear interpolation
/// together with anti-alias filtering (first order interpolation with anti-
/// alias filtering should be quite adequate for this application)
///
@@ -10,10 +10,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-10-31 16:37:24 +0200 (Sat, 31 Oct 2009) $
+// Last changed : $Date: 2011-09-02 15:56:11 -0300 (sex, 02 set 2011) $
// File revision : $Revision: 4 $
//
-// $Id: RateTransposer.cpp 74 2009-10-31 14:37:24Z oparviai $
+// $Id: RateTransposer.cpp 131 2011-09-02 18:56:11Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -42,11 +42,9 @@
#include
#include
#include
-#include
#include "RateTransposer.h"
#include "AAFilter.h"
-using namespace std;
using namespace soundtouch;
@@ -61,18 +59,18 @@ protected:
virtual void resetRegisters();
- virtual uint transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples);
- virtual uint transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples);
public:
RateTransposerInteger();
virtual ~RateTransposerInteger();
- /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
+ /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
/// rate, larger faster rates.
virtual void setRate(float newRate);
@@ -89,11 +87,11 @@ protected:
virtual void resetRegisters();
- virtual uint transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples);
- virtual uint transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples);
public:
@@ -104,18 +102,18 @@ public:
-// Operator 'new' is overloaded so that it automatically creates a suitable instance
+// Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX/SSE/etc-capable CPU available or not.
void * RateTransposer::operator new(size_t s)
{
- throw runtime_error("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
- return NULL;
+ ST_THROW_RT_ERROR("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
+ return newInstance();
}
RateTransposer *RateTransposer::newInstance()
{
-#ifdef INTEGER_SAMPLES
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
return ::new RateTransposerInteger;
#else
return ::new RateTransposerFloat;
@@ -165,7 +163,7 @@ AAFilter *RateTransposer::getAAFilter()
-// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
+// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
// iRate, larger faster iRates.
void RateTransposer::setRate(float newRate)
{
@@ -174,11 +172,11 @@ void RateTransposer::setRate(float newRate)
fRate = newRate;
// design a new anti-alias filter
- if (newRate > 1.0f)
+ if (newRate > 1.0f)
{
fCutoff = 0.5f / newRate;
- }
- else
+ }
+ else
{
fCutoff = 0.5f * newRate;
}
@@ -220,7 +218,7 @@ void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples)
// If the parameter 'uRate' value is smaller than 'SCALE', first transpose
// the samples and then apply the anti-alias filter to remove aliasing.
- // First check that there's enough room in 'storeBuffer'
+ // First check that there's enough room in 'storeBuffer'
// (+16 is to reserve some slack in the destination buffer)
sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
@@ -231,7 +229,7 @@ void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples)
// Apply the anti-alias filter to samples in "store output", output the
// result to "dest"
num = storeBuffer.numSamples();
- count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
+ count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
storeBuffer.ptrBegin(), num, (uint)numChannels);
outputBuffer.putSamples(count);
@@ -253,13 +251,13 @@ void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
// Add the new samples to the end of the storeBuffer
storeBuffer.putSamples(src, nSamples);
- // Anti-alias filter the samples to prevent folding and output the filtered
+ // Anti-alias filter the samples to prevent folding and output the filtered
// data to tempBuffer. Note : because of the FIR filter length, the
// filtering routine takes in 'filter_length' more samples than it outputs.
assert(tempBuffer.isEmpty());
sizeTemp = storeBuffer.numSamples();
- count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
+ count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels);
if (count == 0) return;
@@ -274,7 +272,7 @@ void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
}
-// Transposes sample rate by applying anti-alias filter to prevent folding.
+// Transposes sample rate by applying anti-alias filter to prevent folding.
// Returns amount of samples returned in the "dest" buffer.
// The maximum amount of samples that can be returned at a time is set by
// the 'set_returnBuffer_size' function.
@@ -288,7 +286,7 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
// If anti-alias filter is turned off, simply transpose without applying
// the filter
- if (bUseAAFilter == FALSE)
+ if (bUseAAFilter == FALSE)
{
sizeReq = (uint)((float)nSamples / fRate + 1.0f);
count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples);
@@ -297,26 +295,26 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
}
// Transpose with anti-alias filter
- if (fRate < 1.0f)
+ if (fRate < 1.0f)
{
upsample(src, nSamples);
- }
- else
+ }
+ else
{
downsample(src, nSamples);
}
}
-// Transposes the sample rate of the given samples using linear interpolation.
+// Transposes the sample rate of the given samples using linear interpolation.
// Returns the number of samples returned in the "dest" buffer
inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{
- if (numChannels == 2)
+ if (numChannels == 2)
{
return transposeStereo(dest, src, nSamples);
- }
- else
+ }
+ else
{
return transposeMono(dest, src, nSamples);
}
@@ -363,7 +361,7 @@ int RateTransposer::isEmpty() const
//////////////////////////////////////////////////////////////////////////////
//
// RateTransposerInteger - integer arithmetic implementation
-//
+//
/// fixed-point interpolation routine precision
#define SCALE 65536
@@ -371,7 +369,7 @@ int RateTransposer::isEmpty() const
// Constructor
RateTransposerInteger::RateTransposerInteger() : RateTransposer()
{
- // Notice: use local function calling syntax for sake of clarity,
+ // Notice: use local function calling syntax for sake of clarity,
// to indicate the fact that C++ constructor can't call virtual functions.
RateTransposerInteger::resetRegisters();
RateTransposerInteger::setRate(1.0f);
@@ -386,14 +384,14 @@ RateTransposerInteger::~RateTransposerInteger()
void RateTransposerInteger::resetRegisters()
{
iSlopeCount = 0;
- sPrevSampleL =
+ sPrevSampleL =
sPrevSampleR = 0;
}
-// Transposes the sample rate of the given samples using linear interpolation.
-// 'Mono' version of the routine. Returns the number of samples returned in
+// Transposes the sample rate of the given samples using linear interpolation.
+// 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer
uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{
@@ -402,11 +400,11 @@ uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *sr
if (nSamples == 0) return 0; // no samples, no work
- used = 0;
+ used = 0;
i = 0;
// Process the last sample saved from the previous call first...
- while (iSlopeCount <= SCALE)
+ while (iSlopeCount <= SCALE)
{
vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
@@ -419,7 +417,7 @@ uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *sr
while (1)
{
- while (iSlopeCount > SCALE)
+ while (iSlopeCount > SCALE)
{
iSlopeCount -= SCALE;
used ++;
@@ -440,8 +438,8 @@ end:
}
-// Transposes the sample rate of the given samples using linear interpolation.
-// 'Stereo' version of the routine. Returns the number of samples returned in
+// Transposes the sample rate of the given samples using linear interpolation.
+// 'Stereo' version of the routine. Returns the number of samples returned in
// the "dest" buffer
uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{
@@ -450,11 +448,11 @@ uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *
if (nSamples == 0) return 0; // no samples, no work
- used = 0;
+ used = 0;
i = 0;
// Process the last sample saved from the sPrevSampleLious call first...
- while (iSlopeCount <= SCALE)
+ while (iSlopeCount <= SCALE)
{
vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
@@ -469,7 +467,7 @@ uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *
while (1)
{
- while (iSlopeCount > SCALE)
+ while (iSlopeCount > SCALE)
{
iSlopeCount -= SCALE;
used ++;
@@ -494,7 +492,7 @@ end:
}
-// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
+// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
// iRate, larger faster iRates.
void RateTransposerInteger::setRate(float newRate)
{
@@ -506,13 +504,13 @@ void RateTransposerInteger::setRate(float newRate)
//////////////////////////////////////////////////////////////////////////////
//
// RateTransposerFloat - floating point arithmetic implementation
-//
+//
//////////////////////////////////////////////////////////////////////////////
// Constructor
RateTransposerFloat::RateTransposerFloat() : RateTransposer()
{
- // Notice: use local function calling syntax for sake of clarity,
+ // Notice: use local function calling syntax for sake of clarity,
// to indicate the fact that C++ constructor can't call virtual functions.
RateTransposerFloat::resetRegisters();
RateTransposerFloat::setRate(1.0f);
@@ -527,24 +525,24 @@ RateTransposerFloat::~RateTransposerFloat()
void RateTransposerFloat::resetRegisters()
{
fSlopeCount = 0;
- sPrevSampleL =
+ sPrevSampleL =
sPrevSampleR = 0;
}
-// Transposes the sample rate of the given samples using linear interpolation.
-// 'Mono' version of the routine. Returns the number of samples returned in
+// Transposes the sample rate of the given samples using linear interpolation.
+// 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer
uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{
unsigned int i, used;
- used = 0;
+ used = 0;
i = 0;
// Process the last sample saved from the previous call first...
- while (fSlopeCount <= 1.0f)
+ while (fSlopeCount <= 1.0f)
{
dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
i++;
@@ -556,7 +554,7 @@ uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src,
{
while (1)
{
- while (fSlopeCount > 1.0f)
+ while (fSlopeCount > 1.0f)
{
fSlopeCount -= 1.0f;
used ++;
@@ -575,8 +573,8 @@ end:
}
-// Transposes the sample rate of the given samples using linear interpolation.
-// 'Mono' version of the routine. Returns the number of samples returned in
+// Transposes the sample rate of the given samples using linear interpolation.
+// 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer
uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{
@@ -584,11 +582,11 @@ uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *sr
if (nSamples == 0) return 0; // no samples, no work
- used = 0;
+ used = 0;
i = 0;
// Process the last sample saved from the sPrevSampleLious call first...
- while (fSlopeCount <= 1.0f)
+ while (fSlopeCount <= 1.0f)
{
dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]);
@@ -602,7 +600,7 @@ uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *sr
{
while (1)
{
- while (fSlopeCount > 1.0f)
+ while (fSlopeCount > 1.0f)
{
fSlopeCount -= 1.0f;
used ++;
@@ -610,9 +608,9 @@ uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *sr
}
srcPos = 2 * used;
- dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos]
+ dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos]
+ fSlopeCount * src[srcPos + 2]);
- dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1]
+ dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1]
+ fSlopeCount * src[srcPos + 3]);
i++;
diff --git a/3rdparty/SoundTouch/RateTransposer.h b/3rdparty/SoundTouch/RateTransposer.h
index 6ab0586484..8374a0f834 100644
--- a/3rdparty/SoundTouch/RateTransposer.h
+++ b/3rdparty/SoundTouch/RateTransposer.h
@@ -1,10 +1,10 @@
////////////////////////////////////////////////////////////////////////////////
-///
-/// Sample rate transposer. Changes sample rate by using linear interpolation
+///
+/// Sample rate transposer. Changes sample rate by using linear interpolation
/// together with anti-alias filtering (first order interpolation with anti-
/// alias filtering should be quite adequate for this application).
///
-/// Use either of the derived classes of 'RateTransposerInteger' or
+/// Use either of the derived classes of 'RateTransposerInteger' or
/// 'RateTransposerFloat' for corresponding integer/floating point tranposing
/// algorithm implementation.
///
@@ -14,7 +14,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $
+// Last changed : $Date: 2009-02-21 13:00:14 -0300 (sáb, 21 fev 2009) $
// File revision : $Revision: 4 $
//
// $Id: RateTransposer.h 63 2009-02-21 16:00:14Z oparviai $
@@ -57,9 +57,9 @@ namespace soundtouch
/// A common linear samplerate transposer class.
///
-/// Note: Use function "RateTransposer::newInstance()" to create a new class
-/// instance instead of the "new" operator; that function automatically
-/// chooses a correct implementation depending on if integer or floating
+/// Note: Use function "RateTransposer::newInstance()" to create a new class
+/// instance instead of the "new" operator; that function automatically
+/// chooses a correct implementation depending on if integer or floating
/// arithmetics are to be used.
class RateTransposer : public FIFOProcessor
{
@@ -85,26 +85,26 @@ protected:
virtual void resetRegisters() = 0;
- virtual uint transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples) = 0;
- virtual uint transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ virtual uint transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples) = 0;
- inline uint transpose(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
+ inline uint transpose(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
uint numSamples);
- void downsample(const SAMPLETYPE *src,
+ void downsample(const SAMPLETYPE *src,
uint numSamples);
- void upsample(const SAMPLETYPE *src,
+ void upsample(const SAMPLETYPE *src,
uint numSamples);
- /// Transposes sample rate by applying anti-alias filter to prevent folding.
+ /// Transposes sample rate by applying anti-alias filter to prevent folding.
/// Returns amount of samples returned in the "dest" buffer.
/// The maximum amount of samples that can be returned at a time is set by
/// the 'set_returnBuffer_size' function.
- void processSamples(const SAMPLETYPE *src,
+ void processSamples(const SAMPLETYPE *src,
uint numSamples);
@@ -112,12 +112,12 @@ public:
RateTransposer();
virtual ~RateTransposer();
- /// Operator 'new' is overloaded so that it automatically creates a suitable instance
+ /// Operator 'new' is overloaded so that it automatically creates a suitable instance
/// depending on if we're to use integer or floating point arithmetics.
static void *operator new(size_t s);
- /// Use this function instead of "new" operator to create a new instance of this class.
- /// This function automatically chooses a correct implementation, depending on if
+ /// Use this function instead of "new" operator to create a new instance of this class.
+ /// This function automatically chooses a correct implementation, depending on if
/// integer ot floating point arithmetics are to be used.
static RateTransposer *newInstance();
@@ -136,7 +136,7 @@ public:
/// Returns nonzero if anti-alias filter is enabled.
BOOL isAAFilterEnabled() const;
- /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
+ /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
/// rate, larger faster rates.
virtual void setRate(float newRate);
diff --git a/3rdparty/SoundTouch/STTypes.h b/3rdparty/SoundTouch/STTypes.h
index 1fcd9e2da9..2c4584a142 100644
--- a/3rdparty/SoundTouch/STTypes.h
+++ b/3rdparty/SoundTouch/STTypes.h
@@ -8,10 +8,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-05-17 14:30:57 +0300 (Sun, 17 May 2009) $
+// Last changed : $Date: 2012-12-28 12:53:56 -0200 (sex, 28 dez 2012) $
// File revision : $Revision: 3 $
//
-// $Id: STTypes.h 70 2009-05-17 11:30:57Z oparviai $
+// $Id: STTypes.h 162 2012-12-28 14:53:56Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -42,8 +42,21 @@
typedef unsigned int uint;
typedef unsigned long ulong;
-#ifdef __GNUC__
- // In GCC, include soundtouch_config.h made by config scritps
+// Patch for MinGW: on Win64 long is 32-bit
+#ifdef _WIN64
+ typedef unsigned long long ulongptr;
+#else
+ typedef ulong ulongptr;
+#endif
+
+
+// Helper macro for aligning pointer up to next 16-byte boundary
+#define SOUNDTOUCH_ALIGN_POINTER_16(x) ( ( (ulongptr)(x) + 15 ) & ~(ulongptr)15 )
+
+
+#if (defined(__GNUC__) && !defined(ANDROID))
+ // In GCC, include soundtouch_config.h made by config scritps.
+ // Skip this in Android compilation that uses GCC but without configure scripts.
#include "soundtouch_config.h"
#endif
@@ -60,64 +73,81 @@ typedef unsigned long ulong;
namespace soundtouch
{
+ /// Activate these undef's to overrule the possible sampletype
+ /// setting inherited from some other header file:
+ //#undef SOUNDTOUCH_INTEGER_SAMPLES
+ //#undef SOUNDTOUCH_FLOAT_SAMPLES
-/// Activate these undef's to overrule the possible sampletype
-/// setting inherited from some other header file:
-//#undef INTEGER_SAMPLES
-//#undef FLOAT_SAMPLES
+ #if (defined(__SOFTFP__))
+ // For Android compilation: Force use of Integer samples in case that
+ // compilation uses soft-floating point emulation - soft-fp is way too slow
+ #undef SOUNDTOUCH_FLOAT_SAMPLES
+ #define SOUNDTOUCH_INTEGER_SAMPLES 1
+ #endif
-#if !(INTEGER_SAMPLES || FLOAT_SAMPLES)
+ #if !(SOUNDTOUCH_INTEGER_SAMPLES || SOUNDTOUCH_FLOAT_SAMPLES)
+
+ /// Choose either 32bit floating point or 16bit integer sampletype
+ /// by choosing one of the following defines, unless this selection
+ /// has already been done in some other file.
+ ////
+ /// Notes:
+ /// - In Windows environment, choose the sample format with the
+ /// following defines.
+ /// - In GNU environment, the floating point samples are used by
+ /// default, but integer samples can be chosen by giving the
+ /// following switch to the configure script:
+ /// ./configure --enable-integer-samples
+ /// However, if you still prefer to select the sample format here
+ /// also in GNU environment, then please #undef the INTEGER_SAMPLE
+ /// and FLOAT_SAMPLE defines first as in comments above.
+ //#define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples
+ #define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples
+
+ #endif
- /// Choose either 32bit floating point or 16bit integer sampletype
- /// by choosing one of the following defines, unless this selection
- /// has already been done in some other file.
- ////
- /// Notes:
- /// - In Windows environment, choose the sample format with the
- /// following defines.
- /// - In GNU environment, the floating point samples are used by
- /// default, but integer samples can be chosen by giving the
- /// following switch to the configure script:
- /// ./configure --enable-integer-samples
- /// However, if you still prefer to select the sample format here
- /// also in GNU environment, then please #undef the INTEGER_SAMPLE
- /// and FLOAT_SAMPLE defines first as in comments above.
- //#define INTEGER_SAMPLES 1 //< 16bit integer samples
- #define FLOAT_SAMPLES 1 //< 32bit float samples
-
- #endif
-
- #if (WIN32 || __i386__ || __x86_64__)
- /// Define this to allow X86-specific assembler/intrinsic optimizations.
+ #if (_M_IX86 || __i386__ || __x86_64__ || _M_X64)
+ /// Define this to allow X86-specific assembler/intrinsic optimizations.
/// Notice that library contains also usual C++ versions of each of these
- /// these routines, so if you're having difficulties getting the optimized
- /// routines compiled for whatever reason, you may disable these optimizations
+ /// these routines, so if you're having difficulties getting the optimized
+ /// routines compiled for whatever reason, you may disable these optimizations
/// to make the library compile.
- #define ALLOW_X86_OPTIMIZATIONS 1
+ #define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
+
+ /// In GNU environment, allow the user to override this setting by
+ /// giving the following switch to the configure script:
+ /// ./configure --disable-x86-optimizations
+ /// ./configure --enable-x86-optimizations=no
+ #ifdef SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS
+ #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
+ #endif
+ #else
+ /// Always disable optimizations when not using a x86 systems.
+ #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
#endif
- // If defined, allows the SIMD-optimized routines to take minor shortcuts
- // for improved performance. Undefine to require faithfully similar SIMD
+ // If defined, allows the SIMD-optimized routines to take minor shortcuts
+ // for improved performance. Undefine to require faithfully similar SIMD
// calculations as in normal C implementation.
- #define ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
+ #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
- #ifdef INTEGER_SAMPLES
+ #ifdef SOUNDTOUCH_INTEGER_SAMPLES
// 16bit integer sample type
typedef short SAMPLETYPE;
// data type for sample accumulation: Use 32bit integer to prevent overflows
typedef long LONG_SAMPLETYPE;
- #ifdef FLOAT_SAMPLES
+ #ifdef SOUNDTOUCH_FLOAT_SAMPLES
// check that only one sample type is defined
#error "conflicting sample types defined"
- #endif // FLOAT_SAMPLES
+ #endif // SOUNDTOUCH_FLOAT_SAMPLES
- #ifdef ALLOW_X86_OPTIMIZATIONS
+ #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
// Allow MMX optimizations
- #define ALLOW_MMX 1
+ #define SOUNDTOUCH_ALLOW_MMX 1
#endif
#else
@@ -127,23 +157,31 @@ namespace soundtouch
// data type for sample accumulation: Use double to utilize full precision.
typedef double LONG_SAMPLETYPE;
- #ifdef ALLOW_X86_OPTIMIZATIONS
- // Allow 3DNow! and SSE optimizations
- #if WIN32
- #define ALLOW_3DNOW 1
- #endif
-
- #define ALLOW_SSE 1
+ #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
+ // Allow SSE optimizations
+ #define SOUNDTOUCH_ALLOW_SSE 1
#endif
- #endif // INTEGER_SAMPLES
+ #endif // SOUNDTOUCH_INTEGER_SAMPLES
+
};
+// define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
+// #define ST_NO_EXCEPTION_HANDLING 1
+#ifdef ST_NO_EXCEPTION_HANDLING
+ // Exceptions disabled. Throw asserts instead if enabled.
+ #include
+ #define ST_THROW_RT_ERROR(x) {assert((const char *)x);}
+#else
+ // use c++ standard exceptions
+ #include
+ #define ST_THROW_RT_ERROR(x) {throw std::runtime_error(x);}
+#endif
-// When this #define is active, eliminates a clicking sound when the "rate" or "pitch"
-// parameter setting crosses from value <1 to >=1 or vice versa during processing.
-// Default is off as such crossover is untypical case and involves a slight sound
+// When this #define is active, eliminates a clicking sound when the "rate" or "pitch"
+// parameter setting crosses from value <1 to >=1 or vice versa during processing.
+// Default is off as such crossover is untypical case and involves a slight sound
// quality compromise.
-//#define PREVENT_CLICK_AT_RATE_CROSSOVER 1
+//#define SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER 1
#endif
diff --git a/3rdparty/SoundTouch/SoundTouch.cpp b/3rdparty/SoundTouch/SoundTouch.cpp
index 8abfc23b27..c66c16c54a 100644
--- a/3rdparty/SoundTouch/SoundTouch.cpp
+++ b/3rdparty/SoundTouch/SoundTouch.cpp
@@ -1,27 +1,27 @@
//////////////////////////////////////////////////////////////////////////////
///
-/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
+/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
///
/// Notes:
-/// - Initialize the SoundTouch object instance by setting up the sound stream
-/// parameters with functions 'setSampleRate' and 'setChannels', then set
+/// - Initialize the SoundTouch object instance by setting up the sound stream
+/// parameters with functions 'setSampleRate' and 'setChannels', then set
/// desired tempo/pitch/rate settings with the corresponding functions.
///
-/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
+/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
/// samples that are to be processed are fed into one of the pipe by calling
-/// function 'putSamples', while the ready processed samples can be read
+/// function 'putSamples', while the ready processed samples can be read
/// from the other end of the pipeline with function 'receiveSamples'.
-///
-/// - The SoundTouch processing classes require certain sized 'batches' of
-/// samples in order to process the sound. For this reason the classes buffer
-/// incoming samples until there are enough of samples available for
+///
+/// - The SoundTouch processing classes require certain sized 'batches' of
+/// samples in order to process the sound. For this reason the classes buffer
+/// incoming samples until there are enough of samples available for
/// processing, then they carry out the processing step and consequently
/// make the processed samples available for outputting.
-///
-/// - For the above reason, the processing routines introduce a certain
+///
+/// - For the above reason, the processing routines introduce a certain
/// 'latency' between the input and output, so that the samples input to
-/// SoundTouch may not be immediately available in the output, and neither
-/// the amount of outputtable samples may not immediately be in direct
+/// SoundTouch may not be immediately available in the output, and neither
+/// the amount of outputtable samples may not immediately be in direct
/// relationship with the amount of previously input samples.
///
/// - The tempo/pitch/rate control parameters can be altered during processing.
@@ -30,8 +30,8 @@
/// required.
///
/// - This class utilizes classes 'TDStretch' for tempo change (without modifying
-/// pitch) and 'RateTransposer' for changing the playback rate (that is, both
-/// tempo and pitch in the same ratio) of the sound. The third available control
+/// pitch) and 'RateTransposer' for changing the playback rate (that is, both
+/// tempo and pitch in the same ratio) of the sound. The third available control
/// 'pitch' (change pitch but maintain tempo) is produced by a combination of
/// combining the two other controls.
///
@@ -41,10 +41,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-05-19 07:57:30 +0300 (Tue, 19 May 2009) $
+// Last changed : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $
// File revision : $Revision: 4 $
//
-// $Id: SoundTouch.cpp 73 2009-05-19 04:57:30Z oparviai $
+// $Id: SoundTouch.cpp 143 2012-06-13 19:29:53Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -73,7 +73,6 @@
#include
#include
#include
-#include
#include
#include "SoundTouch.h"
@@ -82,7 +81,7 @@
#include "cpu_detect.h"
using namespace soundtouch;
-
+
/// test if two floating point numbers are equal
#define TEST_FLOAT_EQUAL(a, b) (fabs(a - b) < 1e-10)
@@ -91,7 +90,7 @@ using namespace soundtouch;
extern "C" void soundtouch_ac_test()
{
printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION);
-}
+}
SoundTouch::SoundTouch()
@@ -105,8 +104,8 @@ SoundTouch::SoundTouch()
rate = tempo = 0;
- virtualPitch =
- virtualRate =
+ virtualPitch =
+ virtualRate =
virtualTempo = 1.0;
calcEffectiveRateAndTempo();
@@ -144,9 +143,9 @@ uint SoundTouch::getVersionId()
// Sets the number of channels, 1 = mono, 2 = stereo
void SoundTouch::setChannels(uint numChannels)
{
- if (numChannels != 1 && numChannels != 2)
+ if (numChannels != 1 && numChannels != 2)
{
- throw std::runtime_error("Illegal number of channels");
+ ST_THROW_RT_ERROR("Illegal number of channels");
}
channels = numChannels;
pRateTransposer->setChannels((int)numChannels);
@@ -243,10 +242,10 @@ void SoundTouch::calcEffectiveRateAndTempo()
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate);
if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
-#ifndef PREVENT_CLICK_AT_RATE_CROSSOVER
- if (rate <= 1.0f)
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
+ if (rate <= 1.0f)
{
- if (output != pTDStretch)
+ if (output != pTDStretch)
{
FIFOSamplePipe *tempoOut;
@@ -263,7 +262,7 @@ void SoundTouch::calcEffectiveRateAndTempo()
else
#endif
{
- if (output != pRateTransposer)
+ if (output != pRateTransposer)
{
FIFOSamplePipe *transOut;
@@ -276,7 +275,7 @@ void SoundTouch::calcEffectiveRateAndTempo()
output = pRateTransposer;
}
- }
+ }
}
@@ -293,42 +292,42 @@ void SoundTouch::setSampleRate(uint srate)
// the input of the object.
void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
{
- if (bSrateSet == FALSE)
+ if (bSrateSet == FALSE)
{
- throw std::runtime_error("SoundTouch : Sample rate not defined");
- }
- else if (channels == 0)
+ ST_THROW_RT_ERROR("SoundTouch : Sample rate not defined");
+ }
+ else if (channels == 0)
{
- throw std::runtime_error("SoundTouch : Number of channels not defined");
+ ST_THROW_RT_ERROR("SoundTouch : Number of channels not defined");
}
// Transpose the rate of the new samples if necessary
/* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
- if (rate == 1.0f)
+ if (rate == 1.0f)
{
- // The rate value is same as the original, simply evaluate the tempo changer.
+ // The rate value is same as the original, simply evaluate the tempo changer.
assert(output == pTDStretch);
- if (pRateTransposer->isEmpty() == 0)
+ if (pRateTransposer->isEmpty() == 0)
{
// yet flush the last samples in the pitch transposer buffer
// (may happen if 'rate' changes from a non-zero value to zero)
pTDStretch->moveSamples(*pRateTransposer);
}
pTDStretch->putSamples(samples, nSamples);
- }
+ }
*/
-#ifndef PREVENT_CLICK_AT_RATE_CROSSOVER
- else if (rate <= 1.0f)
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
+ else if (rate <= 1.0f)
{
// transpose the rate down, output the transposed sound to tempo changer buffer
assert(output == pTDStretch);
pRateTransposer->putSamples(samples, nSamples);
pTDStretch->moveSamples(*pRateTransposer);
- }
- else
+ }
+ else
#endif
{
- // evaluate the tempo changer, then transpose the rate up,
+ // evaluate the tempo changer, then transpose the rate up,
assert(output == pRateTransposer);
pTDStretch->putSamples(samples, nSamples);
pRateTransposer->moveSamples(*pTDStretch);
@@ -346,20 +345,36 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
void SoundTouch::flush()
{
int i;
- uint nOut;
- SAMPLETYPE buff[128];
+ int nUnprocessed;
+ int nOut;
+ SAMPLETYPE buff[64*2]; // note: allocate 2*64 to cater 64 sample frames of stereo sound
- nOut = numSamples();
+ // check how many samples still await processing, and scale
+ // that by tempo & rate to get expected output sample count
+ nUnprocessed = numUnprocessedSamples();
+ nUnprocessed = (int)((double)nUnprocessed / (tempo * rate) + 0.5);
- memset(buff, 0, 128 * sizeof(SAMPLETYPE));
+ nOut = numSamples(); // ready samples currently in buffer ...
+ nOut += nUnprocessed; // ... and how many we expect there to be in the end
+
+ memset(buff, 0, 64 * channels * sizeof(SAMPLETYPE));
// "Push" the last active samples out from the processing pipeline by
- // feeding blank samples into the processing pipeline until new,
- // processed samples appear in the output (not however, more than
+ // feeding blank samples into the processing pipeline until new,
+ // processed samples appear in the output (not however, more than
// 8ksamples in any case)
- for (i = 0; i < 128; i ++)
+ for (i = 0; i < 128; i ++)
{
putSamples(buff, 64);
- if (numSamples() != nOut) break; // new samples have appeared in the output!
+ if ((int)numSamples() >= nOut)
+ {
+ // Enough new samples have appeared into the output!
+ // As samples come from processing with bigger chunks, now truncate it
+ // back to maximum "nOut" samples to improve duration accuracy
+ adjustAmountOfSamples(nOut);
+
+ // finish
+ break;
+ }
}
// Clear working buffers
@@ -379,7 +394,7 @@ BOOL SoundTouch::setSetting(int settingId, int value)
// read current tdstretch routine parameters
pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
- switch (settingId)
+ switch (settingId)
{
case SETTING_USE_AA_FILTER :
// enables / disabless anti-alias filter
@@ -425,7 +440,7 @@ int SoundTouch::getSetting(int settingId) const
{
int temp;
- switch (settingId)
+ switch (settingId)
{
case SETTING_USE_AA_FILTER :
return (uint)pRateTransposer->isAAFilterEnabled();
@@ -448,7 +463,13 @@ int SoundTouch::getSetting(int settingId) const
pTDStretch->getParameters(NULL, NULL, NULL, &temp);
return temp;
- default :
+ case SETTING_NOMINAL_INPUT_SEQUENCE :
+ return pTDStretch->getInputSampleReq();
+
+ case SETTING_NOMINAL_OUTPUT_SEQUENCE :
+ return pTDStretch->getOutputBatchSize();
+
+ default :
return 0;
}
}
diff --git a/3rdparty/SoundTouch/SoundTouch.h b/3rdparty/SoundTouch/SoundTouch.h
index 9d82886aa9..6ae0e4a829 100644
--- a/3rdparty/SoundTouch/SoundTouch.h
+++ b/3rdparty/SoundTouch/SoundTouch.h
@@ -1,27 +1,27 @@
//////////////////////////////////////////////////////////////////////////////
///
-/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
+/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
///
/// Notes:
-/// - Initialize the SoundTouch object instance by setting up the sound stream
-/// parameters with functions 'setSampleRate' and 'setChannels', then set
+/// - Initialize the SoundTouch object instance by setting up the sound stream
+/// parameters with functions 'setSampleRate' and 'setChannels', then set
/// desired tempo/pitch/rate settings with the corresponding functions.
///
-/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
+/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
/// samples that are to be processed are fed into one of the pipe by calling
-/// function 'putSamples', while the ready processed samples can be read
+/// function 'putSamples', while the ready processed samples can be read
/// from the other end of the pipeline with function 'receiveSamples'.
-///
-/// - The SoundTouch processing classes require certain sized 'batches' of
-/// samples in order to process the sound. For this reason the classes buffer
-/// incoming samples until there are enough of samples available for
+///
+/// - The SoundTouch processing classes require certain sized 'batches' of
+/// samples in order to process the sound. For this reason the classes buffer
+/// incoming samples until there are enough of samples available for
/// processing, then they carry out the processing step and consequently
/// make the processed samples available for outputting.
-///
-/// - For the above reason, the processing routines introduce a certain
+///
+/// - For the above reason, the processing routines introduce a certain
/// 'latency' between the input and output, so that the samples input to
-/// SoundTouch may not be immediately available in the output, and neither
-/// the amount of outputtable samples may not immediately be in direct
+/// SoundTouch may not be immediately available in the output, and neither
+/// the amount of outputtable samples may not immediately be in direct
/// relationship with the amount of previously input samples.
///
/// - The tempo/pitch/rate control parameters can be altered during processing.
@@ -30,8 +30,8 @@
/// required.
///
/// - This class utilizes classes 'TDStretch' for tempo change (without modifying
-/// pitch) and 'RateTransposer' for changing the playback rate (that is, both
-/// tempo and pitch in the same ratio) of the sound. The third available control
+/// pitch) and 'RateTransposer' for changing the playback rate (that is, both
+/// tempo and pitch in the same ratio) of the sound. The third available control
/// 'pitch' (change pitch but maintain tempo) is produced by a combination of
/// combining the two other controls.
///
@@ -41,10 +41,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-12-28 22:10:14 +0200 (Mon, 28 Dec 2009) $
+// Last changed : $Date: 2012-12-28 17:32:59 -0200 (sex, 28 dez 2012) $
// File revision : $Revision: 4 $
//
-// $Id: SoundTouch.h 78 2009-12-28 20:10:14Z oparviai $
+// $Id: SoundTouch.h 163 2012-12-28 19:32:59Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -79,10 +79,10 @@ namespace soundtouch
{
/// Soundtouch library version string
-#define SOUNDTOUCH_VERSION "1.5.0"
+#define SOUNDTOUCH_VERSION "1.7.1"
/// SoundTouch library version id
-#define SOUNDTOUCH_VERSION_ID (10500)
+#define SOUNDTOUCH_VERSION_ID (10701)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
@@ -98,24 +98,49 @@ namespace soundtouch
/// quality compromising)
#define SETTING_USE_QUICKSEEK 2
-/// Time-stretch algorithm single processing sequence length in milliseconds. This determines
-/// to how long sequences the original sound is chopped in the time-stretch algorithm.
+/// Time-stretch algorithm single processing sequence length in milliseconds. This determines
+/// to how long sequences the original sound is chopped in the time-stretch algorithm.
/// See "STTypes.h" or README for more information.
#define SETTING_SEQUENCE_MS 3
-/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the
-/// best possible overlapping location. This determines from how wide window the algorithm
-/// may look for an optimal joining location when mixing the sound sequences back together.
+/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the
+/// best possible overlapping location. This determines from how wide window the algorithm
+/// may look for an optimal joining location when mixing the sound sequences back together.
/// See "STTypes.h" or README for more information.
#define SETTING_SEEKWINDOW_MS 4
-/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences
-/// are mixed back together, to form a continuous sound stream, this parameter defines over
-/// how long period the two consecutive sequences are let to overlap each other.
+/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences
+/// are mixed back together, to form a continuous sound stream, this parameter defines over
+/// how long period the two consecutive sequences are let to overlap each other.
/// See "STTypes.h" or README for more information.
#define SETTING_OVERLAP_MS 5
+/// Call "getSetting" with this ID to query nominal average processing sequence
+/// size in samples. This value tells approcimate value how many input samples
+/// SoundTouch needs to gather before it does DSP processing run for the sample batch.
+///
+/// Notices:
+/// - This is read-only parameter, i.e. setSetting ignores this parameter
+/// - Returned value is approximate average value, exact processing batch
+/// size may wary from time to time
+/// - This parameter value is not constant but may change depending on
+/// tempo/pitch/rate/samplerate settings.
+#define SETTING_NOMINAL_INPUT_SEQUENCE 6
+
+
+/// Call "getSetting" with this ID to query nominal average processing output
+/// size in samples. This value tells approcimate value how many output samples
+/// SoundTouch outputs once it does DSP processing run for a batch of input samples.
+///
+/// Notices:
+/// - This is read-only parameter, i.e. setSetting ignores this parameter
+/// - Returned value is approximate average value, exact processing batch
+/// size may wary from time to time
+/// - This parameter value is not constant but may change depending on
+/// tempo/pitch/rate/samplerate settings.
+#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7
+
class SoundTouch : public FIFOProcessor
{
private:
@@ -137,7 +162,7 @@ private:
/// Flag: Has sample rate been set?
BOOL bSrateSet;
- /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
+ /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
/// 'virtualPitch' parameters.
void calcEffectiveRateAndTempo();
@@ -181,7 +206,7 @@ public:
/// represent lower pitches, larger values higher pitch.
void setPitch(float newPitch);
- /// Sets pitch change in octaves compared to the original pitch
+ /// Sets pitch change in octaves compared to the original pitch
/// (-1.00 .. +1.00)
void setPitchOctaves(float newPitch);
@@ -221,7 +246,7 @@ public:
/// Changes a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's.
- ///
+ ///
/// \return 'TRUE' if the setting was succesfully changed
BOOL setSetting(int settingId, ///< Setting ID number. see SETTING_... defines.
int value ///< New setting value.
@@ -242,7 +267,7 @@ public:
/// classes 'FIFOProcessor' and 'FIFOSamplePipe')
///
/// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch.
- /// - numSamples() : Get number of 'ready' samples that can be received with
+ /// - numSamples() : Get number of 'ready' samples that can be received with
/// function 'receiveSamples()'
/// - isEmpty() : Returns nonzero if there aren't any 'ready' samples.
/// - clear() : Clears all samples from ready/processing buffers.
diff --git a/3rdparty/SoundTouch/TDStretch.cpp b/3rdparty/SoundTouch/TDStretch.cpp
index e37a0f53b8..8fa598f61c 100644
--- a/3rdparty/SoundTouch/TDStretch.cpp
+++ b/3rdparty/SoundTouch/TDStretch.cpp
@@ -1,10 +1,10 @@
////////////////////////////////////////////////////////////////////////////////
-///
-/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
-/// while maintaining the original pitch by using a time domain WSOLA-like
+///
+/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
+/// while maintaining the original pitch by using a time domain WSOLA-like
/// method with several performance-increasing tweaks.
///
-/// Note : MMX optimized functions reside in a separate, platform-specific
+/// Note : MMX optimized functions reside in a separate, platform-specific
/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
///
/// Author : Copyright (c) Olli Parviainen
@@ -13,10 +13,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-12-28 21:27:04 +0200 (Mon, 28 Dec 2009) $
+// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $
// File revision : $Revision: 1.12 $
//
-// $Id: TDStretch.cpp 77 2009-12-28 19:27:04Z oparviai $
+// $Id: TDStretch.cpp 160 2012-11-08 18:53:01Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -46,7 +46,6 @@
#include
#include
#include
-#include
#include "STTypes.h"
#include "cpu_detect.h"
@@ -91,7 +90,7 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
channels = 2;
pMidBuffer = NULL;
- pRefMidBufferUnaligned = NULL;
+ pMidBufferUnaligned = NULL;
overlapLength = 0;
bAutoSeqSetting = TRUE;
@@ -101,7 +100,7 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
skipFract = 0;
tempo = 1.0f;
- setParameters(48000, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
+ setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
setTempo(1.0f);
clear();
@@ -111,8 +110,7 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
TDStretch::~TDStretch()
{
- delete[] pMidBuffer;
- delete[] pRefMidBufferUnaligned;
+ delete[] pMidBufferUnaligned;
}
@@ -122,11 +120,11 @@ TDStretch::~TDStretch()
//
// 'sampleRate' = sample rate of the sound
// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
-// 'seekwindowMS' = seeking window length for scanning the best overlapping
+// 'seekwindowMS' = seeking window length for scanning the best overlapping
// position (default = 28 ms)
// 'overlapMS' = overlapping length (default = 12 ms)
-void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
+void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
int aSeekWindowMS, int aOverlapMS)
{
// accept only positive parameter values - if zero or negative, use old values instead
@@ -137,19 +135,19 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
{
this->sequenceMs = aSequenceMS;
bAutoSeqSetting = FALSE;
- }
+ }
else if (aSequenceMS == 0)
{
// if zero, use automatic setting
bAutoSeqSetting = TRUE;
}
- if (aSeekWindowMS > 0)
+ if (aSeekWindowMS > 0)
{
this->seekWindowMs = aSeekWindowMS;
bAutoSeekSetting = FALSE;
- }
- else if (aSeekWindowMS == 0)
+ }
+ else if (aSeekWindowMS == 0)
{
// if zero, use automatic setting
bAutoSeekSetting = TRUE;
@@ -196,12 +194,17 @@ void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWind
// Overlaps samples in 'midBuffer' with the samples in 'pInput'
void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
{
- int i, itemp;
+ int i;
+ SAMPLETYPE m1, m2;
- for (i = 0; i < overlapLength ; i ++)
+ m1 = (SAMPLETYPE)0;
+ m2 = (SAMPLETYPE)overlapLength;
+
+ for (i = 0; i < overlapLength ; i ++)
{
- itemp = overlapLength - i;
- pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits;
+ pOutput[i] = (pInput[i] * m1 + pMidBuffer[i] * m2 ) / overlapLength;
+ m1 += 1;
+ m2 -= 1;
}
}
@@ -247,40 +250,22 @@ BOOL TDStretch::isQuickSeekEnabled() const
// Seeks for the optimal overlap-mixing position.
int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
{
- if (channels == 2)
+ if (bQuickSeek)
{
- // stereo sound
- if (bQuickSeek)
- {
- return seekBestOverlapPositionStereoQuick(refPos);
- }
- else
- {
- return seekBestOverlapPositionStereo(refPos);
- }
- }
- else
+ return seekBestOverlapPositionQuick(refPos);
+ }
+ else
{
- // mono sound
- if (bQuickSeek)
- {
- return seekBestOverlapPositionMonoQuick(refPos);
- }
- else
- {
- return seekBestOverlapPositionMono(refPos);
- }
+ return seekBestOverlapPositionFull(refPos);
}
}
-
-
// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position
// of 'ovlPos'.
inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const
{
- if (channels == 2)
+ if (channels == 2)
{
// stereo sound
overlapStereo(pOutput, pInput + 2 * ovlPos);
@@ -292,38 +277,34 @@ inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, ui
-
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
// routine
//
// The best position is determined as the position where the two overlapped
// sample sequences are 'most alike', in terms of the highest cross-correlation
// value over the overlapping period
-int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
+int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
{
int bestOffs;
double bestCorr, corr;
int i;
- // Slopes the amplitudes of the 'midBuffer' samples
- precalcCorrReferenceStereo();
-
bestCorr = FLT_MIN;
bestOffs = 0;
// Scans for the best correlation value by testing each possible position
// over the permitted range.
- for (i = 0; i < seekLength; i ++)
+ for (i = 0; i < seekLength; i ++)
{
// Calculates correlation value for the mixing position corresponding
// to 'i'
- corr = (double)calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
+ corr = calcCrossCorr(refPos + channels * i, pMidBuffer);
// heuristic rule to slightly favour values close to mid of the range
double tmp = (double)(2 * i - seekLength) / (double)seekLength;
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
// Checks for the highest correlation value
- if (corr > bestCorr)
+ if (corr > bestCorr)
{
bestCorr = corr;
bestOffs = i;
@@ -342,16 +323,13 @@ int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
// The best position is determined as the position where the two overlapped
// sample sequences are 'most alike', in terms of the highest cross-correlation
// value over the overlapping period
-int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
+int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
{
int j;
int bestOffs;
double bestCorr, corr;
int scanCount, corrOffset, tempOffset;
- // Slopes the amplitude of the 'midBuffer' samples
- precalcCorrReferenceStereo();
-
bestCorr = FLT_MIN;
bestOffs = _scanOffsets[0][0];
corrOffset = 0;
@@ -360,26 +338,26 @@ int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
// Scans for the best correlation value using four-pass hierarchical search.
//
// The look-up table 'scans' has hierarchical position adjusting steps.
- // In first pass the routine searhes for the highest correlation with
+ // In first pass the routine searhes for the highest correlation with
// relatively coarse steps, then rescans the neighbourhood of the highest
// correlation with better resolution and so on.
- for (scanCount = 0;scanCount < 4; scanCount ++)
+ for (scanCount = 0;scanCount < 4; scanCount ++)
{
j = 0;
- while (_scanOffsets[scanCount][j])
+ while (_scanOffsets[scanCount][j])
{
tempOffset = corrOffset + _scanOffsets[scanCount][j];
if (tempOffset >= seekLength) break;
// Calculates correlation value for the mixing position corresponding
// to 'tempOffset'
- corr = (double)calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
+ corr = (double)calcCrossCorr(refPos + channels * tempOffset, pMidBuffer);
// heuristic rule to slightly favour values close to mid of the range
double tmp = (double)(2 * tempOffset - seekLength) / seekLength;
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
// Checks for the highest correlation value
- if (corr > bestCorr)
+ if (corr > bestCorr)
{
bestCorr = corr;
bestOffs = tempOffset;
@@ -396,112 +374,7 @@ int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
-// Seeks for the optimal overlap-mixing position. The 'mono' version of the
-// routine
-//
-// The best position is determined as the position where the two overlapped
-// sample sequences are 'most alike', in terms of the highest cross-correlation
-// value over the overlapping period
-int TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos)
-{
- int bestOffs;
- double bestCorr, corr;
- int tempOffset;
- const SAMPLETYPE *compare;
-
- // Slopes the amplitude of the 'midBuffer' samples
- precalcCorrReferenceMono();
-
- bestCorr = FLT_MIN;
- bestOffs = 0;
-
- // Scans for the best correlation value by testing each possible position
- // over the permitted range.
- for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)
- {
- compare = refPos + tempOffset;
-
- // Calculates correlation value for the mixing position corresponding
- // to 'tempOffset'
- corr = (double)calcCrossCorrMono(pRefMidBuffer, compare);
- // heuristic rule to slightly favour values close to mid of the range
- double tmp = (double)(2 * tempOffset - seekLength) / seekLength;
- corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
-
- // Checks for the highest correlation value
- if (corr > bestCorr)
- {
- bestCorr = corr;
- bestOffs = tempOffset;
- }
- }
- // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
- clearCrossCorrState();
-
- return bestOffs;
-}
-
-
-// Seeks for the optimal overlap-mixing position. The 'mono' version of the
-// routine
-//
-// The best position is determined as the position where the two overlapped
-// sample sequences are 'most alike', in terms of the highest cross-correlation
-// value over the overlapping period
-int TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos)
-{
- int j;
- int bestOffs;
- double bestCorr, corr;
- int scanCount, corrOffset, tempOffset;
-
- // Slopes the amplitude of the 'midBuffer' samples
- precalcCorrReferenceMono();
-
- bestCorr = FLT_MIN;
- bestOffs = _scanOffsets[0][0];
- corrOffset = 0;
- tempOffset = 0;
-
- // Scans for the best correlation value using four-pass hierarchical search.
- //
- // The look-up table 'scans' has hierarchical position adjusting steps.
- // In first pass the routine searhes for the highest correlation with
- // relatively coarse steps, then rescans the neighbourhood of the highest
- // correlation with better resolution and so on.
- for (scanCount = 0;scanCount < 4; scanCount ++)
- {
- j = 0;
- while (_scanOffsets[scanCount][j])
- {
- tempOffset = corrOffset + _scanOffsets[scanCount][j];
- if (tempOffset >= seekLength) break;
-
- // Calculates correlation value for the mixing position corresponding
- // to 'tempOffset'
- corr = (double)calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
- // heuristic rule to slightly favour values close to mid of the range
- double tmp = (double)(2 * tempOffset - seekLength) / seekLength;
- corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
-
- // Checks for the highest correlation value
- if (corr > bestCorr)
- {
- bestCorr = corr;
- bestOffs = tempOffset;
- }
- j ++;
- }
- corrOffset = bestOffs;
- }
- // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
- clearCrossCorrState();
-
- return bestOffs;
-}
-
-
-/// clear cross correlation routine state if necessary
+/// clear cross correlation routine state if necessary
void TDStretch::clearCrossCorrState()
{
// default implementation is empty.
@@ -531,7 +404,7 @@ void TDStretch::calcSeqParameters()
#define CHECK_LIMITS(x, mi, ma) (((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x)))
double seq, seek;
-
+
if (bAutoSeqSetting)
{
seq = AUTOSEQ_C + AUTOSEQ_K * tempo;
@@ -548,7 +421,7 @@ void TDStretch::calcSeqParameters()
// Update seek window lengths
seekWindowLength = (sampleRate * sequenceMs) / 1000;
- if (seekWindowLength < 2 * overlapLength)
+ if (seekWindowLength < 2 * overlapLength)
{
seekWindowLength = 2 * overlapLength;
}
@@ -557,7 +430,7 @@ void TDStretch::calcSeqParameters()
-// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
+// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
// tempo, larger faster tempo.
void TDStretch::setTempo(float newTempo)
{
@@ -568,11 +441,11 @@ void TDStretch::setTempo(float newTempo)
// Calculate new sequence duration
calcSeqParameters();
- // Calculate ideal skip length (according to tempo value)
+ // Calculate ideal skip length (according to tempo value)
nominalSkip = tempo * (seekWindowLength - overlapLength);
intskip = (int)(nominalSkip + 0.5f);
- // Calculate how many samples are needed in the 'inputBuffer' to
+ // Calculate how many samples are needed in the 'inputBuffer' to
// process another batch of samples
//sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength / 2;
sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength;
@@ -600,18 +473,18 @@ void TDStretch::processNominalTempo()
{
assert(tempo == 1.0f);
- if (bMidBufferDirty)
+ if (bMidBufferDirty)
{
// If there are samples in pMidBuffer waiting for overlapping,
- // do a single sliding overlapping with them in order to prevent a
+ // do a single sliding overlapping with them in order to prevent a
// clicking distortion in the output sound
- if (inputBuffer.numSamples() < overlapLength)
+ if (inputBuffer.numSamples() < overlapLength)
{
// wait until we've got overlapLength input samples
return;
}
- // Mix the samples in the beginning of 'inputBuffer' with the
- // samples in 'midBuffer' using sliding overlapping
+ // Mix the samples in the beginning of 'inputBuffer' with the
+ // samples in 'midBuffer' using sliding overlapping
overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
outputBuffer.putSamples(overlapLength);
inputBuffer.receiveSamples(overlapLength);
@@ -636,7 +509,7 @@ void TDStretch::processSamples()
/* Removed this small optimization - can introduce a click to sound when tempo setting
crosses the nominal value
- if (tempo == 1.0f)
+ if (tempo == 1.0f)
{
// tempo not changed from the original, so bypass the processing
processNominalTempo();
@@ -646,14 +519,13 @@ void TDStretch::processSamples()
// Process samples as long as there are enough samples in 'inputBuffer'
// to form a processing frame.
-// while ((int)inputBuffer.numSamples() >= sampleReq - (outDebt / 4))
- while ((int)inputBuffer.numSamples() >= sampleReq)
+ while ((int)inputBuffer.numSamples() >= sampleReq)
{
// If tempo differs from the normal ('SCALE'), scan for the best overlapping
// position
offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
- // Mix the samples in the 'inputBuffer' at position of 'offset' with the
+ // Mix the samples in the 'inputBuffer' at position of 'offset' with the
// samples in 'midBuffer' using sliding overlapping
// ... first partially overlap with the end of the previous sequence
// (that's in 'midBuffer')
@@ -661,16 +533,8 @@ void TDStretch::processSamples()
outputBuffer.putSamples((uint)overlapLength);
// ... then copy sequence samples from 'inputBuffer' to output:
- temp = (seekLength / 2 - offset);
-
- // compensate cumulated output length diff vs. ideal output
-// temp -= outDebt / 4;
-
- // update ideal vs. true output difference
-// outDebt += temp;
// length of sequence
-// temp += (seekWindowLength - 2 * overlapLength);
temp = (seekWindowLength - 2 * overlapLength);
// crosscheck that we don't have buffer overflow...
@@ -681,11 +545,11 @@ void TDStretch::processSamples()
outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp);
- // Copies the end of the current sequence from 'inputBuffer' to
- // 'midBuffer' for being mixed with the beginning of the next
+ // Copies the end of the current sequence from 'inputBuffer' to
+ // 'midBuffer' for being mixed with the beginning of the next
// processing sequence and so on
assert((offset + temp + overlapLength * 2) <= (int)inputBuffer.numSamples());
- memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength),
+ memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength),
channels * sizeof(SAMPLETYPE) * overlapLength);
// Remove the processed samples from the input buffer. Update
@@ -722,26 +586,24 @@ void TDStretch::acceptNewOverlapLength(int newOverlapLength)
if (overlapLength > prevOvl)
{
- delete[] pMidBuffer;
- delete[] pRefMidBufferUnaligned;
+ delete[] pMidBufferUnaligned;
+
+ pMidBufferUnaligned = new SAMPLETYPE[overlapLength * 2 + 16 / sizeof(SAMPLETYPE)];
+ // ensure that 'pMidBuffer' is aligned to 16 byte boundary for efficiency
+ pMidBuffer = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(pMidBufferUnaligned);
- pMidBuffer = new SAMPLETYPE[overlapLength * 2];
clearMidBuffer();
-
- pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
- // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
- pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & (ulong)-16);
}
}
-// Operator 'new' is overloaded so that it automatically creates a suitable instance
+// Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX/SSE/etc-capable CPU available or not.
void * TDStretch::operator new(size_t s)
{
// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
- throw std::runtime_error("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!");
- return NULL;
+ ST_THROW_RT_ERROR("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!");
+ return newInstance();
}
@@ -751,36 +613,26 @@ TDStretch * TDStretch::newInstance()
uExtensions = detectCPUextensions();
- // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
+ // Check if MMX/SSE instruction set extensions supported by CPU
-#ifdef ALLOW_MMX
+#ifdef SOUNDTOUCH_ALLOW_MMX
// MMX routines available only with integer sample types
if (uExtensions & SUPPORT_MMX)
{
return ::new TDStretchMMX;
}
else
-#endif // ALLOW_MMX
+#endif // SOUNDTOUCH_ALLOW_MMX
-#ifdef ALLOW_SSE
+#ifdef SOUNDTOUCH_ALLOW_SSE
if (uExtensions & SUPPORT_SSE)
{
// SSE support
return ::new TDStretchSSE;
}
else
-#endif // ALLOW_SSE
-
-
-#ifdef ALLOW_3DNOW
- if (uExtensions & SUPPORT_3DNOW)
- {
- // 3DNow! support
- return ::new TDStretch3DNow;
- }
- else
-#endif // ALLOW_3DNOW
+#endif // SOUNDTOUCH_ALLOW_SSE
{
// ISA optimizations not supported, use plain C version
@@ -795,46 +647,9 @@ TDStretch * TDStretch::newInstance()
//
//////////////////////////////////////////////////////////////////////////////
-#ifdef INTEGER_SAMPLES
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
-// is faster to calculate
-void TDStretch::precalcCorrReferenceStereo()
-{
- int i, cnt2;
- int temp, temp2;
-
- for (i=0 ; i < (int)overlapLength ;i ++)
- {
- temp = i * (overlapLength - i);
- cnt2 = i * 2;
-
- temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
- pRefMidBuffer[cnt2] = (short)(temp2);
- temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
- pRefMidBuffer[cnt2 + 1] = (short)(temp2);
- }
-}
-
-
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
-// is faster to calculate
-void TDStretch::precalcCorrReferenceMono()
-{
- int i;
- long temp;
- long temp2;
-
- for (i=0 ; i < (int)overlapLength ;i ++)
- {
- temp = i * (overlapLength - i);
- temp2 = (pMidBuffer[i] * temp) / slopingDivider;
- pRefMidBuffer[i] = (short)temp2;
- }
-}
-
-
-// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
+// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
// version of the routine.
void TDStretch::overlapStereo(short *poutput, const short *input) const
{
@@ -842,7 +657,7 @@ void TDStretch::overlapStereo(short *poutput, const short *input) const
short temp;
int cnt2;
- for (i = 0; i < overlapLength ; i ++)
+ for (i = 0; i < overlapLength ; i ++)
{
temp = (short)(overlapLength - i);
cnt2 = 2 * i;
@@ -868,8 +683,8 @@ void TDStretch::calculateOverlapLength(int aoverlapMs)
assert(aoverlapMs >= 0);
// calculate overlap length so that it's power of 2 - thus it's easy to do
- // integer division by right-shifting. Term "-1" at end is to account for
- // the extra most significatnt bit left unused in result by signed multiplication
+ // integer division by right-shifting. Term "-1" at end is to account for
+ // the extra most significatnt bit left unused in result by signed multiplication
overlapDividerBits = _getClosest2Power((sampleRate * aoverlapMs) / 1000.0) - 1;
if (overlapDividerBits > 9) overlapDividerBits = 9;
if (overlapDividerBits < 3) overlapDividerBits = 3;
@@ -877,113 +692,70 @@ void TDStretch::calculateOverlapLength(int aoverlapMs)
acceptNewOverlapLength(newOvl);
- // calculate sloping divider so that crosscorrelation operation won't
- // overflow 32-bit register. Max. sum of the crosscorrelation sum without
+ // calculate sloping divider so that crosscorrelation operation won't
+ // overflow 32-bit register. Max. sum of the crosscorrelation sum without
// divider would be 2^30*(N^3-N)/3, where N = overlap length
slopingDivider = (newOvl * newOvl - 1) / 3;
}
-long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
+double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare) const
{
long corr;
long norm;
int i;
corr = norm = 0;
- for (i = 1; i < overlapLength; i ++)
+ // Same routine for stereo and mono. For stereo, unroll loop for better
+ // efficiency and gives slightly better resolution against rounding.
+ // For mono it same routine, just unrolls loop by factor of 4
+ for (i = 0; i < channels * overlapLength; i += 4)
{
- corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
- norm += (mixingPos[i] * mixingPos[i]) >> overlapDividerBits;
+ corr += (mixingPos[i] * compare[i] +
+ mixingPos[i + 1] * compare[i + 1] +
+ mixingPos[i + 2] * compare[i + 2] +
+ mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBits;
+ norm += (mixingPos[i] * mixingPos[i] +
+ mixingPos[i + 1] * mixingPos[i + 1] +
+ mixingPos[i + 2] * mixingPos[i + 2] +
+ mixingPos[i + 3] * mixingPos[i + 3]) >> overlapDividerBits;
}
- // Normalize result by dividing by sqrt(norm) - this step is easiest
+ // Normalize result by dividing by sqrt(norm) - this step is easiest
// done using floating point operation
if (norm == 0) norm = 1; // to avoid div by zero
- return (long)((double)corr * SHRT_MAX / sqrt((double)norm));
+ return (double)corr / sqrt((double)norm);
}
-
-long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
-{
- long corr;
- long norm;
- int i;
-
- corr = norm = 0;
- for (i = 2; i < 2 * overlapLength; i += 2)
- {
- corr += (mixingPos[i] * compare[i] +
- mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
- norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBits;
- }
-
- // Normalize result by dividing by sqrt(norm) - this step is easiest
- // done using floating point operation
- if (norm == 0) norm = 1; // to avoid div by zero
- return (long)((double)corr * SHRT_MAX / sqrt((double)norm));
-}
-
-#endif // INTEGER_SAMPLES
+#endif // SOUNDTOUCH_INTEGER_SAMPLES
//////////////////////////////////////////////////////////////////////////////
//
// Floating point arithmetics specific algorithm implementations.
//
-#ifdef FLOAT_SAMPLES
-
-
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
-// is faster to calculate
-void TDStretch::precalcCorrReferenceStereo()
-{
- int i, cnt2;
- float temp;
-
- for (i=0 ; i < (int)overlapLength ;i ++)
- {
- temp = (float)i * (float)(overlapLength - i);
- cnt2 = i * 2;
- pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
- pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
- }
-}
-
-
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
-// is faster to calculate
-void TDStretch::precalcCorrReferenceMono()
-{
- int i;
- float temp;
-
- for (i=0 ; i < (int)overlapLength ;i ++)
- {
- temp = (float)i * (float)(overlapLength - i);
- pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
- }
-}
-
+#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// Overlaps samples in 'midBuffer' with the samples in 'pInput'
void TDStretch::overlapStereo(float *pOutput, const float *pInput) const
{
int i;
- int cnt2;
- float fTemp;
float fScale;
- float fi;
+ float f1;
+ float f2;
fScale = 1.0f / (float)overlapLength;
- for (i = 0; i < (int)overlapLength ; i ++)
+ f1 = 0;
+ f2 = 1.0f;
+
+ for (i = 0; i < 2 * (int)overlapLength ; i += 2)
{
- fTemp = (float)(overlapLength - i) * fScale;
- fi = (float)i * fScale;
- cnt2 = 2 * i;
- pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
- pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
+ pOutput[i + 0] = pInput[i + 0] * f1 + pMidBuffer[i + 0] * f2;
+ pOutput[i + 1] = pInput[i + 1] * f1 + pMidBuffer[i + 1] * f2;
+
+ f1 += fScale;
+ f2 -= fScale;
}
}
@@ -1004,42 +776,33 @@ void TDStretch::calculateOverlapLength(int overlapInMsec)
}
-
-double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
+double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare) const
{
double corr;
double norm;
int i;
corr = norm = 0;
- for (i = 1; i < overlapLength; i ++)
- {
- corr += mixingPos[i] * compare[i];
- norm += mixingPos[i] * mixingPos[i];
- }
-
- if (norm < 1e-9) norm = 1.0; // to avoid div by zero
- return corr / sqrt(norm);
-}
-
-
-double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
-{
- double corr;
- double norm;
- int i;
-
- corr = norm = 0;
- for (i = 2; i < 2 * overlapLength; i += 2)
+ // Same routine for stereo and mono. For Stereo, unroll by factor of 2.
+ // For mono it's same routine yet unrollsd by factor of 4.
+ for (i = 0; i < channels * overlapLength; i += 4)
{
corr += mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1];
- norm += mixingPos[i] * mixingPos[i] +
+
+ norm += mixingPos[i] * mixingPos[i] +
mixingPos[i + 1] * mixingPos[i + 1];
+
+ // unroll the loop for better CPU efficiency:
+ corr += mixingPos[i + 2] * compare[i + 2] +
+ mixingPos[i + 3] * compare[i + 3];
+
+ norm += mixingPos[i + 2] * mixingPos[i + 2] +
+ mixingPos[i + 3] * mixingPos[i + 3];
}
if (norm < 1e-9) norm = 1.0; // to avoid div by zero
return corr / sqrt(norm);
}
-#endif // FLOAT_SAMPLES
+#endif // SOUNDTOUCH_FLOAT_SAMPLES
diff --git a/3rdparty/SoundTouch/TDStretch.h b/3rdparty/SoundTouch/TDStretch.h
index 1962d818a1..6861251014 100644
--- a/3rdparty/SoundTouch/TDStretch.h
+++ b/3rdparty/SoundTouch/TDStretch.h
@@ -1,10 +1,10 @@
////////////////////////////////////////////////////////////////////////////////
-///
-/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
-/// while maintaining the original pitch by using a time domain WSOLA-like method
+///
+/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
+/// while maintaining the original pitch by using a time domain WSOLA-like method
/// with several performance-increasing tweaks.
///
-/// Note : MMX/SSE optimized functions reside in separate, platform-specific files
+/// Note : MMX/SSE optimized functions reside in separate, platform-specific files
/// 'mmx_optimized.cpp' and 'sse_optimized.cpp'
///
/// Author : Copyright (c) Olli Parviainen
@@ -13,10 +13,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-05-17 14:35:13 +0300 (Sun, 17 May 2009) $
+// Last changed : $Date: 2012-04-01 16:49:30 -0300 (dom, 01 abr 2012) $
// File revision : $Revision: 4 $
//
-// $Id: TDStretch.h 71 2009-05-17 11:35:13Z oparviai $
+// $Id: TDStretch.h 137 2012-04-01 19:49:30Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -53,14 +53,14 @@ namespace soundtouch
{
/// Default values for sound processing parameters:
-/// Notice that the default parameters are tuned for contemporary popular music
+/// Notice that the default parameters are tuned for contemporary popular music
/// processing. For speech processing applications these parameters suit better:
/// #define DEFAULT_SEQUENCE_MS 40
/// #define DEFAULT_SEEKWINDOW_MS 15
/// #define DEFAULT_OVERLAP_MS 8
///
-/// Default length of a single processing sequence, in milliseconds. This determines to how
+/// Default length of a single processing sequence, in milliseconds. This determines to how
/// long sequences the original sound is chopped in the time-stretch algorithm.
///
/// The larger this value is, the lesser sequences are used in processing. In principle
@@ -75,15 +75,15 @@ namespace soundtouch
/// according to tempo setting (recommended)
#define USE_AUTO_SEQUENCE_LEN 0
-/// Seeking window default length in milliseconds for algorithm that finds the best possible
-/// overlapping location. This determines from how wide window the algorithm may look for an
-/// optimal joining location when mixing the sound sequences back together.
+/// Seeking window default length in milliseconds for algorithm that finds the best possible
+/// overlapping location. This determines from how wide window the algorithm may look for an
+/// optimal joining location when mixing the sound sequences back together.
///
/// The bigger this window setting is, the higher the possibility to find a better mixing
/// position will become, but at the same time large values may cause a "drifting" artifact
/// because consequent sequences will be taken at more uneven intervals.
///
-/// If there's a disturbing artifact that sounds as if a constant frequency was drifting
+/// If there's a disturbing artifact that sounds as if a constant frequency was drifting
/// around, try reducing this setting.
///
/// Increasing this value increases computational burden & vice versa.
@@ -94,11 +94,11 @@ namespace soundtouch
/// according to tempo setting (recommended)
#define USE_AUTO_SEEKWINDOW_LEN 0
-/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together,
-/// to form a continuous sound stream, this parameter defines over how long period the two
-/// consecutive sequences are let to overlap each other.
+/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together,
+/// to form a continuous sound stream, this parameter defines over how long period the two
+/// consecutive sequences are let to overlap each other.
///
-/// This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting
+/// This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting
/// by a large amount, you might wish to try a smaller value on this.
///
/// Increasing this value increases computational burden & vice versa.
@@ -115,8 +115,7 @@ protected:
float tempo;
SAMPLETYPE *pMidBuffer;
- SAMPLETYPE *pRefMidBuffer;
- SAMPLETYPE *pRefMidBufferUnaligned;
+ SAMPLETYPE *pMidBufferUnaligned;
int overlapLength;
int seekLength;
int seekWindowLength;
@@ -127,8 +126,6 @@ protected:
FIFOSampleBuffer outputBuffer;
FIFOSampleBuffer inputBuffer;
BOOL bQuickSeek;
-// int outDebt;
-// BOOL bMidBufferDirty;
int sampleRate;
int sequenceMs;
@@ -142,13 +139,10 @@ protected:
virtual void clearCrossCorrState();
void calculateOverlapLength(int overlapMs);
- virtual LONG_SAMPLETYPE calcCrossCorrStereo(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
- virtual LONG_SAMPLETYPE calcCrossCorrMono(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
+ virtual double calcCrossCorr(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
- virtual int seekBestOverlapPositionStereo(const SAMPLETYPE *refPos);
- virtual int seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos);
- virtual int seekBestOverlapPositionMono(const SAMPLETYPE *refPos);
- virtual int seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos);
+ virtual int seekBestOverlapPositionFull(const SAMPLETYPE *refPos);
+ virtual int seekBestOverlapPositionQuick(const SAMPLETYPE *refPos);
int seekBestOverlapPosition(const SAMPLETYPE *refPos);
virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const;
@@ -157,9 +151,6 @@ protected:
void clearMidBuffer();
void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const;
- void precalcCorrReferenceMono();
- void precalcCorrReferenceStereo();
-
void calcSeqParameters();
/// Changes the tempo of the given sound samples.
@@ -167,27 +158,27 @@ protected:
/// The maximum amount of samples that can be returned at a time is set by
/// the 'set_returnBuffer_size' function.
void processSamples();
-
+
public:
TDStretch();
virtual ~TDStretch();
- /// Operator 'new' is overloaded so that it automatically creates a suitable instance
+ /// Operator 'new' is overloaded so that it automatically creates a suitable instance
/// depending on if we've a MMX/SSE/etc-capable CPU available or not.
static void *operator new(size_t s);
- /// Use this function instead of "new" operator to create a new instance of this class.
+ /// Use this function instead of "new" operator to create a new instance of this class.
/// This function automatically chooses a correct feature set depending on if the CPU
/// supports MMX/SSE/etc extensions.
static TDStretch *newInstance();
-
+
/// Returns the output buffer object
FIFOSamplePipe *getOutput() { return &outputBuffer; };
/// Returns the input buffer object
FIFOSamplePipe *getInput() { return &inputBuffer; };
- /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
+ /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
/// tempo, larger faster tempo.
void setTempo(float newTempo);
@@ -200,7 +191,7 @@ public:
/// Sets the number of channels, 1 = mono, 2 = stereo
void setChannels(int numChannels);
- /// Enables/disables the quick position seeking algorithm. Zero to disable,
+ /// Enables/disables the quick position seeking algorithm. Zero to disable,
/// nonzero to enable
void enableQuickSeek(BOOL enable);
@@ -212,7 +203,7 @@ public:
//
/// 'sampleRate' = sample rate of the sound
/// 'sequenceMS' = one processing sequence length in milliseconds
- /// 'seekwindowMS' = seeking window length for scanning the best overlapping
+ /// 'seekwindowMS' = seeking window length for scanning the best overlapping
/// position
/// 'overlapMS' = overlapping length
void setParameters(int sampleRate, ///< Samplerate of sound being processed (Hz)
@@ -233,43 +224,45 @@ public:
uint numSamples ///< Number of samples in 'samples' so that one sample
///< contains both channels if stereo
);
+
+ /// return nominal input sample requirement for triggering a processing batch
+ int getInputSampleReq() const
+ {
+ return (int)(nominalSkip + 0.5);
+ }
+
+ /// return nominal output sample amount when running a processing batch
+ int getOutputBatchSize() const
+ {
+ return seekWindowLength - overlapLength;
+ }
};
// Implementation-specific class declarations:
-#ifdef ALLOW_MMX
+#ifdef SOUNDTOUCH_ALLOW_MMX
/// Class that implements MMX optimized routines for 16bit integer samples type.
class TDStretchMMX : public TDStretch
{
protected:
- long calcCrossCorrStereo(const short *mixingPos, const short *compare) const;
+ double calcCrossCorr(const short *mixingPos, const short *compare) const;
virtual void overlapStereo(short *output, const short *input) const;
virtual void clearCrossCorrState();
};
-#endif /// ALLOW_MMX
+#endif /// SOUNDTOUCH_ALLOW_MMX
-#ifdef ALLOW_3DNOW
- /// Class that implements 3DNow! optimized routines for floating point samples type.
- class TDStretch3DNow : public TDStretch
- {
- protected:
- double calcCrossCorrStereo(const float *mixingPos, const float *compare) const;
- };
-#endif /// ALLOW_3DNOW
-
-
-#ifdef ALLOW_SSE
+#ifdef SOUNDTOUCH_ALLOW_SSE
/// Class that implements SSE optimized routines for floating point samples type.
class TDStretchSSE : public TDStretch
{
protected:
- double calcCrossCorrStereo(const float *mixingPos, const float *compare) const;
+ double calcCrossCorr(const float *mixingPos, const float *compare) const;
};
-#endif /// ALLOW_SSE
+#endif /// SOUNDTOUCH_ALLOW_SSE
}
#endif /// TDStretch_H
diff --git a/3rdparty/SoundTouch/cpu_detect.h b/3rdparty/SoundTouch/cpu_detect.h
index 33c5026ce0..809f841b3d 100644
--- a/3rdparty/SoundTouch/cpu_detect.h
+++ b/3rdparty/SoundTouch/cpu_detect.h
@@ -2,8 +2,8 @@
///
/// A header file for detecting the Intel MMX instructions set extension.
///
-/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the
-/// routine implementations for x86 Windows, x86 gnu version and non-x86
+/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the
+/// routine implementations for x86 Windows, x86 gnu version and non-x86
/// platforms, respectively.
///
/// Author : Copyright (c) Olli Parviainen
@@ -12,7 +12,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
+// Last changed : $Date: 2008-02-10 14:26:55 -0200 (dom, 10 fev 2008) $
// File revision : $Revision: 4 $
//
// $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $
diff --git a/3rdparty/SoundTouch/cpu_detect_x86.cpp b/3rdparty/SoundTouch/cpu_detect_x86.cpp
new file mode 100644
index 0000000000..4b09dba20b
--- /dev/null
+++ b/3rdparty/SoundTouch/cpu_detect_x86.cpp
@@ -0,0 +1,137 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Generic version of the x86 CPU extension detection routine.
+///
+/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp'
+/// for the Microsoft compiler version.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// Last changed : $Date: 2012-11-08 16:44:37 -0200 (qui, 08 nov 2012) $
+// File revision : $Revision: 4 $
+//
+// $Id: cpu_detect_x86.cpp 159 2012-11-08 18:44:37Z oparviai $
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// License :
+//
+// SoundTouch audio processing library
+// Copyright (c) Olli Parviainen
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include "cpu_detect.h"
+#include "STTypes.h"
+
+#if defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
+
+ #if defined(__GNUC__) && defined(__i386__)
+ // gcc
+ #include "cpuid.h"
+ #elif defined(_M_IX86)
+ // windows non-gcc
+ #include
+ #define bit_MMX (1 << 23)
+ #define bit_SSE (1 << 25)
+ #define bit_SSE2 (1 << 26)
+ #endif
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// processor instructions extension detection routines
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Flag variable indicating whick ISA extensions are disabled (for debugging)
+static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions
+
+// Disables given set of instruction extensions. See SUPPORT_... defines.
+void disableExtensions(uint dwDisableMask)
+{
+ _dwDisabledISA = dwDisableMask;
+}
+
+
+
+/// Checks which instruction set extensions are supported by the CPU.
+uint detectCPUextensions(void)
+{
+/// If building for a 64bit system (no Itanium) and the user wants optimizations.
+/// Return the OR of SUPPORT_{MMX,SSE,SSE2}. 11001 or 0x19.
+/// Keep the _dwDisabledISA test (2 more operations, could be eliminated).
+#if ((defined(__GNUC__) && defined(__x86_64__)) \
+ || defined(_M_X64)) \
+ && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
+ return 0x19 & ~_dwDisabledISA;
+
+/// If building for a 32bit system and the user wants optimizations.
+/// Keep the _dwDisabledISA test (2 more operations, could be eliminated).
+#elif ((defined(__GNUC__) && defined(__i386__)) \
+ || defined(_M_IX86)) \
+ && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
+
+ if (_dwDisabledISA == 0xffffffff) return 0;
+
+ uint res = 0;
+
+#if defined(__GNUC__)
+ // GCC version of cpuid. Requires GCC 4.3.0 or later for __cpuid intrinsic support.
+ uint eax, ebx, ecx, edx; // unsigned int is the standard type. uint is defined by the compiler and not guaranteed to be portable.
+
+ // Check if no cpuid support.
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) return 0; // always disable extensions.
+
+ if (edx & bit_MMX) res = res | SUPPORT_MMX;
+ if (edx & bit_SSE) res = res | SUPPORT_SSE;
+ if (edx & bit_SSE2) res = res | SUPPORT_SSE2;
+
+#else
+ // Window / VS version of cpuid. Notice that Visual Studio 2005 or later required
+ // for __cpuid intrinsic support.
+ int reg[4] = {-1};
+
+ // Check if no cpuid support.
+ __cpuid(reg,0);
+ if ((unsigned int)reg[0] == 0) return 0; // always disable extensions.
+
+ __cpuid(reg,1);
+ if ((unsigned int)reg[3] & bit_MMX) res = res | SUPPORT_MMX;
+ if ((unsigned int)reg[3] & bit_SSE) res = res | SUPPORT_SSE;
+ if ((unsigned int)reg[3] & bit_SSE2) res = res | SUPPORT_SSE2;
+
+#endif
+
+ return res & ~_dwDisabledISA;
+
+#else
+
+/// One of these is true:
+/// 1) We don't want optimizations.
+/// 2) Using an unsupported compiler.
+/// 3) Running on a non-x86 platform.
+ return 0;
+
+#endif
+}
diff --git a/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp b/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp
index 806de7f288..dbb79236bc 100644
--- a/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp
+++ b/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp
@@ -2,7 +2,7 @@
///
/// Generic version of the x86 CPU extension detection routine.
///
-/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp'
+/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp'
/// for the Microsoft compiler version.
///
/// Author : Copyright (c) Olli Parviainen
@@ -11,10 +11,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $
+// Last changed : $Date: 2011-09-02 15:56:11 -0300 (sex, 02 set 2011) $
// File revision : $Revision: 4 $
//
-// $Id: cpu_detect_x86_gcc.cpp 67 2009-02-25 17:13:51Z oparviai $
+// $Id: cpu_detect_x86_gcc.cpp 131 2011-09-02 18:56:11Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -39,15 +39,9 @@
//
////////////////////////////////////////////////////////////////////////////////
-#include
-#include
#include "cpu_detect.h"
#include "STTypes.h"
-using namespace std;
-
-#include
-
//////////////////////////////////////////////////////////////////////////////
//
// processor instructions extension detection routines
@@ -68,7 +62,7 @@ void disableExtensions(uint dwDisableMask)
/// Checks which instruction set extensions are supported by the CPU.
uint detectCPUextensions(void)
{
-#if (!(ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__))
+#if (!(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__))
return 0; // always disable extensions on non-x86 platforms.
@@ -78,8 +72,11 @@ uint detectCPUextensions(void)
if (_dwDisabledISA == 0xffffffff) return 0;
asm volatile(
+#ifndef __x86_64__
+ // Check if 'cpuid' instructions is available by toggling eflags bit 21.
+ // Skip this for x86-64 as they always have cpuid while stack manipulation
+ // differs from 16/32bit ISA.
"\n\txor %%esi, %%esi" // clear %%esi = result register
- // check if 'cpuid' instructions is available by toggling eflags bit 21
"\n\tpushf" // save eflags to stack
"\n\tmovl (%%esp), %%eax" // load eax from stack (with eflags)
@@ -93,6 +90,8 @@ uint detectCPUextensions(void)
"\n\txor %%edx, %%edx" // clear edx for defaulting no mmx
"\n\tcmp %%ecx, %%eax" // compare to original eflags values
"\n\tjz end" // jumps to 'end' if cpuid not present
+#endif // __x86_64__
+
// cpuid instruction available, test for presence of mmx instructions
"\n\tmovl $1, %%eax"
@@ -129,7 +128,7 @@ uint detectCPUextensions(void)
: "=r" (res)
: /* no inputs */
: "%edx", "%eax", "%ecx", "%esi" );
-
+
return res & ~_dwDisabledISA;
#endif
}
diff --git a/3rdparty/SoundTouch/cpu_detect_x86_win.cpp b/3rdparty/SoundTouch/cpu_detect_x86_win.cpp
index 883a3accc0..666c7b0700 100644
--- a/3rdparty/SoundTouch/cpu_detect_x86_win.cpp
+++ b/3rdparty/SoundTouch/cpu_detect_x86_win.cpp
@@ -2,8 +2,8 @@
///
/// Win32 version of the x86 CPU detect routine.
///
-/// This file is to be compiled in Windows platform with Microsoft Visual C++
-/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version
+/// This file is to be compiled in Windows platform with Microsoft Visual C++
+/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version
/// for all GNU platforms.
///
/// Author : Copyright (c) Olli Parviainen
@@ -12,10 +12,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-02-13 18:22:48 +0200 (Fri, 13 Feb 2009) $
+// Last changed : $Date: 2011-07-17 07:58:40 -0300 (dom, 17 jul 2011) $
// File revision : $Revision: 4 $
//
-// $Id: cpu_detect_x86_win.cpp 62 2009-02-13 16:22:48Z oparviai $
+// $Id: cpu_detect_x86_win.cpp 127 2011-07-17 10:58:40Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -42,9 +42,7 @@
#include "cpu_detect.h"
-#ifndef WIN32
-#error wrong platform - this source code file is exclusively for Win32 platform
-#endif
+#include "STTypes.h"
//////////////////////////////////////////////////////////////////////////////
//
@@ -71,7 +69,9 @@ uint detectCPUextensions(void)
if (_dwDisabledISA == 0xffffffff) return 0;
- _asm
+#ifndef _M_X64
+ // 32bit compilation, detect CPU capabilities with inline assembler.
+ __asm
{
; check if 'cpuid' instructions is available by toggling eflags bit 21
;
@@ -92,7 +92,7 @@ uint detectCPUextensions(void)
cmp eax, ecx ; compare to original eflags values
jz end ; jumps to 'end' if cpuid not present
- ; cpuid instruction available, test for presence of mmx instructions
+ ; cpuid instruction available, test for presence of mmx instructions
mov eax, 1
cpuid
test edx, 0x00800000
@@ -125,5 +125,13 @@ uint detectCPUextensions(void)
mov res, esi
}
+#else
+
+ // Visual C++ 64bit compilation doesn't support inline assembler. However,
+ // all x64 compatible CPUs support MMX & SSE extensions.
+ res = SUPPORT_MMX | SUPPORT_SSE | SUPPORT_SSE2;
+
+#endif
+
return res & ~_dwDisabledISA;
}
diff --git a/3rdparty/SoundTouch/mmx_optimized.cpp b/3rdparty/SoundTouch/mmx_optimized.cpp
index 477119529a..15d8af1b76 100644
--- a/3rdparty/SoundTouch/mmx_optimized.cpp
+++ b/3rdparty/SoundTouch/mmx_optimized.cpp
@@ -1,15 +1,15 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// MMX optimized routines. All MMX optimized functions have been gathered into
-/// this single source code file, regardless to their class or original source
-/// code file, in order to ease porting the library to other compiler and
+/// MMX optimized routines. All MMX optimized functions have been gathered into
+/// this single source code file, regardless to their class or original source
+/// code file, in order to ease porting the library to other compiler and
/// processor platforms.
///
/// The MMX-optimizations are programmed using MMX compiler intrinsics that
/// are supported both by Microsoft Visual C++ and GCC compilers, so this file
/// should compile with both toolsets.
///
-/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
+/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
/// 6.0 processor pack" update to support compiler intrinsic syntax. The update
/// is available for download at Microsoft Developers Network, see here:
/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx
@@ -20,10 +20,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-10-31 16:53:23 +0200 (Sat, 31 Oct 2009) $
+// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $
// File revision : $Revision: 4 $
//
-// $Id: mmx_optimized.cpp 75 2009-10-31 14:53:23Z oparviai $
+// $Id: mmx_optimized.cpp 160 2012-11-08 18:53:01Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -50,13 +50,9 @@
#include "STTypes.h"
-#ifdef ALLOW_MMX
+#ifdef SOUNDTOUCH_ALLOW_MMX
// MMX routines available only with integer sample type
-#if !(WIN32 || __i386__ || __x86_64__)
-#error "wrong platform - this source code file is exclusively for x86 platforms"
-#endif
-
using namespace soundtouch;
//////////////////////////////////////////////////////////////////////////////
@@ -72,23 +68,23 @@ using namespace soundtouch;
// Calculates cross correlation of two buffers
-long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const
+double TDStretchMMX::calcCrossCorr(const short *pV1, const short *pV2) const
{
const __m64 *pVec1, *pVec2;
__m64 shifter;
__m64 accu, normaccu;
long corr, norm;
int i;
-
+
pVec1 = (__m64*)pV1;
pVec2 = (__m64*)pV2;
shifter = _m_from_int(overlapDividerBits);
normaccu = accu = _mm_setzero_si64();
- // Process 4 parallel sets of 2 * stereo samples each during each
- // round to improve CPU-level parallellization.
- for (i = 0; i < overlapLength / 8; i ++)
+ // Process 4 parallel sets of 2 * stereo samples or 4 * mono samples
+ // during each round for improved CPU-level parallellization.
+ for (i = 0; i < channels * overlapLength / 16; i ++)
{
__m64 temp, temp2;
@@ -127,10 +123,11 @@ long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const
// Clear MMS state
_m_empty();
- // Normalize result by dividing by sqrt(norm) - this step is easiest
+ // Normalize result by dividing by sqrt(norm) - this step is easiest
// done using floating point operation
if (norm == 0) norm = 1; // to avoid div by zero
- return (long)((double)corr * USHRT_MAX / sqrt((double)norm));
+
+ return (double)corr / sqrt((double)norm);
// Note: Warning about the missing EMMS instruction is harmless
// as it'll be called elsewhere.
}
@@ -161,7 +158,7 @@ void TDStretchMMX::overlapStereo(short *output, const short *input) const
// mix1 = mixer values for 1st stereo sample
// mix1 = mixer values for 2nd stereo sample
// adder = adder for updating mixer values after each round
-
+
mix1 = _mm_set_pi16(0, overlapLength, 0, overlapLength);
adder = _mm_set_pi16(1, -1, 1, -1);
mix2 = _mm_add_pi16(mix1, adder);
@@ -174,7 +171,7 @@ void TDStretchMMX::overlapStereo(short *output, const short *input) const
for (i = 0; i < overlapLength / 4; i ++)
{
__m64 temp1, temp2;
-
+
// load & shuffle data so that input & mixbuffer data samples are paired
temp1 = _mm_unpacklo_pi16(pVMidBuf[0], pVinput[0]); // = i0l m0l i0r m0r
temp2 = _mm_unpackhi_pi16(pVMidBuf[0], pVinput[0]); // = i1l m1l i1r m1r
@@ -242,10 +239,10 @@ void FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uRe
// Ensure that filter coeffs array is aligned to 16-byte boundary
delete[] filterCoeffsUnalign;
filterCoeffsUnalign = new short[2 * newLength + 8];
- filterCoeffsAlign = (short *)(((ulong)filterCoeffsUnalign + 15) & -16);
+ filterCoeffsAlign = (short *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign);
- // rearrange the filter coefficients for mmx routines
- for (i = 0;i < length; i += 4)
+ // rearrange the filter coefficients for mmx routines
+ for (i = 0;i < length; i += 4)
{
filterCoeffsAlign[2 * i + 0] = coeffs[i + 0];
filterCoeffsAlign[2 * i + 1] = coeffs[i + 2];
@@ -317,4 +314,4 @@ uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, uint numS
return (numSamples & 0xfffffffe) - length;
}
-#endif // ALLOW_MMX
+#endif // SOUNDTOUCH_ALLOW_MMX
diff --git a/3rdparty/SoundTouch/sse_optimized.cpp b/3rdparty/SoundTouch/sse_optimized.cpp
index 7edd1cb79e..3566252cad 100644
--- a/3rdparty/SoundTouch/sse_optimized.cpp
+++ b/3rdparty/SoundTouch/sse_optimized.cpp
@@ -1,20 +1,20 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE
-/// optimized functions have been gathered into this single source
-/// code file, regardless to their class or original source code file, in order
+/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE
+/// optimized functions have been gathered into this single source
+/// code file, regardless to their class or original source code file, in order
/// to ease porting the library to other compiler and processor platforms.
///
/// The SSE-optimizations are programmed using SSE compiler intrinsics that
/// are supported both by Microsoft Visual C++ and GCC compilers, so this file
/// should compile with both toolsets.
///
-/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
-/// 6.0 processor pack" update to support SSE instruction set. The update is
+/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
+/// 6.0 processor pack" update to support SSE instruction set. The update is
/// available for download at Microsoft Developers Network, see here:
/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx
///
-/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and
+/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and
/// perform a search with keywords "processor pack".
///
/// Author : Copyright (c) Olli Parviainen
@@ -23,10 +23,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2009-12-28 22:32:57 +0200 (Mon, 28 Dec 2009) $
+// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $
// File revision : $Revision: 4 $
//
-// $Id: sse_optimized.cpp 80 2009-12-28 20:32:57Z oparviai $
+// $Id: sse_optimized.cpp 160 2012-11-08 18:53:01Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
@@ -56,9 +56,9 @@
using namespace soundtouch;
-#ifdef ALLOW_SSE
+#ifdef SOUNDTOUCH_ALLOW_SSE
-// SSE routines available only with float sample type
+// SSE routines available only with float sample type
//////////////////////////////////////////////////////////////////////////////
//
@@ -71,35 +71,35 @@ using namespace soundtouch;
#include
// Calculates cross correlation of two buffers
-double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) const
+double TDStretchSSE::calcCrossCorr(const float *pV1, const float *pV2) const
{
int i;
const float *pVec1;
const __m128 *pVec2;
__m128 vSum, vNorm;
- // Note. It means a major slow-down if the routine needs to tolerate
- // unaligned __m128 memory accesses. It's way faster if we can skip
+ // Note. It means a major slow-down if the routine needs to tolerate
+ // unaligned __m128 memory accesses. It's way faster if we can skip
// unaligned slots and use _mm_load_ps instruction instead of _mm_loadu_ps.
// This can mean up to ~ 10-fold difference (incl. part of which is
// due to skipping every second round for stereo sound though).
//
- // Compile-time define ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided
+ // Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided
// for choosing if this little cheating is allowed.
-#ifdef ALLOW_NONEXACT_SIMD_OPTIMIZATION
- // Little cheating allowed, return valid correlation only for
+#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
+ // Little cheating allowed, return valid correlation only for
// aligned locations, meaning every second round for stereo sound.
#define _MM_LOAD _mm_load_ps
- if (((ulong)pV1) & 15) return -1e50; // skip unaligned locations
+ if (((ulongptr)pV1) & 15) return -1e50; // skip unaligned locations
#else
// No cheating allowed, use unaligned load & take the resulting
// performance hit.
#define _MM_LOAD _mm_loadu_ps
-#endif
+#endif
// ensure overlapLength is divisible by 8
assert((overlapLength % 8) == 0);
@@ -110,8 +110,9 @@ double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) con
pVec2 = (const __m128*)pV2;
vSum = vNorm = _mm_setzero_ps();
- // Unroll the loop by factor of 4 * 4 operations
- for (i = 0; i < overlapLength / 8; i ++)
+ // Unroll the loop by factor of 4 * 4 operations. Use same routine for
+ // stereo & mono, for mono it just means twice the amount of unrolling.
+ for (i = 0; i < channels * overlapLength / 16; i ++)
{
__m128 vTemp;
// vSum += pV1[0..3] * pV2[0..3]
@@ -152,7 +153,7 @@ double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) con
// Calculates the cross-correlation value between 'pV1' and 'pV2' vectors
corr = norm = 0.0;
- for (i = 0; i < overlapLength / 8; i ++)
+ for (i = 0; i < channels * overlapLength / 16; i ++)
{
corr += pV1[0] * pV2[0] +
pV1[1] * pV2[1] +
@@ -171,81 +172,13 @@ double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) con
pV1[14] * pV2[14] +
pV1[15] * pV2[15];
- for (j = 0; j < 15; j ++) norm += pV1[j] * pV1[j];
+ for (j = 0; j < 15; j ++) norm += pV1[j] * pV1[j];
pV1 += 16;
pV2 += 16;
}
return corr / sqrt(norm);
*/
-
- /* This is a bit outdated, corresponding routine in assembler. This may be teeny-weeny bit
- faster than intrinsic version, but more difficult to maintain & get compiled on multiple
- platforms.
-
- uint overlapLengthLocal = overlapLength;
- float corr;
-
- _asm
- {
- // Very important note: data in 'pV2' _must_ be aligned to
- // 16-byte boundary!
-
- // give prefetch hints to CPU of what data are to be needed soonish
- // give more aggressive hints on pV1 as that changes while pV2 stays
- // same between runs
- prefetcht0 [pV1]
- prefetcht0 [pV2]
- prefetcht0 [pV1 + 32]
-
- mov eax, dword ptr pV1
- mov ebx, dword ptr pV2
-
- xorps xmm0, xmm0
-
- mov ecx, overlapLengthLocal
- shr ecx, 3 // div by eight
-
- loop1:
- prefetcht0 [eax + 64] // give a prefetch hint to CPU what data are to be needed soonish
- prefetcht0 [ebx + 32] // give a prefetch hint to CPU what data are to be needed soonish
- movups xmm1, [eax]
- mulps xmm1, [ebx]
- addps xmm0, xmm1
-
- movups xmm2, [eax + 16]
- mulps xmm2, [ebx + 16]
- addps xmm0, xmm2
-
- prefetcht0 [eax + 96] // give a prefetch hint to CPU what data are to be needed soonish
- prefetcht0 [ebx + 64] // give a prefetch hint to CPU what data are to be needed soonish
-
- movups xmm3, [eax + 32]
- mulps xmm3, [ebx + 32]
- addps xmm0, xmm3
-
- movups xmm4, [eax + 48]
- mulps xmm4, [ebx + 48]
- addps xmm0, xmm4
-
- add eax, 64
- add ebx, 64
-
- dec ecx
- jnz loop1
-
- // add the four floats of xmm0 together and return the result.
-
- movhlps xmm1, xmm0 // move 3 & 4 of xmm0 to 1 & 2 of xmm1
- addps xmm1, xmm0
- movaps xmm2, xmm1
- shufps xmm2, xmm2, 0x01 // move 2 of xmm2 as 1 of xmm2
- addss xmm2, xmm1
- movss corr, xmm2
- }
-
- return (double)corr;
- */
}
@@ -281,15 +214,15 @@ void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uRe
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
// Scale the filter coefficients so that it won't be necessary to scale the filtering result
- // also rearrange coefficients suitably for 3DNow!
+ // also rearrange coefficients suitably for SSE
// Ensure that filter coeffs array is aligned to 16-byte boundary
delete[] filterCoeffsUnalign;
filterCoeffsUnalign = new float[2 * newLength + 4];
- filterCoeffsAlign = (float *)(((unsigned long)filterCoeffsUnalign + 15) & (ulong)-16);
+ filterCoeffsAlign = (float *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign);
fDivider = (float)resultDivider;
- // rearrange the filter coefficients for mmx routines
+ // rearrange the filter coefficients for mmx routines
for (i = 0; i < newLength; i ++)
{
filterCoeffsAlign[2 * i + 0] =
@@ -313,7 +246,7 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
assert(dest != NULL);
assert((length % 8) == 0);
assert(filterCoeffsAlign != NULL);
- assert(((ulong)filterCoeffsAlign) % 16 == 0);
+ assert(((ulongptr)filterCoeffsAlign) % 16 == 0);
// filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2'
for (j = 0; j < count; j += 2)
@@ -324,13 +257,13 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
uint i;
pSrc = (const float*)source; // source audio data
- pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients
+ pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients
// are aligned to 16-byte boundary
sum1 = sum2 = _mm_setzero_ps();
- for (i = 0; i < length / 8; i ++)
+ for (i = 0; i < length / 8; i ++)
{
- // Unroll loop for efficiency & calculate filter for 2*2 stereo samples
+ // Unroll loop for efficiency & calculate filter for 2*2 stereo samples
// at each pass
// sum1 is accu for 2*2 filtered stereo sound data at the primary sound data offset
@@ -365,14 +298,14 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
}
// Ideas for further improvement:
- // 1. If it could be guaranteed that 'source' were always aligned to 16-byte
+ // 1. If it could be guaranteed that 'source' were always aligned to 16-byte
// boundary, a faster aligned '_mm_load_ps' instruction could be used.
- // 2. If it could be guaranteed that 'dest' were always aligned to 16-byte
+ // 2. If it could be guaranteed that 'dest' were always aligned to 16-byte
// boundary, a faster '_mm_store_ps' instruction could be used.
return (uint)count;
- /* original routine in C-language. please notice the C-version has differently
+ /* original routine in C-language. please notice the C-version has differently
organized coefficients though.
double suml1, suml2;
double sumr1, sumr2;
@@ -387,26 +320,26 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
suml2 = sumr2 = 0.0;
ptr = src;
pFil = filterCoeffs;
- for (i = 0; i < lengthLocal; i ++)
+ for (i = 0; i < lengthLocal; i ++)
{
// unroll loop for efficiency.
- suml1 += ptr[0] * pFil[0] +
+ suml1 += ptr[0] * pFil[0] +
ptr[2] * pFil[2] +
ptr[4] * pFil[4] +
ptr[6] * pFil[6];
- sumr1 += ptr[1] * pFil[1] +
+ sumr1 += ptr[1] * pFil[1] +
ptr[3] * pFil[3] +
ptr[5] * pFil[5] +
ptr[7] * pFil[7];
- suml2 += ptr[8] * pFil[0] +
+ suml2 += ptr[8] * pFil[0] +
ptr[10] * pFil[2] +
ptr[12] * pFil[4] +
ptr[14] * pFil[6];
- sumr2 += ptr[9] * pFil[1] +
+ sumr2 += ptr[9] * pFil[1] +
ptr[11] * pFil[3] +
ptr[13] * pFil[5] +
ptr[15] * pFil[7];
@@ -423,88 +356,6 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
dest += 4;
}
*/
-
-
- /* Similar routine in assembly, again obsoleted due to maintainability
- _asm
- {
- // Very important note: data in 'src' _must_ be aligned to
- // 16-byte boundary!
- mov edx, count
- mov ebx, dword ptr src
- mov eax, dword ptr dest
- shr edx, 1
-
- loop1:
- // "outer loop" : during each round 2*2 output samples are calculated
-
- // give prefetch hints to CPU of what data are to be needed soonish
- prefetcht0 [ebx]
- prefetcht0 [filterCoeffsLocal]
-
- mov esi, ebx
- mov edi, filterCoeffsLocal
- xorps xmm0, xmm0
- xorps xmm1, xmm1
- mov ecx, lengthLocal
-
- loop2:
- // "inner loop" : during each round eight FIR filter taps are evaluated for 2*2 samples
- prefetcht0 [esi + 32] // give a prefetch hint to CPU what data are to be needed soonish
- prefetcht0 [edi + 32] // give a prefetch hint to CPU what data are to be needed soonish
-
- movups xmm2, [esi] // possibly unaligned load
- movups xmm3, [esi + 8] // possibly unaligned load
- mulps xmm2, [edi]
- mulps xmm3, [edi]
- addps xmm0, xmm2
- addps xmm1, xmm3
-
- movups xmm4, [esi + 16] // possibly unaligned load
- movups xmm5, [esi + 24] // possibly unaligned load
- mulps xmm4, [edi + 16]
- mulps xmm5, [edi + 16]
- addps xmm0, xmm4
- addps xmm1, xmm5
-
- prefetcht0 [esi + 64] // give a prefetch hint to CPU what data are to be needed soonish
- prefetcht0 [edi + 64] // give a prefetch hint to CPU what data are to be needed soonish
-
- movups xmm6, [esi + 32] // possibly unaligned load
- movups xmm7, [esi + 40] // possibly unaligned load
- mulps xmm6, [edi + 32]
- mulps xmm7, [edi + 32]
- addps xmm0, xmm6
- addps xmm1, xmm7
-
- movups xmm4, [esi + 48] // possibly unaligned load
- movups xmm5, [esi + 56] // possibly unaligned load
- mulps xmm4, [edi + 48]
- mulps xmm5, [edi + 48]
- addps xmm0, xmm4
- addps xmm1, xmm5
-
- add esi, 64
- add edi, 64
- dec ecx
- jnz loop2
-
- // Now xmm0 and xmm1 both have a filtered 2-channel sample each, but we still need
- // to sum the two hi- and lo-floats of these registers together.
-
- movhlps xmm2, xmm0 // xmm2 = xmm2_3 xmm2_2 xmm0_3 xmm0_2
- movlhps xmm2, xmm1 // xmm2 = xmm1_1 xmm1_0 xmm0_3 xmm0_2
- shufps xmm0, xmm1, 0xe4 // xmm0 = xmm1_3 xmm1_2 xmm0_1 xmm0_0
- addps xmm0, xmm2
-
- movaps [eax], xmm0
- add ebx, 16
- add eax, 16
-
- dec edx
- jnz loop1
- }
- */
}
-#endif // ALLOW_SSE
+#endif // SOUNDTOUCH_ALLOW_SSE