mirror of
https://github.com/azahar-emu/soundtouch
synced 2025-11-16 20:10:05 +01:00
Implemented separate Cubic, Linear and Shannon interpolation algorithms.
This commit is contained in:
parent
abfeb3fcc9
commit
a09135884a
@ -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/"
|
||||
|
||||
200
source/SoundTouch/InterpolateCubic.cpp
Normal file
200
source/SoundTouch/InterpolateCubic.cpp
Normal file
@ -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;
|
||||
}
|
||||
67
source/SoundTouch/InterpolateCubic.h
Normal file
67
source/SoundTouch/InterpolateCubic.h
Normal file
@ -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
|
||||
250
source/SoundTouch/InterpolateLinear.cpp
Normal file
250
source/SoundTouch/InterpolateLinear.cpp
Normal file
@ -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;
|
||||
}
|
||||
92
source/SoundTouch/InterpolateLinear.h
Normal file
92
source/SoundTouch/InterpolateLinear.h
Normal file
@ -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
|
||||
185
source/SoundTouch/InterpolateShannon.cpp
Normal file
185
source/SoundTouch/InterpolateShannon.cpp
Normal file
@ -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;
|
||||
}
|
||||
72
source/SoundTouch/InterpolateShannon.h
Normal file
72
source/SoundTouch/InterpolateShannon.h
Normal file
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
// 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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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"
|
||||
@ -385,6 +409,18 @@
|
||||
RelativePath="FIRFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\InterpolateCubic.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\InterpolateLinear.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\InterpolateShannon.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PeakFinder.h"
|
||||
>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user