Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/alexmarsev/soundtouch.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroparviai <oparviai@f3a24b6a-cf45-0410-b55a-8c22e2698227>2014-01-06 22:40:23 +0400
committeroparviai <oparviai@f3a24b6a-cf45-0410-b55a-8c22e2698227>2014-01-06 22:40:23 +0400
commitaaf87217c22fca96f53cbe60bab498a9b68b9c2e (patch)
tree4d34b91542e89bf7a36a3af124e7e0766ce168f0
parentb9b54dc6132fbc008579f29366d4cb24a6e90366 (diff)
Implemented separate Cubic, Linear and Shannon interpolation algorithms.
-rw-r--r--source/SoundStretch/soundstretch.vcproj3
-rw-r--r--source/SoundTouch/InterpolateCubic.cpp200
-rw-r--r--source/SoundTouch/InterpolateCubic.h67
-rw-r--r--source/SoundTouch/InterpolateLinear.cpp250
-rw-r--r--source/SoundTouch/InterpolateLinear.h92
-rw-r--r--source/SoundTouch/InterpolateShannon.cpp185
-rw-r--r--source/SoundTouch/InterpolateShannon.h72
-rw-r--r--source/SoundTouch/Makefile.am6
-rw-r--r--source/SoundTouch/RateTransposer.cpp558
-rw-r--r--source/SoundTouch/RateTransposer.h26
-rw-r--r--source/SoundTouch/SoundTouch.vcproj36
11 files changed, 989 insertions, 506 deletions
diff --git a/source/SoundStretch/soundstretch.vcproj b/source/SoundStretch/soundstretch.vcproj
index 53eb827..5efe8e5 100644
--- a/source/SoundStretch/soundstretch.vcproj
+++ b/source/SoundStretch/soundstretch.vcproj
@@ -4,6 +4,7 @@
Version="9.00"
Name="soundstretch"
ProjectGUID="{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}"
+ RootNamespace="soundstretch"
TargetFrameworkVersion="131072"
>
<Platforms>
@@ -49,6 +50,7 @@
BasicRuntimeChecks="3"
RuntimeLibrary="1"
StructMemberAlignment="5"
+ FloatingPointModel="2"
PrecompiledHeaderFile=".\Debug/soundstretch.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
@@ -147,6 +149,7 @@
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
PrecompiledHeaderFile=".\Release/soundstretch.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
diff --git a/source/SoundTouch/InterpolateCubic.cpp b/source/SoundTouch/InterpolateCubic.cpp
new file mode 100644
index 0000000..8f476ac
--- /dev/null
+++ b/source/SoundTouch/InterpolateCubic.cpp
@@ -0,0 +1,200 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Cubic interpolation routine.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// $Id: RateTransposer.h 177 2014-01-05 21:40:22Z 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;
+}
diff --git a/source/SoundTouch/InterpolateCubic.h b/source/SoundTouch/InterpolateCubic.h
new file mode 100644
index 0000000..7f758a4
--- /dev/null
+++ b/source/SoundTouch/InterpolateCubic.h
@@ -0,0 +1,67 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Cubic interpolation routine.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// $Id: RateTransposer.h 177 2014-01-05 21:40:22Z 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);
+
+ float fract;
+
+public:
+ InterpolateCubic();
+};
+
+}
+
+#endif
diff --git a/source/SoundTouch/InterpolateLinear.cpp b/source/SoundTouch/InterpolateLinear.cpp
new file mode 100644
index 0000000..b40fd46
--- /dev/null
+++ b/source/SoundTouch/InterpolateLinear.cpp
@@ -0,0 +1,250 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Linear interpolation algorithm.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// $Id: RateTransposer.cpp 177 2014-01-05 21:40:22Z 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)
+{
+ // not yet implemented
+ assert(FALSE);
+ return 0;
+}
+
+
+// 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)
+{
+ // not yet implemented
+ return 0;
+}
+
+
+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 = iFract * src[c] + vol1 * src[c + numChannels];
+ *dest = (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(float newRate)
+{
+ iRate = (int)(newRate * SCALE + 0.5f);
+ 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.0f);
+}
+
+
+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;
+
+ vol1 = (1.0f- fract);
+ for (int c = 0; c < numChannels; c ++)
+ {
+ temp = vol1 * src[c] + fract * 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/source/SoundTouch/InterpolateLinear.h b/source/SoundTouch/InterpolateLinear.h
new file mode 100644
index 0000000..3527089
--- /dev/null
+++ b/source/SoundTouch/InterpolateLinear.h
@@ -0,0 +1,92 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Linear interpolation routine.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// $Id: RateTransposer.h 177 2014-01-05 21:40:22Z 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(float newRate);
+};
+
+
+/// Linear transposer class that uses floating point arithmetics
+class InterpolateLinearFloat : public TransposerBase
+{
+protected:
+ float 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/source/SoundTouch/InterpolateShannon.cpp b/source/SoundTouch/InterpolateShannon.cpp
new file mode 100644
index 0000000..f6421a9
--- /dev/null
+++ b/source/SoundTouch/InterpolateShannon.cpp
@@ -0,0 +1,185 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// 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: RateTransposer.h 177 2014-01-05 21:40:22Z 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;
+}
diff --git a/source/SoundTouch/InterpolateShannon.h b/source/SoundTouch/InterpolateShannon.h
new file mode 100644
index 0000000..4823f36
--- /dev/null
+++ b/source/SoundTouch/InterpolateShannon.h
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// 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: RateTransposer.h 177 2014-01-05 21:40:22Z 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);
+
+ float fract;
+
+public:
+ InterpolateShannon();
+};
+
+}
+
+#endif
diff --git a/source/SoundTouch/Makefile.am b/source/SoundTouch/Makefile.am
index b081fb2..3644e6a 100644
--- a/source/SoundTouch/Makefile.am
+++ b/source/SoundTouch/Makefile.am
@@ -28,8 +28,10 @@ noinst_HEADERS=AAFilter.h cpu_detect.h cpu_detect_x86.cpp FIRFilter.h RateTransp
lib_LTLIBRARIES=libSoundTouch.la
#
-libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp RateTransposer.cpp SoundTouch.cpp TDStretch.cpp cpu_detect_x86.cpp BPMDetect.cpp PeakFinder.cpp
-
+libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp \
+ RateTransposer.cpp SoundTouch.cpp TDStretch.cpp cpu_detect_x86.cpp \
+ BPMDetect.cpp PeakFinder.cpp InterpolateLinear.cpp InterpolateCubic.cpp \
+ InterpolateShannon.cpp
# Compiler flags
AM_CXXFLAGS=-O3 -fcheck-new -I../../include
diff --git a/source/SoundTouch/RateTransposer.cpp b/source/SoundTouch/RateTransposer.cpp
index e76c4bb..404f250 100644
--- a/source/SoundTouch/RateTransposer.cpp
+++ b/source/SoundTouch/RateTransposer.cpp
@@ -43,131 +43,14 @@
#include <stdlib.h>
#include <stdio.h>
#include "RateTransposer.h"
+#include "InterpolateLinear.h"
+#include "InterpolateCubic.h"
+#include "InterpolateShannon.h"
#include "AAFilter.h"
using namespace soundtouch;
-
-/// A linear samplerate transposer class that uses integer arithmetics.
-/// for the transposing.
-class LinearTransposerBase: public TransposerBase
-{
-protected:
- virtual int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples) = 0;
- virtual int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples) = 0;
- virtual int transposeMulti(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples) = 0;
-public:
- virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
-
- static LinearTransposerBase *newInstance();
-};
-
-
-/// A linear samplerate transposer class that uses integer arithmetics.
-/// for the transposing.
-class LinearTransposerInteger : public LinearTransposerBase
-{
-protected:
- int iSlopeCount;
- int iRate;
- SAMPLETYPE *sPrevSample;
-
- virtual void resetRegisters();
-
- virtual int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples);
- virtual int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples);
- virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples);
-public:
- LinearTransposerInteger();
- virtual ~LinearTransposerInteger();
-
- /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
- /// rate, larger faster rates.
- virtual void setRate(float newRate);
-};
-
-
-/// A linear samplerate transposer class that uses floating point arithmetics
-/// for the transposing.
-class LinearTransposerFloat : public LinearTransposerBase
-{
-protected:
- float fSlopeCount;
- SAMPLETYPE *sPrevSample;
-
- virtual void resetRegisters();
-
- virtual int transposeStereo(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples);
- virtual int transposeMono(SAMPLETYPE *dest,
- const SAMPLETYPE *src,
- uint numSamples);
- virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples);
-
-public:
- LinearTransposerFloat();
- virtual ~LinearTransposerFloat();
-};
-
-
-TransposerBase::TransposerBase()
-{
- numChannels = 0;
- rate = 1.0f;
-}
-
-
-TransposerBase::~TransposerBase()
-{
-}
-
-
-void TransposerBase::setChannels(int channels)
-{
- numChannels = channels;
- resetRegisters();
-}
-
-
-void TransposerBase::setRate(float newRate)
-{
- rate = newRate;
-}
-
-
-// Operator 'new' is overloaded so that it automatically creates a suitable instance
-// depending on if we've a MMX/SSE/etc-capable CPU available or not.
-/*
-void * RateTransposer::operator new(size_t s)
-{
- ST_THROW_RT_ERROR("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
- return newInstance();
-}
-*/
-
-
-TransposerBase *TransposerBase::newInstance()
-{
-#ifdef SOUNDTOUCH_INTEGER_SAMPLES
- return ::new LinearTransposerInteger;
-#else
- return ::new LinearTransposerFloat;
-#endif
-}
-
-
// Constructor
RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
{
@@ -231,22 +114,6 @@ void RateTransposer::setRate(float newRate)
}
-// Outputs as many samples of the 'outputBuffer' as possible, and if there's
-// any room left, outputs also as many of the incoming samples as possible.
-// The goal is to drive the outputBuffer empty.
-//
-// It's allowed for 'output' and 'input' parameters to point to the same
-// memory position.
-/*
-void RateTransposer::flushinputBuffer()
-{
- if (inputBuffer.isEmpty()) return;
-
- outputBuffer.moveSamples(inputBuffer);
-}
-*/
-
-
// Adds 'nSamples' pcs of samples from the 'samples' memory position into
// the input of the object.
void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
@@ -305,37 +172,6 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
}
-// Transposes the sample rate of the given samples using linear interpolation.
-// Returns the number of samples returned in the "dest" buffer
-int LinearTransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
-{
- int numSrcSamples = src.numSamples();
- int sizeDemand = (int)((float)numSrcSamples / rate) + 8;
- int numOutput;
- SAMPLETYPE *psrc = src.ptrBegin();
- SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
-
-#ifndef USE_MULTICH_ALWAYS
- if (numChannels == 1)
- {
- numOutput = transposeMono(pdest, psrc, numSrcSamples);
- }
- else if (numChannels == 2)
- {
- numOutput = transposeStereo(pdest, psrc, numSrcSamples);
- }
- else
-#endif // USE_MULTICH_ALWAYS
- {
- assert(numChannels > 0);
- numOutput = transposeMulti(pdest, psrc, numSrcSamples);
- }
- dest.putSamples(numOutput);
- src.receiveSamples(numOutput);
- return numOutput;
-}
-
-
// Sets the number of channels, 1 = mono, 2 = stereo
void RateTransposer::setChannels(int nChannels)
{
@@ -372,381 +208,97 @@ int RateTransposer::isEmpty() const
//////////////////////////////////////////////////////////////////////////////
//
-// LinearTransposerInteger - integer arithmetic implementation
+// TransposerBase - Base class for interpolation
//
-/// fixed-point interpolation routine precision
-#define SCALE 65536
-
-// Constructor
-LinearTransposerInteger::LinearTransposerInteger() : LinearTransposerBase()
-{
- // Notice: use local function calling syntax for sake of clarity,
- // to indicate the fact that C++ constructor can't call virtual functions.
- sPrevSample=0;
- resetRegisters();
- setRate(1.0f);
-}
-
-
-LinearTransposerInteger::~LinearTransposerInteger()
-{
- if (sPrevSample) delete[] sPrevSample;
-}
-
-
-void LinearTransposerInteger::resetRegisters()
-{
- iSlopeCount = 0;
- delete[] sPrevSample;
- sPrevSample = new SAMPLETYPE[numChannels];
- memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE));
-}
-
+// Initialize default algorithm
+TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
-// 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 LinearTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
+// static function to set interpolation algorithm
+void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
{
- int i, remain;
- LONG_SAMPLETYPE temp, vol1;
-
- if (nSamples == 0) return 0; // no samples, no work
-
- remain = nSamples - 1;
- i = 0;
-
- // Process the last sample saved from the previous call first...
- while (iSlopeCount <= SCALE)
- {
- vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
- temp = vol1 * sPrevSample[0] + iSlopeCount * src[0];
- dest[i] = (SAMPLETYPE)(temp / SCALE);
- i++;
- iSlopeCount += iRate;
- }
- // now always (iSlopeCount > SCALE)
- iSlopeCount -= SCALE;
-
- while (1)
- {
- while (iSlopeCount > SCALE)
- {
- iSlopeCount -= SCALE;
- src ++;
- remain --;
- if (remain == 0) goto end;
- }
- vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
- temp = src[0] * vol1 + iSlopeCount * src[1];
- dest[i] = (SAMPLETYPE)(temp / SCALE);
-
- i++;
- iSlopeCount += iRate;
- }
-end:
- // Store the last sample for the next round
- sPrevSample[0] = src[0];
-
- return i;
+ TransposerBase::algorithm = a;
}
// 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 LinearTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
+// Returns the number of samples returned in the "dest" buffer
+int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
{
- int i, remain;
- LONG_SAMPLETYPE temp, vol1;
-
- if (nSamples == 0) return 0; // no samples, no work
-
- remain = nSamples - 1;
- i = 0;
-
- // Process the last sample saved from the sPrevSampleLious call first...
- while (iSlopeCount <= SCALE)
- {
- vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
- temp = vol1 * sPrevSample[0] + iSlopeCount * src[0];
- dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
- temp = vol1 * sPrevSample[1] + iSlopeCount * src[1];
- dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
- i++;
- iSlopeCount += iRate;
- }
- // now always (iSlopeCount > SCALE)
- iSlopeCount -= SCALE;
+ int numSrcSamples = src.numSamples();
+ int sizeDemand = (int)((float)numSrcSamples / rate) + 8;
+ int numOutput;
+ SAMPLETYPE *psrc = src.ptrBegin();
+ SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
- while (1)
+#ifndef USE_MULTICH_ALWAYS
+ if (numChannels == 1)
{
- while (iSlopeCount > SCALE)
- {
- iSlopeCount -= SCALE;
- remain --;
- src += 2;
- if (remain == 0) goto end;
- }
- vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
- temp = src[0] * vol1 + iSlopeCount * src[2];
- dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
- temp = src[1] * vol1 + iSlopeCount * src[3];
- dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
-
- i++;
- iSlopeCount += iRate;
+ numOutput = transposeMono(pdest, psrc, numSrcSamples);
}
-end:
- // Store the last sample for the next round
- sPrevSample[0] = src[0];
- sPrevSample[1] = src[1];
-
- return i;
-}
-
-
-int LinearTransposerInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
-{
- int i, remaining;
- LONG_SAMPLETYPE temp, vol1;
-
- if (nSamples == 0) return 0; // no samples, no work
-
- remaining = nSamples - 1;
- i = 0;
-
- // Process the last sample saved from the sPrevSampleLious call first...
- while (iSlopeCount <= SCALE)
+ else if (numChannels == 2)
{
- for (int c = 0; c < numChannels; c ++)
- {
- vol1 = (SCALE - iSlopeCount);
- temp = vol1 * sPrevSample[c] + iSlopeCount * src[c];
- *dest = (SAMPLETYPE)(temp / SCALE);
- dest ++;
- }
- i++;
-
- iSlopeCount += iRate;
- }
- // now always (iSlopeCount > SCALE)
- iSlopeCount -= SCALE;
-
- while (1)
+ numOutput = transposeStereo(pdest, psrc, numSrcSamples);
+ }
+ else
+#endif // USE_MULTICH_ALWAYS
{
- while (iSlopeCount > SCALE)
- {
- iSlopeCount -= SCALE;
- src += numChannels;
- remaining --;
- if (remaining == 0) goto end;
- }
-
- for (int c = 0; c < numChannels; c ++)
- {
- vol1 = (SCALE - iSlopeCount);
- temp = src[c] * vol1 + iSlopeCount * src[c + numChannels];
- *dest = (SAMPLETYPE)(temp / SCALE);
- dest++;
- }
-
- i++;
- iSlopeCount += iRate;
+ assert(numChannels > 0);
+ numOutput = transposeMulti(pdest, psrc, numSrcSamples);
}
-end:
- // Store the last sample for the next round
- memcpy(sPrevSample, src, numChannels * sizeof(SAMPLETYPE));
-
- return i;
-}
-
-// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
-// iRate, larger faster iRates.
-void LinearTransposerInteger::setRate(float newRate)
-{
- iRate = (int)(newRate * SCALE + 0.5f);
- TransposerBase::setRate(newRate);
+ dest.putSamples(numOutput);
+ src.receiveSamples(numSrcSamples);
+ return numOutput;
}
-//////////////////////////////////////////////////////////////////////////////
-//
-// LinearTransposerFloat - floating point arithmetic implementation
-//
-//////////////////////////////////////////////////////////////////////////////
-
-// Constructor
-LinearTransposerFloat::LinearTransposerFloat() : LinearTransposerBase()
+TransposerBase::TransposerBase()
{
- // Notice: use local function calling syntax for sake of clarity,
- // to indicate the fact that C++ constructor can't call virtual functions.
- sPrevSample = NULL;
- resetRegisters();
- setRate(1.0f);
+ numChannels = 0;
+ rate = 1.0f;
}
-LinearTransposerFloat::~LinearTransposerFloat()
+TransposerBase::~TransposerBase()
{
- delete[] sPrevSample;
}
-void LinearTransposerFloat::resetRegisters()
+void TransposerBase::setChannels(int channels)
{
- fSlopeCount = 0;
- delete[] sPrevSample;
- sPrevSample = new SAMPLETYPE[numChannels];
- memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE));
+ numChannels = channels;
+ resetRegisters();
}
-
-// 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 LinearTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
+void TransposerBase::setRate(float newRate)
{
- int i, remain;
-
- remain = nSamples - 1;
- i = 0;
-
- // Process the last sample saved from the previous call first...
- while (fSlopeCount <= 1.0f)
- {
- dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]);
- i++;
- fSlopeCount += rate;
- }
- fSlopeCount -= 1.0f;
-
- if (nSamples > 1)
- {
- while (1)
- {
- while (fSlopeCount > 1.0f)
- {
- fSlopeCount -= 1.0f;
- src ++;
- remain --;
- if (remain == 0) goto end;
- }
- dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[0] + fSlopeCount * src[1]);
- i++;
- fSlopeCount += rate;
- }
- }
-end:
- // Store the last sample for the next round
- sPrevSample[0] = src[0];
-
- return i;
+ rate = newRate;
}
-// 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 LinearTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
+// static factory function
+TransposerBase *TransposerBase::newInstance()
{
- int i, remain;
-
- if (nSamples == 0) return 0; // no samples, no work
-
- remain = nSamples - 1;
- i = 0;
-
- // Process the last sample saved from the sPrevSampleLious call first...
- while (fSlopeCount <= 1.0f)
- {
- dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]);
- dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[1] + fSlopeCount * src[1]);
- i++;
- fSlopeCount += rate;
- }
- // now always (iSlopeCount > 1.0f)
- fSlopeCount -= 1.0f;
-
- if (nSamples > 1)
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
+ // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus)
+ return ::new InterpolateLinearInteger;
+#else
+ switch (algorithm)
{
- while (1)
- {
- while (fSlopeCount > 1.0f)
- {
- fSlopeCount -= 1.0f;
- remain --;
- src += 2;
- if (remain == 0) goto end;
- }
-
- dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[0]
- + fSlopeCount * src[2]);
- dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[1]
- + fSlopeCount * src[3]);
-
- i++;
- fSlopeCount += rate;
- }
- }
-end:
- // Store the last sample for the next round
- sPrevSample[0] = src[0];
- sPrevSample[1] = src[1];
-
- return i;
-}
-
-int LinearTransposerFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
-{
- int i, remaining;
-
- if (nSamples == 0) return 0; // no samples, no work
+ case LINEAR:
+ return new InterpolateLinearFloat;
- remaining = nSamples - 1;
- i = 0;
+ case CUBIC:
+ return new InterpolateCubic;
- // Process the last sample saved from the sPrevSampleLious call first...
- while (fSlopeCount <= 1.0f)
- {
- for (int c = 0; c < numChannels; c ++)
- {
- *dest = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[c] + fSlopeCount * src[c]);
- dest ++;
- }
- i++;
- fSlopeCount += rate;
- }
- // now always (iSlopeCount > 1.0f)
- fSlopeCount -= 1.0f;
+ case SHANNON:
+ return new InterpolateShannon;
- while (remaining > 0)
- {
- while (fSlopeCount > 1.0f)
- {
- fSlopeCount -= 1.0f;
- src += numChannels;
- remaining --;
- if (remaining == 0) goto end;
- }
-
- for (int c = 0; c < numChannels; c ++)
- {
- *dest = (SAMPLETYPE)((1.0f - fSlopeCount) * src[c]
- + fSlopeCount * src[c + numChannels]);
- dest++;
- }
-
- i++;
- fSlopeCount += rate;
+ default:
+ assert(false);
+ return NULL;
}
-
-end:
- // Store the last sample for the next round
- memcpy(sPrevSample, src, numChannels * sizeof(SAMPLETYPE));
-
- return i;
+#endif
}
diff --git a/source/SoundTouch/RateTransposer.h b/source/SoundTouch/RateTransposer.h
index 81e9ca5..adf79dc 100644
--- a/source/SoundTouch/RateTransposer.h
+++ b/source/SoundTouch/RateTransposer.h
@@ -58,9 +58,28 @@ namespace soundtouch
/// Abstract base class for transposer implementations (linear, advanced vs integer, float etc)
class TransposerBase
{
+public:
+ enum ALGORITHM {
+ LINEAR = 0,
+ CUBIC,
+ SHANNON
+ };
+
protected:
virtual void resetRegisters() = 0;
+ virtual int transposeMono(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples) = 0;
+ virtual int transposeStereo(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples) = 0;
+ virtual int transposeMulti(SAMPLETYPE *dest,
+ const SAMPLETYPE *src,
+ int &srcSamples) = 0;
+
+ static ALGORITHM algorithm;
+
public:
float rate;
int numChannels;
@@ -68,10 +87,15 @@ public:
TransposerBase();
virtual ~TransposerBase();
- virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) = 0;
+ virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
virtual void setRate(float newRate);
virtual void setChannels(int channels);
+
+ // static factory function
static TransposerBase *newInstance();
+
+ // static function to set interpolation algorithm
+ static void setAlgorithm(ALGORITHM a);
};
diff --git a/source/SoundTouch/SoundTouch.vcproj b/source/SoundTouch/SoundTouch.vcproj
index 56d0651..437190a 100644
--- a/source/SoundTouch/SoundTouch.vcproj
+++ b/source/SoundTouch/SoundTouch.vcproj
@@ -49,6 +49,7 @@
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Release/SoundTouch.pch"
AssemblerListingLocation=".\Release/"
@@ -124,6 +125,7 @@
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
+ FloatingPointModel="2"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=".\Debug/SoundTouch.pch"
AssemblerListingLocation=".\Debug/"
@@ -257,6 +259,28 @@
BrowseInformation="1"
/>
</FileConfiguration>
+ <FileConfiguration
+ Name="debug release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\InterpolateCubic.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\InterpolateLinear.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\InterpolateShannon.cpp"
+ >
</File>
<File
RelativePath=".\mmx_optimized.cpp"
@@ -386,6 +410,18 @@
>
</File>
<File
+ RelativePath=".\InterpolateCubic.h"
+ >
+ </File>
+ <File
+ RelativePath=".\InterpolateLinear.h"
+ >
+ </File>
+ <File
+ RelativePath=".\InterpolateShannon.h"
+ >
+ </File>
+ <File
RelativePath=".\PeakFinder.h"
>
</File>