mirror of
https://github.com/azahar-emu/soundtouch
synced 2025-11-07 15:40:04 +01:00
Compare commits
No commits in common. "master" and "2.3.3" have entirely different histories.
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
project(SoundTouch VERSION 2.3.3 LANGUAGES CXX)
|
project(SoundTouch VERSION 2.3.3 LANGUAGES CXX)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
@ -13,8 +13,7 @@ else()
|
|||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
list(APPEND COMPILE_OPTIONS -O3)
|
list(APPEND COMPILE_OPTIONS -O3)
|
||||||
else()
|
else()
|
||||||
# Apply -ffast-math to allow compiler autovectorization generate effective SIMD code for arm compilation
|
list(APPEND COMPILE_OPTIONS -Ofast)
|
||||||
list(APPEND COMPILE_OPTIONS -O3 -ffast-math)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -97,7 +96,6 @@ install(
|
|||||||
include/soundtouch_config.h
|
include/soundtouch_config.h
|
||||||
DESTINATION
|
DESTINATION
|
||||||
"${CMAKE_INSTALL_INCLUDEDIR}/soundtouch"
|
"${CMAKE_INSTALL_INCLUDEDIR}/soundtouch"
|
||||||
COMPONENT SoundTouch
|
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS SoundTouch
|
install(TARGETS SoundTouch
|
||||||
@ -106,7 +104,6 @@ install(TARGETS SoundTouch
|
|||||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
COMPONENT SoundTouch
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
@ -129,7 +126,6 @@ if(SOUNDSTRETCH)
|
|||||||
|
|
||||||
install(TARGETS soundstretch
|
install(TARGETS soundstretch
|
||||||
DESTINATION bin
|
DESTINATION bin
|
||||||
COMPONENT soundstretch
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -148,8 +144,8 @@ if(SOUNDTOUCH_DLL)
|
|||||||
target_compile_definitions(SoundTouchDLL PRIVATE DLL_EXPORTS)
|
target_compile_definitions(SoundTouchDLL PRIVATE DLL_EXPORTS)
|
||||||
target_include_directories(SoundTouchDLL PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
target_include_directories(SoundTouchDLL PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||||
target_link_libraries(SoundTouchDLL PRIVATE SoundTouch)
|
target_link_libraries(SoundTouchDLL PRIVATE SoundTouch)
|
||||||
install(FILES source/SoundTouchDLL/SoundTouchDLL.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/soundtouch" COMPONENT SoundTouchDLL)
|
install(FILES source/SoundTouchDLL/SoundTouchDLL.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/soundtouch")
|
||||||
install(TARGETS SoundTouchDLL EXPORT SoundTouchTargets COMPONENT SoundTouchDLL)
|
install(TARGETS SoundTouchDLL EXPORT SoundTouchTargets)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
########################
|
########################
|
||||||
@ -161,7 +157,7 @@ set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
|
|||||||
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
set(VERSION "${CMAKE_PROJECT_VERSION}")
|
set(VERSION "${CMAKE_PROJECT_VERSION}")
|
||||||
configure_file(soundtouch.pc.in "${CMAKE_CURRENT_BINARY_DIR}/soundtouch.pc" @ONLY)
|
configure_file(soundtouch.pc.in "${CMAKE_CURRENT_BINARY_DIR}/soundtouch.pc" @ONLY)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/soundtouch.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT SoundTouch)
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/soundtouch.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
|
||||||
# CMake config
|
# CMake config
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
@ -171,7 +167,6 @@ install(
|
|||||||
FILE SoundTouchTargets.cmake
|
FILE SoundTouchTargets.cmake
|
||||||
NAMESPACE SoundTouch::
|
NAMESPACE SoundTouch::
|
||||||
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
|
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
|
||||||
COMPONENT SoundTouch
|
|
||||||
)
|
)
|
||||||
configure_package_config_file(SoundTouchConfig.cmake.in
|
configure_package_config_file(SoundTouchConfig.cmake.in
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
|
||||||
@ -187,5 +182,4 @@ install(
|
|||||||
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfigVersion.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfigVersion.cmake"
|
||||||
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
|
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
|
||||||
COMPONENT SoundTouch
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -205,7 +205,7 @@
|
|||||||
separate mono channels, this isn't recommended because processing the
|
separate mono channels, this isn't recommended because processing the
|
||||||
channels separately would result in losing the phase coherency between
|
channels separately would result in losing the phase coherency between
|
||||||
the channels, which consequently would ruin the stereo effect.</p>
|
the channels, which consequently would ruin the stereo effect.</p>
|
||||||
<p>Sample rates between 8000-48000Hz are supported.</p>
|
<p>Sample rates between 8000-48000H are supported.</p>
|
||||||
<h3>3.2. Processing latency</h3>
|
<h3>3.2. Processing latency</h3>
|
||||||
<p>The processing and latency constraints of the SoundTouch library are:</p>
|
<p>The processing and latency constraints of the SoundTouch library are:</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@ -31,8 +31,9 @@ AC_DISABLE_STATIC dnl This makes libtool only build shared libs
|
|||||||
|
|
||||||
AC_LANG(C++)
|
AC_LANG(C++)
|
||||||
|
|
||||||
# Compiler flags. Apply -ffast-math to allow compiler autovectorization generate effective SIMD code for arm compilation
|
# Compiler flags. Apply -Ofast (implies -O3 -ffast-math) to allow gcc autovectorization
|
||||||
CXXFLAGS="${CXXFLAGS} -O3 -ffast-math -Wall -Wextra -Wzero-as-null-pointer-constant -Wno-unknown-pragmas"
|
# generate effective SIMD code.
|
||||||
|
CXXFLAGS="${CXXFLAGS} -Ofast -Wall -Wextra -Wzero-as-null-pointer-constant -Wno-unknown-pragmas"
|
||||||
|
|
||||||
# Set AR_FLAGS to avoid build warning "ar: `u' modifier ignored since `D' is the default (see `U')"
|
# Set AR_FLAGS to avoid build warning "ar: `u' modifier ignored since `D' is the default (see `U')"
|
||||||
AR_FLAGS='cr'
|
AR_FLAGS='cr'
|
||||||
|
|||||||
@ -56,9 +56,8 @@ typedef unsigned long ulong;
|
|||||||
|
|
||||||
namespace soundtouch
|
namespace soundtouch
|
||||||
{
|
{
|
||||||
/// Max allowed number of channels. This is not a hard limit but to have some
|
/// Max allowed number of channels
|
||||||
/// maximum value for argument sanity checks -- can be increased if necessary
|
#define SOUNDTOUCH_MAX_CHANNELS 16
|
||||||
#define SOUNDTOUCH_MAX_CHANNELS 32
|
|
||||||
|
|
||||||
/// Activate these undef's to overrule the possible sampletype
|
/// Activate these undef's to overrule the possible sampletype
|
||||||
/// setting inherited from some other header file:
|
/// setting inherited from some other header file:
|
||||||
|
|||||||
@ -199,7 +199,7 @@ void RunParameters::throwLicense() const
|
|||||||
ST_THROW_RT_ERROR(licenseText);
|
ST_THROW_RT_ERROR(licenseText);
|
||||||
}
|
}
|
||||||
|
|
||||||
double RunParameters::parseSwitchValue(const STRING& str) const
|
float RunParameters::parseSwitchValue(const STRING& str) const
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ double RunParameters::parseSwitchValue(const STRING& str) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read numerical parameter value after '='
|
// Read numerical parameter value after '='
|
||||||
return stof(str.substr(pos + 1).c_str());
|
return (float)stof(str.substr(pos + 1).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -48,17 +48,17 @@ private:
|
|||||||
void throwLicense() const;
|
void throwLicense() const;
|
||||||
void parseSwitchParam(const STRING& str);
|
void parseSwitchParam(const STRING& str);
|
||||||
void checkLimits();
|
void checkLimits();
|
||||||
double parseSwitchValue(const STRING& tr) const;
|
float parseSwitchValue(const STRING& tr) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STRING inFileName;
|
STRING inFileName;
|
||||||
STRING outFileName;
|
STRING outFileName;
|
||||||
double tempoDelta{ 0 };
|
float tempoDelta{ 0 };
|
||||||
double pitchDelta{ 0 };
|
float pitchDelta{ 0 };
|
||||||
double rateDelta{ 0 };
|
float rateDelta{ 0 };
|
||||||
int quick{ 0 };
|
int quick{ 0 };
|
||||||
int noAntiAlias{ 0 };
|
int noAntiAlias{ 0 };
|
||||||
double goalBPM{ 0 };
|
float goalBPM{ 0 };
|
||||||
bool detectBPM{ false };
|
bool detectBPM{ false };
|
||||||
bool speech{ false };
|
bool speech{ false };
|
||||||
|
|
||||||
|
|||||||
@ -145,9 +145,9 @@ static void setup(SoundTouch& soundTouch, const WavInFile& inFile, const RunPara
|
|||||||
#endif
|
#endif
|
||||||
// print processing information only if outFileName given i.e. some processing will happen
|
// print processing information only if outFileName given i.e. some processing will happen
|
||||||
fprintf(stderr, "Processing the file with the following changes:\n");
|
fprintf(stderr, "Processing the file with the following changes:\n");
|
||||||
fprintf(stderr, " tempo change = %+lg %%\n", params.tempoDelta);
|
fprintf(stderr, " tempo change = %+g %%\n", params.tempoDelta);
|
||||||
fprintf(stderr, " pitch change = %+lg semitones\n", params.pitchDelta);
|
fprintf(stderr, " pitch change = %+g semitones\n", params.pitchDelta);
|
||||||
fprintf(stderr, " rate change = %+lg %%\n\n", params.rateDelta);
|
fprintf(stderr, " rate change = %+g %%\n\n", params.rateDelta);
|
||||||
fprintf(stderr, "Working...");
|
fprintf(stderr, "Working...");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -240,7 +240,7 @@ static void detectBPM(WavInFile& inFile, RunParameters& params)
|
|||||||
|
|
||||||
if (bpmValue > 0)
|
if (bpmValue > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Detected BPM rate %.1lf\n\n", bpmValue);
|
fprintf(stderr, "Detected BPM rate %.1f\n\n", bpmValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -252,7 +252,7 @@ static void detectBPM(WavInFile& inFile, RunParameters& params)
|
|||||||
{
|
{
|
||||||
// adjust tempo to given bpm
|
// adjust tempo to given bpm
|
||||||
params.tempoDelta = (params.goalBPM / bpmValue - 1.0f) * 100.0f;
|
params.tempoDelta = (params.goalBPM / bpmValue - 1.0f) * 100.0f;
|
||||||
fprintf(stderr, "The file will be converted to %.1lf BPM\n\n", params.goalBPM);
|
fprintf(stderr, "The file will be converted to %.1f BPM\n\n", params.goalBPM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -301,7 +301,7 @@ void BPMDetect::updateXCorr(int process_samples)
|
|||||||
pBuffer = buffer->ptrBegin();
|
pBuffer = buffer->ptrBegin();
|
||||||
|
|
||||||
// calculate decay factor for xcorr filtering
|
// calculate decay factor for xcorr filtering
|
||||||
float xcorr_decay = (float)pow(0.5, process_samples / (XCORR_DECAY_TIME_CONSTANT * TARGET_SRATE));
|
float xcorr_decay = (float)pow(0.5, 1.0 / (XCORR_DECAY_TIME_CONSTANT * TARGET_SRATE / process_samples));
|
||||||
|
|
||||||
// prescale pbuffer
|
// prescale pbuffer
|
||||||
float tmp[XCORR_UPDATE_SEQUENCE];
|
float tmp[XCORR_UPDATE_SEQUENCE];
|
||||||
|
|||||||
@ -56,6 +56,7 @@ using namespace soundtouch;
|
|||||||
FIRFilter::FIRFilter()
|
FIRFilter::FIRFilter()
|
||||||
{
|
{
|
||||||
resultDivFactor = 0;
|
resultDivFactor = 0;
|
||||||
|
resultDivider = 0;
|
||||||
length = 0;
|
length = 0;
|
||||||
lengthDiv8 = 0;
|
lengthDiv8 = 0;
|
||||||
filterCoeffs = nullptr;
|
filterCoeffs = nullptr;
|
||||||
@ -154,7 +155,7 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
|
|||||||
assert(src != nullptr);
|
assert(src != nullptr);
|
||||||
assert(dest != nullptr);
|
assert(dest != nullptr);
|
||||||
assert(filterCoeffs != nullptr);
|
assert(filterCoeffs != nullptr);
|
||||||
assert(numChannels <= SOUNDTOUCH_MAX_CHANNELS);
|
assert(numChannels < 16);
|
||||||
|
|
||||||
// hint compiler autovectorization that loop length is divisible by 8
|
// hint compiler autovectorization that loop length is divisible by 8
|
||||||
int ilength = length & -8;
|
int ilength = length & -8;
|
||||||
@ -206,24 +207,24 @@ void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint u
|
|||||||
assert(newLength > 0);
|
assert(newLength > 0);
|
||||||
if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
|
if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
|
||||||
|
|
||||||
|
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
|
||||||
|
// scale coefficients already here if using floating samples
|
||||||
|
double scale = 1.0 / resultDivider;
|
||||||
|
#else
|
||||||
|
short scale = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
lengthDiv8 = newLength / 8;
|
lengthDiv8 = newLength / 8;
|
||||||
length = lengthDiv8 * 8;
|
length = lengthDiv8 * 8;
|
||||||
assert(length == newLength);
|
assert(length == newLength);
|
||||||
|
|
||||||
resultDivFactor = uResultDivFactor;
|
resultDivFactor = uResultDivFactor;
|
||||||
|
resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
|
||||||
|
|
||||||
delete[] filterCoeffs;
|
delete[] filterCoeffs;
|
||||||
filterCoeffs = new SAMPLETYPE[length];
|
filterCoeffs = new SAMPLETYPE[length];
|
||||||
delete[] filterCoeffsStereo;
|
delete[] filterCoeffsStereo;
|
||||||
filterCoeffsStereo = new SAMPLETYPE[length*2];
|
filterCoeffsStereo = new SAMPLETYPE[length*2];
|
||||||
|
|
||||||
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
|
|
||||||
// scale coefficients already here if using floating samples
|
|
||||||
const double scale = ::pow(0.5, (int)resultDivFactor);;
|
|
||||||
#else
|
|
||||||
const short scale = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (uint i = 0; i < length; i ++)
|
for (uint i = 0; i < length; i ++)
|
||||||
{
|
{
|
||||||
filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale);
|
filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale);
|
||||||
|
|||||||
@ -52,6 +52,9 @@ protected:
|
|||||||
// Result divider factor in 2^k format
|
// Result divider factor in 2^k format
|
||||||
uint resultDivFactor;
|
uint resultDivFactor;
|
||||||
|
|
||||||
|
// Result divider value.
|
||||||
|
SAMPLETYPE resultDivider;
|
||||||
|
|
||||||
// Memory for filter coefficients
|
// Memory for filter coefficients
|
||||||
SAMPLETYPE *filterCoeffs;
|
SAMPLETYPE *filterCoeffs;
|
||||||
SAMPLETYPE *filterCoeffsStereo;
|
SAMPLETYPE *filterCoeffsStereo;
|
||||||
|
|||||||
@ -211,6 +211,9 @@ FIRFilterSSE::~FIRFilterSSE()
|
|||||||
// (overloaded) Calculates filter coefficients for SSE routine
|
// (overloaded) Calculates filter coefficients for SSE routine
|
||||||
void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor)
|
void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor)
|
||||||
{
|
{
|
||||||
|
uint i;
|
||||||
|
float fDivider;
|
||||||
|
|
||||||
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
|
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
|
||||||
|
|
||||||
// Scale the filter coefficients so that it won't be necessary to scale the filtering result
|
// Scale the filter coefficients so that it won't be necessary to scale the filtering result
|
||||||
@ -220,13 +223,13 @@ void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uRe
|
|||||||
filterCoeffsUnalign = new float[2 * newLength + 4];
|
filterCoeffsUnalign = new float[2 * newLength + 4];
|
||||||
filterCoeffsAlign = (float *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign);
|
filterCoeffsAlign = (float *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign);
|
||||||
|
|
||||||
const float scale = ::pow(0.5, (int)resultDivFactor);
|
fDivider = (float)resultDivider;
|
||||||
|
|
||||||
// rearrange the filter coefficients for sse routines
|
// rearrange the filter coefficients for mmx routines
|
||||||
for (auto i = 0U; i < newLength; i ++)
|
for (i = 0; i < newLength; i ++)
|
||||||
{
|
{
|
||||||
filterCoeffsAlign[2 * i + 0] =
|
filterCoeffsAlign[2 * i + 0] =
|
||||||
filterCoeffsAlign[2 * i + 1] = coeffs[i] * scale;
|
filterCoeffsAlign[2 * i + 1] = coeffs[i + 0] / fDivider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user