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" > @@ -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 +#include +#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 +#include +#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 +#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 #include #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 +// Initialize default algorithm +TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC; -// Constructor -LinearTransposerInteger::LinearTransposerInteger() : LinearTransposerBase() + +// static function to set interpolation algorithm +void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a) { - // Notice: use local function calling syntax for sake of clarity, - // to indicate the fact that C++ constructor can't call virtual functions. - sPrevSample=0; + TransposerBase::algorithm = a; +} + + +// Transposes the sample rate of the given samples using linear interpolation. +// Returns the number of samples returned in the "dest" buffer +int TransposerBase::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(numSrcSamples); + return numOutput; +} + + +TransposerBase::TransposerBase() +{ + numChannels = 0; + rate = 1.0f; +} + + +TransposerBase::~TransposerBase() +{ +} + + +void TransposerBase::setChannels(int channels) +{ + numChannels = channels; resetRegisters(); - setRate(1.0f); } -LinearTransposerInteger::~LinearTransposerInteger() +void TransposerBase::setRate(float newRate) { - if (sPrevSample) delete[] sPrevSample; + rate = newRate; } -void LinearTransposerInteger::resetRegisters() +// static factory function +TransposerBase *TransposerBase::newInstance() { - iSlopeCount = 0; - delete[] sPrevSample; - sPrevSample = new SAMPLETYPE[numChannels]; - memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE)); -} - - - -// 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) -{ - 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; -} - - -// 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) -{ - 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; - - while (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; - } -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) - { - 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) - { - 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; - } -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); -} - - -////////////////////////////////////////////////////////////////////////////// -// -// LinearTransposerFloat - floating point arithmetic implementation -// -////////////////////////////////////////////////////////////////////////////// - -// Constructor -LinearTransposerFloat::LinearTransposerFloat() : LinearTransposerBase() -{ - // 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); -} - - -LinearTransposerFloat::~LinearTransposerFloat() -{ - delete[] sPrevSample; -} - - -void LinearTransposerFloat::resetRegisters() -{ - fSlopeCount = 0; - delete[] sPrevSample; - sPrevSample = new SAMPLETYPE[numChannels]; - memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE)); -} - - - -// 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) -{ - 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; -} - - -// 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) -{ - 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) - { - 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 - - remaining = nSamples - 1; - i = 0; - - // 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; - - 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; - } - -end: - // Store the last sample for the next round - memcpy(sPrevSample, src, numChannels * sizeof(SAMPLETYPE)); - - return i; +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus) + return ::new InterpolateLinearInteger; +#else + switch (algorithm) + { + case LINEAR: + return new InterpolateLinearFloat; + + case CUBIC: + return new InterpolateCubic; + + case SHANNON: + return new InterpolateShannon; + + default: + assert(false); + return NULL; + } +#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" /> + + + + + + + + + + + + + + +