From d311fe03a57368290031bbf927a4e68cd20dc4f0 Mon Sep 17 00:00:00 2001
From: Mystro256 <alexjnewt@hotmail.com>
Date: Sun, 5 Apr 2020 10:56:07 -0400
Subject: [PATCH 1/4] soundtouch: update to 2.1.2
Note that soundtouch_config.h is a custom file.
---
Externals/soundtouch/AAFilter.cpp | 16 +-
Externals/soundtouch/AAFilter.h | 7 -
Externals/soundtouch/BPMDetect.cpp | 400 +++++++++----
Externals/soundtouch/BPMDetect.h | 241 ++++----
Externals/soundtouch/FIFOSampleBuffer.cpp | 15 +-
Externals/soundtouch/FIFOSampleBuffer.h | 9 +-
Externals/soundtouch/FIFOSamplePipe.h | 28 +-
Externals/soundtouch/FIRFilter.cpp | 20 +-
Externals/soundtouch/FIRFilter.h | 7 -
Externals/soundtouch/InterpolateCubic.cpp | 396 +++++++------
Externals/soundtouch/InterpolateCubic.h | 130 +++--
Externals/soundtouch/InterpolateLinear.cpp | 596 ++++++++++----------
Externals/soundtouch/InterpolateLinear.h | 180 +++---
Externals/soundtouch/InterpolateShannon.cpp | 366 ++++++------
Externals/soundtouch/InterpolateShannon.h | 140 +++--
Externals/soundtouch/PeakFinder.cpp | 19 +-
Externals/soundtouch/PeakFinder.h | 11 +-
Externals/soundtouch/RateTransposer.cpp | 35 +-
Externals/soundtouch/RateTransposer.h | 22 +-
Externals/soundtouch/STTypes.h | 32 +-
Externals/soundtouch/SoundTouch.cpp | 154 ++---
Externals/soundtouch/SoundTouch.h | 91 ++-
Externals/soundtouch/SoundTouch.vcxproj | 3 +-
Externals/soundtouch/TDStretch.cpp | 131 +++--
Externals/soundtouch/TDStretch.h | 16 +-
Externals/soundtouch/cpu_detect.h | 7 -
Externals/soundtouch/cpu_detect_x86.cpp | 8 -
Externals/soundtouch/mmx_optimized.cpp | 21 +-
Externals/soundtouch/soundtouch_config.h | 2 +
Externals/soundtouch/sse_optimized.cpp | 7 -
30 files changed, 1661 insertions(+), 1449 deletions(-)
create mode 100644 Externals/soundtouch/soundtouch_config.h
diff --git a/Externals/soundtouch/AAFilter.cpp b/Externals/soundtouch/AAFilter.cpp
index c69f356f68..76a3da65d4 100644
--- a/Externals/soundtouch/AAFilter.cpp
+++ b/Externals/soundtouch/AAFilter.cpp
@@ -12,13 +12,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
-// File revision : $Revision: 4 $
-//
-// $Id: AAFilter.cpp 177 2014-01-05 21:40:22Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -49,7 +42,7 @@
using namespace soundtouch;
-#define PI 3.141592655357989
+#define PI 3.14159265358979323846
#define TWOPI (2 * PI)
// define this to save AA filter coefficients to a file
@@ -75,7 +68,6 @@ using namespace soundtouch;
#define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
#endif
-
/*****************************************************************************
*
* Implementation of the class 'AAFilter'
@@ -90,14 +82,12 @@ AAFilter::AAFilter(uint len)
}
-
AAFilter::~AAFilter()
{
delete pFIR;
}
-
// Sets new anti-alias filter cut-off edge frequency, scaled to
// sampling frequency (nyquist frequency = 0.5).
// The filter will cut frequencies higher than the given frequency.
@@ -108,7 +98,6 @@ void AAFilter::setCutoffFreq(double newCutoffFreq)
}
-
// Sets number of FIR filter taps
void AAFilter::setLength(uint newLength)
{
@@ -117,7 +106,6 @@ void AAFilter::setLength(uint newLength)
}
-
// Calculates coefficients for a low-pass FIR filter using Hamming window
void AAFilter::calculateCoeffs()
{
@@ -177,12 +165,10 @@ void AAFilter::calculateCoeffs()
for (i = 0; i < length; i ++)
{
temp = work[i] * scaleCoeff;
-//#if SOUNDTOUCH_INTEGER_SAMPLES
// scale & round to nearest integer
temp += (temp >= 0) ? 0.5 : -0.5;
// ensure no overfloods
assert(temp >= -32768 && temp <= 32767);
-//#endif
coeffs[i] = (SAMPLETYPE)temp;
}
diff --git a/Externals/soundtouch/AAFilter.h b/Externals/soundtouch/AAFilter.h
index 33e96948ec..8e5697f796 100644
--- a/Externals/soundtouch/AAFilter.h
+++ b/Externals/soundtouch/AAFilter.h
@@ -13,13 +13,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2014-01-07 21:41:23 +0200 (Tue, 07 Jan 2014) $
-// File revision : $Revision: 4 $
-//
-// $Id: AAFilter.h 187 2014-01-07 19:41:23Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
diff --git a/Externals/soundtouch/BPMDetect.cpp b/Externals/soundtouch/BPMDetect.cpp
index 39dae83761..5ad19269dd 100644
--- a/Externals/soundtouch/BPMDetect.cpp
+++ b/Externals/soundtouch/BPMDetect.cpp
@@ -26,13 +26,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: BPMDetect.cpp 202 2015-02-21 21:24:29Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -54,45 +47,62 @@
//
////////////////////////////////////////////////////////////////////////////////
+#define _USE_MATH_DEFINES
+
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
+#include <cfloat>
#include "FIFOSampleBuffer.h"
#include "PeakFinder.h"
#include "BPMDetect.h"
using namespace soundtouch;
-#define INPUT_BLOCK_SAMPLES 2048
-#define DECIMATED_BLOCK_SAMPLES 256
+// algorithm input sample block size
+static const int INPUT_BLOCK_SIZE = 2048;
+
+// decimated sample block size
+static const int DECIMATED_BLOCK_SIZE = 256;
+
+/// Target sample rate after decimation
+static const int TARGET_SRATE = 1000;
+
+/// XCorr update sequence size, update in about 200msec chunks
+static const int XCORR_UPDATE_SEQUENCE = (int)(TARGET_SRATE / 5);
-/// decay constant for calculating RMS volume sliding average approximation
-/// (time constant is about 10 sec)
-const float avgdecay = 0.99986f;
+/// Moving average N size
+static const int MOVING_AVERAGE_N = 15;
-/// Normalization coefficient for calculating RMS sliding average approximation.
-const float avgnorm = (1 - avgdecay);
+/// XCorr decay time constant, decay to half in 30 seconds
+/// If it's desired to have the system adapt quicker to beat rate
+/// changes within a continuing music stream, then the
+/// 'xcorr_decay_time_constant' value can be reduced, yet that
+/// can increase possibility of glitches in bpm detection.
+static const double XCORR_DECAY_TIME_CONSTANT = 30.0;
+/// Data overlap factor for beat detection algorithm
+static const int OVERLAP_FACTOR = 4;
+
+static const double TWOPI = (2 * M_PI);
////////////////////////////////////////////////////////////////////////////////
// Enable following define to create bpm analysis file:
-// #define _CREATE_BPM_DEBUG_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)
+ static void _SaveDebugData(const char *name, const float *data, int minpos, int maxpos, double coeff)
{
- FILE *fptr = fopen(DEBUGFILE_NAME, "wt");
+ FILE *fptr = fopen(name, "wt");
int i;
if (fptr)
{
- printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n");
+ printf("\nWriting BPM debug data into file %s\n", name);
for (i = minpos; i < maxpos; i ++)
{
fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]);
@@ -100,42 +110,90 @@ const float avgnorm = (1 - avgdecay);
fclose(fptr);
}
}
+
+ void _SaveDebugBeatPos(const char *name, const std::vector<BEAT> &beats)
+ {
+ printf("\nWriting beat detections data into file %s\n", name);
+
+ FILE *fptr = fopen(name, "wt");
+ if (fptr)
+ {
+ for (uint i = 0; i < beats.size(); i++)
+ {
+ BEAT b = beats[i];
+ fprintf(fptr, "%lf\t%lf\n", b.pos, b.strength);
+ }
+ fclose(fptr);
+ }
+ }
#else
- #define _SaveDebugData(a,b,c,d)
+ #define _SaveDebugData(name, a,b,c,d)
+ #define _SaveDebugBeatPos(name, b)
#endif
+// Hamming window
+void hamming(float *w, int N)
+{
+ for (int i = 0; i < N; i++)
+ {
+ w[i] = (float)(0.54 - 0.46 * cos(TWOPI * i / (N - 1)));
+ }
+
+}
+
////////////////////////////////////////////////////////////////////////////////
+//
+// IIR2_filter - 2nd order IIR filter
+
+IIR2_filter::IIR2_filter(const double *lpf_coeffs)
+{
+ memcpy(coeffs, lpf_coeffs, 5 * sizeof(double));
+ memset(prev, 0, sizeof(prev));
+}
+
+float IIR2_filter::update(float x)
+{
+ prev[0] = x;
+ double y = x * coeffs[0];
+
+ for (int i = 4; i >= 1; i--)
+ {
+ y += coeffs[i] * prev[i];
+ prev[i] = prev[i - 1];
+ }
+
+ prev[3] = y;
+ return (float)y;
+}
+
+
+// IIR low-pass filter coefficients, calculated with matlab/octave cheby2(2,40,0.05)
+const double _LPF_coeffs[5] = { 0.00996655391939, -0.01944529148401, 0.00996655391939, 1.96867605796247, -0.96916387431724 };
-BPMDetect::BPMDetect(int numChannels, int aSampleRate)
+////////////////////////////////////////////////////////////////////////////////
+
+BPMDetect::BPMDetect(int numChannels, int aSampleRate) :
+ beat_lpf(_LPF_coeffs)
{
+ beats.reserve(250); // initial reservation to prevent frequent reallocation
+
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);
+ decimateBy = sampleRate / TARGET_SRATE;
+ if ((decimateBy <= 0) || (decimateBy * DECIMATED_BLOCK_SIZE < INPUT_BLOCK_SIZE))
+ {
+ ST_THROW_RT_ERROR("Too small samplerate");
+ }
// Calculate window length & starting item according to desired min & max bpms
windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
- windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM);
+ windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM_RANGE);
assert(windowLen > windowStart);
@@ -143,23 +201,38 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate)
xcorr = new float[windowLen];
memset(xcorr, 0, windowLen * sizeof(float));
+ pos = 0;
+ peakPos = 0;
+ peakVal = 0;
+ init_scaler = 1;
+ beatcorr_ringbuffpos = 0;
+ beatcorr_ringbuff = new float[windowLen];
+ memset(beatcorr_ringbuff, 0, windowLen * sizeof(float));
+
// allocate processing buffer
buffer = new FIFOSampleBuffer();
// we do processing in mono mode
buffer->setChannels(1);
buffer->clear();
-}
+ // calculate hamming windows
+ hamw = new float[XCORR_UPDATE_SEQUENCE];
+ hamming(hamw, XCORR_UPDATE_SEQUENCE);
+ hamw2 = new float[XCORR_UPDATE_SEQUENCE / 2];
+ hamming(hamw2, XCORR_UPDATE_SEQUENCE / 2);
+}
BPMDetect::~BPMDetect()
{
delete[] xcorr;
+ delete[] beatcorr_ringbuff;
+ delete[] hamw;
+ delete[] hamw2;
delete buffer;
}
-
/// convert to mono, low-pass filter & decimate to about 500 Hz.
/// return number of outputted samples.
///
@@ -216,7 +289,6 @@ int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples)
}
-
// Calculates autocorrelation function of the sample history buffer
void BPMDetect::updateXCorr(int process_samples)
{
@@ -224,72 +296,124 @@ void BPMDetect::updateXCorr(int process_samples)
SAMPLETYPE *pBuffer;
assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
+ assert(process_samples == XCORR_UPDATE_SEQUENCE);
pBuffer = buffer->ptrBegin();
+
+ // calculate decay factor for xcorr filtering
+ float xcorr_decay = (float)pow(0.5, 1.0 / (XCORR_DECAY_TIME_CONSTANT * TARGET_SRATE / process_samples));
+
+ // prescale pbuffer
+ float tmp[XCORR_UPDATE_SEQUENCE];
+ for (int i = 0; i < process_samples; i++)
+ {
+ tmp[i] = hamw[i] * hamw[i] * pBuffer[i];
+ }
+
#pragma omp parallel for
for (offs = windowStart; offs < windowLen; offs ++)
{
- LONG_SAMPLETYPE sum;
+ float 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
+ sum += tmp[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] *= xcorr_decay; // decay 'xcorr' here with suitable time constant.
- xcorr[offs] += (float)sum;
+ xcorr[offs] += (float)fabs(sum);
}
}
-// Calculates envelope of the sample data
-void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
+// Detect individual beat positions
+void BPMDetect::updateBeatPos(int process_samples)
{
- const static double decay = 0.7f; // decay constant for smoothing the envelope
- const static double norm = (1 - decay);
+ SAMPLETYPE *pBuffer;
- int i;
- LONG_SAMPLETYPE out;
- double val;
+ assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
+
+ pBuffer = buffer->ptrBegin();
+ assert(process_samples == XCORR_UPDATE_SEQUENCE / 2);
+
+ // static double thr = 0.0003;
+ double posScale = (double)this->decimateBy / (double)this->sampleRate;
+ int resetDur = (int)(0.12 / posScale + 0.5);
+
+ // prescale pbuffer
+ float tmp[XCORR_UPDATE_SEQUENCE / 2];
+ for (int i = 0; i < process_samples; i++)
+ {
+ tmp[i] = hamw2[i] * hamw2[i] * pBuffer[i];
+ }
- for (i = 0; i < numsamples; i ++)
+ #pragma omp parallel for
+ for (int offs = windowStart; offs < windowLen; offs++)
{
- // 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))
+ float sum = 0;
+ for (int i = 0; i < process_samples; i++)
{
- val = 0;
+ sum += tmp[i] * pBuffer[offs + i];
}
+ beatcorr_ringbuff[(beatcorr_ringbuffpos + offs) % windowLen] += (float)((sum > 0) ? sum : 0); // accumulate only positive correlations
+ }
- // smooth amplitude envelope
- envelopeAccu *= decay;
- envelopeAccu += val;
- out = (LONG_SAMPLETYPE)(envelopeAccu * norm);
+ int skipstep = XCORR_UPDATE_SEQUENCE / OVERLAP_FACTOR;
-#ifdef SOUNDTOUCH_INTEGER_SAMPLES
- // cut peaks (shouldn't be necessary though)
- if (out > 32767) out = 32767;
-#endif // SOUNDTOUCH_INTEGER_SAMPLES
- samples[i] = (SAMPLETYPE)out;
+ // compensate empty buffer at beginning by scaling coefficient
+ float scale = (float)windowLen / (float)(skipstep * init_scaler);
+ if (scale > 1.0f)
+ {
+ init_scaler++;
+ }
+ else
+ {
+ scale = 1.0f;
+ }
+
+ // detect beats
+ for (int i = 0; i < skipstep; i++)
+ {
+ LONG_SAMPLETYPE max = 0;
+
+ float sum = beatcorr_ringbuff[beatcorr_ringbuffpos];
+ sum -= beat_lpf.update(sum);
+
+ if (sum > peakVal)
+ {
+ // found new local largest value
+ peakVal = sum;
+ peakPos = pos;
+ }
+ if (pos > peakPos + resetDur)
+ {
+ // largest value not updated for 200msec => accept as beat
+ peakPos += skipstep;
+ if (peakVal > 0)
+ {
+ // add detected beat to end of "beats" vector
+ BEAT temp = { (float)(peakPos * posScale), (float)(peakVal * scale) };
+ beats.push_back(temp);
+ }
+
+ peakVal = 0;
+ peakPos = pos;
+ }
+
+ beatcorr_ringbuff[beatcorr_ringbuffpos] = 0;
+ pos++;
+ beatcorr_ringbuffpos = (beatcorr_ringbuffpos + 1) % windowLen;
}
}
+#define max(x,y) ((x) > (y) ? (x) : (y))
void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
{
- SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES];
+ SAMPLETYPE decimated[DECIMATED_BLOCK_SIZE];
// iterate so that max INPUT_BLOCK_SAMPLES processed per iteration
while (numSamples > 0)
@@ -297,48 +421,70 @@ void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
int block;
int decSamples;
- block = (numSamples > INPUT_BLOCK_SAMPLES) ? INPUT_BLOCK_SAMPLES : numSamples;
+ block = (numSamples > INPUT_BLOCK_SIZE) ? INPUT_BLOCK_SIZE : 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)
+ // when the buffer has enough samples for processing...
+ int req = max(windowLen + XCORR_UPDATE_SEQUENCE, 2 * XCORR_UPDATE_SEQUENCE);
+ while ((int)buffer->numSamples() >= req)
{
- 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);
+ // ... update autocorrelations...
+ updateXCorr(XCORR_UPDATE_SEQUENCE);
+ // ...update beat position calculation...
+ updateBeatPos(XCORR_UPDATE_SEQUENCE / 2);
+ // ... and remove proceessed samples from the buffer
+ int n = XCORR_UPDATE_SEQUENCE / OVERLAP_FACTOR;
+ buffer->receiveSamples(n);
}
}
-
void BPMDetect::removeBias()
{
int i;
- float minval = 1e12f; // arbitrary large number
+ // Remove linear bias: calculate linear regression coefficient
+ // 1. calc mean of 'xcorr' and 'i'
+ double mean_i = 0;
+ double mean_x = 0;
+ for (i = windowStart; i < windowLen; i++)
+ {
+ mean_x += xcorr[i];
+ }
+ mean_x /= (windowLen - windowStart);
+ mean_i = 0.5 * (windowLen - 1 + windowStart);
+
+ // 2. calculate linear regression coefficient
+ double b = 0;
+ double div = 0;
+ for (i = windowStart; i < windowLen; i++)
+ {
+ double xt = xcorr[i] - mean_x;
+ double xi = i - mean_i;
+ b += xt * xi;
+ div += xi * xi;
+ }
+ b /= div;
+
+ // subtract linear regression and resolve min. value bias
+ float minval = FLT_MAX; // arbitrary large number
for (i = windowStart; i < windowLen; i ++)
{
+ xcorr[i] -= (float)(b * i);
if (xcorr[i] < minval)
{
minval = xcorr[i];
}
}
+ // subtract min.value
for (i = windowStart; i < windowLen; i ++)
{
xcorr[i] -= minval;
@@ -346,26 +492,82 @@ void BPMDetect::removeBias()
}
+// Calculate N-point moving average for "source" values
+void MAFilter(float *dest, const float *source, int start, int end, int N)
+{
+ for (int i = start; i < end; i++)
+ {
+ int i1 = i - N / 2;
+ int i2 = i + N / 2 + 1;
+ if (i1 < start) i1 = start;
+ if (i2 > end) i2 = end;
+
+ double sum = 0;
+ for (int j = i1; j < i2; j ++)
+ {
+ sum += source[j];
+ }
+ dest[i] = (float)(sum / (i2 - i1));
+ }
+}
+
+
float BPMDetect::getBpm()
{
double peakPos;
double coeff;
PeakFinder peakFinder;
+ // remove bias from xcorr data
+ removeBias();
+
coeff = 60.0 * ((double)sampleRate / (double)decimateBy);
- // save bpm debug analysis data if debug data enabled
- _SaveDebugData(xcorr, windowStart, windowLen, coeff);
+ // save bpm debug data if debug data writing enabled
+ _SaveDebugData("soundtouch-bpm-xcorr.txt", xcorr, windowStart, windowLen, coeff);
- // remove bias from xcorr data
- removeBias();
+ // Smoothen by N-point moving-average
+ float *data = new float[windowLen];
+ memset(data, 0, sizeof(float) * windowLen);
+ MAFilter(data, xcorr, windowStart, windowLen, MOVING_AVERAGE_N);
// find peak position
- peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen);
+ peakPos = peakFinder.detectPeak(data, windowStart, windowLen);
+
+ // save bpm debug data if debug data writing enabled
+ _SaveDebugData("soundtouch-bpm-smoothed.txt", data, windowStart, windowLen, coeff);
+
+ delete[] data;
assert(decimateBy != 0);
if (peakPos < 1e-9) return 0.0; // detection failed.
+ _SaveDebugBeatPos("soundtouch-detected-beats.txt", beats);
+
// calculate BPM
- return (float) (coeff / peakPos);
+ float bpm = (float)(coeff / peakPos);
+ return (bpm >= MIN_BPM && bpm <= MAX_BPM_VALID) ? bpm : 0;
+}
+
+
+/// Get beat position arrays. Note: The array includes also really low beat detection values
+/// in absence of clear strong beats. Consumer may wish to filter low values away.
+/// - "pos" receive array of beat positions
+/// - "values" receive array of beat detection strengths
+/// - max_num indicates max.size of "pos" and "values" array.
+///
+/// You can query a suitable array sized by calling this with NULL in "pos" & "values".
+///
+/// \return number of beats in the arrays.
+int BPMDetect::getBeats(float *pos, float *values, int max_num)
+{
+ int num = beats.size();
+ if ((!pos) || (!values)) return num; // pos or values NULL, return just size
+
+ for (int i = 0; (i < num) && (i < max_num); i++)
+ {
+ pos[i] = beats[i].pos;
+ values[i] = beats[i].strength;
+ }
+ return num;
}
diff --git a/Externals/soundtouch/BPMDetect.h b/Externals/soundtouch/BPMDetect.h
index 69d98143a7..8ece78448d 100644
--- a/Externals/soundtouch/BPMDetect.h
+++ b/Externals/soundtouch/BPMDetect.h
@@ -26,13 +26,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2012-08-30 22:53:44 +0300 (Thu, 30 Aug 2012) $
-// File revision : $Revision: 4 $
-//
-// $Id: BPMDetect.h 150 2012-08-30 19:53:44Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -57,108 +50,156 @@
#ifndef _BPMDetect_H_
#define _BPMDetect_H_
+#include <vector>
#include "STTypes.h"
#include "FIFOSampleBuffer.h"
namespace soundtouch
{
-/// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
-#define MIN_BPM 29
+ /// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
+ #define MIN_BPM 45
-/// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit.
-#define MAX_BPM 200
+ /// Maximum allowed BPM rate range. Used for calculating algorithm parametrs
+ #define MAX_BPM_RANGE 200
+ /// Maximum allowed BPM rate range. Used to restrict accepted result below a reasonable limit.
+ #define MAX_BPM_VALID 190
-/// Class for calculating BPM rate for audio data.
-class BPMDetect
-{
-protected:
- /// Auto-correlation accumulator bins.
- float *xcorr;
-
- /// Amplitude envelope sliding average approximation level accumulator
- double envelopeAccu;
-
- /// RMS volume sliding average approximation level accumulator
- double RMSVolumeAccu;
-
- /// Sample average counter.
- int decimateCount;
-
- /// Sample average accumulator for FIFO-like decimation.
- soundtouch::LONG_SAMPLETYPE decimateSum;
-
- /// Decimate sound by this coefficient to reach approx. 500 Hz.
- int decimateBy;
-
- /// Auto-correlation window length
- int windowLen;
-
- /// Number of channels (1 = mono, 2 = stereo)
- int channels;
-
- /// sample rate
- int sampleRate;
-
- /// 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
- /// though).
- void updateXCorr(int process_samples /// How many samples are processed.
- );
-
- /// Decimates samples to approx. 500 Hz.
- ///
- /// \return Number of output samples.
- int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer
- const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
- int numsamples ///< Number of source samples.
- );
-
- /// Calculates amplitude envelope for the buffer of samples.
- /// Result is output to 'samples'.
- void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer
- 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.
- int sampleRate ///< Sample rate in Hz.
- );
-
- /// Destructor.
- virtual ~BPMDetect();
-
- /// 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.
- ///
- /// 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
- );
-
-
- /// Analyzes the results and returns the BPM rate. Use this function to read result
- /// after whole song data has been input to the class by consecutive calls of
- /// 'inputSamples' function.
- ///
- /// \return Beats-per-minute rate, or zero if detection failed.
- float getBpm();
-};
+////////////////////////////////////////////////////////////////////////////////
-}
+ typedef struct
+ {
+ float pos;
+ float strength;
+ } BEAT;
+
+ class IIR2_filter
+ {
+ double coeffs[5];
+ double prev[5];
+
+ public:
+ IIR2_filter(const double *lpf_coeffs);
+ float update(float x);
+ };
+
+
+ /// Class for calculating BPM rate for audio data.
+ class BPMDetect
+ {
+ protected:
+ /// Auto-correlation accumulator bins.
+ float *xcorr;
+
+ /// Sample average counter.
+ int decimateCount;
+
+ /// Sample average accumulator for FIFO-like decimation.
+ soundtouch::LONG_SAMPLETYPE decimateSum;
+
+ /// Decimate sound by this coefficient to reach approx. 500 Hz.
+ int decimateBy;
+
+ /// Auto-correlation window length
+ int windowLen;
+
+ /// Number of channels (1 = mono, 2 = stereo)
+ int channels;
+
+ /// sample rate
+ int sampleRate;
+
+ /// Beginning of auto-correlation window: Autocorrelation isn't being updated for
+ /// the first these many correlation bins.
+ int windowStart;
+
+ /// window functions for data preconditioning
+ float *hamw;
+ float *hamw2;
+
+ // beat detection variables
+ int pos;
+ int peakPos;
+ int beatcorr_ringbuffpos;
+ int init_scaler;
+ float peakVal;
+ float *beatcorr_ringbuff;
+
+ /// FIFO-buffer for decimated processing samples.
+ soundtouch::FIFOSampleBuffer *buffer;
+
+ /// Collection of detected beat positions
+ //BeatCollection beats;
+ std::vector<BEAT> beats;
+
+ // 2nd order low-pass-filter
+ IIR2_filter beat_lpf;
+
+ /// 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.
+ );
+
+ /// Decimates samples to approx. 500 Hz.
+ ///
+ /// \return Number of output samples.
+ int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer
+ const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
+ int numsamples ///< Number of source samples.
+ );
+
+ /// Calculates amplitude envelope for the buffer of samples.
+ /// Result is output to 'samples'.
+ void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer
+ int numsamples ///< Number of samples in buffer
+ );
+
+ /// remove constant bias from xcorr data
+ void removeBias();
+
+ // Detect individual beat positions
+ void updateBeatPos(int process_samples);
+
+
+ public:
+ /// Constructor.
+ BPMDetect(int numChannels, ///< Number of channels in sample data.
+ int sampleRate ///< Sample rate in Hz.
+ );
+
+ /// Destructor.
+ virtual ~BPMDetect();
+
+ /// 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.
+ ///
+ /// 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
+ );
+
+ /// Analyzes the results and returns the BPM rate. Use this function to read result
+ /// after whole song data has been input to the class by consecutive calls of
+ /// 'inputSamples' function.
+ ///
+ /// \return Beats-per-minute rate, or zero if detection failed.
+ float getBpm();
+
+ /// Get beat position arrays. Note: The array includes also really low beat detection values
+ /// in absence of clear strong beats. Consumer may wish to filter low values away.
+ /// - "pos" receive array of beat positions
+ /// - "values" receive array of beat detection strengths
+ /// - max_num indicates max.size of "pos" and "values" array.
+ ///
+ /// You can query a suitable array sized by calling this with NULL in "pos" & "values".
+ ///
+ /// \return number of beats in the arrays.
+ int getBeats(float *pos, float *strength, int max_num);
+ };
+}
#endif // _BPMDetect_H_
diff --git a/Externals/soundtouch/FIFOSampleBuffer.cpp b/Externals/soundtouch/FIFOSampleBuffer.cpp
index 5f5ec4b7db..8341163a60 100644
--- a/Externals/soundtouch/FIFOSampleBuffer.cpp
+++ b/Externals/soundtouch/FIFOSampleBuffer.cpp
@@ -15,13 +15,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2012-11-08 20:53:01 +0200 (Thu, 08 Nov 2012) $
-// File revision : $Revision: 4 $
-//
-// $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -80,7 +73,8 @@ void FIFOSampleBuffer::setChannels(int numChannels)
{
uint usedBytes;
- assert(numChannels > 0);
+ if (!verifyNumberOfChannels(numChannels)) return;
+
usedBytes = channels * samplesInBuffer;
channels = (uint)numChannels;
samplesInBuffer = usedBytes / channels;
@@ -131,7 +125,7 @@ void FIFOSampleBuffer::putSamples(uint nSamples)
//
// 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,
+// successfully 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
@@ -158,7 +152,7 @@ SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
}
-// Ensures that the buffer has enought capacity, i.e. space for _at least_
+// Ensures that the buffer has enough capacity, i.e. space for _at least_
// 'capacityRequirement' number of samples. The buffer is grown in steps of
// 4 kilobytes to eliminate the need for frequently growing up the buffer,
// as well as to round the buffer size up to the virtual memory page size.
@@ -271,4 +265,3 @@ uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
}
return samplesInBuffer;
}
-
diff --git a/Externals/soundtouch/FIFOSampleBuffer.h b/Externals/soundtouch/FIFOSampleBuffer.h
index 6f33df3daa..de298dd82b 100644
--- a/Externals/soundtouch/FIFOSampleBuffer.h
+++ b/Externals/soundtouch/FIFOSampleBuffer.h
@@ -15,13 +15,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
-// File revision : $Revision: 4 $
-//
-// $Id: FIFOSampleBuffer.h 177 2014-01-05 21:40:22Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -119,7 +112,7 @@ public:
/// '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
+ ///< should be so that the caller can successfully insert the
///< desired samples to the buffer. If necessary, the function
///< grows the buffer size to comply with this requirement.
);
diff --git a/Externals/soundtouch/FIFOSamplePipe.h b/Externals/soundtouch/FIFOSamplePipe.h
index 6e3105970b..38ef31a5c2 100644
--- a/Externals/soundtouch/FIFOSamplePipe.h
+++ b/Externals/soundtouch/FIFOSamplePipe.h
@@ -17,13 +17,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2012-06-13 22:29:53 +0300 (Wed, 13 Jun 2012) $
-// File revision : $Revision: 4 $
-//
-// $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -58,6 +51,18 @@ namespace soundtouch
/// Abstract base class for FIFO (first-in-first-out) sample processing classes.
class FIFOSamplePipe
{
+protected:
+
+ bool verifyNumberOfChannels(int nChannels) const
+ {
+ if ((nChannels > 0) && (nChannels <= SOUNDTOUCH_MAX_CHANNELS))
+ {
+ return true;
+ }
+ ST_THROW_RT_ERROR("Error: Illegal number of channels");
+ return false;
+ }
+
public:
// virtual default destructor
virtual ~FIFOSamplePipe() {}
@@ -122,7 +127,6 @@ public:
};
-
/// 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
@@ -145,7 +149,6 @@ protected:
output = pOutput;
}
-
/// Constructor. Doesn't define output pipe; it has to be set be
/// 'setOutPipe' function.
FIFOProcessor()
@@ -153,7 +156,6 @@ protected:
output = NULL;
}
-
/// Constructor. Configures output pipe.
FIFOProcessor(FIFOSamplePipe *pOutput ///< Output pipe.
)
@@ -161,13 +163,11 @@ protected:
output = pOutput;
}
-
/// Destructor.
virtual ~FIFOProcessor()
{
}
-
/// 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!
@@ -194,7 +194,6 @@ public:
return output->receiveSamples(outBuffer, maxSamples);
}
-
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
///
@@ -206,14 +205,12 @@ public:
return output->receiveSamples(maxSamples);
}
-
/// Returns number of samples currently available.
virtual uint numSamples() const
{
return output->numSamples();
}
-
/// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const
{
@@ -226,7 +223,6 @@ public:
{
return output->adjustAmountOfSamples(numSamples);
}
-
};
}
diff --git a/Externals/soundtouch/FIRFilter.cpp b/Externals/soundtouch/FIRFilter.cpp
index e56969b053..218e50ef5a 100644
--- a/Externals/soundtouch/FIRFilter.cpp
+++ b/Externals/soundtouch/FIRFilter.cpp
@@ -2,22 +2,21 @@
///
/// General FIR digital filter routines with MMX optimization.
///
-/// Note : MMX optimized functions reside in a separate, platform-specific file,
+/// Notes : MMX optimized functions reside in a separate, platform-specific file,
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
///
+/// This source file contains OpenMP optimizations that allow speeding up the
+/// corss-correlation algorithm by executing it in several threads / CPU cores
+/// in parallel. See the following article link for more detailed discussion
+/// about SoundTouch OpenMP optimizations:
+/// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices
+///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: FIRFilter.cpp 202 2015-02-21 21:24:29Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -69,6 +68,7 @@ FIRFilter::~FIRFilter()
delete[] filterCoeffs;
}
+
// Usual C-version of the filter routine for stereo sound
uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{
@@ -127,8 +127,6 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
}
-
-
// Usual C-version of the filter routine for mono sound
uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{
@@ -254,7 +252,6 @@ uint FIRFilter::getLength() const
}
-
// Applies the filter to the given sequence of samples.
//
// Note : The amount of outputted samples is by value of 'filter_length'
@@ -284,7 +281,6 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample
}
-
// 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)
diff --git a/Externals/soundtouch/FIRFilter.h b/Externals/soundtouch/FIRFilter.h
index 6b14238ce8..297b0f81ec 100644
--- a/Externals/soundtouch/FIRFilter.h
+++ b/Externals/soundtouch/FIRFilter.h
@@ -11,13 +11,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: FIRFilter.h 202 2015-02-21 21:24:29Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
diff --git a/Externals/soundtouch/InterpolateCubic.cpp b/Externals/soundtouch/InterpolateCubic.cpp
index 8aa7374c74..fe49684817 100644
--- a/Externals/soundtouch/InterpolateCubic.cpp
+++ b/Externals/soundtouch/InterpolateCubic.cpp
@@ -1,200 +1,196 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// Cubic interpolation routine.
-///
-/// Author : Copyright (c) Olli Parviainen
-/// Author e-mail : oparviai 'at' iki.fi
-/// SoundTouch WWW: http://www.surina.net/soundtouch
-///
-////////////////////////////////////////////////////////////////////////////////
-//
-// $Id: InterpolateCubic.cpp 179 2014-01-06 18:41:42Z 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 <stddef.h>
-#include <math.h>
-#include "InterpolateCubic.h"
-#include "STTypes.h"
-
-using namespace soundtouch;
-
-// cubic interpolation coefficients
-static const float _coeffs[]=
-{ -0.5f, 1.0f, -0.5f, 0.0f,
- 1.5f, -2.5f, 0.0f, 1.0f,
- -1.5f, 2.0f, 0.5f, 0.0f,
- 0.5f, -0.5f, 0.0f, 0.0f};
-
-
-InterpolateCubic::InterpolateCubic()
-{
- fract = 0;
-}
-
-
-void InterpolateCubic::resetRegisters()
-{
- fract = 0;
-}
-
-
-/// Transpose mono audio. Returns number of produced output samples, and
-/// updates "srcSamples" to amount of consumed source samples
-int InterpolateCubic::transposeMono(SAMPLETYPE *pdest,
- const SAMPLETYPE *psrc,
- int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 4;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- float out;
- const float x3 = 1.0f;
- const float x2 = (float)fract; // x
- const float x1 = x2*x2; // x^2
- const float x0 = x1*x2; // x^3
- float y0, y1, y2, y3;
-
- assert(fract < 1.0);
-
- y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
- y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
- y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
- y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
-
- out = y0 * psrc[0] + y1 * psrc[1] + y2 * psrc[2] + y3 * psrc[3];
-
- pdest[i] = (SAMPLETYPE)out;
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- psrc += whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
-
-
-/// Transpose stereo audio. Returns number of produced output samples, and
-/// updates "srcSamples" to amount of consumed source samples
-int InterpolateCubic::transposeStereo(SAMPLETYPE *pdest,
- const SAMPLETYPE *psrc,
- int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 4;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- const float x3 = 1.0f;
- const float x2 = (float)fract; // x
- const float x1 = x2*x2; // x^2
- const float x0 = x1*x2; // x^3
- float y0, y1, y2, y3;
- float out0, out1;
-
- assert(fract < 1.0);
-
- y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
- y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
- y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
- y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
-
- out0 = y0 * psrc[0] + y1 * psrc[2] + y2 * psrc[4] + y3 * psrc[6];
- out1 = y0 * psrc[1] + y1 * psrc[3] + y2 * psrc[5] + y3 * psrc[7];
-
- pdest[2*i] = (SAMPLETYPE)out0;
- pdest[2*i+1] = (SAMPLETYPE)out1;
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- psrc += 2*whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
-
-
-/// Transpose multi-channel audio. Returns number of produced output samples, and
-/// updates "srcSamples" to amount of consumed source samples
-int InterpolateCubic::transposeMulti(SAMPLETYPE *pdest,
- const SAMPLETYPE *psrc,
- int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 4;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- const float x3 = 1.0f;
- const float x2 = (float)fract; // x
- const float x1 = x2*x2; // x^2
- const float x0 = x1*x2; // x^3
- float y0, y1, y2, y3;
-
- assert(fract < 1.0);
-
- y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
- y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
- y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
- y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
-
- for (int c = 0; c < numChannels; c ++)
- {
- float out;
- out = y0 * psrc[c] + y1 * psrc[c + numChannels] + y2 * psrc[c + 2 * numChannels] + y3 * psrc[c + 3 * numChannels];
- pdest[0] = (SAMPLETYPE)out;
- pdest ++;
- }
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- psrc += numChannels*whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Cubic interpolation routine.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 <stddef.h>
+#include <math.h>
+#include "InterpolateCubic.h"
+#include "STTypes.h"
+
+using namespace soundtouch;
+
+// cubic interpolation coefficients
+static const float _coeffs[]=
+{ -0.5f, 1.0f, -0.5f, 0.0f,
+ 1.5f, -2.5f, 0.0f, 1.0f,
+ -1.5f, 2.0f, 0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f};
+
+
+InterpolateCubic::InterpolateCubic()
+{
+ fract = 0;
+}
+
+
+void InterpolateCubic::resetRegisters()
+{
+ fract = 0;
+}
+
+
+/// Transpose mono audio. Returns number of produced output samples, and
+/// updates "srcSamples" to amount of consumed source samples
+int InterpolateCubic::transposeMono(SAMPLETYPE *pdest,
+ const SAMPLETYPE *psrc,
+ int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 4;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ float out;
+ const float x3 = 1.0f;
+ const float x2 = (float)fract; // x
+ const float x1 = x2*x2; // x^2
+ const float x0 = x1*x2; // x^3
+ float y0, y1, y2, y3;
+
+ assert(fract < 1.0);
+
+ y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
+ y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
+ y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
+ y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
+
+ out = y0 * psrc[0] + y1 * psrc[1] + y2 * psrc[2] + y3 * psrc[3];
+
+ pdest[i] = (SAMPLETYPE)out;
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ psrc += whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
+
+
+/// Transpose stereo audio. Returns number of produced output samples, and
+/// updates "srcSamples" to amount of consumed source samples
+int InterpolateCubic::transposeStereo(SAMPLETYPE *pdest,
+ const SAMPLETYPE *psrc,
+ int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 4;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ const float x3 = 1.0f;
+ const float x2 = (float)fract; // x
+ const float x1 = x2*x2; // x^2
+ const float x0 = x1*x2; // x^3
+ float y0, y1, y2, y3;
+ float out0, out1;
+
+ assert(fract < 1.0);
+
+ y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
+ y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
+ y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
+ y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
+
+ out0 = y0 * psrc[0] + y1 * psrc[2] + y2 * psrc[4] + y3 * psrc[6];
+ out1 = y0 * psrc[1] + y1 * psrc[3] + y2 * psrc[5] + y3 * psrc[7];
+
+ pdest[2*i] = (SAMPLETYPE)out0;
+ pdest[2*i+1] = (SAMPLETYPE)out1;
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ psrc += 2*whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
+
+
+/// Transpose multi-channel audio. Returns number of produced output samples, and
+/// updates "srcSamples" to amount of consumed source samples
+int InterpolateCubic::transposeMulti(SAMPLETYPE *pdest,
+ const SAMPLETYPE *psrc,
+ int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 4;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ const float x3 = 1.0f;
+ const float x2 = (float)fract; // x
+ const float x1 = x2*x2; // x^2
+ const float x0 = x1*x2; // x^3
+ float y0, y1, y2, y3;
+
+ assert(fract < 1.0);
+
+ y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
+ y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
+ y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
+ y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
+
+ for (int c = 0; c < numChannels; c ++)
+ {
+ float out;
+ out = y0 * psrc[c] + y1 * psrc[c + numChannels] + y2 * psrc[c + 2 * numChannels] + y3 * psrc[c + 3 * numChannels];
+ pdest[0] = (SAMPLETYPE)out;
+ pdest ++;
+ }
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ psrc += numChannels*whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
diff --git a/Externals/soundtouch/InterpolateCubic.h b/Externals/soundtouch/InterpolateCubic.h
index f98e701d7b..457821033f 100644
--- a/Externals/soundtouch/InterpolateCubic.h
+++ b/Externals/soundtouch/InterpolateCubic.h
@@ -1,67 +1,63 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// Cubic interpolation routine.
-///
-/// Author : Copyright (c) Olli Parviainen
-/// Author e-mail : oparviai 'at' iki.fi
-/// SoundTouch WWW: http://www.surina.net/soundtouch
-///
-////////////////////////////////////////////////////////////////////////////////
-//
-// $Id: InterpolateCubic.h 225 2015-07-26 14:45:48Z 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 _InterpolateCubic_H_
-#define _InterpolateCubic_H_
-
-#include "RateTransposer.h"
-#include "STTypes.h"
-
-namespace soundtouch
-{
-
-class InterpolateCubic : public TransposerBase
-{
-protected:
- virtual void resetRegisters();
- virtual int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- virtual int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- virtual int transposeMulti(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
-
- double fract;
-
-public:
- InterpolateCubic();
-};
-
-}
-
-#endif
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Cubic interpolation routine.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 _InterpolateCubic_H_
+#define _InterpolateCubic_H_
+
+#include "RateTransposer.h"
+#include "STTypes.h"
+
+namespace soundtouch
+{
+
+class InterpolateCubic : public TransposerBase
+{
+protected:
+ virtual void resetRegisters();
+ virtual int transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ virtual int transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ virtual int transposeMulti(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+
+ double fract;
+
+public:
+ InterpolateCubic();
+};
+
+}
+
+#endif
diff --git a/Externals/soundtouch/InterpolateLinear.cpp b/Externals/soundtouch/InterpolateLinear.cpp
index 8119813857..c3aa1994cf 100644
--- a/Externals/soundtouch/InterpolateLinear.cpp
+++ b/Externals/soundtouch/InterpolateLinear.cpp
@@ -1,300 +1,296 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// Linear interpolation algorithm.
-///
-/// Author : Copyright (c) Olli Parviainen
-/// Author e-mail : oparviai 'at' iki.fi
-/// SoundTouch WWW: http://www.surina.net/soundtouch
-///
-////////////////////////////////////////////////////////////////////////////////
-//
-// $Id: InterpolateLinear.cpp 225 2015-07-26 14:45:48Z 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 <assert.h>
-#include <stdlib.h>
-#include "InterpolateLinear.h"
-
-using namespace soundtouch;
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// InterpolateLinearInteger - integer arithmetic implementation
-//
-
-/// fixed-point interpolation routine precision
-#define SCALE 65536
-
-
-// Constructor
-InterpolateLinearInteger::InterpolateLinearInteger() : TransposerBase()
-{
- // Notice: use local function calling syntax for sake of clarity,
- // to indicate the fact that C++ constructor can't call virtual functions.
- resetRegisters();
- setRate(1.0f);
-}
-
-
-void InterpolateLinearInteger::resetRegisters()
-{
- iFract = 0;
-}
-
-
-// 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
-int InterpolateLinearInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 1;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- LONG_SAMPLETYPE temp;
-
- assert(iFract < SCALE);
-
- temp = (SCALE - iFract) * src[0] + iFract * src[1];
- dest[i] = (SAMPLETYPE)(temp / SCALE);
- i++;
-
- iFract += iRate;
-
- int iWhole = iFract / SCALE;
- iFract -= iWhole * SCALE;
- srcCount += iWhole;
- src += iWhole;
- }
- srcSamples = srcCount;
-
- return i;
-}
-
-
-// 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
-int InterpolateLinearInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 1;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- LONG_SAMPLETYPE temp0;
- LONG_SAMPLETYPE temp1;
-
- assert(iFract < SCALE);
-
- temp0 = (SCALE - iFract) * src[0] + iFract * src[2];
- temp1 = (SCALE - iFract) * src[1] + iFract * src[3];
- dest[0] = (SAMPLETYPE)(temp0 / SCALE);
- dest[1] = (SAMPLETYPE)(temp1 / SCALE);
- dest += 2;
- i++;
-
- iFract += iRate;
-
- int iWhole = iFract / SCALE;
- iFract -= iWhole * SCALE;
- srcCount += iWhole;
- src += 2*iWhole;
- }
- srcSamples = srcCount;
-
- return i;
-}
-
-
-int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 1;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- LONG_SAMPLETYPE temp, vol1;
-
- assert(iFract < SCALE);
- vol1 = (SCALE - iFract);
- for (int c = 0; c < numChannels; c ++)
- {
- temp = vol1 * src[c] + iFract * src[c + numChannels];
- dest[0] = (SAMPLETYPE)(temp / SCALE);
- dest ++;
- }
- i++;
-
- iFract += iRate;
-
- int iWhole = iFract / SCALE;
- iFract -= iWhole * SCALE;
- srcCount += iWhole;
- src += iWhole * numChannels;
- }
- srcSamples = srcCount;
-
- return i;
-}
-
-
-// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
-// iRate, larger faster iRates.
-void InterpolateLinearInteger::setRate(double newRate)
-{
- iRate = (int)(newRate * SCALE + 0.5);
- TransposerBase::setRate(newRate);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// InterpolateLinearFloat - floating point arithmetic implementation
-//
-//////////////////////////////////////////////////////////////////////////////
-
-
-// Constructor
-InterpolateLinearFloat::InterpolateLinearFloat() : TransposerBase()
-{
- // Notice: use local function calling syntax for sake of clarity,
- // to indicate the fact that C++ constructor can't call virtual functions.
- resetRegisters();
- setRate(1.0);
-}
-
-
-void InterpolateLinearFloat::resetRegisters()
-{
- fract = 0;
-}
-
-
-// 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
-int InterpolateLinearFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 1;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- double out;
- assert(fract < 1.0);
-
- out = (1.0 - fract) * src[0] + fract * src[1];
- dest[i] = (SAMPLETYPE)out;
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- src += whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
-
-
-// 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
-int InterpolateLinearFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 1;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- double out0, out1;
- assert(fract < 1.0);
-
- out0 = (1.0 - fract) * src[0] + fract * src[2];
- out1 = (1.0 - fract) * src[1] + fract * src[3];
- dest[2*i] = (SAMPLETYPE)out0;
- dest[2*i+1] = (SAMPLETYPE)out1;
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- src += 2*whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
-
-
-int InterpolateLinearFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 1;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- float temp, vol1, fract_float;
-
- vol1 = (float)(1.0 - fract);
- fract_float = (float)fract;
- for (int c = 0; c < numChannels; c ++)
- {
- temp = vol1 * src[c] + fract_float * src[c + numChannels];
- *dest = (SAMPLETYPE)temp;
- dest ++;
- }
- i++;
-
- fract += rate;
-
- int iWhole = (int)fract;
- fract -= iWhole;
- srcCount += iWhole;
- src += iWhole * numChannels;
- }
- srcSamples = srcCount;
-
- return i;
-}
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Linear interpolation algorithm.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 <assert.h>
+#include <stdlib.h>
+#include "InterpolateLinear.h"
+
+using namespace soundtouch;
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// InterpolateLinearInteger - integer arithmetic implementation
+//
+
+/// fixed-point interpolation routine precision
+#define SCALE 65536
+
+
+// Constructor
+InterpolateLinearInteger::InterpolateLinearInteger() : TransposerBase()
+{
+ // Notice: use local function calling syntax for sake of clarity,
+ // to indicate the fact that C++ constructor can't call virtual functions.
+ resetRegisters();
+ setRate(1.0f);
+}
+
+
+void InterpolateLinearInteger::resetRegisters()
+{
+ iFract = 0;
+}
+
+
+// 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
+int InterpolateLinearInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 1;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ LONG_SAMPLETYPE temp;
+
+ assert(iFract < SCALE);
+
+ temp = (SCALE - iFract) * src[0] + iFract * src[1];
+ dest[i] = (SAMPLETYPE)(temp / SCALE);
+ i++;
+
+ iFract += iRate;
+
+ int iWhole = iFract / SCALE;
+ iFract -= iWhole * SCALE;
+ srcCount += iWhole;
+ src += iWhole;
+ }
+ srcSamples = srcCount;
+
+ return i;
+}
+
+
+// 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
+int InterpolateLinearInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 1;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ LONG_SAMPLETYPE temp0;
+ LONG_SAMPLETYPE temp1;
+
+ assert(iFract < SCALE);
+
+ temp0 = (SCALE - iFract) * src[0] + iFract * src[2];
+ temp1 = (SCALE - iFract) * src[1] + iFract * src[3];
+ dest[0] = (SAMPLETYPE)(temp0 / SCALE);
+ dest[1] = (SAMPLETYPE)(temp1 / SCALE);
+ dest += 2;
+ i++;
+
+ iFract += iRate;
+
+ int iWhole = iFract / SCALE;
+ iFract -= iWhole * SCALE;
+ srcCount += iWhole;
+ src += 2*iWhole;
+ }
+ srcSamples = srcCount;
+
+ return i;
+}
+
+
+int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 1;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ LONG_SAMPLETYPE temp, vol1;
+
+ assert(iFract < SCALE);
+ vol1 = (SCALE - iFract);
+ for (int c = 0; c < numChannels; c ++)
+ {
+ temp = vol1 * src[c] + iFract * src[c + numChannels];
+ dest[0] = (SAMPLETYPE)(temp / SCALE);
+ dest ++;
+ }
+ i++;
+
+ iFract += iRate;
+
+ int iWhole = iFract / SCALE;
+ iFract -= iWhole * SCALE;
+ srcCount += iWhole;
+ src += iWhole * numChannels;
+ }
+ srcSamples = srcCount;
+
+ return i;
+}
+
+
+// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
+// iRate, larger faster iRates.
+void InterpolateLinearInteger::setRate(double newRate)
+{
+ iRate = (int)(newRate * SCALE + 0.5);
+ TransposerBase::setRate(newRate);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// InterpolateLinearFloat - floating point arithmetic implementation
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+// Constructor
+InterpolateLinearFloat::InterpolateLinearFloat() : TransposerBase()
+{
+ // Notice: use local function calling syntax for sake of clarity,
+ // to indicate the fact that C++ constructor can't call virtual functions.
+ resetRegisters();
+ setRate(1.0);
+}
+
+
+void InterpolateLinearFloat::resetRegisters()
+{
+ fract = 0;
+}
+
+
+// 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
+int InterpolateLinearFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 1;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ double out;
+ assert(fract < 1.0);
+
+ out = (1.0 - fract) * src[0] + fract * src[1];
+ dest[i] = (SAMPLETYPE)out;
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ src += whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
+
+
+// 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
+int InterpolateLinearFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 1;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ double out0, out1;
+ assert(fract < 1.0);
+
+ out0 = (1.0 - fract) * src[0] + fract * src[2];
+ out1 = (1.0 - fract) * src[1] + fract * src[3];
+ dest[2*i] = (SAMPLETYPE)out0;
+ dest[2*i+1] = (SAMPLETYPE)out1;
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ src += 2*whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
+
+
+int InterpolateLinearFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 1;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ float temp, vol1, fract_float;
+
+ vol1 = (float)(1.0 - fract);
+ fract_float = (float)fract;
+ for (int c = 0; c < numChannels; c ++)
+ {
+ temp = vol1 * src[c] + fract_float * src[c + numChannels];
+ *dest = (SAMPLETYPE)temp;
+ dest ++;
+ }
+ i++;
+
+ fract += rate;
+
+ int iWhole = (int)fract;
+ fract -= iWhole;
+ srcCount += iWhole;
+ src += iWhole * numChannels;
+ }
+ srcSamples = srcCount;
+
+ return i;
+}
diff --git a/Externals/soundtouch/InterpolateLinear.h b/Externals/soundtouch/InterpolateLinear.h
index 6a7e11d18b..faa2e2c5a5 100644
--- a/Externals/soundtouch/InterpolateLinear.h
+++ b/Externals/soundtouch/InterpolateLinear.h
@@ -1,92 +1,88 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// Linear interpolation routine.
-///
-/// Author : Copyright (c) Olli Parviainen
-/// Author e-mail : oparviai 'at' iki.fi
-/// SoundTouch WWW: http://www.surina.net/soundtouch
-///
-////////////////////////////////////////////////////////////////////////////////
-//
-// $Id: InterpolateLinear.h 225 2015-07-26 14:45:48Z 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 _InterpolateLinear_H_
-#define _InterpolateLinear_H_
-
-#include "RateTransposer.h"
-#include "STTypes.h"
-
-namespace soundtouch
-{
-
-/// Linear transposer class that uses integer arithmetics
-class InterpolateLinearInteger : public TransposerBase
-{
-protected:
- int iFract;
- int iRate;
-
- virtual void resetRegisters();
-
- virtual int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- virtual int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
-public:
- InterpolateLinearInteger();
-
- /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
- /// rate, larger faster rates.
- virtual void setRate(double newRate);
-};
-
-
-/// Linear transposer class that uses floating point arithmetics
-class InterpolateLinearFloat : public TransposerBase
-{
-protected:
- double fract;
-
- virtual void resetRegisters();
-
- virtual int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- virtual int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
-
-public:
- InterpolateLinearFloat();
-};
-
-}
-
-#endif
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Linear interpolation routine.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 _InterpolateLinear_H_
+#define _InterpolateLinear_H_
+
+#include "RateTransposer.h"
+#include "STTypes.h"
+
+namespace soundtouch
+{
+
+/// Linear transposer class that uses integer arithmetic
+class InterpolateLinearInteger : public TransposerBase
+{
+protected:
+ int iFract;
+ int iRate;
+
+ virtual void resetRegisters();
+
+ virtual int transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ virtual int transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
+public:
+ InterpolateLinearInteger();
+
+ /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
+ /// rate, larger faster rates.
+ virtual void setRate(double newRate);
+};
+
+
+/// Linear transposer class that uses floating point arithmetic
+class InterpolateLinearFloat : public TransposerBase
+{
+protected:
+ double fract;
+
+ virtual void resetRegisters();
+
+ virtual int transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ virtual int transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
+
+public:
+ InterpolateLinearFloat();
+};
+
+}
+
+#endif
diff --git a/Externals/soundtouch/InterpolateShannon.cpp b/Externals/soundtouch/InterpolateShannon.cpp
index 1085fd14cb..1d69a2e884 100644
--- a/Externals/soundtouch/InterpolateShannon.cpp
+++ b/Externals/soundtouch/InterpolateShannon.cpp
@@ -1,185 +1,181 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// Sample interpolation routine using 8-tap band-limited Shannon interpolation
-/// with kaiser window.
-///
-/// Notice. This algorithm is remarkably much heavier than linear or cubic
-/// interpolation, and not remarkably better than cubic algorithm. Thus mostly
-/// for experimental purposes
-///
-/// Author : Copyright (c) Olli Parviainen
-/// Author e-mail : oparviai 'at' iki.fi
-/// SoundTouch WWW: http://www.surina.net/soundtouch
-///
-////////////////////////////////////////////////////////////////////////////////
-//
-// $Id: InterpolateShannon.cpp 195 2014-04-06 15:57:21Z 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 <math.h>
-#include "InterpolateShannon.h"
-#include "STTypes.h"
-
-using namespace soundtouch;
-
-
-/// Kaiser window with beta = 2.0
-/// Values scaled down by 5% to avoid overflows
-static const double _kaiser8[8] =
-{
- 0.41778693317814,
- 0.64888025049173,
- 0.83508562409944,
- 0.93887857733412,
- 0.93887857733412,
- 0.83508562409944,
- 0.64888025049173,
- 0.41778693317814
-};
-
-
-InterpolateShannon::InterpolateShannon()
-{
- fract = 0;
-}
-
-
-void InterpolateShannon::resetRegisters()
-{
- fract = 0;
-}
-
-
-#define PI 3.1415926536
-#define sinc(x) (sin(PI * (x)) / (PI * (x)))
-
-/// Transpose mono audio. Returns number of produced output samples, and
-/// updates "srcSamples" to amount of consumed source samples
-int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,
- const SAMPLETYPE *psrc,
- int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 8;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- double out;
- assert(fract < 1.0);
-
- out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0];
- out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1];
- out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2];
- if (fract < 1e-6)
- {
- out += psrc[3] * _kaiser8[3]; // sinc(0) = 1
- }
- else
- {
- out += psrc[3] * sinc(- fract) * _kaiser8[3];
- }
- out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4];
- out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5];
- out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6];
- out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7];
-
- pdest[i] = (SAMPLETYPE)out;
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- psrc += whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
-
-
-/// Transpose stereo audio. Returns number of produced output samples, and
-/// updates "srcSamples" to amount of consumed source samples
-int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
- const SAMPLETYPE *psrc,
- int &srcSamples)
-{
- int i;
- int srcSampleEnd = srcSamples - 8;
- int srcCount = 0;
-
- i = 0;
- while (srcCount < srcSampleEnd)
- {
- double out0, out1, w;
- assert(fract < 1.0);
-
- w = sinc(-3.0 - fract) * _kaiser8[0];
- out0 = psrc[0] * w; out1 = psrc[1] * w;
- w = sinc(-2.0 - fract) * _kaiser8[1];
- out0 += psrc[2] * w; out1 += psrc[3] * w;
- w = sinc(-1.0 - fract) * _kaiser8[2];
- out0 += psrc[4] * w; out1 += psrc[5] * w;
- w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1
- out0 += psrc[6] * w; out1 += psrc[7] * w;
- w = sinc( 1.0 - fract) * _kaiser8[4];
- out0 += psrc[8] * w; out1 += psrc[9] * w;
- w = sinc( 2.0 - fract) * _kaiser8[5];
- out0 += psrc[10] * w; out1 += psrc[11] * w;
- w = sinc( 3.0 - fract) * _kaiser8[6];
- out0 += psrc[12] * w; out1 += psrc[13] * w;
- w = sinc( 4.0 - fract) * _kaiser8[7];
- out0 += psrc[14] * w; out1 += psrc[15] * w;
-
- pdest[2*i] = (SAMPLETYPE)out0;
- pdest[2*i+1] = (SAMPLETYPE)out1;
- i ++;
-
- // update position fraction
- fract += rate;
- // update whole positions
- int whole = (int)fract;
- fract -= whole;
- psrc += 2*whole;
- srcCount += whole;
- }
- srcSamples = srcCount;
- return i;
-}
-
-
-/// Transpose stereo audio. Returns number of produced output samples, and
-/// updates "srcSamples" to amount of consumed source samples
-int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
- const SAMPLETYPE *psrc,
- int &srcSamples)
-{
- // not implemented
- assert(false);
- return 0;
-}
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Sample interpolation routine using 8-tap band-limited Shannon interpolation
+/// with kaiser window.
+///
+/// Notice. This algorithm is remarkably much heavier than linear or cubic
+/// interpolation, and not remarkably better than cubic algorithm. Thus mostly
+/// for experimental purposes
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 <math.h>
+#include "InterpolateShannon.h"
+#include "STTypes.h"
+
+using namespace soundtouch;
+
+
+/// Kaiser window with beta = 2.0
+/// Values scaled down by 5% to avoid overflows
+static const double _kaiser8[8] =
+{
+ 0.41778693317814,
+ 0.64888025049173,
+ 0.83508562409944,
+ 0.93887857733412,
+ 0.93887857733412,
+ 0.83508562409944,
+ 0.64888025049173,
+ 0.41778693317814
+};
+
+
+InterpolateShannon::InterpolateShannon()
+{
+ fract = 0;
+}
+
+
+void InterpolateShannon::resetRegisters()
+{
+ fract = 0;
+}
+
+
+#define PI 3.1415926536
+#define sinc(x) (sin(PI * (x)) / (PI * (x)))
+
+/// Transpose mono audio. Returns number of produced output samples, and
+/// updates "srcSamples" to amount of consumed source samples
+int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,
+ const SAMPLETYPE *psrc,
+ int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 8;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ double out;
+ assert(fract < 1.0);
+
+ out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0];
+ out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1];
+ out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2];
+ if (fract < 1e-6)
+ {
+ out += psrc[3] * _kaiser8[3]; // sinc(0) = 1
+ }
+ else
+ {
+ out += psrc[3] * sinc(- fract) * _kaiser8[3];
+ }
+ out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4];
+ out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5];
+ out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6];
+ out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7];
+
+ pdest[i] = (SAMPLETYPE)out;
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ psrc += whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
+
+
+/// Transpose stereo audio. Returns number of produced output samples, and
+/// updates "srcSamples" to amount of consumed source samples
+int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
+ const SAMPLETYPE *psrc,
+ int &srcSamples)
+{
+ int i;
+ int srcSampleEnd = srcSamples - 8;
+ int srcCount = 0;
+
+ i = 0;
+ while (srcCount < srcSampleEnd)
+ {
+ double out0, out1, w;
+ assert(fract < 1.0);
+
+ w = sinc(-3.0 - fract) * _kaiser8[0];
+ out0 = psrc[0] * w; out1 = psrc[1] * w;
+ w = sinc(-2.0 - fract) * _kaiser8[1];
+ out0 += psrc[2] * w; out1 += psrc[3] * w;
+ w = sinc(-1.0 - fract) * _kaiser8[2];
+ out0 += psrc[4] * w; out1 += psrc[5] * w;
+ w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1
+ out0 += psrc[6] * w; out1 += psrc[7] * w;
+ w = sinc( 1.0 - fract) * _kaiser8[4];
+ out0 += psrc[8] * w; out1 += psrc[9] * w;
+ w = sinc( 2.0 - fract) * _kaiser8[5];
+ out0 += psrc[10] * w; out1 += psrc[11] * w;
+ w = sinc( 3.0 - fract) * _kaiser8[6];
+ out0 += psrc[12] * w; out1 += psrc[13] * w;
+ w = sinc( 4.0 - fract) * _kaiser8[7];
+ out0 += psrc[14] * w; out1 += psrc[15] * w;
+
+ pdest[2*i] = (SAMPLETYPE)out0;
+ pdest[2*i+1] = (SAMPLETYPE)out1;
+ i ++;
+
+ // update position fraction
+ fract += rate;
+ // update whole positions
+ int whole = (int)fract;
+ fract -= whole;
+ psrc += 2*whole;
+ srcCount += whole;
+ }
+ srcSamples = srcCount;
+ return i;
+}
+
+
+/// Transpose stereo audio. Returns number of produced output samples, and
+/// updates "srcSamples" to amount of consumed source samples
+int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
+ const SAMPLETYPE *psrc,
+ int &srcSamples)
+{
+ // not implemented
+ assert(false);
+ return 0;
+}
diff --git a/Externals/soundtouch/InterpolateShannon.h b/Externals/soundtouch/InterpolateShannon.h
index 54703d9808..c621cf1e1d 100644
--- a/Externals/soundtouch/InterpolateShannon.h
+++ b/Externals/soundtouch/InterpolateShannon.h
@@ -1,72 +1,68 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// Sample interpolation routine using 8-tap band-limited Shannon interpolation
-/// with kaiser window.
-///
-/// Notice. This algorithm is remarkably much heavier than linear or cubic
-/// interpolation, and not remarkably better than cubic algorithm. Thus mostly
-/// for experimental purposes
-///
-/// Author : Copyright (c) Olli Parviainen
-/// Author e-mail : oparviai 'at' iki.fi
-/// SoundTouch WWW: http://www.surina.net/soundtouch
-///
-////////////////////////////////////////////////////////////////////////////////
-//
-// $Id: InterpolateShannon.h 225 2015-07-26 14:45:48Z 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 _InterpolateShannon_H_
-#define _InterpolateShannon_H_
-
-#include "RateTransposer.h"
-#include "STTypes.h"
-
-namespace soundtouch
-{
-
-class InterpolateShannon : public TransposerBase
-{
-protected:
- void resetRegisters();
- int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
- int transposeMulti(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- int &srcSamples);
-
- double fract;
-
-public:
- InterpolateShannon();
-};
-
-}
-
-#endif
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Sample interpolation routine using 8-tap band-limited Shannon interpolation
+/// with kaiser window.
+///
+/// Notice. This algorithm is remarkably much heavier than linear or cubic
+/// interpolation, and not remarkably better than cubic algorithm. Thus mostly
+/// for experimental purposes
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 _InterpolateShannon_H_
+#define _InterpolateShannon_H_
+
+#include "RateTransposer.h"
+#include "STTypes.h"
+
+namespace soundtouch
+{
+
+class InterpolateShannon : public TransposerBase
+{
+protected:
+ void resetRegisters();
+ int transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ int transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+ int transposeMulti(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples);
+
+ double fract;
+
+public:
+ InterpolateShannon();
+};
+
+}
+
+#endif
diff --git a/Externals/soundtouch/PeakFinder.cpp b/Externals/soundtouch/PeakFinder.cpp
index b1e2205c3f..34db39bc23 100644
--- a/Externals/soundtouch/PeakFinder.cpp
+++ b/Externals/soundtouch/PeakFinder.cpp
@@ -11,13 +11,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-05-18 18:22:02 +0300 (Mon, 18 May 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: PeakFinder.cpp 213 2015-05-18 15:22:02Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -64,7 +57,7 @@ int PeakFinder::findTop(const float *data, int peakpos) const
refvalue = data[peakpos];
- // seek within ±10 points
+ // seek within �10 points
start = peakpos - 10;
if (start < minPos) start = minPos;
end = peakpos + 10;
@@ -149,7 +142,7 @@ int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, i
peaklevel = data[peakpos];
assert(peaklevel >= level);
pos = peakpos;
- while ((pos >= minPos) && (pos < maxPos))
+ while ((pos >= minPos) && (pos + direction < maxPos))
{
if (data[pos + direction] < level) return pos; // crossing found
pos += direction;
@@ -178,7 +171,6 @@ double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos)
}
-
/// get exact center of peak near given position by calculating local mass of center
double PeakFinder::getPeakCenter(const float *data, int peakpos) const
{
@@ -218,7 +210,6 @@ double PeakFinder::getPeakCenter(const float *data, int peakpos) const
}
-
double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
{
@@ -249,12 +240,12 @@ double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
// - 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 ++)
+ for (i = 1; i < 3; i ++)
{
double peaktmp, harmonic;
int i1,i2;
- harmonic = (double)i * 0.5;
+ harmonic = (double)pow(2.0, i);
peakpos = (int)(highPeak / harmonic + 0.5f);
if (peakpos < minPos) break;
peakpos = findTop(data, peakpos); // seek true local maximum index
@@ -265,7 +256,7 @@ double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
// accept harmonic peak if
// (a) it is found
- // (b) is within ±4% of the expected harmonic interval
+ // (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;
diff --git a/Externals/soundtouch/PeakFinder.h b/Externals/soundtouch/PeakFinder.h
index 594f230882..9fe66adac5 100644
--- a/Externals/soundtouch/PeakFinder.h
+++ b/Externals/soundtouch/PeakFinder.h
@@ -9,13 +9,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2011-12-30 22:33:46 +0200 (Fri, 30 Dec 2011) $
-// File revision : $Revision: 4 $
-//
-// $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -51,8 +44,8 @@ protected:
/// 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.
+ int firstPos, ///< Index of first vector item belonging to the peak.
+ int lastPos ///< Index of last vector item belonging to the peak.
) const;
/// Finds the data vector index where the monotoniously decreasing signal crosses the
diff --git a/Externals/soundtouch/RateTransposer.cpp b/Externals/soundtouch/RateTransposer.cpp
index 95b9437a24..2efaf0424d 100644
--- a/Externals/soundtouch/RateTransposer.cpp
+++ b/Externals/soundtouch/RateTransposer.cpp
@@ -10,13 +10,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: RateTransposer.cpp 225 2015-07-26 14:45:48Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -57,7 +50,13 @@ TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
// Constructor
RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
{
- bUseAAFilter = true;
+ bUseAAFilter =
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
+ true;
+#else
+ // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
+ false;
+#endif
// Instantiates the anti-alias filter
pAAFilter = new AAFilter(64);
@@ -65,7 +64,6 @@ RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
}
-
RateTransposer::~RateTransposer()
{
delete pAAFilter;
@@ -73,11 +71,13 @@ RateTransposer::~RateTransposer()
}
-
/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
void RateTransposer::enableAAFilter(bool newMode)
{
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
+ // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
bUseAAFilter = newMode;
+#endif
}
@@ -94,7 +94,6 @@ AAFilter *RateTransposer::getAAFilter()
}
-
// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
// iRate, larger faster iRates.
void RateTransposer::setRate(double newRate)
@@ -177,11 +176,10 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
// Sets the number of channels, 1 = mono, 2 = stereo
void RateTransposer::setChannels(int nChannels)
{
- assert(nChannels > 0);
+ if (!verifyNumberOfChannels(nChannels) ||
+ (pTransposer->numChannels == nChannels)) return;
- if (pTransposer->numChannels == nChannels) return;
pTransposer->setChannels(nChannels);
-
inputBuffer.setChannels(nChannels);
midBuffer.setChannels(nChannels);
outputBuffer.setChannels(nChannels);
@@ -208,6 +206,13 @@ int RateTransposer::isEmpty() const
}
+/// Return approximate initial input-output latency
+int RateTransposer::getLatency() const
+{
+ return (bUseAAFilter) ? pAAFilter->getLength() : 0;
+}
+
+
//////////////////////////////////////////////////////////////////////////////
//
// TransposerBase - Base class for interpolation
@@ -280,7 +285,7 @@ void TransposerBase::setRate(double newRate)
TransposerBase *TransposerBase::newInstance()
{
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
- // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus)
+ // Notice: For integer arithmetic support only linear algorithm (due to simplest calculus)
return ::new InterpolateLinearInteger;
#else
switch (algorithm)
diff --git a/Externals/soundtouch/RateTransposer.h b/Externals/soundtouch/RateTransposer.h
index e9cedfac9c..52b7441b89 100644
--- a/Externals/soundtouch/RateTransposer.h
+++ b/Externals/soundtouch/RateTransposer.h
@@ -14,13 +14,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: RateTransposer.h 225 2015-07-26 14:45:48Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -132,21 +125,9 @@ public:
RateTransposer();
virtual ~RateTransposer();
- /// 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
- /// integer ot floating point arithmetics are to be used.
-// static RateTransposer *newInstance();
-
/// Returns the output buffer object
FIFOSamplePipe *getOutput() { return &outputBuffer; };
- /// Returns the store buffer object
-// FIFOSamplePipe *getStore() { return &storeBuffer; };
-
/// Return anti-alias filter object
AAFilter *getAAFilter();
@@ -172,6 +153,9 @@ public:
/// Returns nonzero if there aren't any samples available for outputting.
int isEmpty() const;
+
+ /// Return approximate initial input-output latency
+ int getLatency() const;
};
}
diff --git a/Externals/soundtouch/STTypes.h b/Externals/soundtouch/STTypes.h
index a07bc3dcea..862505e769 100644
--- a/Externals/soundtouch/STTypes.h
+++ b/Externals/soundtouch/STTypes.h
@@ -8,13 +8,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-05-18 18:25:07 +0300 (Mon, 18 May 2015) $
-// File revision : $Revision: 3 $
-//
-// $Id: STTypes.h 215 2015-05-18 15:25:07Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -57,16 +50,19 @@ typedef unsigned long ulong;
#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"
+ #include "soundtouch_config.h"
#endif
namespace soundtouch
{
+ /// Max allowed number of channels
+ #define SOUNDTOUCH_MAX_CHANNELS 16
+
/// Activate these undef's to overrule the possible sampletype
/// setting inherited from some other header file:
- #undef SOUNDTOUCH_INTEGER_SAMPLES
- #undef SOUNDTOUCH_FLOAT_SAMPLES
+ //#undef SOUNDTOUCH_INTEGER_SAMPLES
+ //#undef SOUNDTOUCH_FLOAT_SAMPLES
/// If following flag is defined, always uses multichannel processing
/// routines also for mono and stero sound. This is for routine testing
@@ -75,7 +71,7 @@ namespace soundtouch
/// runtime performance so recommendation is to keep this off.
// #define USE_MULTICH_ALWAYS
- #if (defined(__SOFTFP__))
+ #if (defined(__SOFTFP__) && defined(ANDROID))
// 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
@@ -98,8 +94,8 @@ namespace soundtouch
/// 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
+ //#define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples
+ #define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples
#endif
@@ -110,7 +106,7 @@ namespace soundtouch
/// routines compiled for whatever reason, you may disable these optimizations
/// to make the library compile.
- //#define SOUNDTOUCH_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:
@@ -143,8 +139,10 @@ namespace soundtouch
#endif // SOUNDTOUCH_FLOAT_SAMPLES
#ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
- // Allow MMX optimizations
- #define SOUNDTOUCH_ALLOW_MMX 1
+ // Allow MMX optimizations (not available in X64 mode)
+ #if (!_M_X64)
+ #define SOUNDTOUCH_ALLOW_MMX 1
+ #endif
#endif
#else
@@ -164,7 +162,7 @@ namespace soundtouch
};
// define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
- #define ST_NO_EXCEPTION_HANDLING 1
+// #define ST_NO_EXCEPTION_HANDLING 1
#ifdef ST_NO_EXCEPTION_HANDLING
// Exceptions disabled. Throw asserts instead if enabled.
#include <assert.h>
diff --git a/Externals/soundtouch/SoundTouch.cpp b/Externals/soundtouch/SoundTouch.cpp
index edccce238d..1618884cf5 100644
--- a/Externals/soundtouch/SoundTouch.cpp
+++ b/Externals/soundtouch/SoundTouch.cpp
@@ -41,13 +41,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: SoundTouch.cpp 225 2015-07-26 14:45:48Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -110,15 +103,14 @@ SoundTouch::SoundTouch()
calcEffectiveRateAndTempo();
- samplesExpectedOut = 0;
- samplesOutput = 0;
+ samplesExpectedOut = 0;
+ samplesOutput = 0;
channels = 0;
bSrateSet = false;
}
-
SoundTouch::~SoundTouch()
{
delete pRateTransposer;
@@ -126,7 +118,6 @@ SoundTouch::~SoundTouch()
}
-
/// Get SoundTouch library version string
const char *SoundTouch::getVersionString()
{
@@ -146,18 +137,14 @@ uint SoundTouch::getVersionId()
// Sets the number of channels, 1 = mono, 2 = stereo
void SoundTouch::setChannels(uint numChannels)
{
- /*if (numChannels != 1 && numChannels != 2)
- {
- //ST_THROW_RT_ERROR("Illegal number of channels");
- return;
- }*/
+ if (!verifyNumberOfChannels(numChannels)) return;
+
channels = numChannels;
pRateTransposer->setChannels((int)numChannels);
pTDStretch->setChannels((int)numChannels);
}
-
// Sets new rate control value. Normal rate = 1.0, smaller values
// represent slower rate, larger faster rates.
void SoundTouch::setRate(double newRate)
@@ -167,7 +154,6 @@ void SoundTouch::setRate(double newRate)
}
-
// Sets new rate control value as a difference in percents compared
// to the original rate (-50 .. +100 %)
void SoundTouch::setRateChange(double newRate)
@@ -177,7 +163,6 @@ void SoundTouch::setRateChange(double newRate)
}
-
// Sets new tempo control value. Normal tempo = 1.0, smaller values
// represent slower tempo, larger faster tempo.
void SoundTouch::setTempo(double newTempo)
@@ -187,7 +172,6 @@ void SoundTouch::setTempo(double newTempo)
}
-
// Sets new tempo control value as a difference in percents compared
// to the original tempo (-50 .. +100 %)
void SoundTouch::setTempoChange(double newTempo)
@@ -197,7 +181,6 @@ void SoundTouch::setTempoChange(double newTempo)
}
-
// Sets new pitch control value. Original pitch = 1.0, smaller values
// represent lower pitches, larger values higher pitch.
void SoundTouch::setPitch(double newPitch)
@@ -207,7 +190,6 @@ void SoundTouch::setPitch(double newPitch)
}
-
// Sets pitch change in octaves compared to the original pitch
// (-1.00 .. +1.00)
void SoundTouch::setPitchOctaves(double newPitch)
@@ -217,7 +199,6 @@ void SoundTouch::setPitchOctaves(double newPitch)
}
-
// Sets pitch change in semi-tones compared to the original pitch
// (-12 .. +12)
void SoundTouch::setPitchSemiTones(int newPitch)
@@ -226,7 +207,6 @@ void SoundTouch::setPitchSemiTones(int newPitch)
}
-
void SoundTouch::setPitchSemiTones(double newPitch)
{
setPitchOctaves(newPitch / 12.0);
@@ -240,11 +220,11 @@ void SoundTouch::calcEffectiveRateAndTempo()
double oldTempo = tempo;
double oldRate = rate;
- tempo = virtualTempo / virtualPitch;
- rate = virtualPitch * virtualRate;
+ tempo = virtualTempo / virtualPitch;
+ rate = virtualPitch * virtualRate;
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate);
- if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
+ if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
if (rate <= 1.0f)
@@ -286,9 +266,9 @@ void SoundTouch::calcEffectiveRateAndTempo()
// Sets sample rate.
void SoundTouch::setSampleRate(uint srate)
{
- bSrateSet = true;
// set sample rate, leave other tempo changer parameters as they are.
pTDStretch->setParameters((int)srate);
+ bSrateSet = true;
}
@@ -305,25 +285,9 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
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)
- {
- // The rate value is same as the original, simply evaluate the tempo changer.
- assert(output == pTDStretch);
- 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);
- }
- */
-
- // accumulate how many samples are expected out from processing, given the current
- // processing setting
- samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo);
+ // accumulate how many samples are expected out from processing, given the current
+ // processing setting
+ samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo);
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
if (rate <= 1.0f)
@@ -354,28 +318,28 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
void SoundTouch::flush()
{
int i;
- int numStillExpected;
+ int numStillExpected;
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels];
- // how many samples are still expected to output
- numStillExpected = (int)((long)(samplesExpectedOut + 0.5) - samplesOutput);
+ // how many samples are still expected to output
+ numStillExpected = (int)((long)(samplesExpectedOut + 0.5) - samplesOutput);
+ if (numStillExpected < 0) numStillExpected = 0;
memset(buff, 0, 128 * 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
// 24ksamples in any case)
- for (i = 0; (numStillExpected > (int)numSamples()) && (i < 200); i ++)
- {
- putSamples(buff, 128);
- }
+ for (i = 0; (numStillExpected > (int)numSamples()) && (i < 200); i ++)
+ {
+ putSamples(buff, 128);
+ }
- adjustAmountOfSamples(numStillExpected);
+ adjustAmountOfSamples(numStillExpected);
delete[] buff;
// Clear input buffers
- // pRateTransposer->clearInput();
pTDStretch->clearInput();
// yet leave the output intouched as that's where the
// flushed samples are!
@@ -446,7 +410,7 @@ int SoundTouch::getSetting(int settingId) const
return pRateTransposer->getAAFilter()->getLength();
case SETTING_USE_QUICKSEEK :
- return (uint) pTDStretch->isQuickSeekEnabled();
+ return (uint)pTDStretch->isQuickSeekEnabled();
case SETTING_SEQUENCE_MS:
pTDStretch->getParameters(NULL, &temp, NULL, NULL);
@@ -460,13 +424,53 @@ int SoundTouch::getSetting(int settingId) const
pTDStretch->getParameters(NULL, NULL, NULL, &temp);
return temp;
- case SETTING_NOMINAL_INPUT_SEQUENCE :
- return pTDStretch->getInputSampleReq();
+ case SETTING_NOMINAL_INPUT_SEQUENCE :
+ {
+ int size = pTDStretch->getInputSampleReq();
+
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
+ if (rate <= 1.0)
+ {
+ // transposing done before timestretch, which impacts latency
+ return (int)(size * rate + 0.5);
+ }
+#endif
+ return size;
+ }
+
+ case SETTING_NOMINAL_OUTPUT_SEQUENCE :
+ {
+ int size = pTDStretch->getOutputBatchSize();
+
+ if (rate > 1.0)
+ {
+ // transposing done after timestretch, which impacts latency
+ return (int)(size / rate + 0.5);
+ }
+ return size;
+ }
+
+ case SETTING_INITIAL_LATENCY:
+ {
+ double latency = pTDStretch->getLatency();
+ int latency_tr = pRateTransposer->getLatency();
+
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
+ if (rate <= 1.0)
+ {
+ // transposing done before timestretch, which impacts latency
+ latency = (latency + latency_tr) * rate;
+ }
+ else
+#endif
+ {
+ latency += (double)latency_tr / rate;
+ }
- case SETTING_NOMINAL_OUTPUT_SEQUENCE :
- return pTDStretch->getOutputBatchSize();
+ return (int)(latency + 0.5);
+ }
- default :
+ default :
return 0;
}
}
@@ -476,13 +480,13 @@ int SoundTouch::getSetting(int settingId) const
// buffers.
void SoundTouch::clear()
{
- samplesExpectedOut = 0;
+ samplesExpectedOut = 0;
+ samplesOutput = 0;
pRateTransposer->clear();
pTDStretch->clear();
}
-
/// Returns number of samples currently unprocessed.
uint SoundTouch::numUnprocessedSamples() const
{
@@ -499,7 +503,6 @@ uint SoundTouch::numUnprocessedSamples() const
}
-
/// 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.
@@ -507,9 +510,9 @@ uint SoundTouch::numUnprocessedSamples() const
/// \return Number of samples returned.
uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
{
- uint ret = FIFOProcessor::receiveSamples(output, maxSamples);
- samplesOutput += (long)ret;
- return ret;
+ uint ret = FIFOProcessor::receiveSamples(output, maxSamples);
+ samplesOutput += (long)ret;
+ return ret;
}
@@ -520,7 +523,16 @@ uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
/// with 'ptrBegin' function.
uint SoundTouch::receiveSamples(uint maxSamples)
{
- uint ret = FIFOProcessor::receiveSamples(maxSamples);
- samplesOutput += (long)ret;
- return ret;
+ uint ret = FIFOProcessor::receiveSamples(maxSamples);
+ samplesOutput += (long)ret;
+ return ret;
+}
+
+
+/// Get ratio between input and output audio durations, useful for calculating
+/// processed output duration: if you'll process a stream of N samples, then
+/// you can expect to get out N * getInputOutputSampleRatio() samples.
+double SoundTouch::getInputOutputSampleRatio()
+{
+ return 1.0 / (tempo * rate);
}
diff --git a/Externals/soundtouch/SoundTouch.h b/Externals/soundtouch/SoundTouch.h
index 24e8716e04..e963ddfde8 100644
--- a/Externals/soundtouch/SoundTouch.h
+++ b/Externals/soundtouch/SoundTouch.h
@@ -41,13 +41,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-09-20 10:38:32 +0300 (Sun, 20 Sep 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: SoundTouch.h 230 2015-09-20 07:38:32Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -79,10 +72,10 @@ namespace soundtouch
{
/// Soundtouch library version string
-#define SOUNDTOUCH_VERSION "1.9.2"
+#define SOUNDTOUCH_VERSION "2.1.3"
/// SoundTouch library version id
-#define SOUNDTOUCH_VERSION_ID (10902)
+#define SOUNDTOUCH_VERSION_ID (20103)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
@@ -116,30 +109,61 @@ namespace soundtouch
#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.
+/// Call "getSetting" with this ID to query processing sequence size in samples.
+/// This value gives approximate value of how many input samples you'll need to
+/// feed into SoundTouch after initial buffering to get out a new batch of
+/// output samples.
+///
+/// This value does not include initial buffering at beginning of a new processing
+/// stream, use SETTING_INITIAL_LATENCY to get the initial buffering size.
///
/// 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
+/// - This parameter value is not constant but change depending on
/// tempo/pitch/rate/samplerate settings.
-#define SETTING_NOMINAL_INPUT_SEQUENCE 6
+#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
+/// - This parameter value is not constant but change depending on
/// tempo/pitch/rate/samplerate settings.
-#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7
+#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7
+
+
+/// Call "getSetting" with this ID to query initial processing latency, i.e.
+/// approx. how many samples you'll need to enter to SoundTouch pipeline before
+/// you can expect to get first batch of ready output samples out.
+///
+/// After the first output batch, you can then expect to get approx.
+/// SETTING_NOMINAL_OUTPUT_SEQUENCE ready samples out for every
+/// SETTING_NOMINAL_INPUT_SEQUENCE samples that you enter into SoundTouch.
+///
+/// Example:
+/// processing with parameter -tempo=5
+/// => initial latency = 5509 samples
+/// input sequence = 4167 samples
+/// output sequence = 3969 samples
+///
+/// Accordingly, you can expect to feed in approx. 5509 samples at beginning of
+/// the stream, and then you'll get out the first 3969 samples. After that, for
+/// every approx. 4167 samples that you'll put in, you'll receive again approx.
+/// 3969 samples out.
+///
+/// This also means that average latency during stream processing is
+/// INITIAL_LATENCY-OUTPUT_SEQUENCE/2, in the above example case 5509-3969/2
+/// = 3524 samples
+///
+/// Notices:
+/// - This is read-only parameter, i.e. setSetting ignores this parameter
+/// - This parameter value is not constant but change depending on
+/// tempo/pitch/rate/samplerate settings.
+#define SETTING_INITIAL_LATENCY 8
+
class SoundTouch : public FIFOProcessor
{
@@ -228,6 +252,24 @@ public:
/// Sets sample rate.
void setSampleRate(uint srate);
+ /// Get ratio between input and output audio durations, useful for calculating
+ /// processed output duration: if you'll process a stream of N samples, then
+ /// you can expect to get out N * getInputOutputSampleRatio() samples.
+ ///
+ /// This ratio will give accurate target duration ratio for a full audio track,
+ /// given that the the whole track is processed with same processing parameters.
+ ///
+ /// If this ratio is applied to calculate intermediate offsets inside a processing
+ /// stream, then this ratio is approximate and can deviate +- some tens of milliseconds
+ /// from ideal offset, yet by end of the audio stream the duration ratio will become
+ /// exact.
+ ///
+ /// Example: if processing with parameters "-tempo=15 -pitch=-3", the function
+ /// will return value 0.8695652... Now, if processing an audio stream whose duration
+ /// is exactly one million audio samples, then you can expect the processed
+ /// output duration be 0.869565 * 1000000 = 869565 samples.
+ double getInputOutputSampleRatio();
+
/// Flushes the last samples from the processing pipeline to the output.
/// Clears also the internal processing buffers.
//
@@ -271,7 +313,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
+ /// \return 'true' if the setting was successfully changed
bool setSetting(int settingId, ///< Setting ID number. see SETTING_... defines.
int value ///< New setting value.
);
@@ -286,6 +328,11 @@ public:
/// Returns number of samples currently unprocessed.
virtual uint numUnprocessedSamples() const;
+ /// Return number of channels
+ uint numChannels() const
+ {
+ return channels;
+ }
/// Other handy functions that are implemented in the ancestor classes (see
/// classes 'FIFOProcessor' and 'FIFOSamplePipe')
diff --git a/Externals/soundtouch/SoundTouch.vcxproj b/Externals/soundtouch/SoundTouch.vcxproj
index c29234fada..8ea3563cdf 100644
--- a/Externals/soundtouch/SoundTouch.vcxproj
+++ b/Externals/soundtouch/SoundTouch.vcxproj
@@ -44,6 +44,7 @@
<ClInclude Include="PeakFinder.h" />
<ClInclude Include="RateTransposer.h" />
<ClInclude Include="SoundTouch.h" />
+ <ClInclude Include="soundtouch_config.h" />
<ClInclude Include="STTypes.h" />
<ClInclude Include="TDStretch.h" />
</ItemGroup>
@@ -53,4 +54,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Externals/soundtouch/TDStretch.cpp b/Externals/soundtouch/TDStretch.cpp
index bb473a9f63..ce49310900 100644
--- a/Externals/soundtouch/TDStretch.cpp
+++ b/Externals/soundtouch/TDStretch.cpp
@@ -4,8 +4,14 @@
/// 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
-/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
+/// Notes : MMX optimized functions reside in a separate, platform-specific
+/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'.
+///
+/// This source file contains OpenMP optimizations that allow speeding up the
+/// corss-correlation algorithm by executing it in several threads / CPU cores
+/// in parallel. See the following article link for more detailed discussion
+/// about SoundTouch OpenMP optimizations:
+/// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
@@ -13,13 +19,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
-// File revision : $Revision: 1.12 $
-//
-// $Id: TDStretch.cpp 226 2015-08-08 21:00:15Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -128,8 +127,13 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
int aSeekWindowMS, int aOverlapMS)
{
// accept only positive parameter values - if zero or negative, use old values instead
- if (aSampleRate > 0) this->sampleRate = aSampleRate;
- if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
+ if (aSampleRate > 0)
+ {
+ if (aSampleRate > 192000) ST_THROW_RT_ERROR("Error: Excessive samplerate");
+ this->sampleRate = aSampleRate;
+ }
+
+ if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
if (aSequenceMS > 0)
{
@@ -219,6 +223,7 @@ void TDStretch::clearInput()
{
inputBuffer.clear();
clearMidBuffer();
+ isBeginning = true;
}
@@ -297,12 +302,13 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
int i;
double norm;
- bestCorr = FLT_MIN;
+ bestCorr = -FLT_MAX;
bestOffs = 0;
// Scans for the best correlation value by testing each possible position
// over the permitted range.
bestCorr = calcCrossCorr(refPos, pMidBuffer, norm);
+ bestCorr = (bestCorr + 0.1) * 0.75;
#pragma omp parallel for
for (i = 1; i < seekLength; i ++)
@@ -354,7 +360,7 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
// with improved precision
//
// Based on testing:
-// - This algorithm gives on average 99% as good match as the full algorith
+// - This algorithm gives on average 99% as good match as the full algorithm
// - this quick seek algorithm finds the best match on ~90% of cases
// - on those 10% of cases when this algorithm doesn't find best match,
// it still finds on average ~90% match vs. the best possible match
@@ -373,12 +379,10 @@ int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
// note: 'float' types used in this function in case that the platform would need to use software-fp
- bestCorr = FLT_MIN;
- bestOffs = SCANWIND;
- bestCorr2 = FLT_MIN;
- bestOffs2 = 0;
-
- int best = 0;
+ bestCorr =
+ bestCorr2 = -FLT_MAX;
+ bestOffs =
+ bestOffs2 = SCANWIND;
// Scans for the best correlation value by testing each possible position
// over the permitted range. Look for two best matches on the first pass to
@@ -436,7 +440,6 @@ int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
{
bestCorr = corr;
bestOffs = i;
- best = 1;
}
}
@@ -458,7 +461,6 @@ int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
{
bestCorr = corr;
bestOffs = i;
- best = 2;
}
}
@@ -515,18 +517,18 @@ void TDStretch::clearCrossCorrState()
void TDStretch::calcSeqParameters()
{
// Adjust tempo param according to tempo, so that variating processing sequence length is used
- // at varius tempo settings, between the given low...top limits
+ // at various tempo settings, between the given low...top limits
#define AUTOSEQ_TEMPO_LOW 0.5 // auto setting low tempo range (-50%)
#define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%)
// sequence-ms setting values at above low & top tempo
- #define AUTOSEQ_AT_MIN 125.0
- #define AUTOSEQ_AT_MAX 50.0
+ #define AUTOSEQ_AT_MIN 90.0
+ #define AUTOSEQ_AT_MAX 40.0
#define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
#define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW))
// seek-window-ms setting values at above low & top tempoq
- #define AUTOSEEK_AT_MIN 25.0
+ #define AUTOSEEK_AT_MIN 20.0
#define AUTOSEEK_AT_MAX 15.0
#define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
#define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW))
@@ -586,9 +588,8 @@ void TDStretch::setTempo(double newTempo)
// Sets the number of channels, 1 = mono, 2 = stereo
void TDStretch::setChannels(int numChannels)
{
- assert(numChannels > 0);
- if (channels == numChannels) return;
-// assert(numChannels == 1 || numChannels == 2);
+ if (!verifyNumberOfChannels(numChannels) ||
+ (channels == numChannels)) return;
channels = numChannels;
inputBuffer.setChannels(channels);
@@ -637,7 +638,8 @@ void TDStretch::processNominalTempo()
// the result into 'outputBuffer'
void TDStretch::processSamples()
{
- int ovlSkip, offset;
+ int ovlSkip;
+ int offset = 0;
int temp;
/* Removed this small optimization - can introduce a click to sound when tempo setting
@@ -654,35 +656,61 @@ void TDStretch::processSamples()
// to form a processing frame.
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
- // samples in 'midBuffer' using sliding overlapping
- // ... first partially overlap with the end of the previous sequence
- // (that's in 'midBuffer')
- overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset);
- outputBuffer.putSamples((uint)overlapLength);
+ if (isBeginning == false)
+ {
+ // apart from the very beginning of the track,
+ // scan for the best overlapping position & do overlap-add
+ offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
+
+ // 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')
+ overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset);
+ outputBuffer.putSamples((uint)overlapLength);
+ offset += overlapLength;
+ }
+ else
+ {
+ // Adjust processing offset at beginning of track by not perform initial overlapping
+ // and compensating that in the 'input buffer skip' calculation
+ isBeginning = false;
+ int skip = (int)(tempo * overlapLength + 0.5);
+
+ #ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
+ #ifdef SOUNDTOUCH_ALLOW_SSE
+ // if SSE mode, round the skip amount to value corresponding to aligned memory address
+ if (channels == 1)
+ {
+ skip &= -4;
+ }
+ else if (channels == 2)
+ {
+ skip &= -2;
+ }
+ #endif
+ #endif
+ skipFract -= skip;
+ assert(nominalSkip >= -skipFract);
+ }
// ... then copy sequence samples from 'inputBuffer' to output:
- // length of sequence
- temp = (seekWindowLength - 2 * overlapLength);
-
// crosscheck that we don't have buffer overflow...
- if ((int)inputBuffer.numSamples() < (offset + temp + overlapLength * 2))
+ if ((int)inputBuffer.numSamples() < (offset + seekWindowLength - overlapLength))
{
continue; // just in case, shouldn't really happen
}
- outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp);
+ // length of sequence
+ temp = (seekWindowLength - 2 * overlapLength);
+ outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * offset, (uint)temp);
// 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),
+ assert((offset + temp + overlapLength) <= (int)inputBuffer.numSamples());
+ memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp),
channels * sizeof(SAMPLETYPE) * overlapLength);
// Remove the processed samples from the input buffer. Update
@@ -776,7 +804,7 @@ TDStretch * TDStretch::newInstance()
//////////////////////////////////////////////////////////////////////////////
//
-// Integer arithmetics specific algorithm implementations.
+// Integer arithmetic specific algorithm implementations.
//
//////////////////////////////////////////////////////////////////////////////
@@ -879,7 +907,12 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
if (lnorm > maxnorm)
{
- maxnorm = lnorm;
+ // modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
+ #pragma omp critical
+ if (lnorm > maxnorm)
+ {
+ maxnorm = lnorm;
+ }
}
// Normalize result by dividing by sqrt(norm) - this step is easiest
// done using floating point operation
@@ -936,7 +969,7 @@ double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *c
//////////////////////////////////////////////////////////////////////////////
//
-// Floating point arithmetics specific algorithm implementations.
+// Floating point arithmetic specific algorithm implementations.
//
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
diff --git a/Externals/soundtouch/TDStretch.h b/Externals/soundtouch/TDStretch.h
index 213304c982..4118f9f474 100644
--- a/Externals/soundtouch/TDStretch.h
+++ b/Externals/soundtouch/TDStretch.h
@@ -13,13 +13,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: TDStretch.h 226 2015-08-08 21:00:15Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -134,6 +127,7 @@ protected:
bool bQuickSeek;
bool bAutoSeqSetting;
bool bAutoSeekSetting;
+ bool isBeginning;
SAMPLETYPE *pMidBuffer;
SAMPLETYPE *pMidBufferUnaligned;
@@ -163,7 +157,6 @@ protected:
void calcSeqParameters();
void adaptNormalizer();
-
/// Changes the tempo of the given sound samples.
/// Returns amount of samples returned in the "output" buffer.
/// The maximum amount of samples that can be returned at a time is set by
@@ -247,8 +240,13 @@ public:
{
return seekWindowLength - overlapLength;
}
-};
+ /// return approximate initial input-output latency
+ int getLatency() const
+ {
+ return sampleReq;
+ }
+};
// Implementation-specific class declarations:
diff --git a/Externals/soundtouch/cpu_detect.h b/Externals/soundtouch/cpu_detect.h
index 025781dae1..0cdc22356f 100644
--- a/Externals/soundtouch/cpu_detect.h
+++ b/Externals/soundtouch/cpu_detect.h
@@ -12,13 +12,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
-// File revision : $Revision: 4 $
-//
-// $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
diff --git a/Externals/soundtouch/cpu_detect_x86.cpp b/Externals/soundtouch/cpu_detect_x86.cpp
index 5ef0246216..b1286106eb 100644
--- a/Externals/soundtouch/cpu_detect_x86.cpp
+++ b/Externals/soundtouch/cpu_detect_x86.cpp
@@ -11,13 +11,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2014-01-07 20:24:28 +0200 (Tue, 07 Jan 2014) $
-// File revision : $Revision: 4 $
-//
-// $Id: cpu_detect_x86.cpp 183 2014-01-07 18:24:28Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -75,7 +68,6 @@ void disableExtensions(uint dwDisableMask)
}
-
/// Checks which instruction set extensions are supported by the CPU.
uint detectCPUextensions(void)
{
diff --git a/Externals/soundtouch/mmx_optimized.cpp b/Externals/soundtouch/mmx_optimized.cpp
index 8ad2811b9a..741ba4f22e 100644
--- a/Externals/soundtouch/mmx_optimized.cpp
+++ b/Externals/soundtouch/mmx_optimized.cpp
@@ -20,13 +20,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: mmx_optimized.cpp 226 2015-08-08 21:00:15Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
@@ -125,7 +118,12 @@ double TDStretchMMX::calcCrossCorr(const short *pV1, const short *pV2, double &d
if (norm > (long)maxnorm)
{
- maxnorm = norm;
+ // modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
+ #pragma omp critical
+ if (norm > (long)maxnorm)
+ {
+ maxnorm = norm;
+ }
}
// Normalize result by dividing by sqrt(norm) - this step is easiest
@@ -219,7 +217,6 @@ void TDStretchMMX::clearCrossCorrState()
}
-
// MMX-optimized version of the function overlapStereo
void TDStretchMMX::overlapStereo(short *output, const short *input) const
{
@@ -335,7 +332,6 @@ void FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uRe
}
-
// mmx-optimized version of the filter routine for stereo sound
uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, uint numSamples) const
{
@@ -392,4 +388,9 @@ uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, uint numS
return (numSamples & 0xfffffffe) - length;
}
+#else
+
+// workaround to not complain about empty module
+bool _dontcomplain_mmx_empty;
+
#endif // SOUNDTOUCH_ALLOW_MMX
diff --git a/Externals/soundtouch/soundtouch_config.h b/Externals/soundtouch/soundtouch_config.h
new file mode 100644
index 0000000000..950e3353e2
--- /dev/null
+++ b/Externals/soundtouch/soundtouch_config.h
@@ -0,0 +1,2 @@
+#define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples
+//#define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples
diff --git a/Externals/soundtouch/sse_optimized.cpp b/Externals/soundtouch/sse_optimized.cpp
index 490d0d2080..0dc637015f 100644
--- a/Externals/soundtouch/sse_optimized.cpp
+++ b/Externals/soundtouch/sse_optimized.cpp
@@ -23,13 +23,6 @@
///
////////////////////////////////////////////////////////////////////////////////
//
-// Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
-// File revision : $Revision: 4 $
-//
-// $Id: sse_optimized.cpp 226 2015-08-08 21:00:15Z oparviai $
-//
-////////////////////////////////////////////////////////////////////////////////
-//
// License :
//
// SoundTouch audio processing library
--
2.29.2