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"
|
Version="9.00"
|
||||||
Name="soundstretch"
|
Name="soundstretch"
|
||||||
ProjectGUID="{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}"
|
ProjectGUID="{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}"
|
||||||
|
RootNamespace="soundstretch"
|
||||||
TargetFrameworkVersion="131072"
|
TargetFrameworkVersion="131072"
|
||||||
>
|
>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
@ -49,6 +50,7 @@
|
|||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
StructMemberAlignment="5"
|
StructMemberAlignment="5"
|
||||||
|
FloatingPointModel="2"
|
||||||
PrecompiledHeaderFile=".\Debug/soundstretch.pch"
|
PrecompiledHeaderFile=".\Debug/soundstretch.pch"
|
||||||
AssemblerListingLocation=".\Debug/"
|
AssemblerListingLocation=".\Debug/"
|
||||||
ObjectFile=".\Debug/"
|
ObjectFile=".\Debug/"
|
||||||
@ -147,6 +149,7 @@
|
|||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
|
FloatingPointModel="2"
|
||||||
PrecompiledHeaderFile=".\Release/soundstretch.pch"
|
PrecompiledHeaderFile=".\Release/soundstretch.pch"
|
||||||
AssemblerListingLocation=".\Release/"
|
AssemblerListingLocation=".\Release/"
|
||||||
ObjectFile=".\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
|
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
|
# Compiler flags
|
||||||
AM_CXXFLAGS=-O3 -fcheck-new -I../../include
|
AM_CXXFLAGS=-O3 -fcheck-new -I../../include
|
||||||
|
|||||||
@ -43,131 +43,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "RateTransposer.h"
|
#include "RateTransposer.h"
|
||||||
|
#include "InterpolateLinear.h"
|
||||||
|
#include "InterpolateCubic.h"
|
||||||
|
#include "InterpolateShannon.h"
|
||||||
#include "AAFilter.h"
|
#include "AAFilter.h"
|
||||||
|
|
||||||
using namespace soundtouch;
|
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
|
// Constructor
|
||||||
RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
|
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
|
// Adds 'nSamples' pcs of samples from the 'samples' memory position into
|
||||||
// the input of the object.
|
// the input of the object.
|
||||||
void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
|
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
|
// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
void RateTransposer::setChannels(int nChannels)
|
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
|
// Initialize default algorithm
|
||||||
#define SCALE 65536
|
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,
|
TransposerBase::algorithm = a;
|
||||||
// to indicate the fact that C++ constructor can't call virtual functions.
|
}
|
||||||
sPrevSample=0;
|
|
||||||
|
|
||||||
|
// 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();
|
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;
|
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||||
delete[] sPrevSample;
|
// Notice: For integer arithmetics support only linear algorithm (due to simplest calculus)
|
||||||
sPrevSample = new SAMPLETYPE[numChannels];
|
return ::new InterpolateLinearInteger;
|
||||||
memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE));
|
#else
|
||||||
}
|
switch (algorithm)
|
||||||
|
{
|
||||||
|
case LINEAR:
|
||||||
|
return new InterpolateLinearFloat;
|
||||||
// Transposes the sample rate of the given samples using linear interpolation.
|
|
||||||
// 'Mono' version of the routine. Returns the number of samples returned in
|
case CUBIC:
|
||||||
// the "dest" buffer
|
return new InterpolateCubic;
|
||||||
int LinearTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
|
|
||||||
{
|
case SHANNON:
|
||||||
int i, remain;
|
return new InterpolateShannon;
|
||||||
LONG_SAMPLETYPE temp, vol1;
|
|
||||||
|
default:
|
||||||
if (nSamples == 0) return 0; // no samples, no work
|
assert(false);
|
||||||
|
return NULL;
|
||||||
remain = nSamples - 1;
|
}
|
||||||
i = 0;
|
#endif
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,9 +58,28 @@ namespace soundtouch
|
|||||||
/// Abstract base class for transposer implementations (linear, advanced vs integer, float etc)
|
/// Abstract base class for transposer implementations (linear, advanced vs integer, float etc)
|
||||||
class TransposerBase
|
class TransposerBase
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum ALGORITHM {
|
||||||
|
LINEAR = 0,
|
||||||
|
CUBIC,
|
||||||
|
SHANNON
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void resetRegisters() = 0;
|
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:
|
public:
|
||||||
float rate;
|
float rate;
|
||||||
int numChannels;
|
int numChannels;
|
||||||
@ -68,10 +87,15 @@ public:
|
|||||||
TransposerBase();
|
TransposerBase();
|
||||||
virtual ~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 setRate(float newRate);
|
||||||
virtual void setChannels(int channels);
|
virtual void setChannels(int channels);
|
||||||
|
|
||||||
|
// static factory function
|
||||||
static TransposerBase *newInstance();
|
static TransposerBase *newInstance();
|
||||||
|
|
||||||
|
// static function to set interpolation algorithm
|
||||||
|
static void setAlgorithm(ALGORITHM a);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
|
FloatingPointModel="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
PrecompiledHeaderFile=".\Release/SoundTouch.pch"
|
PrecompiledHeaderFile=".\Release/SoundTouch.pch"
|
||||||
AssemblerListingLocation=".\Release/"
|
AssemblerListingLocation=".\Release/"
|
||||||
@ -124,6 +125,7 @@
|
|||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
|
FloatingPointModel="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
PrecompiledHeaderFile=".\Debug/SoundTouch.pch"
|
PrecompiledHeaderFile=".\Debug/SoundTouch.pch"
|
||||||
AssemblerListingLocation=".\Debug/"
|
AssemblerListingLocation=".\Debug/"
|
||||||
@ -257,6 +259,28 @@
|
|||||||
BrowseInformation="1"
|
BrowseInformation="1"
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</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>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\mmx_optimized.cpp"
|
RelativePath=".\mmx_optimized.cpp"
|
||||||
@ -385,6 +409,18 @@
|
|||||||
RelativePath="FIRFilter.h"
|
RelativePath="FIRFilter.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\InterpolateCubic.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\InterpolateLinear.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\InterpolateShannon.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\PeakFinder.h"
|
RelativePath=".\PeakFinder.h"
|
||||||
>
|
>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user