Compare commits

..

1 Commits

Author SHA1 Message Date
Olli
67fec0e8d5 Bump version to 2.1 2018-09-08 17:54:14 +03:00
87 changed files with 11719 additions and 13021 deletions

15
.gitignore vendored
View File

@ -38,18 +38,3 @@ source/SoundTouchDll/Win32/
source/SoundTouchDll/x64/ source/SoundTouchDll/x64/
source/SoundTouchDll/DllTest/Win32/ source/SoundTouchDll/DllTest/Win32/
source/SoundTouchDll/DllTest/x64/ source/SoundTouchDll/DllTest/x64/
.vs
# Files generated by Android Studio
source/android-lib/.gradle
source/android-lib/.idea
**/*.iml
source/android-lib/local.properties
source/android-lib/build
source/android-lib/.externalNativeBuild
# CMake build directory
build*
CMakeFiles
CMakeCache.txt
*.cmake

View File

@ -1,191 +0,0 @@
cmake_minimum_required(VERSION 3.5)
project(SoundTouch VERSION 2.3.3 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)
set(COMPILE_OPTIONS)
if(MSVC)
set(COMPILE_DEFINITIONS /O2 /fp:fast)
else()
list(APPEND COMPILE_OPTIONS -Wall -Wextra -Wzero-as-null-pointer-constant -Wno-unknown-pragmas)
if(EMSCRIPTEN)
list(APPEND COMPILE_OPTIONS -O3)
else()
# Apply -ffast-math to allow compiler autovectorization generate effective SIMD code for arm compilation
list(APPEND COMPILE_OPTIONS -O3 -ffast-math)
endif()
endif()
#####################
# SoundTouch library
add_library(SoundTouch
source/SoundTouch/AAFilter.cpp
source/SoundTouch/BPMDetect.cpp
source/SoundTouch/cpu_detect_x86.cpp
source/SoundTouch/FIFOSampleBuffer.cpp
source/SoundTouch/FIRFilter.cpp
source/SoundTouch/InterpolateCubic.cpp
source/SoundTouch/InterpolateLinear.cpp
source/SoundTouch/InterpolateShannon.cpp
source/SoundTouch/mmx_optimized.cpp
source/SoundTouch/PeakFinder.cpp
source/SoundTouch/RateTransposer.cpp
source/SoundTouch/SoundTouch.cpp
source/SoundTouch/sse_optimized.cpp
source/SoundTouch/TDStretch.cpp
)
target_include_directories(SoundTouch PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_definitions(SoundTouch PRIVATE ${COMPILE_DEFINITIONS})
target_compile_options(SoundTouch PRIVATE ${COMPILE_OPTIONS})
if(BUILD_SHARED_LIBS)
set_target_properties(SoundTouch PROPERTIES
VERSION ${CMAKE_PROJECT_VERSION}
)
if(WIN32)
set_target_properties(SoundTouch PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS TRUE
)
else()
set_target_properties(SoundTouch PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
)
endif()
endif()
option(INTEGER_SAMPLES "Use integers instead of floats for samples" OFF)
if(INTEGER_SAMPLES)
target_compile_definitions(SoundTouch PRIVATE SOUNDTOUCH_INTEGER_SAMPLES)
else()
target_compile_definitions(SoundTouch PRIVATE SOUNDTOUCH_FLOAT_SAMPLES)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7.*|armv8.*|aarch64.*)$")
set(NEON_CPU ON)
else()
set(NEON_CPU OFF)
endif()
option(NEON "Use ARM Neon SIMD instructions if in ARM CPU" ON)
if(${NEON} AND ${NEON_CPU})
target_compile_definitions(SoundTouch PRIVATE SOUNDTOUCH_USE_NEON)
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64.*$")
target_compile_options(SoundTouch PRIVATE -mfpu=neon)
endif()
endif()
find_package(OpenMP)
option(OPENMP "Use parallel multicore calculation through OpenMP" OFF)
if(OPENMP AND OPENMP_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
install(
FILES
include/BPMDetect.h
include/FIFOSampleBuffer.h
include/FIFOSamplePipe.h
include/STTypes.h
include/SoundTouch.h
include/soundtouch_config.h
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}/soundtouch"
COMPONENT SoundTouch
)
install(TARGETS SoundTouch
EXPORT SoundTouchTargets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT SoundTouch
)
#######################
# soundstretch utility
option(SOUNDSTRETCH "Build soundstretch command line utility." ON)
if(SOUNDSTRETCH)
add_executable(soundstretch
source/SoundStretch/main.cpp
source/SoundStretch/RunParameters.cpp
source/SoundStretch/WavFile.cpp
)
target_include_directories(soundstretch PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_compile_definitions(soundstretch PRIVATE ${COMPILE_DEFINITIONS})
target_compile_options(soundstretch PRIVATE ${COMPILE_OPTIONS})
target_link_libraries(soundstretch PRIVATE SoundTouch)
if(INTEGER_SAMPLES)
target_compile_definitions(soundstretch PRIVATE SOUNDTOUCH_INTEGER_SAMPLES)
endif()
install(TARGETS soundstretch
DESTINATION bin
COMPONENT soundstretch
)
endif()
########################
# SoundTouchDll library
option(SOUNDTOUCH_DLL "Build SoundTouchDLL C wrapper library" OFF)
if(SOUNDTOUCH_DLL)
add_library(SoundTouchDLL SHARED
source/SoundTouchDLL/SoundTouchDLL.cpp
source/SoundTouchDLL/SoundTouchDLL.rc
)
set_target_properties(SoundTouch PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
target_compile_options(SoundTouchDLL PRIVATE ${COMPILE_OPTIONS})
set_target_properties(SoundTouchDLL PROPERTIES CXX_VISIBILITY_PRESET hidden)
target_compile_definitions(SoundTouchDLL PRIVATE DLL_EXPORTS)
target_include_directories(SoundTouchDLL PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries(SoundTouchDLL PRIVATE SoundTouch)
install(FILES source/SoundTouchDLL/SoundTouchDLL.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/soundtouch" COMPONENT SoundTouchDLL)
install(TARGETS SoundTouchDLL EXPORT SoundTouchTargets COMPONENT SoundTouchDLL)
endif()
########################
# pkgconfig
set(prefix "${CMAKE_INSTALL_PREFIX}")
set(execprefix "\${prefix}")
set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
set(VERSION "${CMAKE_PROJECT_VERSION}")
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)
# CMake config
include(CMakePackageConfigHelpers)
set(SOUNDTOUCH_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/SoundTouch")
install(
EXPORT SoundTouchTargets
FILE SoundTouchTargets.cmake
NAMESPACE SoundTouch::
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
COMPONENT SoundTouch
)
configure_package_config_file(SoundTouchConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
INSTALL_DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfigVersion.cmake"
VERSION "${CMAKE_PROJECT_VERSION}"
COMPATIBILITY SameMajorVersion
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/SoundTouchConfigVersion.cmake"
DESTINATION "${SOUNDTOUCH_INSTALL_CMAKEDIR}"
COMPONENT SoundTouch
)

View File

@ -2,7 +2,7 @@
Version 2.1, February 1999 Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc. Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@ -117,7 +117,7 @@ be combined with the library in order to run.
0. This License Agreement applies to any software library or other 0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of other authoried party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License"). this Lesser General Public License (also called "this License").
Each licensee is addressed as "you". Each licensee is addressed as "you".

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/SoundTouchTargets.cmake")
check_required_components(SoundTouch)
get_target_property(SoundTouch_LOCATION SoundTouch::SoundTouch LOCATION)
message(STATUS "Found SoundTouch: ${SoundTouch_LOCATION}")
if(@SOUNDTOUCH_DLL@)
check_required_components(SoundTouchDLL)
get_target_property(SoundTouchDLL_LOCATION SoundTouch::SoundTouchDLL LOCATION)
message(STATUS "Found SoundTouchDLL: ${SoundTouchDLL_LOCATION}")
endif()

View File

@ -1,8 +1,8 @@
set SOUND_DIR=c:\dev\test_sounds set SOUND_DIR=d:\dev\test_sounds
set OUT_DIR=. set OUT_DIR=.
set TEST_NAME=semmari set TEST_NAME=semmari
set OUT_NAME=out set OUT_NAME=out
set SS=soundstretch_x64 set SS=soundstretch
set TEST_PARAM=-pitch=-3 -bpm set TEST_PARAM=-pitch=-3 -bpm
call %SS% %SOUND_DIR%\%TEST_NAME%-8b1.wav %OUT_DIR%\%OUT_NAME%-8b1.wav %TEST_PARAM% call %SS% %SOUND_DIR%\%TEST_NAME%-8b1.wav %OUT_DIR%\%OUT_NAME%-8b1.wav %TEST_PARAM%

View File

@ -1,7 +1,5 @@
#!/bin/sh #!/bin/sh
unset ACLOCAL
if [ "$1" = "--clean" ] if [ "$1" = "--clean" ]
then then
if [ -a Makefile ] if [ -a Makefile ]
@ -16,6 +14,9 @@ then
rm -rf configure libtool aclocal.m4 `find . -name Makefile.in` autom4te*.cache config/config.guess config/config.h.in config/config.sub config/depcomp config/install-sh config/ltmain.sh config/missing config/mkinstalldirs config/stamp-h config/stamp-h.in rm -rf configure libtool aclocal.m4 `find . -name Makefile.in` autom4te*.cache config/config.guess config/config.h.in config/config.sub config/depcomp config/install-sh config/ltmain.sh config/missing config/mkinstalldirs config/stamp-h config/stamp-h.in
#gettextie files
#rm -f ABOUT-NLS config/config.rpath config/m4/codeset.m4 config/m4/gettext.m4 config/m4/glibc21.m4 config/m4/iconv.m4 config/m4/intdiv0.m4 config/m4/inttypes-pri.m4 config/m4/inttypes.m4 config/m4/inttypes_h.m4 config/m4/isc-posix.m4 config/m4/lcmessage.m4 config/m4/lib-ld.m4 config/m4/lib-link.m4 config/m4/lib-prefix.m4 config/m4/progtest.m4 config/m4/stdint_h.m4 config/m4/uintmax_t.m4 config/m4/ulonglong.m4 po/Makefile.in.in po/Rules-quot po/boldquot.sed po/en@boldquot.header po/en@quot.header po/insert-header.sin po/quot.sed po/remove-potcdate.sin
else else
export AUTOMAKE="automake --add-missing --foreign --copy" export AUTOMAKE="automake --add-missing --foreign --copy"
autoreconf -fisv && rm -f `find . -name "*~"` && rm -f ChangeLog autoreconf -fisv && rm -f `find . -name "*~"` && rm -f ChangeLog

View File

@ -15,25 +15,22 @@ dnl this program; if not, write to the Free Software Foundation, Inc., 59 Temple
dnl Place - Suite 330, Boston, MA 02111-1307, USA dnl Place - Suite 330, Boston, MA 02111-1307, USA
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_INIT([SoundTouch],[2.3.2],[http://www.surina.net/soundtouch]) AC_INIT([SoundTouch], [2.0.0], [http://www.surina.net/soundtouch])
dnl Default to libSoundTouch.so.$LIB_SONAME.0.0 dnl Default to libSoundTouch.so.$LIB_SONAME.0.0
LIB_SONAME=1 LIB_SONAME=1
AC_SUBST(LIB_SONAME) AC_SUBST(LIB_SONAME)
AC_CONFIG_AUX_DIR(config) AC_CONFIG_AUX_DIR(config)
AC_CONFIG_MACRO_DIR([config/m4]) AC_CONFIG_MACRO_DIR([config/m4])
AC_CONFIG_HEADERS([config.h include/soundtouch_config.h]) AM_CONFIG_HEADER([config.h include/soundtouch_config.h])
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
#AC_DISABLE_SHARED dnl This makes libtool only build static libs #AC_DISABLE_SHARED dnl This makes libtool only build static libs
AC_DISABLE_STATIC dnl This makes libtool only build shared libs AC_DISABLE_STATIC dnl This makes libtool only build shared libs
#AC_USE_SYSTEM_EXTENSIONS dnl enable posix extensions in glibc #AC_GNU_SOURCE dnl enable posix extensions in glibc
AC_LANG(C++) AC_LANG(C++)
# Compiler flags. Apply -ffast-math to allow compiler autovectorization generate effective SIMD code for arm compilation
CXXFLAGS="${CXXFLAGS} -O3 -ffast-math -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'
@ -50,7 +47,7 @@ AC_PROG_INSTALL
#AC_PROG_LN_S #AC_PROG_LN_S
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
LT_INIT dnl turn on using libtool AM_PROG_LIBTOOL dnl turn on using libtool
@ -58,11 +55,10 @@ LT_INIT dnl turn on using libtool
dnl ############################################################################ dnl ############################################################################
dnl # Checks for header files # dnl # Checks for header files #
dnl ############################################################################ dnl ############################################################################
AC_HEADER_STDC
#AC_HEADER_SYS_WAIT #AC_HEADER_SYS_WAIT
# add any others you want to check for here # add any others you want to check for here
AC_CHECK_HEADERS([cpuid.h]) AC_CHECK_HEADERS([cpuid.h])
AC_CHECK_HEADERS([arm_neon.h])
if test "x$ac_cv_header_cpuid_h" = "xno"; then if test "x$ac_cv_header_cpuid_h" = "xno"; then
AC_MSG_WARN([The cpuid.h file was not found therefore the x86 optimizations will be disabled.]) AC_MSG_WARN([The cpuid.h file was not found therefore the x86 optimizations will be disabled.])
@ -81,34 +77,31 @@ AC_C_INLINE
AC_ARG_ENABLE(integer-samples, AC_ARG_ENABLE(integer-samples,
[AS_HELP_STRING([--enable-integer-samples],[use integer samples instead of floats [default=no]])],, [AC_HELP_STRING([--enable-integer-samples],
[use integer samples instead of floats
[default=no]])],,
[enable_integer_samples=no]) [enable_integer_samples=no])
AC_ARG_ENABLE(openmp, AC_ARG_ENABLE(openmp,
[AS_HELP_STRING([--enable-openmp],[use parallel multicore calculation through OpenMP [default=no]])],, [AC_HELP_STRING([--enable-openmp],
[use parallel multicore calculation through OpenMP [default=no]])],,
[enable_openmp=no]) [enable_openmp=no])
# Let the user enable/disable the x86 optimizations. # Let the user enable/disable the x86 optimizations.
# Useful when compiling on non-x86 architectures. # Useful when compiling on non-x86 architectures.
AC_ARG_ENABLE([x86-optimizations], AC_ARG_ENABLE([x86-optimizations],
[AS_HELP_STRING([--enable-x86-optimizations], [AS_HELP_STRING([--enable-x86-optimizations],
[use MMX or SSE optimization [default=yes]])],[enable_x86_optimizations="${enableval}"], [use MMX or SSE optimization
[default=yes]])],[enable_x86_optimizations="${enableval}"],
[enable_x86_optimizations=yes]) [enable_x86_optimizations=yes])
# Let the user enable/disable the x86 optimizations.
# Useful when compiling on non-x86 architectures.
AC_ARG_ENABLE([neon-optimizations],
[AS_HELP_STRING([--enable-neon-optimizations],
[use ARM NEON optimization [default=yes]])],[enable_neon_optimizations="${enableval}"],
[enable_neon_optimizations=yes])
# Tell the Makefile.am if the user wants to disable optimizations. # Tell the Makefile.am if the user wants to disable optimizations.
# Makefile.am will enable them by default if support is available. # Makefile.am will enable them by default if support is available.
# Note: We check if optimizations are supported a few lines down. # Note: We check if optimizations are supported a few lines down.
AM_CONDITIONAL([X86_OPTIMIZATIONS], [test "x$enable_x86_optimizations" = "xyes"]) AM_CONDITIONAL([X86_OPTIMIZATIONS], [test "x$enable_x86_optimizations" = "xyes"])
if test "x$enable_integer_samples" = "xyes"; then if test "x$enable_integer_samples" = "xyes"; then
echo "****** Integer sample type enabled ******" echo "****** Integer sample type enabled ******"
AC_DEFINE(SOUNDTOUCH_INTEGER_SAMPLES,1,[Use Integer as Sample type]) AC_DEFINE(SOUNDTOUCH_INTEGER_SAMPLES,1,[Use Integer as Sample type])
@ -116,7 +109,7 @@ else
echo "****** Float sample type enabled ******" echo "****** Float sample type enabled ******"
AC_DEFINE(SOUNDTOUCH_FLOAT_SAMPLES,1,[Use Float as Sample type]) AC_DEFINE(SOUNDTOUCH_FLOAT_SAMPLES,1,[Use Float as Sample type])
fi fi
AM_CONDITIONAL([SOUNDTOUCH_FLOAT_SAMPLES], [test "x$enable_integer_samples" != "xyes"])
if test "x$enable_openmp" = "xyes"; then if test "x$enable_openmp" = "xyes"; then
echo "****** openmp optimizations enabled ******" echo "****** openmp optimizations enabled ******"
@ -202,52 +195,6 @@ else
CPPFLAGS="-DSOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS $CPPFLAGS" CPPFLAGS="-DSOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS $CPPFLAGS"
fi fi
if test "x$enable_neon_optimizations" = "xyes" -a "x$ac_cv_header_arm_neon_h" = "xyes"; then
# Check for ARM NEON support
original_saved_CXXFLAGS=$CXXFLAGS
have_neon=no
CXXFLAGS="-mfpu=neon -march=native $CXXFLAGS"
# Check if can compile neon code using intrinsics, require GCC >= 4.3 for autovectorization.
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3))
#error "Need GCC >= 4.3 for neon autovectorization"
#endif
#include <arm_neon.h>
int main () {
int32x4_t t = {1};
return vaddq_s32(t,t)[0] == 2;
}]])],[have_neon=yes])
CXXFLAGS=$original_saved_CXXFLAGS
if test "x$have_neon" = "xyes" ; then
echo "****** NEON support enabled ******"
CPPFLAGS="-mfpu=neon -march=native -mtune=native $CPPFLAGS"
AC_DEFINE(SOUNDTOUCH_USE_NEON,1,[Use ARM NEON extension])
fi
fi
AC_CANONICAL_HOST
HOST_OS=""
AS_CASE([$host_cpu],
[x86_64],
[
x86_64=true
x86=true
],
[i?86],
[
x86=true
])
AM_CONDITIONAL([X86], [test "$x86" = true])
AM_CONDITIONAL([X86_64], [test "$x86_64" = true])
AC_SUBST([HOST_OS])
# Set AM_CXXFLAGS # Set AM_CXXFLAGS
AC_SUBST([AM_CXXFLAGS], [$AM_CXXFLAGS]) AC_SUBST([AM_CXXFLAGS], [$AM_CXXFLAGS])
@ -270,6 +217,8 @@ AM_CONDITIONAL([HAVE_SSE], [test "x$have_sse_intrinsics" = "xyes"])
dnl ############################################################################ dnl ############################################################################
dnl # Checks for library functions/classes # dnl # Checks for library functions/classes #
dnl ############################################################################ dnl ############################################################################
AC_FUNC_MALLOC
AC_TYPE_SIGNAL
dnl make -lm get added to the LIBS dnl make -lm get added to the LIBS
AC_CHECK_LIB(m, sqrt,,AC_MSG_ERROR([compatible libc math library not found])) AC_CHECK_LIB(m, sqrt,,AC_MSG_ERROR([compatible libc math library not found]))
@ -302,12 +251,11 @@ AC_CONFIG_FILES([
source/Makefile source/Makefile
source/SoundTouch/Makefile source/SoundTouch/Makefile
source/SoundStretch/Makefile source/SoundStretch/Makefile
source/SoundTouchDLL/Makefile
include/Makefile include/Makefile
]) ])
AC_CONFIG_FILES([soundtouch.pc AC_OUTPUT(
]) soundtouch.pc
AC_OUTPUT )
dnl use 'echo' to put stuff here if you want a message to the builder dnl use 'echo' to put stuff here if you want a message to the builder

View File

@ -196,7 +196,7 @@ namespace soundtouch
/// - "values" receive array of beat detection strengths /// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array. /// - max_num indicates max.size of "pos" and "values" array.
/// ///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values". /// You can query a suitable array sized by calling this with NULL in "pos" & "values".
/// ///
/// \return number of beats in the arrays. /// \return number of beats in the arrays.
int getBeats(float *pos, float *strength, int max_num); int getBeats(float *pos, float *strength, int max_num);

View File

@ -91,7 +91,7 @@ public:
); );
/// destructor /// destructor
~FIFOSampleBuffer() override; ~FIFOSampleBuffer();
/// Returns a pointer to the beginning of the output samples. /// Returns a pointer to the beginning of the output samples.
/// This function is provided for accessing the output samples directly. /// This function is provided for accessing the output samples directly.
@ -100,7 +100,7 @@ public:
/// When using this function to output samples, also remember to 'remove' the /// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the /// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function /// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin() override; virtual SAMPLETYPE *ptrBegin();
/// Returns a pointer to the end of the used part of the sample buffer (i.e. /// Returns a pointer to the end of the used part of the sample buffer (i.e.
/// where the new samples are to be inserted). This function may be used for /// where the new samples are to be inserted). This function may be used for
@ -121,7 +121,7 @@ public:
/// the sample buffer. /// the sample buffer.
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples. virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
uint numSamples ///< Number of samples to insert. uint numSamples ///< Number of samples to insert.
) override; );
/// Adjusts the book-keeping to increase number of samples in the buffer without /// Adjusts the book-keeping to increase number of samples in the buffer without
/// copying any actual samples. /// copying any actual samples.
@ -139,7 +139,7 @@ public:
/// \return Number of samples returned. /// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples. virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max. uint maxSamples ///< How many samples to receive at max.
) override; );
/// Adjusts book-keeping so that given number of samples are removed from beginning of the /// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere. /// sample buffer without copying them anywhere.
@ -147,10 +147,10 @@ public:
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function. /// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
) override; );
/// Returns number of samples currently available. /// Returns number of samples currently available.
virtual uint numSamples() const override; virtual uint numSamples() const;
/// Sets number of channels, 1 = mono, 2 = stereo. /// Sets number of channels, 1 = mono, 2 = stereo.
void setChannels(int numChannels); void setChannels(int numChannels);
@ -162,17 +162,14 @@ public:
} }
/// Returns nonzero if there aren't any samples available for outputting. /// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const override; virtual int isEmpty() const;
/// Clears all the samples. /// Clears all the samples.
virtual void clear() override; virtual void clear();
/// allow trimming (downwards) amount of samples in pipeline. /// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples /// Returns adjusted amount of samples
uint adjustAmountOfSamples(uint numSamples) override; uint adjustAmountOfSamples(uint numSamples);
/// Add silence to end of buffer
void addSilent(uint nSamples);
}; };
} }

View File

@ -88,11 +88,11 @@ public:
void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data. void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data.
) )
{ {
const uint oNumSamples = other.numSamples(); int oNumSamples = other.numSamples();
putSamples(other.ptrBegin(), oNumSamples); putSamples(other.ptrBegin(), oNumSamples);
other.receiveSamples(oNumSamples); other.receiveSamples(oNumSamples);
} };
/// Output samples from beginning of the sample buffer. Copies requested samples to /// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than /// output buffer and removes them from the sample buffer. If there are less than
@ -144,8 +144,8 @@ protected:
/// Sets output pipe. /// Sets output pipe.
void setOutPipe(FIFOSamplePipe *pOutput) void setOutPipe(FIFOSamplePipe *pOutput)
{ {
assert(output == nullptr); assert(output == NULL);
assert(pOutput != nullptr); assert(pOutput != NULL);
output = pOutput; output = pOutput;
} }
@ -153,7 +153,7 @@ protected:
/// 'setOutPipe' function. /// 'setOutPipe' function.
FIFOProcessor() FIFOProcessor()
{ {
output = nullptr; output = NULL;
} }
/// Constructor. Configures output pipe. /// Constructor. Configures output pipe.
@ -164,7 +164,7 @@ protected:
} }
/// Destructor. /// Destructor.
virtual ~FIFOProcessor() override virtual ~FIFOProcessor()
{ {
} }
@ -175,7 +175,7 @@ protected:
/// When using this function to output samples, also remember to 'remove' the /// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the /// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function /// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin() override virtual SAMPLETYPE *ptrBegin()
{ {
return output->ptrBegin(); return output->ptrBegin();
} }
@ -189,7 +189,7 @@ public:
/// \return Number of samples returned. /// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples. virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max. uint maxSamples ///< How many samples to receive at max.
) override )
{ {
return output->receiveSamples(outBuffer, maxSamples); return output->receiveSamples(outBuffer, maxSamples);
} }
@ -200,26 +200,26 @@ public:
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function. /// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
) override )
{ {
return output->receiveSamples(maxSamples); return output->receiveSamples(maxSamples);
} }
/// Returns number of samples currently available. /// Returns number of samples currently available.
virtual uint numSamples() const override virtual uint numSamples() const
{ {
return output->numSamples(); return output->numSamples();
} }
/// Returns nonzero if there aren't any samples available for outputting. /// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const override virtual int isEmpty() const
{ {
return output->isEmpty(); return output->isEmpty();
} }
/// allow trimming (downwards) amount of samples in pipeline. /// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples /// Returns adjusted amount of samples
virtual uint adjustAmountOfSamples(uint numSamples) override virtual uint adjustAmountOfSamples(uint numSamples)
{ {
return output->adjustAmountOfSamples(numSamples); return output->adjustAmountOfSamples(numSamples);
} }

View File

@ -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:
@ -122,10 +121,10 @@ namespace soundtouch
#endif #endif
// If defined, allows the SIMD-optimized routines to skip unevenly aligned // If defined, allows the SIMD-optimized routines to take minor shortcuts
// memory offsets that can cause performance penalty in some SIMD implementations. // for improved performance. Undefine to require faithfully similar SIMD
// Causes slight compromise in sound quality. // calculations as in normal C implementation.
// #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1 #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
#ifdef SOUNDTOUCH_INTEGER_SAMPLES #ifdef SOUNDTOUCH_INTEGER_SAMPLES
@ -150,9 +149,8 @@ namespace soundtouch
// floating point samples // floating point samples
typedef float SAMPLETYPE; typedef float SAMPLETYPE;
// data type for sample accumulation: Use float also here to enable // data type for sample accumulation: Use double to utilize full precision.
// efficient autovectorization typedef double LONG_SAMPLETYPE;
typedef float LONG_SAMPLETYPE;
#ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
// Allow SSE optimizations // Allow SSE optimizations
@ -161,13 +159,7 @@ namespace soundtouch
#endif // SOUNDTOUCH_INTEGER_SAMPLES #endif // SOUNDTOUCH_INTEGER_SAMPLES
#if ((SOUNDTOUCH_ALLOW_SSE) || (__SSE__) || (SOUNDTOUCH_USE_NEON)) };
#if SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
#define ST_SIMD_AVOID_UNALIGNED
#endif
#endif
}
// define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions: // define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
// #define ST_NO_EXCEPTION_HANDLING 1 // #define ST_NO_EXCEPTION_HANDLING 1

View File

@ -72,10 +72,10 @@ namespace soundtouch
{ {
/// Soundtouch library version string /// Soundtouch library version string
#define SOUNDTOUCH_VERSION "2.3.3" #define SOUNDTOUCH_VERSION "2.1"
/// SoundTouch library version id /// SoundTouch library version id
#define SOUNDTOUCH_VERSION_ID (20303) #define SOUNDTOUCH_VERSION_ID (20100)
// //
// Available setting IDs for the 'setSetting' & 'get_setting' functions: // Available setting IDs for the 'setSetting' & 'get_setting' functions:
@ -209,7 +209,7 @@ protected :
public: public:
SoundTouch(); SoundTouch();
virtual ~SoundTouch() override; virtual ~SoundTouch();
/// Get SoundTouch library version string /// Get SoundTouch library version string
static const char *getVersionString(); static const char *getVersionString();
@ -287,7 +287,7 @@ public:
uint numSamples ///< Number of samples in buffer. Notice uint numSamples ///< Number of samples in buffer. Notice
///< that in case of stereo-sound a single sample ///< that in case of stereo-sound a single sample
///< contains data for both channels. ///< contains data for both channels.
) override; );
/// Output samples from beginning of the sample buffer. Copies requested samples to /// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than /// output buffer and removes them from the sample buffer. If there are less than
@ -296,7 +296,7 @@ public:
/// \return Number of samples returned. /// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples. virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max. uint maxSamples ///< How many samples to receive at max.
) override; );
/// Adjusts book-keeping so that given number of samples are removed from beginning of the /// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere. /// sample buffer without copying them anywhere.
@ -304,11 +304,11 @@ public:
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function. /// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe. virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
) override; );
/// Clears all the samples in the object's output and internal processing /// Clears all the samples in the object's output and internal processing
/// buffers. /// buffers.
virtual void clear() override; virtual void clear();
/// Changes a setting controlling the processing system behaviour. See the /// Changes a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's. /// 'SETTING_...' defines for available setting ID's.

View File

@ -1,3 +0,0 @@
// autotools configuration step replaces this file with a configured version.
// this empty file stub is provided to avoid error about missing include file
// when not using autotools build

View File

@ -3,6 +3,3 @@
/* Use Integer as Sample type */ /* Use Integer as Sample type */
#undef SOUNDTOUCH_INTEGER_SAMPLES #undef SOUNDTOUCH_INTEGER_SAMPLES
/* Use ARM NEON extension */
#undef SOUNDTOUCH_USE_NEON

View File

@ -31,9 +31,8 @@ echo ***************************************************************************
echo ** echo **
echo ** ERROR: Visual Studio path not set. echo ** ERROR: Visual Studio path not set.
echo ** echo **
echo ** Open "tools"->"Developer Command Line" from Visual Studio IDE, or echo ** Run "vsvars32.bat" or "vcvars32.bat" from Visual Studio installation dir,
echo ** run "vcvars32.bat" from Visual Studio installation dir, e.g. echo ** e.g. "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin",
echo ** "C:\Program Files (x86)\Microsoft Visual Studio xxx\VC\bin",
echo ** then try again. echo ** then try again.
echo ** echo **
echo **************************************************************************** echo ****************************************************************************

View File

@ -1,7 +1,5 @@
# SoundTouch library # SoundTouch library
## About
SoundTouch is an open-source audio processing library that allows changing the sound tempo, pitch and playback rate parameters independently from each other: SoundTouch is an open-source audio processing library that allows changing the sound tempo, pitch and playback rate parameters independently from each other:
* Change **tempo** while maintaining the original pitch * Change **tempo** while maintaining the original pitch
* Change **pitch** while maintaining the original tempo * Change **pitch** while maintaining the original tempo
@ -9,9 +7,7 @@ SoundTouch is an open-source audio processing library that allows changing the s
same time same time
* Change any combination of tempo/pitch/rate * Change any combination of tempo/pitch/rate
Visit [SoundTouch website](https://www.surina.net/soundtouch) and see the [README file](https://www.surina.net/soundtouch/readme.html) for more information and audio examples. Visit [SoundTouch website](https://www.surina.net/soundtouch) and see the [README file](README.html) for more information and audio examples.
### The latest stable release is 2.3.3
## Example ## Example
@ -21,7 +17,7 @@ Use SoundStretch example app for modifying wav audio files, for example as follo
soundstretch my_original_file.wav output_file.wav -tempo=+15 -pitch=-3 soundstretch my_original_file.wav output_file.wav -tempo=+15 -pitch=-3
``` ```
See the [README file](http://soundtouch.surina.net/README.html) for more usage examples and instructions how to build SoundTouch + SoundStretch. See the [README file](README.html) for more usage examples and instructions how to build SoundTouch + SoundStretch.
Ready [SoundStretch application executables](https://www.surina.net/soundtouch/download.html) are available for download for Windows and Mac OS. Ready [SoundStretch application executables](https://www.surina.net/soundtouch/download.html) are available for download for Windows and Mac OS.
@ -37,18 +33,6 @@ SoundTouch is written in C++ and compiles in virtually any platform:
The source code package includes dynamic library import modules for C#, Java and Pascal/Delphi languages. The source code package includes dynamic library import modules for C#, Java and Pascal/Delphi languages.
## Tarballs
Source code release tarballs:
* https://www.surina.net/soundtouch/soundtouch-2.3.3.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.2.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.2.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.1.2.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.1.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.0.0.tar.gz
## License ## License
SoundTouch is released under LGPL v2.1: SoundTouch is released under LGPL v2.1:

View File

@ -103,7 +103,6 @@ in the <strong>soundtouch-jni.cpp </strong>source code file for more details.</p
the Java interface class that loasd & accesses the JNI routines in the natively compiled library. the Java interface class that loasd & accesses the JNI routines in the natively compiled library.
The example Android application uses this class as interface for processing audio files The example Android application uses this class as interface for processing audio files
with SoundTouch.</li> with SoundTouch.</li>
<li><b>Android-lib/build.gradle</b>: Top level build script file for Android Studio 3.1.4+</li>
</ul> </ul>
<p> <p>
Feel free to examine and extend the provided cpp/java source code example file pair to Feel free to examine and extend the provided cpp/java source code example file pair to

View File

@ -1,55 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
}
}
allprojects {
repositories {
jcenter()
google()
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "net.surina.soundtouchexample"
minSdkVersion 14
targetSdkVersion 21
externalNativeBuild.ndkBuild {
arguments "NDK_APPLICATION=jni/Application.mk",
"APP_ALLOW_MISSING_DEPS:=true"
}
}
sourceSets {
main {
manifest.srcFile "./AndroidManifest.xml"
java.srcDirs = ["./src"]
res.srcDirs = ["res"]
}
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
}
}
buildTypes {
release {
minifyEnabled false
}
}
}

View File

@ -1,6 +0,0 @@
#Sat Jan 13 09:12:34 PST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip

View File

@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,8 +1,22 @@
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../SoundStretch
# *** Remember: Change -O0 into -O2 in add-applications.mk *** # *** Remember: Change -O0 into -O2 in add-applications.mk ***
LOCAL_MODULE := soundtouch LOCAL_MODULE := soundtouch
@ -24,7 +38,7 @@ LOCAL_LDLIBS += -llog
# Custom Flags: # Custom Flags:
# -fvisibility=hidden : don't export all symbols # -fvisibility=hidden : don't export all symbols
LOCAL_CFLAGS += -fvisibility=hidden -fdata-sections -ffunction-sections -ffast-math LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections
# OpenMP mode : enable these flags to enable using OpenMP for parallel computation # OpenMP mode : enable these flags to enable using OpenMP for parallel computation
#LOCAL_CFLAGS += -fopenmp #LOCAL_CFLAGS += -fopenmp

View File

@ -4,6 +4,6 @@
APP_ABI := all #armeabi-v7a armeabi APP_ABI := all #armeabi-v7a armeabi
APP_OPTIM := release APP_OPTIM := release
APP_STL := c++_static APP_STL := stlport_static
APP_CPPFLAGS := -fexceptions # -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS APP_CPPFLAGS := -fexceptions # -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS

View File

@ -41,12 +41,12 @@ static void _setErrmsg(const char *msg)
_errMsg = msg; _errMsg = msg;
} }
#if 0 // apparently following workaround not needed any more with concurrent Android SDKs
#ifdef _OPENMP #ifdef _OPENMP
#include <pthread.h> #include <pthread.h>
extern pthread_key_t gomp_tls_key; extern pthread_key_t gomp_tls_key;
static void * _p_gomp_tls = nullptr; static void * _p_gomp_tls = NULL;
/// Function to initialize threading for OpenMP. /// Function to initialize threading for OpenMP.
/// ///
@ -54,7 +54,7 @@ static void * _p_gomp_tls = nullptr;
/// called from the Android App main thread because in the main thread the gomp_tls storage is /// called from the Android App main thread because in the main thread the gomp_tls storage is
/// properly set, however, Android does not properly initialize gomp_tls storage for other threads. /// properly set, however, Android does not properly initialize gomp_tls storage for other threads.
/// Thus if OpenMP routines are invoked from some other thread than the main thread, /// Thus if OpenMP routines are invoked from some other thread than the main thread,
/// the OpenMP routine will crash the application due to nullptr access on uninitialized storage. /// the OpenMP routine will crash the application due to NULL pointer access on uninitialized storage.
/// ///
/// This workaround stores the gomp_tls storage from main thread, and copies to other threads. /// This workaround stores the gomp_tls storage from main thread, and copies to other threads.
/// In order this to work, the Application main thread needws to call at least "getVersionString" /// In order this to work, the Application main thread needws to call at least "getVersionString"
@ -63,7 +63,7 @@ static int _init_threading(bool warn)
{ {
void *ptr = pthread_getspecific(gomp_tls_key); void *ptr = pthread_getspecific(gomp_tls_key);
LOGV("JNI thread-specific TLS storage %ld", (long)ptr); LOGV("JNI thread-specific TLS storage %ld", (long)ptr);
if (ptr == nullptr) if (ptr == NULL)
{ {
LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls); LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls);
pthread_setspecific(gomp_tls_key, _p_gomp_tls); pthread_setspecific(gomp_tls_key, _p_gomp_tls);
@ -74,7 +74,7 @@ static int _init_threading(bool warn)
_p_gomp_tls = ptr; _p_gomp_tls = ptr;
} }
// Where critical, show warning if storage still not properly initialized // Where critical, show warning if storage still not properly initialized
if ((warn) && (_p_gomp_tls == nullptr)) if ((warn) && (_p_gomp_tls == NULL))
{ {
_setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!"); _setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!");
return -1; return -1;
@ -90,7 +90,6 @@ static int _init_threading(bool warn)
} }
#endif #endif
#endif
// Processes the sound file // Processes the sound file
static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName) static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName)
@ -163,9 +162,8 @@ extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionSt
// Call example SoundTouch routine // Call example SoundTouch routine
verStr = SoundTouch::getVersionString(); verStr = SoundTouch::getVersionString();
// gomp_tls storage bug workaround - see comments in _init_threading() function! /// gomp_tls storage bug workaround - see comments in _init_threading() function!
// update: apparently this is not needed any more with concurrent Android SDKs _init_threading(false);
// _init_threading(false);
int threads = 0; int threads = 0;
#pragma omp parallel #pragma omp parallel
@ -234,8 +232,7 @@ extern "C" DLL_PUBLIC int Java_net_surina_soundtouch_SoundTouch_processFile(JNIE
LOGV("JNI process file %s", inputFile); LOGV("JNI process file %s", inputFile);
/// gomp_tls storage bug workaround - see comments in _init_threading() function! /// gomp_tls storage bug workaround - see comments in _init_threading() function!
// update: apparently this is not needed any more with concurrent Android SDKs if (_init_threading(true)) return -1;
// if (_init_threading(true)) return -1;
try try
{ {

View File

@ -17,9 +17,8 @@
include $(top_srcdir)/config/am_include.mk include $(top_srcdir)/config/am_include.mk
if SOUNDTOUCH_FLOAT_SAMPLES SUBDIRS=SoundTouch SoundStretch
# build SoundTouchDLL only if float samples used
SUBDIRS=SoundTouch SoundStretch SoundTouchDLL # set to something if you want other stuff to be included in the distribution tarball
else #EXTRA_DIST=
SUBDIRS=SoundTouch SoundStretch
endif

View File

@ -40,11 +40,11 @@ soundstretch_SOURCES=main.cpp RunParameters.cpp WavFile.cpp
soundstretch_LDADD=../SoundTouch/libSoundTouch.la -lm soundstretch_LDADD=../SoundTouch/libSoundTouch.la -lm
## linker flags. ## linker flags.
# Linker flag -s disabled to prevent stripping symbols by default # OP 2011-7-17 Linker flag -s disabled to prevent stripping symbols by default
#soundstretch_LDFLAGS=-s #soundstretch_LDFLAGS=-s
## additional compiler flags ## additional compiler flags
soundstretch_CXXFLAGS=$(AM_CXXFLAGS) soundstretch_CXXFLAGS=-O3 $(AM_CXXFLAGS)
#clean-local: #clean-local:
# -rm -f additional-files-to-remove-on-make-clean # -rm -f additional-files-to-remove-on-make-clean

View File

@ -30,15 +30,12 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <string> #include <string>
#include <cstdlib> #include <stdlib.h>
#include "RunParameters.h" #include "RunParameters.h"
using namespace std; using namespace std;
namespace soundstretch
{
// Program usage instructions // Program usage instructions
static const char licenseText[] = static const char licenseText[] =
@ -97,8 +94,9 @@ static int _toLowerCase(int c)
return c; return c;
} }
// Constructor // Constructor
RunParameters::RunParameters(int nParams, const CHARTYPE* paramStr[]) RunParameters::RunParameters(const int nParams, const char * const paramStr[])
{ {
int i; int i;
int nFirstParam; int nFirstParam;
@ -114,17 +112,28 @@ RunParameters::RunParameters(int nParams, const CHARTYPE* paramStr[])
} }
string msg = whatText; string msg = whatText;
msg += usage; msg += usage;
throw(msg); ST_THROW_RT_ERROR(msg.c_str());
} }
inFileName = NULL;
outFileName = NULL;
tempoDelta = 0;
pitchDelta = 0;
rateDelta = 0;
quick = 0;
noAntiAlias = 0;
goalBPM = 0;
speech = false;
detectBPM = false;
// Get input & output file names // Get input & output file names
inFileName = paramStr[1]; inFileName = (char*)paramStr[1];
outFileName = paramStr[2]; outFileName = (char*)paramStr[2];
if (outFileName[0] == '-') if (outFileName[0] == '-')
{ {
// outputfile name was omitted but other parameter switches given instead // no outputfile name was given but parameters
outFileName = STRING_CONST(""); outFileName = NULL;
nFirstParam = 2; nFirstParam = 2;
} }
else else
@ -173,33 +182,25 @@ void RunParameters::checkLimits()
} }
} }
// Convert STRING to std::string. Actually needed only if STRING is std::wstring, but conversion penalty is negligible
std::string convertString(const STRING& str)
{
std::string res;
for (auto c : str)
{
res += (char)c;
}
return res;
}
// Unknown switch parameter -- throws an exception with an error message // Unknown switch parameter -- throws an exception with an error message
void RunParameters::throwIllegalParamExp(const STRING &str) const void RunParameters::throwIllegalParamExp(const string &str) const
{ {
string msg = "ERROR : Illegal parameter \""; string msg = "ERROR : Illegal parameter \"";
msg += convertString(str); msg += str;
msg += "\".\n\n"; msg += "\".\n\n";
msg += usage; msg += usage;
ST_THROW_RT_ERROR(msg); ST_THROW_RT_ERROR(msg.c_str());
} }
void RunParameters::throwLicense() const 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,14 +212,14 @@ 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)atof(str.substr(pos + 1).c_str());
} }
// Interprets a single switch parameter string of format "-switch=xx" // Interprets a single switch parameter string of format "-switch=xx"
// Valid switches are "-tempo=xx", "-pitch=xx" and "-rate=xx". Stores // Valid switches are "-tempo=xx", "-pitch=xx" and "-rate=xx". Stores
// switch values into 'params' structure. // switch values into 'params' structure.
void RunParameters::parseSwitchParam(const STRING& str) void RunParameters::parseSwitchParam(const string &str)
{ {
int upS; int upS;
@ -288,5 +289,3 @@ void RunParameters::parseSwitchParam(const STRING& str)
throwIllegalParamExp(str); throwIllegalParamExp(str);
} }
} }
}

View File

@ -32,39 +32,34 @@
#ifndef RUNPARAMETERS_H #ifndef RUNPARAMETERS_H
#define RUNPARAMETERS_H #define RUNPARAMETERS_H
#include <string>
#include "STTypes.h" #include "STTypes.h"
#include "SS_CharTypes.h" #include <string>
#include "WavFile.h"
namespace soundstretch using namespace std;
{
/// Parses command line parameters into program parameters /// Parses command line parameters into program parameters
class RunParameters class RunParameters
{ {
private: private:
void throwIllegalParamExp(const STRING& str) const; void throwIllegalParamExp(const string &str) const;
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 &str) const;
public: public:
STRING inFileName; char *inFileName;
STRING outFileName; char *outFileName;
double tempoDelta{ 0 }; float tempoDelta;
double pitchDelta{ 0 }; float pitchDelta;
double rateDelta{ 0 }; float rateDelta;
int quick{ 0 }; int quick;
int noAntiAlias{ 0 }; int noAntiAlias;
double goalBPM{ 0 }; float goalBPM;
bool detectBPM{ false }; bool detectBPM;
bool speech{ false }; bool speech;
RunParameters(int nParams, const CHARTYPE* paramStr[]); RunParameters(const int nParams, const char * const paramStr[]);
}; };
}
#endif #endif

View File

@ -1,52 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Char type for SoundStretch
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// 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 SS_CHARTYPE_H
#define SS_CHARTYPE_H
#include <string>
namespace soundstretch
{
#if _WIN32
// wide-char types for supporting non-latin file paths in Windows
using CHARTYPE = wchar_t;
using STRING = std::wstring;
#define STRING_CONST(x) (L"" x)
#else
// gnu platform can natively support UTF-8 paths using "char*" set
using CHARTYPE = char;
using STRING = std::string;
#define STRING_CONST(x) (x)
#endif
}
#endif //SS_CHARTYPE_H

View File

@ -42,23 +42,14 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <cstring> #include <cstring>
#include <cassert> #include <assert.h>
#include <climits> #include <limits.h>
#include "WavFile.h" #include "WavFile.h"
#include "STTypes.h" #include "STTypes.h"
using namespace std; using namespace std;
namespace soundstretch
{
#if _WIN32
#define FOPEN(name, mode) _wfopen(name, STRING_CONST(mode))
#else
#define FOPEN(name, mode) fopen(name, mode)
#endif
static const char riffStr[] = "RIFF"; static const char riffStr[] = "RIFF";
static const char waveStr[] = "WAVE"; static const char waveStr[] = "WAVE";
static const char fmtStr[] = "fmt "; static const char fmtStr[] = "fmt ";
@ -75,67 +66,67 @@ static const char dataStr[] = "data";
// while PowerPC of Mac's and many other RISC cpu's are big-endian. // while PowerPC of Mac's and many other RISC cpu's are big-endian.
#ifdef BYTE_ORDER #ifdef BYTE_ORDER
// In gcc compiler detect the byte order automatically // In gcc compiler detect the byte order automatically
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
// big-endian platform. // big-endian platform.
#define _BIG_ENDIAN_ #define _BIG_ENDIAN_
#endif #endif
#endif #endif
#ifdef _BIG_ENDIAN_ #ifdef _BIG_ENDIAN_
// big-endian CPU, swap bytes in 16 & 32 bit words // big-endian CPU, swap bytes in 16 & 32 bit words
// helper-function to swap byte-order of 32bit integer // helper-function to swap byte-order of 32bit integer
static inline int _swap32(int& dwData) static inline int _swap32(int &dwData)
{ {
dwData = ((dwData >> 24) & 0x000000FF) | dwData = ((dwData >> 24) & 0x000000FF) |
((dwData >> 8) & 0x0000FF00) | ((dwData >> 8) & 0x0000FF00) |
((dwData << 8) & 0x00FF0000) | ((dwData << 8) & 0x00FF0000) |
((dwData << 24) & 0xFF000000); ((dwData << 24) & 0xFF000000);
return dwData; return dwData;
} }
// helper-function to swap byte-order of 16bit integer // helper-function to swap byte-order of 16bit integer
static inline short _swap16(short& wData) static inline short _swap16(short &wData)
{ {
wData = ((wData >> 8) & 0x00FF) | wData = ((wData >> 8) & 0x00FF) |
((wData << 8) & 0xFF00); ((wData << 8) & 0xFF00);
return wData; return wData;
} }
// helper-function to swap byte-order of buffer of 16bit integers // helper-function to swap byte-order of buffer of 16bit integers
static inline void _swap16Buffer(short* pData, int numWords) static inline void _swap16Buffer(short *pData, int numWords)
{ {
int i; int i;
for (i = 0; i < numWords; i++) for (i = 0; i < numWords; i ++)
{ {
pData[i] = _swap16(pData[i]); pData[i] = _swap16(pData[i]);
} }
} }
#else // BIG_ENDIAN #else // BIG_ENDIAN
// little-endian CPU, WAV file is ok as such // little-endian CPU, WAV file is ok as such
// dummy helper-function // dummy helper-function
static inline int _swap32(int& dwData) static inline int _swap32(int &dwData)
{ {
// do nothing // do nothing
return dwData; return dwData;
} }
// dummy helper-function // dummy helper-function
static inline short _swap16(short& wData) static inline short _swap16(short &wData)
{ {
// do nothing // do nothing
return wData; return wData;
} }
// dummy helper-function // dummy helper-function
static inline void _swap16Buffer(short*, int) static inline void _swap16Buffer(short *pData, int numBytes)
{ {
// do nothing // do nothing
} }
#endif // BIG_ENDIAN #endif // BIG_ENDIAN
@ -147,7 +138,7 @@ static inline void _swap16Buffer(short*, int)
WavFileBase::WavFileBase() WavFileBase::WavFileBase()
{ {
convBuff = nullptr; convBuff = NULL;
convBuffSize = 0; convBuffSize = 0;
} }
@ -160,7 +151,7 @@ WavFileBase::~WavFileBase()
/// Get pointer to conversion buffer of at min. given size /// Get pointer to conversion buffer of at min. given size
void* WavFileBase::getConvBuffer(int sizeBytes) void *WavFileBase::getConvBuffer(int sizeBytes)
{ {
if (convBuffSize < sizeBytes) if (convBuffSize < sizeBytes)
{ {
@ -178,26 +169,32 @@ void* WavFileBase::getConvBuffer(int sizeBytes)
// Class WavInFile // Class WavInFile
// //
WavInFile::WavInFile(const STRING& fileName) WavInFile::WavInFile(const char *fileName)
{ {
// Try to open the file for reading // Try to open the file for reading
fptr = FOPEN(fileName.c_str(), "rb"); fptr = fopen(fileName, "rb");
if (fptr == nullptr) if (fptr == NULL)
{ {
ST_THROW_RT_ERROR("Error : Unable to open file for reading."); // didn't succeed
string msg = "Error : Unable to open file \"";
msg += fileName;
msg += "\" for reading.";
ST_THROW_RT_ERROR(msg.c_str());
} }
init(); init();
} }
WavInFile::WavInFile(FILE* file) WavInFile::WavInFile(FILE *file)
{ {
// Try to open the file for reading // Try to open the file for reading
fptr = file; fptr = file;
if (!file) if (!file)
{ {
ST_THROW_RT_ERROR("Error : Unable to access input stream for reading"); // didn't succeed
string msg = "Error : Unable to access input stream for reading";
ST_THROW_RT_ERROR(msg.c_str());
} }
init(); init();
@ -216,6 +213,7 @@ void WavInFile::init()
hdrsOk = readWavHeaders(); hdrsOk = readWavHeaders();
if (hdrsOk != 0) if (hdrsOk != 0)
{ {
// Something didn't match in the wav file headers
ST_THROW_RT_ERROR("Input file is corrupt or not a WAV file"); ST_THROW_RT_ERROR("Input file is corrupt or not a WAV file");
} }
@ -225,6 +223,7 @@ void WavInFile::init()
(header.format.byte_per_sample < 1) || (header.format.byte_per_sample > 320) || (header.format.byte_per_sample < 1) || (header.format.byte_per_sample > 320) ||
(header.format.bits_per_sample < 8) || (header.format.bits_per_sample > 32)) (header.format.bits_per_sample < 8) || (header.format.bits_per_sample > 32))
{ {
// Something didn't match in the wav file headers
ST_THROW_RT_ERROR("Error: Illegal wav file header format parameters."); ST_THROW_RT_ERROR("Error: Illegal wav file header format parameters.");
} }
@ -235,7 +234,7 @@ void WavInFile::init()
WavInFile::~WavInFile() WavInFile::~WavInFile()
{ {
if (fptr) fclose(fptr); if (fptr) fclose(fptr);
fptr = nullptr; fptr = NULL;
} }
@ -261,7 +260,7 @@ int WavInFile::checkCharTags() const
} }
int WavInFile::read(unsigned char* buffer, int maxElems) int WavInFile::read(unsigned char *buffer, int maxElems)
{ {
int numBytes; int numBytes;
uint afterDataRead; uint afterDataRead;
@ -290,7 +289,7 @@ int WavInFile::read(unsigned char* buffer, int maxElems)
} }
int WavInFile::read(short* buffer, int maxElems) int WavInFile::read(short *buffer, int maxElems)
{ {
unsigned int afterDataRead; unsigned int afterDataRead;
int numBytes; int numBytes;
@ -302,12 +301,12 @@ int WavInFile::read(short* buffer, int maxElems)
case 8: case 8:
{ {
// 8 bit format // 8 bit format
unsigned char* temp = (unsigned char*)getConvBuffer(maxElems); unsigned char *temp = (unsigned char*)getConvBuffer(maxElems);
int i; int i;
numElems = read(temp, maxElems); numElems = read(temp, maxElems);
// convert from 8 to 16 bit // convert from 8 to 16 bit
for (i = 0; i < numElems; i++) for (i = 0; i < numElems; i ++)
{ {
buffer[i] = (short)(((short)temp[i] - 128) * 256); buffer[i] = (short)(((short)temp[i] - 128) * 256);
} }
@ -334,7 +333,7 @@ int WavInFile::read(short* buffer, int maxElems)
numElems = numBytes / 2; numElems = numBytes / 2;
// 16bit samples, swap byte order if necessary // 16bit samples, swap byte order if necessary
_swap16Buffer((short*)buffer, numElems); _swap16Buffer((short *)buffer, numElems);
break; break;
} }
@ -354,7 +353,7 @@ int WavInFile::read(short* buffer, int maxElems)
/// Read data in float format. Notice that when reading in float format /// Read data in float format. Notice that when reading in float format
/// 8/16/24/32 bit sample formats are supported /// 8/16/24/32 bit sample formats are supported
int WavInFile::read(float* buffer, int maxElems) int WavInFile::read(float *buffer, int maxElems)
{ {
unsigned int afterDataRead; unsigned int afterDataRead;
int numBytes; int numBytes;
@ -383,7 +382,7 @@ int WavInFile::read(float* buffer, int maxElems)
} }
// read raw data into temporary buffer // read raw data into temporary buffer
char* temp = (char*)getConvBuffer(numBytes); char *temp = (char*)getConvBuffer(numBytes);
numBytes = (int)fread(temp, 1, numBytes, fptr); numBytes = (int)fread(temp, 1, numBytes, fptr);
dataRead += numBytes; dataRead += numBytes;
@ -394,9 +393,9 @@ int WavInFile::read(float* buffer, int maxElems)
{ {
case 1: case 1:
{ {
unsigned char* temp2 = (unsigned char*)temp; unsigned char *temp2 = (unsigned char*)temp;
double conv = 1.0 / 128.0; double conv = 1.0 / 128.0;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
buffer[i] = (float)(temp2[i] * conv - 1.0); buffer[i] = (float)(temp2[i] * conv - 1.0);
} }
@ -405,9 +404,9 @@ int WavInFile::read(float* buffer, int maxElems)
case 2: case 2:
{ {
short* temp2 = (short*)temp; short *temp2 = (short*)temp;
double conv = 1.0 / 32768.0; double conv = 1.0 / 32768.0;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
short value = temp2[i]; short value = temp2[i];
buffer[i] = (float)(_swap16(value) * conv); buffer[i] = (float)(_swap16(value) * conv);
@ -417,9 +416,9 @@ int WavInFile::read(float* buffer, int maxElems)
case 3: case 3:
{ {
char* temp2 = (char*)temp; char *temp2 = (char *)temp;
double conv = 1.0 / 8388608.0; double conv = 1.0 / 8388608.0;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
int value = *((int*)temp2); int value = *((int*)temp2);
value = _swap32(value) & 0x00ffffff; // take 24 bits value = _swap32(value) & 0x00ffffff; // take 24 bits
@ -432,10 +431,10 @@ int WavInFile::read(float* buffer, int maxElems)
case 4: case 4:
{ {
int* temp2 = (int*)temp; int *temp2 = (int *)temp;
double conv = 1.0 / 2147483648.0; double conv = 1.0 / 2147483648.0;
assert(sizeof(int) == 4); assert(sizeof(int) == 4);
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
int value = temp2[i]; int value = temp2[i];
buffer[i] = (float)(_swap32(value) * conv); buffer[i] = (float)(_swap32(value) * conv);
@ -451,7 +450,7 @@ int WavInFile::read(float* buffer, int maxElems)
int WavInFile::eof() const int WavInFile::eof() const
{ {
// return true if all data has been read or file eof has reached // return true if all data has been read or file eof has reached
return ((uint)dataRead == header.data.data_len || feof(fptr)); return (dataRead == header.data.data_len || feof(fptr));
} }
@ -463,7 +462,7 @@ static int isAlpha(char c)
// test if all characters are between a white space ' ' and little 'z' // test if all characters are between a white space ' ' and little 'z'
static int isAlphaStr(const char* str) static int isAlphaStr(const char *str)
{ {
char c; char c;
@ -471,7 +470,7 @@ static int isAlphaStr(const char* str)
while (c) while (c)
{ {
if (isAlpha(c) == 0) return 0; if (isAlpha(c) == 0) return 0;
str++; str ++;
c = str[0]; c = str[0];
} }
@ -484,7 +483,7 @@ int WavInFile::readRIFFBlock()
if (fread(&(header.riff), sizeof(WavRiff), 1, fptr) != 1) return -1; if (fread(&(header.riff), sizeof(WavRiff), 1, fptr) != 1) return -1;
// swap 32bit data byte order if necessary // swap 32bit data byte order if necessary
_swap32((int&)header.riff.package_len); _swap32((int &)header.riff.package_len);
// header.riff.riff_char should equal to 'RIFF'); // header.riff.riff_char should equal to 'RIFF');
if (memcmp(riffStr, header.riff.riff_char, 4) != 0) return -1; if (memcmp(riffStr, header.riff.riff_char, 4) != 0) return -1;
@ -501,7 +500,7 @@ int WavInFile::readHeaderBlock()
string sLabel; string sLabel;
// lead label string // lead label string
if (fread(label, 1, 4, fptr) != 4) return -1; if (fread(label, 1, 4, fptr) !=4) return -1;
label[4] = 0; label[4] = 0;
if (isAlphaStr(label) == 0) return -1; // not a valid label if (isAlphaStr(label) == 0) return -1; // not a valid label
@ -537,12 +536,12 @@ int WavInFile::readHeaderBlock()
if (fread(&(header.format.fixed), nLen, 1, fptr) != 1) return -1; if (fread(&(header.format.fixed), nLen, 1, fptr) != 1) return -1;
// swap byte order if necessary // swap byte order if necessary
_swap16((short&)header.format.fixed); // short int fixed; _swap16((short &)header.format.fixed); // short int fixed;
_swap16((short&)header.format.channel_number); // short int channel_number; _swap16((short &)header.format.channel_number); // short int channel_number;
_swap32((int&)header.format.sample_rate); // int sample_rate; _swap32((int &)header.format.sample_rate); // int sample_rate;
_swap32((int&)header.format.byte_rate); // int byte_rate; _swap32((int &)header.format.byte_rate); // int byte_rate;
_swap16((short&)header.format.byte_per_sample); // short int byte_per_sample; _swap16((short &)header.format.byte_per_sample); // short int byte_per_sample;
_swap16((short&)header.format.bits_per_sample); // short int bits_per_sample; _swap16((short &)header.format.bits_per_sample); // short int bits_per_sample;
// if format_len is larger than expected, skip the extra data // if format_len is larger than expected, skip the extra data
if (nDump > 0) if (nDump > 0)
@ -582,7 +581,7 @@ int WavInFile::readHeaderBlock()
if (fread(&(header.fact.fact_sample_len), nLen, 1, fptr) != 1) return -1; if (fread(&(header.fact.fact_sample_len), nLen, 1, fptr) != 1) return -1;
// swap byte order if necessary // swap byte order if necessary
_swap32((int&)header.fact.fact_sample_len); // int sample_length; _swap32((int &)header.fact.fact_sample_len); // int sample_length;
// if fact_len is larger than expected, skip the extra data // if fact_len is larger than expected, skip the extra data
if (nDump > 0) if (nDump > 0)
@ -599,7 +598,7 @@ int WavInFile::readHeaderBlock()
if (fread(&(header.data.data_len), sizeof(uint), 1, fptr) != 1) return -1; if (fread(&(header.data.data_len), sizeof(uint), 1, fptr) != 1) return -1;
// swap byte order if necessary // swap byte order if necessary
_swap32((int&)header.data.data_len); _swap32((int &)header.data.data_len);
return 1; return 1;
} }
@ -612,7 +611,7 @@ int WavInFile::readHeaderBlock()
// read length // read length
if (fread(&len, sizeof(len), 1, fptr) != 1) return -1; if (fread(&len, sizeof(len), 1, fptr) != 1) return -1;
// scan through the block // scan through the block
for (i = 0; i < len; i++) for (i = 0; i < len; i ++)
{ {
if (fread(&temp, 1, 1, fptr) != 1) return -1; if (fread(&temp, 1, 1, fptr) != 1) return -1;
if (feof(fptr)) return -1; // unexpected eof if (feof(fptr)) return -1; // unexpected eof
@ -704,13 +703,17 @@ uint WavInFile::getElapsedMS() const
// Class WavOutFile // Class WavOutFile
// //
WavOutFile::WavOutFile(const STRING& fileName, int sampleRate, int bits, int channels) WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int channels)
{ {
bytesWritten = 0; bytesWritten = 0;
fptr = FOPEN(fileName.c_str(), "wb"); fptr = fopen(fileName, "wb");
if (fptr == nullptr) if (fptr == NULL)
{ {
ST_THROW_RT_ERROR("Error : Unable to open file for writing."); string msg = "Error : Unable to open file \"";
msg += fileName;
msg += "\" for writing.";
//pmsg = msg.c_str;
ST_THROW_RT_ERROR(msg.c_str());
} }
fillInHeader(sampleRate, bits, channels); fillInHeader(sampleRate, bits, channels);
@ -718,13 +721,14 @@ WavOutFile::WavOutFile(const STRING& fileName, int sampleRate, int bits, int cha
} }
WavOutFile::WavOutFile(FILE* file, int sampleRate, int bits, int channels) WavOutFile::WavOutFile(FILE *file, int sampleRate, int bits, int channels)
{ {
bytesWritten = 0; bytesWritten = 0;
fptr = file; fptr = file;
if (fptr == nullptr) if (fptr == NULL)
{ {
ST_THROW_RT_ERROR("Error : Unable to access output file stream."); string msg = "Error : Unable to access output file stream.";
ST_THROW_RT_ERROR(msg.c_str());
} }
fillInHeader(sampleRate, bits, channels); fillInHeader(sampleRate, bits, channels);
@ -736,7 +740,7 @@ WavOutFile::~WavOutFile()
{ {
finishHeader(); finishHeader();
if (fptr) fclose(fptr); if (fptr) fclose(fptr);
fptr = nullptr; fptr = NULL;
} }
@ -797,17 +801,17 @@ void WavOutFile::writeHeader()
// swap byte order if necessary // swap byte order if necessary
hdrTemp = header; hdrTemp = header;
_swap32((int&)hdrTemp.riff.package_len); _swap32((int &)hdrTemp.riff.package_len);
_swap32((int&)hdrTemp.format.format_len); _swap32((int &)hdrTemp.format.format_len);
_swap16((short&)hdrTemp.format.fixed); _swap16((short &)hdrTemp.format.fixed);
_swap16((short&)hdrTemp.format.channel_number); _swap16((short &)hdrTemp.format.channel_number);
_swap32((int&)hdrTemp.format.sample_rate); _swap32((int &)hdrTemp.format.sample_rate);
_swap32((int&)hdrTemp.format.byte_rate); _swap32((int &)hdrTemp.format.byte_rate);
_swap16((short&)hdrTemp.format.byte_per_sample); _swap16((short &)hdrTemp.format.byte_per_sample);
_swap16((short&)hdrTemp.format.bits_per_sample); _swap16((short &)hdrTemp.format.bits_per_sample);
_swap32((int&)hdrTemp.data.data_len); _swap32((int &)hdrTemp.data.data_len);
_swap32((int&)hdrTemp.fact.fact_len); _swap32((int &)hdrTemp.fact.fact_len);
_swap32((int&)hdrTemp.fact.fact_sample_len); _swap32((int &)hdrTemp.fact.fact_sample_len);
// write the supplemented header in the beginning of the file // write the supplemented header in the beginning of the file
fseek(fptr, 0, SEEK_SET); fseek(fptr, 0, SEEK_SET);
@ -822,7 +826,7 @@ void WavOutFile::writeHeader()
} }
void WavOutFile::write(const unsigned char* buffer, int numElems) void WavOutFile::write(const unsigned char *buffer, int numElems)
{ {
int res; int res;
@ -842,7 +846,7 @@ void WavOutFile::write(const unsigned char* buffer, int numElems)
} }
void WavOutFile::write(const short* buffer, int numElems) void WavOutFile::write(const short *buffer, int numElems)
{ {
int res; int res;
@ -854,9 +858,9 @@ void WavOutFile::write(const short* buffer, int numElems)
case 8: case 8:
{ {
int i; int i;
unsigned char* temp = (unsigned char*)getConvBuffer(numElems); unsigned char *temp = (unsigned char *)getConvBuffer(numElems);
// convert from 16bit format to 8bit format // convert from 16bit format to 8bit format
for (i = 0; i < numElems; i++) for (i = 0; i < numElems; i ++)
{ {
temp[i] = (unsigned char)(buffer[i] / 256 + 128); temp[i] = (unsigned char)(buffer[i] / 256 + 128);
} }
@ -870,8 +874,8 @@ void WavOutFile::write(const short* buffer, int numElems)
// 16bit format // 16bit format
// use temp buffer to swap byte order if necessary // use temp buffer to swap byte order if necessary
short* pTemp = (short*)getConvBuffer(numElems * sizeof(short)); short *pTemp = (short *)getConvBuffer(numElems * sizeof(short));
memcpy(pTemp, buffer, (size_t)numElems * 2L); memcpy(pTemp, buffer, numElems * 2);
_swap16Buffer(pTemp, numElems); _swap16Buffer(pTemp, numElems);
res = (int)fwrite(pTemp, 2, numElems, fptr); res = (int)fwrite(pTemp, 2, numElems, fptr);
@ -911,7 +915,7 @@ inline int saturate(float fvalue, float minval, float maxval)
} }
void WavOutFile::write(const float* buffer, int numElems) void WavOutFile::write(const float *buffer, int numElems)
{ {
int numBytes; int numBytes;
int bytesPerSample; int bytesPerSample;
@ -920,14 +924,14 @@ void WavOutFile::write(const float* buffer, int numElems)
bytesPerSample = header.format.bits_per_sample / 8; bytesPerSample = header.format.bits_per_sample / 8;
numBytes = numElems * bytesPerSample; numBytes = numElems * bytesPerSample;
void* temp = getConvBuffer(numBytes + 7); // round bit up to avoid buffer overrun with 24bit-value assignment short *temp = (short*)getConvBuffer(numBytes);
switch (bytesPerSample) switch (bytesPerSample)
{ {
case 1: case 1:
{ {
unsigned char* temp2 = (unsigned char*)temp; unsigned char *temp2 = (unsigned char *)temp;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
temp2[i] = (unsigned char)saturate(buffer[i] * 128.0f + 128.0f, 0.0f, 255.0f); temp2[i] = (unsigned char)saturate(buffer[i] * 128.0f + 128.0f, 0.0f, 255.0f);
} }
@ -936,8 +940,8 @@ void WavOutFile::write(const float* buffer, int numElems)
case 2: case 2:
{ {
short* temp2 = (short*)temp; short *temp2 = (short *)temp;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
short value = (short)saturate(buffer[i] * 32768.0f, -32768.0f, 32767.0f); short value = (short)saturate(buffer[i] * 32768.0f, -32768.0f, 32767.0f);
temp2[i] = _swap16(value); temp2[i] = _swap16(value);
@ -947,8 +951,8 @@ void WavOutFile::write(const float* buffer, int numElems)
case 3: case 3:
{ {
char* temp2 = (char*)temp; char *temp2 = (char *)temp;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
int value = saturate(buffer[i] * 8388608.0f, -8388608.0f, 8388607.0f); int value = saturate(buffer[i] * 8388608.0f, -8388608.0f, 8388607.0f);
*((int*)temp2) = _swap32(value); *((int*)temp2) = _swap32(value);
@ -959,8 +963,8 @@ void WavOutFile::write(const float* buffer, int numElems)
case 4: case 4:
{ {
int* temp2 = (int*)temp; int *temp2 = (int *)temp;
for (int i = 0; i < numElems; i++) for (int i = 0; i < numElems; i ++)
{ {
int value = saturate(buffer[i] * 2147483648.0f, -2147483648.0f, 2147483647.0f); int value = saturate(buffer[i] * 2147483648.0f, -2147483648.0f, 2147483647.0f);
temp2[i] = _swap32(value); temp2[i] = _swap32(value);
@ -980,5 +984,3 @@ void WavOutFile::write(const float* buffer, int numElems)
} }
bytesWritten += numBytes; bytesWritten += numBytes;
} }
}

View File

@ -40,12 +40,7 @@
#ifndef WAVFILE_H #ifndef WAVFILE_H
#define WAVFILE_H #define WAVFILE_H
#include <cstdio> #include <stdio.h>
#include <string>
#include "SS_CharTypes.h"
namespace soundstretch
{
#ifndef uint #ifndef uint
typedef unsigned int uint; typedef unsigned int uint;
@ -123,6 +118,9 @@ private:
/// File pointer. /// File pointer.
FILE *fptr; FILE *fptr;
/// Position within the audio stream
long position;
/// Counter of how many bytes of sample data have been read from the file. /// Counter of how many bytes of sample data have been read from the file.
long dataRead; long dataRead;
@ -150,7 +148,7 @@ private:
public: public:
/// Constructor: Opens the given WAV file. If the file can't be opened, /// Constructor: Opens the given WAV file. If the file can't be opened,
/// throws 'runtime_error' exception. /// throws 'runtime_error' exception.
WavInFile(const STRING& filename); WavInFile(const char *filename);
WavInFile(FILE *file); WavInFile(FILE *file);
@ -246,7 +244,7 @@ private:
public: public:
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception /// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
/// if file creation fails. /// if file creation fails.
WavOutFile(const STRING& fileName, ///< Filename WavOutFile(const char *fileName, ///< Filename
int sampleRate, ///< Sample rate (e.g. 44100 etc) int sampleRate, ///< Sample rate (e.g. 44100 etc)
int bits, ///< Bits per sample (8 or 16 bits) int bits, ///< Bits per sample (8 or 16 bits)
int channels ///< Number of channels (1=mono, 2=stereo) int channels ///< Number of channels (1=mono, 2=stereo)
@ -276,6 +274,4 @@ public:
); );
}; };
}
#endif #endif

View File

@ -29,12 +29,10 @@
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <memory>
#include <stdexcept> #include <stdexcept>
#include <string> #include <stdio.h>
#include <cstdio> #include <string.h>
#include <ctime> #include <time.h>
#include "RunParameters.h" #include "RunParameters.h"
#include "WavFile.h" #include "WavFile.h"
#include "SoundTouch.h" #include "SoundTouch.h"
@ -43,21 +41,18 @@
using namespace soundtouch; using namespace soundtouch;
using namespace std; using namespace std;
namespace soundstretch
{
// Processing chunk size (size chosen to be divisible by 2, 4, 6, 8, 10, 12, 14, 16 channels ...) // Processing chunk size (size chosen to be divisible by 2, 4, 6, 8, 10, 12, 14, 16 channels ...)
#define BUFF_SIZE 6720 #define BUFF_SIZE 6720
#if _WIN32 #if _WIN32
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>
// Macro for Win32 standard input/output stream support: Sets a file stream into binary mode // Macro for Win32 standard input/output stream support: Sets a file stream into binary mode
#define SET_STREAM_TO_BIN_MODE(f) (_setmode(_fileno(f), _O_BINARY)) #define SET_STREAM_TO_BIN_MODE(f) (_setmode(_fileno(f), _O_BINARY))
#else #else
// Not needed for GNU environment... // Not needed for GNU environment...
#define SET_STREAM_TO_BIN_MODE(f) {} #define SET_STREAM_TO_BIN_MODE(f) {}
#endif #endif
@ -73,81 +68,90 @@ static const char _helloText[] =
"more information.\n" "more information.\n"
"\n"; "\n";
static void openFiles(unique_ptr<WavInFile>& inFile, unique_ptr<WavOutFile>& outFile, const RunParameters& params) static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParameters *params)
{ {
if (params.inFileName == STRING_CONST("stdin")) int bits, samplerate, channels;
if (strcmp(params->inFileName, "stdin") == 0)
{ {
// used 'stdin' as input file // used 'stdin' as input file
SET_STREAM_TO_BIN_MODE(stdin); SET_STREAM_TO_BIN_MODE(stdin);
inFile = make_unique<WavInFile>(stdin); *inFile = new WavInFile(stdin);
} }
else else
{ {
// open input file... // open input file...
inFile = make_unique<WavInFile>(params.inFileName.c_str()); *inFile = new WavInFile(params->inFileName);
} }
// ... open output file with same sound parameters // ... open output file with same sound parameters
const int bits = (int)inFile->getNumBits(); bits = (int)(*inFile)->getNumBits();
const int samplerate = (int)inFile->getSampleRate(); samplerate = (int)(*inFile)->getSampleRate();
const int channels = (int)inFile->getNumChannels(); channels = (int)(*inFile)->getNumChannels();
if (!params.outFileName.empty()) if (params->outFileName)
{ {
if (params.outFileName == STRING_CONST("stdout")) if (strcmp(params->outFileName, "stdout") == 0)
{ {
SET_STREAM_TO_BIN_MODE(stdout); SET_STREAM_TO_BIN_MODE(stdout);
outFile = make_unique<WavOutFile>(stdout, samplerate, bits, channels); *outFile = new WavOutFile(stdout, samplerate, bits, channels);
} }
else else
{ {
outFile = make_unique<WavOutFile>(params.outFileName.c_str(), samplerate, bits, channels); *outFile = new WavOutFile(params->outFileName, samplerate, bits, channels);
} }
} }
else
{
*outFile = NULL;
}
} }
// Sets the 'SoundTouch' object up according to input file sound format & // Sets the 'SoundTouch' object up according to input file sound format &
// command line parameters // command line parameters
static void setup(SoundTouch& soundTouch, const WavInFile& inFile, const RunParameters& params) static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunParameters *params)
{ {
const int sampleRate = (int)inFile.getSampleRate(); int sampleRate;
const int channels = (int)inFile.getNumChannels(); int channels;
soundTouch.setSampleRate(sampleRate);
soundTouch.setChannels(channels);
soundTouch.setTempoChange(params.tempoDelta); sampleRate = (int)inFile->getSampleRate();
soundTouch.setPitchSemiTones(params.pitchDelta); channels = (int)inFile->getNumChannels();
soundTouch.setRateChange(params.rateDelta); pSoundTouch->setSampleRate(sampleRate);
pSoundTouch->setChannels(channels);
soundTouch.setSetting(SETTING_USE_QUICKSEEK, params.quick); pSoundTouch->setTempoChange(params->tempoDelta);
soundTouch.setSetting(SETTING_USE_AA_FILTER, !(params.noAntiAlias)); pSoundTouch->setPitchSemiTones(params->pitchDelta);
pSoundTouch->setRateChange(params->rateDelta);
if (params.speech) pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, params->quick);
pSoundTouch->setSetting(SETTING_USE_AA_FILTER, !(params->noAntiAlias));
if (params->speech)
{ {
// use settings for speech processing // use settings for speech processing
soundTouch.setSetting(SETTING_SEQUENCE_MS, 40); pSoundTouch->setSetting(SETTING_SEQUENCE_MS, 40);
soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 15); pSoundTouch->setSetting(SETTING_SEEKWINDOW_MS, 15);
soundTouch.setSetting(SETTING_OVERLAP_MS, 8); pSoundTouch->setSetting(SETTING_OVERLAP_MS, 8);
fprintf(stderr, "Tune processing parameters for speech processing.\n"); fprintf(stderr, "Tune processing parameters for speech processing.\n");
} }
// print processing information // print processing information
if (!params.outFileName.empty()) if (params->outFileName)
{ {
#ifdef SOUNDTOUCH_INTEGER_SAMPLES #ifdef SOUNDTOUCH_INTEGER_SAMPLES
fprintf(stderr, "Uses 16bit integer sample type in processing.\n\n"); fprintf(stderr, "Uses 16bit integer sample type in processing.\n\n");
#else #else
#ifndef SOUNDTOUCH_FLOAT_SAMPLES #ifndef SOUNDTOUCH_FLOAT_SAMPLES
#error "Sampletype not defined" #error "Sampletype not defined"
#endif #endif
fprintf(stderr, "Uses 32bit floating point sample type in processing.\n\n"); fprintf(stderr, "Uses 32bit floating point sample type in processing.\n\n");
#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
@ -161,24 +165,30 @@ static void setup(SoundTouch& soundTouch, const WavInFile& inFile, const RunPara
// Processes the sound // Processes the sound
static void process(SoundTouch& soundTouch, WavInFile& inFile, WavOutFile& outFile) static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outFile)
{ {
SAMPLETYPE sampleBuffer[BUFF_SIZE];
int nSamples; int nSamples;
int nChannels;
int buffSizeSamples;
SAMPLETYPE sampleBuffer[BUFF_SIZE];
const int nChannels = (int)inFile.getNumChannels(); if ((inFile == NULL) || (outFile == NULL)) return; // nothing to do.
nChannels = (int)inFile->getNumChannels();
assert(nChannels > 0); assert(nChannels > 0);
const int buffSizeSamples = BUFF_SIZE / nChannels; buffSizeSamples = BUFF_SIZE / nChannels;
// Process samples read from the input file // Process samples read from the input file
while (inFile.eof() == 0) while (inFile->eof() == 0)
{ {
int num;
// Read a chunk of samples from the input file // Read a chunk of samples from the input file
const int num = inFile.read(sampleBuffer, BUFF_SIZE); num = inFile->read(sampleBuffer, BUFF_SIZE);
int nSamples = num / (int)inFile.getNumChannels(); nSamples = num / (int)inFile->getNumChannels();
// Feed the samples into SoundTouch processor // Feed the samples into SoundTouch processor
soundTouch.putSamples(sampleBuffer, nSamples); pSoundTouch->putSamples(sampleBuffer, nSamples);
// Read ready samples from SoundTouch processor & write them output file. // Read ready samples from SoundTouch processor & write them output file.
// NOTES: // NOTES:
@ -190,57 +200,61 @@ static void process(SoundTouch& soundTouch, WavInFile& inFile, WavOutFile& outFi
// outputs samples. // outputs samples.
do do
{ {
nSamples = soundTouch.receiveSamples(sampleBuffer, buffSizeSamples); nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
outFile.write(sampleBuffer, nSamples * nChannels); outFile->write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0); } while (nSamples != 0);
} }
// Now the input file is processed, yet 'flush' few last samples that are // Now the input file is processed, yet 'flush' few last samples that are
// hiding in the SoundTouch's internal processing pipeline. // hiding in the SoundTouch's internal processing pipeline.
soundTouch.flush(); pSoundTouch->flush();
do do
{ {
nSamples = soundTouch.receiveSamples(sampleBuffer, buffSizeSamples); nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
outFile.write(sampleBuffer, nSamples * nChannels); outFile->write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0); } while (nSamples != 0);
} }
// Detect BPM rate of inFile and adjust tempo setting accordingly if necessary // Detect BPM rate of inFile and adjust tempo setting accordingly if necessary
static void detectBPM(WavInFile& inFile, RunParameters& params) static void detectBPM(WavInFile *inFile, RunParameters *params)
{ {
BPMDetect bpm(inFile.getNumChannels(), inFile.getSampleRate()); float bpmValue;
int nChannels;
BPMDetect bpm(inFile->getNumChannels(), inFile->getSampleRate());
SAMPLETYPE sampleBuffer[BUFF_SIZE]; SAMPLETYPE sampleBuffer[BUFF_SIZE];
// detect bpm rate // detect bpm rate
fprintf(stderr, "Detecting BPM rate..."); fprintf(stderr, "Detecting BPM rate...");
fflush(stderr); fflush(stderr);
const int nChannels = (int)inFile.getNumChannels(); nChannels = (int)inFile->getNumChannels();
int readSize = BUFF_SIZE - BUFF_SIZE % nChannels; // round read size down to multiple of num.channels assert(BUFF_SIZE % nChannels == 0);
// Process the 'inFile' in small blocks, repeat until whole file has // Process the 'inFile' in small blocks, repeat until whole file has
// been processed // been processed
while (inFile.eof() == 0) while (inFile->eof() == 0)
{ {
int num, samples;
// Read sample data from input file // Read sample data from input file
const int num = inFile.read(sampleBuffer, readSize); num = inFile->read(sampleBuffer, BUFF_SIZE);
// Enter the new samples to the bpm analyzer class // Enter the new samples to the bpm analyzer class
const int samples = num / nChannels; samples = num / nChannels;
bpm.inputSamples(sampleBuffer, samples); bpm.inputSamples(sampleBuffer, samples);
} }
// Now the whole song data has been analyzed. Read the resulting bpm. // Now the whole song data has been analyzed. Read the resulting bpm.
const float bpmValue = bpm.getBpm(); bpmValue = bpm.getBpm();
fprintf(stderr, "Done!\n"); fprintf(stderr, "Done!\n");
// rewind the file after bpm detection // rewind the file after bpm detection
inFile.rewind(); inFile->rewind();
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
{ {
@ -248,74 +262,61 @@ static void detectBPM(WavInFile& inFile, RunParameters& params)
return; return;
} }
if (params.goalBPM > 0) if (params->goalBPM > 0)
{ {
// 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);
} }
} }
void printHelloText()
{
SoundTouch soundTouch;
fprintf(stderr, _helloText, soundTouch.getVersionString());
}
void ss_main(RunParameters& params) int main(const int nParams, const char * const paramStr[])
{ {
unique_ptr<WavInFile> inFile; WavInFile *inFile;
unique_ptr<WavOutFile> outFile; WavOutFile *outFile;
RunParameters *params;
SoundTouch soundTouch; SoundTouch soundTouch;
fprintf(stderr, _helloText, SoundTouch::getVersionString());
try
{
// Parse command line parameters
params = new RunParameters(nParams, paramStr);
// Open input & output files // Open input & output files
openFiles(inFile, outFile, params); openFiles(&inFile, &outFile, params);
if (params.detectBPM == true) if (params->detectBPM == true)
{ {
// detect sound BPM (and adjust processing parameters // detect sound BPM (and adjust processing parameters
// accordingly if necessary) // accordingly if necessary)
detectBPM(*inFile, params); detectBPM(inFile, params);
} }
// Setup the 'SoundTouch' object for processing the sound // Setup the 'SoundTouch' object for processing the sound
setup(soundTouch, *inFile, params); setup(&soundTouch, inFile, params);
// clock_t cs = clock(); // for benchmarking processing duration // clock_t cs = clock(); // for benchmarking processing duration
// Process the sound // Process the sound
if (inFile && outFile) process(&soundTouch, inFile, outFile);
{
process(soundTouch, *inFile, *outFile);
}
// clock_t ce = clock(); // for benchmarking processing duration // clock_t ce = clock(); // for benchmarking processing duration
// printf("duration: %lf\n", (double)(ce-cs)/CLOCKS_PER_SEC); // printf("duration: %lf\n", (double)(ce-cs)/CLOCKS_PER_SEC);
// Close WAV file handles & dispose of the objects
delete inFile;
delete outFile;
delete params;
fprintf(stderr, "Done!\n"); fprintf(stderr, "Done!\n");
}
}
#if _WIN32
int wmain(int argc, const wchar_t* args[])
#else
int main(int argc, const char* args[])
#endif
{
try
{
soundstretch::printHelloText();
soundstretch::RunParameters params(argc, args);
soundstretch::ss_main(params);
} }
catch (const runtime_error& e) catch (const runtime_error &e)
{ {
// An exception occurred during processing, display an error message
fprintf(stderr, "%s\n", e.what()); fprintf(stderr, "%s\n", e.what());
return -1; return -1;
} }
catch (const string& e)
{
fprintf(stderr, "%s\n", e.c_str());
return -1;
}
return 0; return 0;
} }

View File

@ -21,32 +21,32 @@
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}</ProjectGuid> <ProjectGuid>{5AACDFFA-D491-44B8-A332-DA7ACCAAF2AF}</ProjectGuid>
<RootNamespace>soundstretch</RootNamespace> <RootNamespace>soundstretch</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@ -114,10 +114,9 @@
<BrowseInformation>true</BrowseInformation> <BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner> <SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -134,7 +133,10 @@
<GenerateMapFile>true</GenerateMapFile> <GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName> <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention /> <DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin <Command>if not exist ..\..\bin mkdir ..\..\bin
@ -165,7 +167,6 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -180,7 +181,9 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<GenerateMapFile>true</GenerateMapFile> <GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName> <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention /> <DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin <Command>if not exist ..\..\bin mkdir ..\..\bin
@ -212,7 +215,6 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet> </EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -229,7 +231,9 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<GenerateMapFile>true</GenerateMapFile> <GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName> <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention /> <DataExecutionPrevention />
<TargetMachine>MachineX64</TargetMachine>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin <Command>if not exist ..\..\bin mkdir ..\..\bin
@ -262,7 +266,6 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>
</EnableEnhancedInstructionSet> </EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -277,7 +280,9 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
<GenerateMapFile>true</GenerateMapFile> <GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName> <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention /> <DataExecutionPrevention />
<TargetMachine>MachineX64</TargetMachine>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>if not exist ..\..\bin mkdir ..\..\bin <Command>if not exist ..\..\bin mkdir ..\..\bin
@ -318,7 +323,6 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\bin\</Command>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="RunParameters.h" /> <ClInclude Include="RunParameters.h" />
<ClInclude Include="SS_CharTypes.h" />
<ClInclude Include="WavFile.h" /> <ClInclude Include="WavFile.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -54,7 +54,7 @@ using namespace soundtouch;
static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len) static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
{ {
FILE *fptr = fopen("aa_filter_coeffs.txt", "wt"); FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
if (fptr == nullptr) return; if (fptr == NULL) return;
for (int i = 0; i < len; i ++) for (int i = 0; i < len; i ++)
{ {

View File

@ -186,10 +186,8 @@ BPMDetect::BPMDetect(int numChannels, int aSampleRate) :
// choose decimation factor so that result is approx. 1000 Hz // choose decimation factor so that result is approx. 1000 Hz
decimateBy = sampleRate / TARGET_SRATE; decimateBy = sampleRate / TARGET_SRATE;
if ((decimateBy <= 0) || (decimateBy * DECIMATED_BLOCK_SIZE < INPUT_BLOCK_SIZE)) assert(decimateBy > 0);
{ assert(INPUT_BLOCK_SIZE < decimateBy * DECIMATED_BLOCK_SIZE);
ST_THROW_RT_ERROR("Too small samplerate");
}
// Calculate window length & starting item according to desired min & max bpms // Calculate window length & starting item according to desired min & max bpms
windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM); windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
@ -301,7 +299,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];
@ -313,7 +311,7 @@ void BPMDetect::updateXCorr(int process_samples)
#pragma omp parallel for #pragma omp parallel for
for (offs = windowStart; offs < windowLen; offs ++) for (offs = windowStart; offs < windowLen; offs ++)
{ {
float sum; double sum;
int i; int i;
sum = 0; sum = 0;
@ -341,6 +339,7 @@ void BPMDetect::updateBeatPos(int process_samples)
// static double thr = 0.0003; // static double thr = 0.0003;
double posScale = (double)this->decimateBy / (double)this->sampleRate; double posScale = (double)this->decimateBy / (double)this->sampleRate;
int resetDur = (int)(0.12 / posScale + 0.5); int resetDur = (int)(0.12 / posScale + 0.5);
double corrScale = 1.0 / (double)(windowLen - windowStart);
// prescale pbuffer // prescale pbuffer
float tmp[XCORR_UPDATE_SEQUENCE / 2]; float tmp[XCORR_UPDATE_SEQUENCE / 2];
@ -352,7 +351,7 @@ void BPMDetect::updateBeatPos(int process_samples)
#pragma omp parallel for #pragma omp parallel for
for (int offs = windowStart; offs < windowLen; offs++) for (int offs = windowStart; offs < windowLen; offs++)
{ {
float sum = 0; double sum = 0;
for (int i = 0; i < process_samples; i++) for (int i = 0; i < process_samples; i++)
{ {
sum += tmp[i] * pBuffer[offs + i]; sum += tmp[i] * pBuffer[offs + i];
@ -376,6 +375,8 @@ void BPMDetect::updateBeatPos(int process_samples)
// detect beats // detect beats
for (int i = 0; i < skipstep; i++) for (int i = 0; i < skipstep; i++)
{ {
LONG_SAMPLETYPE max = 0;
float sum = beatcorr_ringbuff[beatcorr_ringbuffpos]; float sum = beatcorr_ringbuff[beatcorr_ringbuffpos];
sum -= beat_lpf.update(sum); sum -= beat_lpf.update(sum);
@ -554,13 +555,13 @@ float BPMDetect::getBpm()
/// - "values" receive array of beat detection strengths /// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array. /// - max_num indicates max.size of "pos" and "values" array.
/// ///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values". /// You can query a suitable array sized by calling this with NULL in "pos" & "values".
/// ///
/// \return number of beats in the arrays. /// \return number of beats in the arrays.
int BPMDetect::getBeats(float *pos, float *values, int max_num) int BPMDetect::getBeats(float *pos, float *values, int max_num)
{ {
int num = (int)beats.size(); int num = beats.size();
if ((!pos) || (!values)) return num; // pos or values nullptr, return just size if ((!pos) || (!values)) return num; // pos or values NULL, return just size
for (int i = 0; (i < num) && (i < max_num); i++) for (int i = 0; (i < num) && (i < max_num); i++)
{ {

View File

@ -50,8 +50,8 @@ FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
{ {
assert(numChannels > 0); assert(numChannels > 0);
sizeInBytes = 0; // reasonable initial value sizeInBytes = 0; // reasonable initial value
buffer = nullptr; buffer = NULL;
bufferUnaligned = nullptr; bufferUnaligned = NULL;
samplesInBuffer = 0; samplesInBuffer = 0;
bufferPos = 0; bufferPos = 0;
channels = (uint)numChannels; channels = (uint)numChannels;
@ -63,8 +63,8 @@ FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
FIFOSampleBuffer::~FIFOSampleBuffer() FIFOSampleBuffer::~FIFOSampleBuffer()
{ {
delete[] bufferUnaligned; delete[] bufferUnaligned;
bufferUnaligned = nullptr; bufferUnaligned = NULL;
buffer = nullptr; buffer = NULL;
} }
@ -166,7 +166,7 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096; sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
assert(sizeInBytes % 2 == 0); assert(sizeInBytes % 2 == 0);
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
if (tempUnaligned == nullptr) if (tempUnaligned == NULL)
{ {
ST_THROW_RT_ERROR("Couldn't allocate memory!\n"); ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
} }
@ -265,11 +265,3 @@ uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
} }
return samplesInBuffer; return samplesInBuffer;
} }
/// Add silence to end of buffer
void FIFOSampleBuffer::addSilent(uint nSamples)
{
memset(ptrEnd(nSamples), 0, sizeof(SAMPLETYPE) * nSamples * channels);
samplesInBuffer += nSamples;
}

View File

@ -56,17 +56,16 @@ using namespace soundtouch;
FIRFilter::FIRFilter() FIRFilter::FIRFilter()
{ {
resultDivFactor = 0; resultDivFactor = 0;
resultDivider = 0;
length = 0; length = 0;
lengthDiv8 = 0; lengthDiv8 = 0;
filterCoeffs = nullptr; filterCoeffs = NULL;
filterCoeffsStereo = nullptr;
} }
FIRFilter::~FIRFilter() FIRFilter::~FIRFilter()
{ {
delete[] filterCoeffs; delete[] filterCoeffs;
delete[] filterCoeffsStereo;
} }
@ -74,27 +73,40 @@ FIRFilter::~FIRFilter()
uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{ {
int j, end; int j, end;
// hint compiler autovectorization that loop length is divisible by 8 #ifdef SOUNDTOUCH_FLOAT_SAMPLES
uint ilength = length & -8; // when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
#endif
assert((length != 0) && (length == ilength) && (src != nullptr) && (dest != nullptr) && (filterCoeffs != nullptr)); assert(length != 0);
assert(numSamples > ilength); assert(src != NULL);
assert(dest != NULL);
assert(filterCoeffs != NULL);
end = 2 * (numSamples - ilength); end = 2 * (numSamples - length);
#pragma omp parallel for #pragma omp parallel for
for (j = 0; j < end; j += 2) for (j = 0; j < end; j += 2)
{ {
const SAMPLETYPE *ptr; const SAMPLETYPE *ptr;
LONG_SAMPLETYPE suml, sumr; LONG_SAMPLETYPE suml, sumr;
uint i;
suml = sumr = 0; suml = sumr = 0;
ptr = src + j; ptr = src + j;
for (uint i = 0; i < ilength; i ++) for (i = 0; i < length; i += 4)
{ {
suml += ptr[2 * i] * filterCoeffsStereo[2 * i]; // loop is unrolled by factor of 4 here for efficiency
sumr += ptr[2 * i + 1] * filterCoeffsStereo[2 * i + 1]; suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
ptr[2 * i + 2] * filterCoeffs[i + 1] +
ptr[2 * i + 4] * filterCoeffs[i + 2] +
ptr[2 * i + 6] * filterCoeffs[i + 3];
sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
ptr[2 * i + 3] * filterCoeffs[i + 1] +
ptr[2 * i + 5] * filterCoeffs[i + 2] +
ptr[2 * i + 7] * filterCoeffs[i + 3];
} }
#ifdef SOUNDTOUCH_INTEGER_SAMPLES #ifdef SOUNDTOUCH_INTEGER_SAMPLES
@ -104,11 +116,14 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml; suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
// saturate to 16 bit integer limits // saturate to 16 bit integer limits
sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr; sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
#else
suml *= dScaler;
sumr *= dScaler;
#endif // SOUNDTOUCH_INTEGER_SAMPLES #endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)suml; dest[j] = (SAMPLETYPE)suml;
dest[j + 1] = (SAMPLETYPE)sumr; dest[j + 1] = (SAMPLETYPE)sumr;
} }
return numSamples - ilength; return numSamples - length;
} }
@ -116,29 +131,37 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{ {
int j, end; int j, end;
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
#endif
// hint compiler autovectorization that loop length is divisible by 8 assert(length != 0);
int ilength = length & -8;
assert(ilength != 0); end = numSamples - length;
end = numSamples - ilength;
#pragma omp parallel for #pragma omp parallel for
for (j = 0; j < end; j ++) for (j = 0; j < end; j ++)
{ {
const SAMPLETYPE *pSrc = src + j; const SAMPLETYPE *pSrc = src + j;
LONG_SAMPLETYPE sum; LONG_SAMPLETYPE sum;
int i; uint i;
sum = 0; sum = 0;
for (i = 0; i < ilength; i ++) for (i = 0; i < length; i += 4)
{ {
sum += pSrc[i] * filterCoeffs[i]; // loop is unrolled by factor of 4 here for efficiency
sum += pSrc[i + 0] * filterCoeffs[i + 0] +
pSrc[i + 1] * filterCoeffs[i + 1] +
pSrc[i + 2] * filterCoeffs[i + 2] +
pSrc[i + 3] * filterCoeffs[i + 3];
} }
#ifdef SOUNDTOUCH_INTEGER_SAMPLES #ifdef SOUNDTOUCH_INTEGER_SAMPLES
sum >>= resultDivFactor; sum >>= resultDivFactor;
// saturate to 16 bit integer limits // saturate to 16 bit integer limits
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum; sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
#else
sum *= dScaler;
#endif // SOUNDTOUCH_INTEGER_SAMPLES #endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)sum; dest[j] = (SAMPLETYPE)sum;
} }
@ -150,24 +173,26 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
{ {
int j, end; int j, end;
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// when using floating point samples, use a scaler instead of a divider
// because division is much slower operation than multiplying.
double dScaler = 1.0 / (double)resultDivider;
#endif
assert(length != 0); assert(length != 0);
assert(src != nullptr); assert(src != NULL);
assert(dest != nullptr); assert(dest != NULL);
assert(filterCoeffs != nullptr); assert(filterCoeffs != NULL);
assert(numChannels <= SOUNDTOUCH_MAX_CHANNELS); assert(numChannels < 16);
// hint compiler autovectorization that loop length is divisible by 8 end = numChannels * (numSamples - length);
int ilength = length & -8;
end = numChannels * (numSamples - ilength);
#pragma omp parallel for #pragma omp parallel for
for (j = 0; j < end; j += numChannels) for (j = 0; j < end; j += numChannels)
{ {
const SAMPLETYPE *ptr; const SAMPLETYPE *ptr;
LONG_SAMPLETYPE sums[16]; LONG_SAMPLETYPE sums[16];
uint c; uint c, i;
int i;
for (c = 0; c < numChannels; c ++) for (c = 0; c < numChannels; c ++)
{ {
@ -176,7 +201,7 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
ptr = src + j; ptr = src + j;
for (i = 0; i < ilength; i ++) for (i = 0; i < length; i ++)
{ {
SAMPLETYPE coef=filterCoeffs[i]; SAMPLETYPE coef=filterCoeffs[i];
for (c = 0; c < numChannels; c ++) for (c = 0; c < numChannels; c ++)
@ -190,11 +215,13 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
{ {
#ifdef SOUNDTOUCH_INTEGER_SAMPLES #ifdef SOUNDTOUCH_INTEGER_SAMPLES
sums[c] >>= resultDivFactor; sums[c] >>= resultDivFactor;
#else
sums[c] *= dScaler;
#endif // SOUNDTOUCH_INTEGER_SAMPLES #endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j+c] = (SAMPLETYPE)sums[c]; dest[j+c] = (SAMPLETYPE)sums[c];
} }
} }
return numSamples - ilength; return numSamples - length;
} }
@ -211,27 +238,11 @@ void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint u
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; memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
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 ++)
{
filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale);
// create also stereo set of filter coefficients: this allows compiler
// to autovectorize filter evaluation much more efficiently
filterCoeffsStereo[2 * i] = (SAMPLETYPE)(coeffs[i] * scale);
filterCoeffsStereo[2 * i + 1] = (SAMPLETYPE)(coeffs[i] * scale);
}
} }
@ -272,7 +283,7 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample
// Operator 'new' is overloaded so that it automatically creates a suitable instance // Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX-capable CPU available or not. // depending on if we've a MMX-capable CPU available or not.
void * FIRFilter::operator new(size_t) void * FIRFilter::operator new(size_t s)
{ {
// Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead! // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"); ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
@ -285,7 +296,6 @@ FIRFilter * FIRFilter::newInstance()
uint uExtensions; uint uExtensions;
uExtensions = detectCPUextensions(); uExtensions = detectCPUextensions();
(void)uExtensions;
// Check if MMX/SSE instruction set extensions supported by CPU // Check if MMX/SSE instruction set extensions supported by CPU

View File

@ -52,9 +52,11 @@ 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;
virtual uint evaluateFilterStereo(SAMPLETYPE *dest, virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
@ -103,12 +105,12 @@ public:
short *filterCoeffsUnalign; short *filterCoeffsUnalign;
short *filterCoeffsAlign; short *filterCoeffsAlign;
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const override; virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const;
public: public:
FIRFilterMMX(); FIRFilterMMX();
~FIRFilterMMX(); ~FIRFilterMMX();
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor) override; virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
}; };
#endif // SOUNDTOUCH_ALLOW_MMX #endif // SOUNDTOUCH_ALLOW_MMX
@ -122,12 +124,12 @@ public:
float *filterCoeffsUnalign; float *filterCoeffsUnalign;
float *filterCoeffsAlign; float *filterCoeffsAlign;
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const override; virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
public: public:
FIRFilterSSE(); FIRFilterSSE();
~FIRFilterSSE(); ~FIRFilterSSE();
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor) override; virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
}; };
#endif // SOUNDTOUCH_ALLOW_SSE #endif // SOUNDTOUCH_ALLOW_SSE

View File

@ -41,27 +41,21 @@ namespace soundtouch
class InterpolateCubic : public TransposerBase class InterpolateCubic : public TransposerBase
{ {
protected: protected:
virtual void resetRegisters();
virtual int transposeMono(SAMPLETYPE *dest, virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
virtual int transposeStereo(SAMPLETYPE *dest, virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
virtual int transposeMulti(SAMPLETYPE *dest, virtual int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
double fract; double fract;
public: public:
InterpolateCubic(); InterpolateCubic();
virtual void resetRegisters() override;
virtual int getLatency() const override
{
return 1;
}
}; };
} }

View File

@ -142,7 +142,7 @@ int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE
LONG_SAMPLETYPE temp, vol1; LONG_SAMPLETYPE temp, vol1;
assert(iFract < SCALE); assert(iFract < SCALE);
vol1 = (LONG_SAMPLETYPE)(SCALE - iFract); vol1 = (SCALE - iFract);
for (int c = 0; c < numChannels; c ++) for (int c = 0; c < numChannels; c ++)
{ {
temp = vol1 * src[c] + iFract * src[c + numChannels]; temp = vol1 * src[c] + iFract * src[c + numChannels];

View File

@ -45,26 +45,21 @@ protected:
int iFract; int iFract;
int iRate; int iRate;
virtual void resetRegisters();
virtual int transposeMono(SAMPLETYPE *dest, virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
virtual int transposeStereo(SAMPLETYPE *dest, virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples) override; virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
public: public:
InterpolateLinearInteger(); InterpolateLinearInteger();
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
/// rate, larger faster rates. /// rate, larger faster rates.
virtual void setRate(double newRate) override; virtual void setRate(double newRate);
virtual void resetRegisters() override;
virtual int getLatency() const override
{
return 0;
}
}; };
@ -74,6 +69,8 @@ class InterpolateLinearFloat : public TransposerBase
protected: protected:
double fract; double fract;
virtual void resetRegisters();
virtual int transposeMono(SAMPLETYPE *dest, virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples); int &srcSamples);
@ -84,13 +81,6 @@ protected:
public: public:
InterpolateLinearFloat(); InterpolateLinearFloat();
virtual void resetRegisters();
int getLatency() const
{
return 0;
}
}; };
} }

View File

@ -171,9 +171,9 @@ int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
/// Transpose stereo audio. Returns number of produced output samples, and /// Transpose stereo audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples /// updates "srcSamples" to amount of consumed source samples
int InterpolateShannon::transposeMulti(SAMPLETYPE *, int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
const SAMPLETYPE *, const SAMPLETYPE *psrc,
int &) int &srcSamples)
{ {
// not implemented // not implemented
assert(false); assert(false);

View File

@ -46,27 +46,21 @@ namespace soundtouch
class InterpolateShannon : public TransposerBase class InterpolateShannon : public TransposerBase
{ {
protected: protected:
void resetRegisters();
int transposeMono(SAMPLETYPE *dest, int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
int transposeStereo(SAMPLETYPE *dest, int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
int transposeMulti(SAMPLETYPE *dest, int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) override; int &srcSamples);
double fract; double fract;
public: public:
InterpolateShannon(); InterpolateShannon();
void resetRegisters() override;
virtual int getLatency() const override
{
return 3;
}
}; };
} }

View File

@ -33,7 +33,7 @@ libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp \
InterpolateShannon.cpp InterpolateShannon.cpp
# Compiler flags # Compiler flags
#AM_CXXFLAGS+= AM_CXXFLAGS+=-O3
# Compile the files that need MMX and SSE individually. # Compile the files that need MMX and SSE individually.
libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la

View File

@ -57,7 +57,7 @@ int PeakFinder::findTop(const float *data, int peakpos) const
refvalue = data[peakpos]; refvalue = data[peakpos];
// seek within ±10 points // seek within <EFBFBD>10 points
start = peakpos - 10; start = peakpos - 10;
if (start < minPos) start = minPos; if (start < minPos) start = minPos;
end = peakpos + 10; end = peakpos + 10;
@ -142,7 +142,7 @@ int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, i
peaklevel = data[peakpos]; peaklevel = data[peakpos];
assert(peaklevel >= level); assert(peaklevel >= level);
pos = peakpos; pos = peakpos;
while ((pos >= minPos) && (pos + direction < maxPos)) while ((pos >= minPos) && (pos < maxPos))
{ {
if (data[pos + direction] < level) return pos; // crossing found if (data[pos + direction] < level) return pos; // crossing found
pos += direction; pos += direction;
@ -256,7 +256,7 @@ double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
// accept harmonic peak if // accept harmonic peak if
// (a) it is found // (a) it is found
// (b) is within ±4% of the expected harmonic interval // (b) is within <EFBFBD>4% of the expected harmonic interval
// (c) has at least half x-corr value of the max. peak // (c) has at least half x-corr value of the max. peak
double diff = harmonic * peaktmp / highPeak; double diff = harmonic * peaktmp / highPeak;

View File

@ -61,7 +61,6 @@ RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
// Instantiates the anti-alias filter // Instantiates the anti-alias filter
pAAFilter = new AAFilter(64); pAAFilter = new AAFilter(64);
pTransposer = TransposerBase::newInstance(); pTransposer = TransposerBase::newInstance();
clear();
} }
@ -78,7 +77,6 @@ void RateTransposer::enableAAFilter(bool newMode)
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
// Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
bUseAAFilter = newMode; bUseAAFilter = newMode;
clear();
#endif #endif
} }
@ -131,6 +129,8 @@ void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
// the 'set_returnBuffer_size' function. // the 'set_returnBuffer_size' function.
void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
{ {
uint count;
if (nSamples == 0) return; if (nSamples == 0) return;
// Store samples to input buffer // Store samples to input buffer
@ -140,7 +140,7 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
// the filter // the filter
if (bUseAAFilter == false) if (bUseAAFilter == false)
{ {
(void)pTransposer->transpose(outputBuffer, inputBuffer); count = pTransposer->transpose(outputBuffer, inputBuffer);
return; return;
} }
@ -192,11 +192,6 @@ void RateTransposer::clear()
outputBuffer.clear(); outputBuffer.clear();
midBuffer.clear(); midBuffer.clear();
inputBuffer.clear(); inputBuffer.clear();
pTransposer->resetRegisters();
// prefill buffer to avoid losing first samples at beginning of stream
int prefill = getLatency();
inputBuffer.addSilent(prefill);
} }
@ -214,8 +209,7 @@ int RateTransposer::isEmpty() const
/// Return approximate initial input-output latency /// Return approximate initial input-output latency
int RateTransposer::getLatency() const int RateTransposer::getLatency() const
{ {
return pTransposer->getLatency() + return (bUseAAFilter) ? pAAFilter->getLength() : 0;
((bUseAAFilter) ? (pAAFilter->getLength() / 2) : 0);
} }
@ -307,7 +301,7 @@ TransposerBase *TransposerBase::newInstance()
default: default:
assert(false); assert(false);
return nullptr; return NULL;
} }
#endif #endif
} }

View File

@ -59,6 +59,8 @@ public:
}; };
protected: protected:
virtual void resetRegisters() = 0;
virtual int transposeMono(SAMPLETYPE *dest, virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src, const SAMPLETYPE *src,
int &srcSamples) = 0; int &srcSamples) = 0;
@ -81,9 +83,6 @@ public:
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src); virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
virtual void setRate(double newRate); virtual void setRate(double newRate);
virtual void setChannels(int channels); virtual void setChannels(int channels);
virtual int getLatency() const = 0;
virtual void resetRegisters() = 0;
// static factory function // static factory function
static TransposerBase *newInstance(); static TransposerBase *newInstance();
@ -124,7 +123,7 @@ protected:
public: public:
RateTransposer(); RateTransposer();
virtual ~RateTransposer() override; virtual ~RateTransposer();
/// Returns the output buffer object /// Returns the output buffer object
FIFOSamplePipe *getOutput() { return &outputBuffer; }; FIFOSamplePipe *getOutput() { return &outputBuffer; };
@ -147,13 +146,13 @@ public:
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into /// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object. /// the input of the object.
void putSamples(const SAMPLETYPE *samples, uint numSamples) override; void putSamples(const SAMPLETYPE *samples, uint numSamples);
/// Clears all the samples in the object /// Clears all the samples in the object
void clear() override; void clear();
/// Returns nonzero if there aren't any samples available for outputting. /// Returns nonzero if there aren't any samples available for outputting.
int isEmpty() const override; int isEmpty() const;
/// Return approximate initial input-output latency /// Return approximate initial input-output latency
int getLatency() const; int getLatency() const;

View File

@ -413,15 +413,15 @@ int SoundTouch::getSetting(int settingId) const
return (uint)pTDStretch->isQuickSeekEnabled(); return (uint)pTDStretch->isQuickSeekEnabled();
case SETTING_SEQUENCE_MS: case SETTING_SEQUENCE_MS:
pTDStretch->getParameters(nullptr, &temp, nullptr, nullptr); pTDStretch->getParameters(NULL, &temp, NULL, NULL);
return temp; return temp;
case SETTING_SEEKWINDOW_MS: case SETTING_SEEKWINDOW_MS:
pTDStretch->getParameters(nullptr, nullptr, &temp, nullptr); pTDStretch->getParameters(NULL, NULL, &temp, NULL);
return temp; return temp;
case SETTING_OVERLAP_MS: case SETTING_OVERLAP_MS:
pTDStretch->getParameters(nullptr, nullptr, nullptr, &temp); pTDStretch->getParameters(NULL, NULL, NULL, &temp);
return temp; return temp;
case SETTING_NOMINAL_INPUT_SEQUENCE : case SETTING_NOMINAL_INPUT_SEQUENCE :

View File

@ -20,32 +20,32 @@
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{68A5DD20-7057-448B-8FE0-B6AC8D205509}</ProjectGuid> <ProjectGuid>{68A5DD20-7057-448B-8FE0-B6AC8D205509}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@ -112,7 +112,6 @@
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName> <XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile> <BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -154,7 +153,6 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\lib</Command>
</EnableEnhancedInstructionSet> </EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName> <XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile> <BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -185,12 +183,11 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\lib</Command>
<BrowseInformation>true</BrowseInformation> <BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner> <SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName> <XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile> <BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -230,7 +227,6 @@ copy $(OutDir)$(TargetName)$(TargetExt) ..\..\lib</Command>
</EnableEnhancedInstructionSet> </EnableEnhancedInstructionSet>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName> <XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformationFile>$(IntDir)</BrowseInformationFile> <BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

View File

@ -1,4 +1,4 @@
/////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// ///
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo /// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
/// while maintaining the original pitch by using a time domain WSOLA-like /// while maintaining the original pitch by using a time domain WSOLA-like
@ -54,6 +54,26 @@ using namespace soundtouch;
#define max(x, y) (((x) > (y)) ? (x) : (y)) #define max(x, y) (((x) > (y)) ? (x) : (y))
/*****************************************************************************
*
* Constant definitions
*
*****************************************************************************/
// Table for the hierarchical mixing position seeking algorithm
const short _scanOffsets[5][24]={
{ 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806,
868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0},
{-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 121, 114, 97, 114, 98, 105, 108, 32, 104, 99, 117, 111,
116, 100, 110, 117, 111, 115, 0, 0, 0, 0, 0, 0}};
/***************************************************************************** /*****************************************************************************
* *
* Implementation of the class 'TDStretch' * Implementation of the class 'TDStretch'
@ -66,13 +86,18 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
bQuickSeek = false; bQuickSeek = false;
channels = 2; channels = 2;
pMidBuffer = nullptr; pMidBuffer = NULL;
pMidBufferUnaligned = nullptr; pMidBufferUnaligned = NULL;
overlapLength = 0; overlapLength = 0;
bAutoSeqSetting = true; bAutoSeqSetting = true;
bAutoSeekSetting = true; bAutoSeekSetting = true;
maxnorm = 0;
maxnormf = 1e8;
skipFract = 0;
tempo = 1.0f; tempo = 1.0f;
setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
setTempo(1.0f); setTempo(1.0f);
@ -143,7 +168,7 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
/// Get routine control parameters, see setParameters() function. /// Get routine control parameters, see setParameters() function.
/// Any of the parameters to this function can be nullptr, in such case corresponding parameter /// Any of the parameters to this function can be NULL, in such case corresponding parameter
/// value isn't returned. /// value isn't returned.
void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const
{ {
@ -199,9 +224,6 @@ void TDStretch::clearInput()
inputBuffer.clear(); inputBuffer.clear();
clearMidBuffer(); clearMidBuffer();
isBeginning = true; isBeginning = true;
maxnorm = 0;
maxnormf = 1e8;
skipFract = 0;
} }
@ -293,10 +315,9 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
{ {
double corr; double corr;
// Calculates correlation value for the mixing position corresponding to 'i' // Calculates correlation value for the mixing position corresponding to 'i'
#if defined(_OPENMP) || defined(ST_SIMD_AVOID_UNALIGNED) #ifdef _OPENMP
// in parallel OpenMP mode, can't use norm accumulator version as parallel executor won't // in parallel OpenMP mode, can't use norm accumulator version as parallel executor won't
// iterate the loop in sequential order // iterate the loop in sequential order
// in SIMD mode, avoid accumulator version to allow avoiding unaligned positions
corr = calcCrossCorr(refPos + channels * i, pMidBuffer, norm); corr = calcCrossCorr(refPos + channels * i, pMidBuffer, norm);
#else #else
// In non-parallel version call "calcCrossCorrAccumulate" that is otherwise same // In non-parallel version call "calcCrossCorrAccumulate" that is otherwise same
@ -654,10 +675,11 @@ void TDStretch::processSamples()
// Adjust processing offset at beginning of track by not perform initial overlapping // Adjust processing offset at beginning of track by not perform initial overlapping
// and compensating that in the 'input buffer skip' calculation // and compensating that in the 'input buffer skip' calculation
isBeginning = false; isBeginning = false;
int skip = (int)(tempo * overlapLength + 0.5 * seekLength + 0.5); int skip = (int)(tempo * overlapLength + 0.5);
#ifdef ST_SIMD_AVOID_UNALIGNED #ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
// in SIMD mode, round the skip amount to value corresponding to aligned memory address #ifdef SOUNDTOUCH_ALLOW_SSE
// if SSE mode, round the skip amount to value corresponding to aligned memory address
if (channels == 1) if (channels == 1)
{ {
skip &= -4; skip &= -4;
@ -667,11 +689,9 @@ void TDStretch::processSamples()
skip &= -2; skip &= -2;
} }
#endif #endif
#endif
skipFract -= skip; skipFract -= skip;
if (skipFract <= -nominalSkip) assert(nominalSkip >= -skipFract);
{
skipFract = -nominalSkip;
}
} }
// ... then copy sequence samples from 'inputBuffer' to output: // ... then copy sequence samples from 'inputBuffer' to output:
@ -740,7 +760,7 @@ void TDStretch::acceptNewOverlapLength(int newOverlapLength)
// Operator 'new' is overloaded so that it automatically creates a suitable instance // 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. // depending on if we've a MMX/SSE/etc-capable CPU available or not.
void * TDStretch::operator new(size_t) void * TDStretch::operator new(size_t s)
{ {
// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead! // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
ST_THROW_RT_ERROR("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!"); ST_THROW_RT_ERROR("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!");
@ -753,7 +773,6 @@ TDStretch * TDStretch::newInstance()
uint uExtensions; uint uExtensions;
uExtensions = detectCPUextensions(); uExtensions = detectCPUextensions();
(void)uExtensions;
// Check if MMX/SSE instruction set extensions supported by CPU // Check if MMX/SSE instruction set extensions supported by CPU
@ -811,19 +830,21 @@ void TDStretch::overlapStereo(short *poutput, const short *input) const
// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Multi' // Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Multi'
// version of the routine. // version of the routine.
void TDStretch::overlapMulti(short *poutput, const short *input) const void TDStretch::overlapMulti(SAMPLETYPE *poutput, const SAMPLETYPE *input) const
{ {
short m1; SAMPLETYPE m1=(SAMPLETYPE)0;
int i = 0; SAMPLETYPE m2;
int i=0;
for (m1 = 0; m1 < overlapLength; m1 ++) for (m2 = (SAMPLETYPE)overlapLength; m2; m2 --)
{ {
short m2 = (short)(overlapLength - m1);
for (int c = 0; c < channels; c ++) for (int c = 0; c < channels; c ++)
{ {
poutput[i] = (input[i] * m1 + pMidBuffer[i] * m2) / overlapLength; poutput[i] = (input[i] * m1 + pMidBuffer[i] * m2) / overlapLength;
i++; i++;
} }
m1++;
} }
} }
@ -868,23 +889,20 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
unsigned long lnorm; unsigned long lnorm;
int i; int i;
#ifdef ST_SIMD_AVOID_UNALIGNED
// in SIMD mode skip 'mixingPos' positions that aren't aligned to 16-byte boundary
if (((ulongptr)mixingPos) & 15) return -1e50;
#endif
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
corr = lnorm = 0; corr = lnorm = 0;
// Same routine for stereo and mono // Same routine for stereo and mono. For stereo, unroll loop for better
for (i = 0; i < ilength; i += 2) // efficiency and gives slightly better resolution against rounding.
// For mono it same routine, just unrolls loop by factor of 4
for (i = 0; i < channels * overlapLength; i += 4)
{ {
corr += (mixingPos[i] * compare[i] + corr += (mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
corr += (mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBitsNorm;
lnorm += (mixingPos[i] * mixingPos[i] + lnorm += (mixingPos[i] * mixingPos[i] +
mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBitsNorm; mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
// do intermediate scalings to avoid integer overflow lnorm += (mixingPos[i + 2] * mixingPos[i + 2] +
mixingPos[i + 3] * mixingPos[i + 3]) >> overlapDividerBitsNorm;
} }
if (lnorm > maxnorm) if (lnorm > maxnorm)
@ -907,12 +925,9 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm) double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm)
{ {
long corr; long corr;
long lnorm; unsigned long lnorm;
int i; int i;
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
// cancel first normalizer tap from previous round // cancel first normalizer tap from previous round
lnorm = 0; lnorm = 0;
for (i = 1; i <= channels; i ++) for (i = 1; i <= channels; i ++)
@ -921,11 +936,15 @@ double TDStretch::calcCrossCorrAccumulate(const short *mixingPos, const short *c
} }
corr = 0; corr = 0;
// Same routine for stereo and mono. // Same routine for stereo and mono. For stereo, unroll loop for better
for (i = 0; i < ilength; i += 2) // efficiency and gives slightly better resolution against rounding.
// For mono it same routine, just unrolls loop by factor of 4
for (i = 0; i < channels * overlapLength; i += 4)
{ {
corr += (mixingPos[i] * compare[i] + corr += (mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBitsNorm; // notice: do intermediate division here to avoid integer overflow
corr += (mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBitsNorm;
} }
// update normalizer with last samples of this round // update normalizer with last samples of this round
@ -1026,24 +1045,27 @@ void TDStretch::calculateOverlapLength(int overlapInMsec)
/// Calculate cross-correlation /// Calculate cross-correlation
double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, double &anorm) double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, double &anorm)
{ {
float corr; double corr;
float norm; double norm;
int i; int i;
#ifdef ST_SIMD_AVOID_UNALIGNED
// in SIMD mode skip 'mixingPos' positions that aren't aligned to 16-byte boundary
if (((ulongptr)mixingPos) & 15) return -1e50;
#endif
// hint compiler autovectorization that loop length is divisible by 8
int ilength = (channels * overlapLength) & -8;
corr = norm = 0; corr = norm = 0;
// Same routine for stereo and mono // Same routine for stereo and mono. For Stereo, unroll by factor of 2.
for (i = 0; i < ilength; i ++) // For mono it's same routine yet unrollsd by factor of 4.
for (i = 0; i < channels * overlapLength; i += 4)
{ {
corr += mixingPos[i] * compare[i]; corr += mixingPos[i] * compare[i] +
norm += mixingPos[i] * mixingPos[i]; mixingPos[i + 1] * compare[i + 1];
norm += mixingPos[i] * mixingPos[i] +
mixingPos[i + 1] * mixingPos[i + 1];
// unroll the loop for better CPU efficiency:
corr += mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3];
norm += mixingPos[i + 2] * mixingPos[i + 2] +
mixingPos[i + 3] * mixingPos[i + 3];
} }
anorm = norm; anorm = norm;
@ -1054,7 +1076,7 @@ double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare, do
/// Update cross-correlation by accumulating "norm" coefficient by previously calculated value /// Update cross-correlation by accumulating "norm" coefficient by previously calculated value
double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm) double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm)
{ {
float corr; double corr;
int i; int i;
corr = 0; corr = 0;
@ -1065,13 +1087,14 @@ double TDStretch::calcCrossCorrAccumulate(const float *mixingPos, const float *c
norm -= mixingPos[-i] * mixingPos[-i]; norm -= mixingPos[-i] * mixingPos[-i];
} }
// hint compiler autovectorization that loop length is divisible by 8 // Same routine for stereo and mono. For Stereo, unroll by factor of 2.
int ilength = (channels * overlapLength) & -8; // For mono it's same routine yet unrollsd by factor of 4.
for (i = 0; i < channels * overlapLength; i += 4)
// Same routine for stereo and mono
for (i = 0; i < ilength; i ++)
{ {
corr += mixingPos[i] * compare[i]; corr += mixingPos[i] * compare[i] +
mixingPos[i + 1] * compare[i + 1] +
mixingPos[i + 2] * compare[i + 2] +
mixingPos[i + 3] * compare[i + 3];
} }
// update normalizer with last samples of this round // update normalizer with last samples of this round

View File

@ -165,7 +165,7 @@ protected:
public: public:
TDStretch(); TDStretch();
virtual ~TDStretch() override; virtual ~TDStretch();
/// Operator 'new' is overloaded so that it automatically creates a suitable instance /// 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. /// depending on if we've a MMX/SSE/etc-capable CPU available or not.
@ -187,7 +187,7 @@ public:
void setTempo(double newTempo); void setTempo(double newTempo);
/// Returns nonzero if there aren't any samples available for outputting. /// Returns nonzero if there aren't any samples available for outputting.
virtual void clear() override; virtual void clear();
/// Clears the input buffer /// Clears the input buffer
void clearInput(); void clearInput();
@ -217,7 +217,7 @@ public:
); );
/// Get routine control parameters, see setParameters() function. /// Get routine control parameters, see setParameters() function.
/// Any of the parameters to this function can be nullptr, in such case corresponding parameter /// Any of the parameters to this function can be NULL, in such case corresponding parameter
/// value isn't returned. /// value isn't returned.
void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const; void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const;
@ -227,7 +227,7 @@ public:
const SAMPLETYPE *samples, ///< Input sample data const SAMPLETYPE *samples, ///< Input sample data
uint numSamples ///< Number of samples in 'samples' so that one sample uint numSamples ///< Number of samples in 'samples' so that one sample
///< contains both channels if stereo ///< contains both channels if stereo
) override; );
/// return nominal input sample requirement for triggering a processing batch /// return nominal input sample requirement for triggering a processing batch
int getInputSampleReq() const int getInputSampleReq() const
@ -256,10 +256,10 @@ public:
class TDStretchMMX : public TDStretch class TDStretchMMX : public TDStretch
{ {
protected: protected:
double calcCrossCorr(const short *mixingPos, const short *compare, double &norm) override; double calcCrossCorr(const short *mixingPos, const short *compare, double &norm);
double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm) override; double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm);
virtual void overlapStereo(short *output, const short *input) const override; virtual void overlapStereo(short *output, const short *input) const;
virtual void clearCrossCorrState() override; virtual void clearCrossCorrState();
}; };
#endif /// SOUNDTOUCH_ALLOW_MMX #endif /// SOUNDTOUCH_ALLOW_MMX
@ -269,8 +269,8 @@ public:
class TDStretchSSE : public TDStretch class TDStretchSSE : public TDStretch
{ {
protected: protected:
double calcCrossCorr(const float *mixingPos, const float *compare, double &norm) override; double calcCrossCorr(const float *mixingPos, const float *compare, double &norm);
double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm) override; double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm);
}; };
#endif /// SOUNDTOUCH_ALLOW_SSE #endif /// SOUNDTOUCH_ALLOW_SSE

View File

@ -294,8 +294,8 @@ void TDStretchMMX::overlapStereo(short *output, const short *input) const
FIRFilterMMX::FIRFilterMMX() : FIRFilter() FIRFilterMMX::FIRFilterMMX() : FIRFilter()
{ {
filterCoeffsAlign = nullptr; filterCoeffsAlign = NULL;
filterCoeffsUnalign = nullptr; filterCoeffsUnalign = NULL;
} }

View File

@ -80,7 +80,7 @@ double TDStretchSSE::calcCrossCorr(const float *pV1, const float *pV2, double &a
// Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided // Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided
// for choosing if this little cheating is allowed. // for choosing if this little cheating is allowed.
#ifdef ST_SIMD_AVOID_UNALIGNED #ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION
// Little cheating allowed, return valid correlation only for // Little cheating allowed, return valid correlation only for
// aligned locations, meaning every second round for stereo sound. // aligned locations, meaning every second round for stereo sound.
@ -195,22 +195,25 @@ double TDStretchSSE::calcCrossCorrAccumulate(const float *pV1, const float *pV2,
FIRFilterSSE::FIRFilterSSE() : FIRFilter() FIRFilterSSE::FIRFilterSSE() : FIRFilter()
{ {
filterCoeffsAlign = nullptr; filterCoeffsAlign = NULL;
filterCoeffsUnalign = nullptr; filterCoeffsUnalign = NULL;
} }
FIRFilterSSE::~FIRFilterSSE() FIRFilterSSE::~FIRFilterSSE()
{ {
delete[] filterCoeffsUnalign; delete[] filterCoeffsUnalign;
filterCoeffsAlign = nullptr; filterCoeffsAlign = NULL;
filterCoeffsUnalign = nullptr; filterCoeffsUnalign = NULL;
} }
// (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;
} }
} }
@ -242,10 +245,10 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
if (count < 2) return 0; if (count < 2) return 0;
assert(source != nullptr); assert(source != NULL);
assert(dest != nullptr); assert(dest != NULL);
assert((length % 8) == 0); assert((length % 8) == 0);
assert(filterCoeffsAlign != nullptr); assert(filterCoeffsAlign != NULL);
assert(((ulongptr)filterCoeffsAlign) % 16 == 0); assert(((ulongptr)filterCoeffsAlign) % 16 == 0);
// filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2' // filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2'

View File

@ -16,10 +16,9 @@
#include "../../SoundStretch/WavFile.h" #include "../../SoundStretch/WavFile.h"
using namespace std; using namespace std;
using namespace soundstretch;
// DllTest main // DllTest main
int wmain(int argc, const wchar_t *argv[]) int main(int argc, char *argv[])
{ {
// Check program arguments // Check program arguments
if (argc < 4) if (argc < 4)
@ -28,22 +27,22 @@ int wmain(int argc, const wchar_t *argv[])
return -1; return -1;
} }
wstring inFileName = argv[1]; const char *inFileName = argv[1];
wstring outFileName = argv[2]; const char *outFileName = argv[2];
wstring str_sampleType = argv[3]; string str_sampleType = argv[3];
bool floatSample; bool floatSample;
if (str_sampleType == L"float") if (str_sampleType.compare("float") == 0)
{ {
floatSample = true; floatSample = true;
} }
else if (str_sampleType == L"short") else if (str_sampleType.compare("short") == 0)
{ {
floatSample = false; floatSample = false;
} }
else else
{ {
cerr << "Missing or invalid sampletype. Expected either short or float" << endl; cerr << "Missing or invalid sampletype '" << str_sampleType << "'. Expected either short or float" << endl;
return -1; return -1;
} }

View File

@ -22,32 +22,32 @@
<ProjectGuid>{E3C0726F-28F4-4F0B-8183-B87CA60C063C}</ProjectGuid> <ProjectGuid>{E3C0726F-28F4-4F0B-8183-B87CA60C063C}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>DllTest</RootNamespace> <RootNamespace>DllTest</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>

View File

@ -1,10 +0,0 @@
This is Lazarus Pascal example that loads the SoundTouch dynamic-load library
and queries the library version as a simple example how to load SoundTouch from
Pascal / Lazarus.
Set the SoundTouch dynamic library file name in the 'InitDLL' procedure of
file 'SoundTouchDLL.pas' depending on if you're building for Windows or Linux.
The example expects the the 'libSoundTouchDll.so' (linux) or 'SoundTouch.dll' (Windows)
library binary files is found within this project directory, either via soft-link
(in Linux) or as a copied file.

View File

@ -1 +0,0 @@
../.libs/libSoundTouchDll.so

View File

@ -1,36 +0,0 @@
object Form1: TForm1
Left = 2237
Height = 128
Top = 242
Width = 381
Caption = 'SoundTouch test'
ClientHeight = 128
ClientWidth = 381
LCLVersion = '2.2.0.4'
object Load: TButton
Left = 19
Height = 50
Top = 16
Width = 144
Caption = 'Load SoundTouch'
OnClick = LoadClick
TabOrder = 0
end
object EditVersion: TEdit
Left = 184
Height = 34
Top = 80
Width = 184
TabOrder = 1
Text = 'n/a'
TextHint = 'click to populate'
end
object Label1: TLabel
Left = 19
Height = 17
Top = 90
Width = 156
Caption = 'Soundtouch lib version:'
WordWrap = True
end
end

View File

@ -1,49 +0,0 @@
unit main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, SoundTouchDLL;
type
{ TForm1 }
TForm1 = class(TForm)
EditVersion: TEdit;
Label1: TLabel;
Load: TButton;
procedure LoadClick(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.LoadClick(Sender: TObject);
var
version:string;
begin
if IsSoundTouchLoaded() then
version := SoundTouchGetVersionString()
else
version := '<library loading failed>';
EditVersion.Text:= version;
end;
end.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<SessionStorage Value="InProjectDir"/>
<Title Value="soundtouchtest"/>
<Scaled Value="True"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<XPManifest>
<DpiAware Value="True"/>
</XPManifest>
<Icon Value="0"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages>
<Item>
<PackageName Value="LCL"/>
</Item>
</RequiredPackages>
<Units>
<Unit>
<Filename Value="soundtouchtest.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="soundtouchtest"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf3"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -1,25 +0,0 @@
program soundtouchtest;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
{$IFDEF HASAMIGA}
athreads,
{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, main
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Scaled:=True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@ -1,186 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectSession>
<Version Value="12"/>
<BuildModes Active="Default"/>
<Units>
<Unit>
<Filename Value="soundtouchtest.lpr"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="21"/>
</Unit>
<Unit>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/>
<CursorPos X="26" Y="43"/>
<UsageCount Value="21"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit>
<Unit>
<Filename Value="../SoundTouchDLL.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="37"/>
<CursorPos X="19"/>
<UsageCount Value="10"/>
</Unit>
<Unit>
<Filename Value="/usr/lib/lazarus/2.2.0/lcl/interfaces/gtk2/gtk2proc.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="7149"/>
<CursorPos X="3" Y="7184"/>
<UsageCount Value="10"/>
</Unit>
<Unit>
<Filename Value="/usr/lib/lazarus/2.2.0/components/freetype/easylazfreetype.pas"/>
<UnitName Value="EasyLazFreeType"/>
<EditorIndex Value="-1"/>
<TopLine Value="539"/>
<CursorPos X="16" Y="574"/>
<UsageCount Value="10"/>
</Unit>
<Unit>
<Filename Value="SoundTouchDLL.pas"/>
<EditorIndex Value="1"/>
<TopLine Value="326"/>
<CursorPos X="127" Y="379"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit>
</Units>
<JumpHistory HistoryIndex="29">
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="427" Column="37" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="427" Column="32" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="444" Column="48" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="416" Column="116" TopLine="403"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="439" TopLine="403"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="45" Column="40"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="243" Column="38" TopLine="197"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="487" Column="38" TopLine="429"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="42" Column="8"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="41" Column="44"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="44" Column="6"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="43" Column="39"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="44" Column="7"/>
</Position>
<Position>
<Filename Value="main.pas"/>
<Caret Line="38" Column="7"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="467" TopLine="423"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="212" Column="32" TopLine="78"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="361" Column="37" TopLine="308"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="466" Column="37" TopLine="413"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="467" Column="37" TopLine="413"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="466" Column="13" TopLine="413"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="361" Column="13" TopLine="326"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="110" Column="3" TopLine="74"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="180" Column="37" TopLine="145"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="179" Column="55" TopLine="145"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="146" Column="3" TopLine="145"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="149" TopLine="111"/>
</Position>
<Position>
<Filename Value="SoundTouchDLL.pas"/>
<Caret Line="151" Column="31" TopLine="116"/>
</Position>
</JumpHistory>
<RunParams>
<FormatVersion Value="2"/>
<Modes ActiveMode=""/>
</RunParams>
</ProjectSession>
</CONFIG>

View File

@ -1,47 +0,0 @@
## Process this file with automake to create Makefile.in
##
## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
##
## SoundTouch is free software; you can redistribute it and/or modify it under the
## terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## SoundTouch 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 General Public License for more details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the Free Software Foundation, Inc., 59 Temple
## Place - Suite 330, Boston, MA 02111-1307, USA
include $(top_srcdir)/config/am_include.mk
noinst_HEADERS=../SoundTouch/AAFilter.h ../SoundTouch/cpu_detect.h ../SoundTouch/cpu_detect_x86.cpp ../SoundTouch/FIRFilter.h \
../SoundTouch/RateTransposer.h ../SoundTouch/TDStretch.h ../SoundTouch/PeakFinder.h ../SoundTouch/InterpolateCubic.h \
../SoundTouch/InterpolateLinear.h ../SoundTouch/InterpolateShannon.h
include_HEADERS=SoundTouchDLL.h
lib_LTLIBRARIES=libSoundTouchDll.la
#
libSoundTouchDll_la_SOURCES=../SoundTouch/AAFilter.cpp ../SoundTouch/FIRFilter.cpp \
../SoundTouch/FIFOSampleBuffer.cpp ../SoundTouch/RateTransposer.cpp ../SoundTouch/SoundTouch.cpp \
../SoundTouch/TDStretch.cpp ../SoundTouch/sse_optimized.cpp ../SoundTouch/cpu_detect_x86.cpp \
../SoundTouch/BPMDetect.cpp ../SoundTouch/PeakFinder.cpp ../SoundTouch/InterpolateLinear.cpp \
../SoundTouch/InterpolateCubic.cpp ../SoundTouch/InterpolateShannon.cpp SoundTouchDLL.cpp
# Compiler flags
# Modify the default 0.0.0 to LIB_SONAME.0.0
AM_LDFLAGS=$(LDFLAGS) -version-info @LIB_SONAME@
if X86
CXXFLAGS1=-mstackrealign -msse
endif
if X86_64
CXXFLAGS2=-fPIC
endif
AM_CXXFLAGS=$(CXXFLAGS) $(CXXFLAGS1) $(CXXFLAGS2) -shared -DDLL_EXPORTS -fvisibility=hidden

View File

@ -90,10 +90,10 @@ SOUNDTOUCHDLL_API HANDLE __cdecl soundtouch_createInstance()
{ {
tmp->dwMagic = STMAGIC; tmp->dwMagic = STMAGIC;
tmp->pst = new SoundTouch(); tmp->pst = new SoundTouch();
if (tmp->pst == nullptr) if (tmp->pst == NULL)
{ {
delete tmp; delete tmp;
tmp = nullptr; tmp = NULL;
} }
} }
return (HANDLE)tmp; return (HANDLE)tmp;
@ -107,7 +107,7 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_destroyInstance(HANDLE h)
sth->dwMagic = 0; sth->dwMagic = 0;
if (sth->pst) delete sth->pst; if (sth->pst) delete sth->pst;
sth->pst = nullptr; sth->pst = NULL;
delete sth; delete sth;
} }
@ -207,37 +207,21 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitchSemiTones(HANDLE h, float newP
/// Sets the number of channels, 1 = mono, 2 = stereo /// Sets the number of channels, 1 = mono, 2 = stereo
SOUNDTOUCHDLL_API int __cdecl soundtouch_setChannels(HANDLE h, uint numChannels) SOUNDTOUCHDLL_API void __cdecl soundtouch_setChannels(HANDLE h, uint numChannels)
{ {
STHANDLE *sth = (STHANDLE*)h; STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return 0; if (sth->dwMagic != STMAGIC) return;
try
{
sth->pst->setChannels(numChannels); sth->pst->setChannels(numChannels);
}
catch (const std::exception&)
{
return 0;
}
return 1;
} }
/// Sets sample rate. /// Sets sample rate.
SOUNDTOUCHDLL_API int __cdecl soundtouch_setSampleRate(HANDLE h, uint srate) SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, uint srate)
{ {
STHANDLE *sth = (STHANDLE*)h; STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return 0; if (sth->dwMagic != STMAGIC) return;
try
{
sth->pst->setSampleRate(srate); sth->pst->setSampleRate(srate);
}
catch (const std::exception&)
{
return 0;
}
return 1;
} }
/// Flushes the last samples from the processing pipeline to the output. /// Flushes the last samples from the processing pipeline to the output.
@ -247,26 +231,18 @@ SOUNDTOUCHDLL_API int __cdecl soundtouch_setSampleRate(HANDLE h, uint srate)
/// stream. This function may introduce additional blank samples in the end /// stream. This function may introduce additional blank samples in the end
/// of the sound stream, and thus it's not recommended to call this function /// of the sound stream, and thus it's not recommended to call this function
/// in the middle of a sound stream. /// in the middle of a sound stream.
SOUNDTOUCHDLL_API int __cdecl soundtouch_flush(HANDLE h) SOUNDTOUCHDLL_API void __cdecl soundtouch_flush(HANDLE h)
{ {
STHANDLE *sth = (STHANDLE*)h; STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return 0; if (sth->dwMagic != STMAGIC) return;
try
{
sth->pst->flush(); sth->pst->flush();
}
catch (const std::exception&)
{
return 0;
}
return 1;
} }
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into /// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object. Notice that sample rate _has_to_ be set before /// the input of the object. Notice that sample rate _has_to_ be set before
/// calling this function, otherwise throws a runtime_error exception. /// calling this function, otherwise throws a runtime_error exception.
SOUNDTOUCHDLL_API int __cdecl soundtouch_putSamples(HANDLE h, SOUNDTOUCHDLL_API void __cdecl soundtouch_putSamples(HANDLE h,
const SAMPLETYPE *samples, ///< Pointer to sample buffer. const SAMPLETYPE *samples, ///< Pointer to sample buffer.
unsigned int numSamples ///< Number of samples in buffer. Notice unsigned int numSamples ///< Number of samples in buffer. Notice
///< that in case of stereo-sound a single sample ///< that in case of stereo-sound a single sample
@ -274,17 +250,9 @@ SOUNDTOUCHDLL_API int __cdecl soundtouch_putSamples(HANDLE h,
) )
{ {
STHANDLE *sth = (STHANDLE*)h; STHANDLE *sth = (STHANDLE*)h;
if (sth->dwMagic != STMAGIC) return 0; if (sth->dwMagic != STMAGIC) return;
try
{
sth->pst->putSamples(samples, numSamples); sth->pst->putSamples(samples, numSamples);
}
catch (const std::exception&)
{
return 0;
}
return 1;
} }
/// int16 version of soundtouch_putSamples(): This accept int16 (short) sample data /// int16 version of soundtouch_putSamples(): This accept int16 (short) sample data
@ -373,9 +341,11 @@ SOUNDTOUCHDLL_API uint __cdecl soundtouch_numUnprocessedSamples(HANDLE h)
} }
/// Receive ready samples from the processing pipeline. /// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
/// ///
/// if called with outBuffer=nullptr, just reduces amount of ready samples within the pipeline. /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
SOUNDTOUCHDLL_API uint __cdecl soundtouch_receiveSamples(HANDLE h, SOUNDTOUCHDLL_API uint __cdecl soundtouch_receiveSamples(HANDLE h,
SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples. SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
unsigned int maxSamples ///< How many samples to receive at max. unsigned int maxSamples ///< How many samples to receive at max.
@ -406,7 +376,7 @@ SOUNDTOUCHDLL_API uint __cdecl soundtouch_receiveSamples_i16(HANDLE h,
if (sth->dwMagic != STMAGIC) return 0; if (sth->dwMagic != STMAGIC) return 0;
uint outTotal = 0; uint outTotal = 0;
if (outBuffer == nullptr) if (outBuffer == NULL)
{ {
// only reduce sample count, not receive samples // only reduce sample count, not receive samples
return sth->pst->receiveSamples(maxSamples); return sth->pst->receiveSamples(maxSamples);
@ -474,18 +444,11 @@ SOUNDTOUCHDLL_API HANDLE __cdecl bpm_createInstance(int numChannels, int sampleR
if (tmp) if (tmp)
{ {
tmp->dwMagic = BPMMAGIC; tmp->dwMagic = BPMMAGIC;
try
{
tmp->pbpm = new BPMDetect(numChannels, sampleRate); tmp->pbpm = new BPMDetect(numChannels, sampleRate);
} if (tmp->pbpm == NULL)
catch (const std::exception&)
{
tmp->pbpm = nullptr;
}
if (tmp->pbpm == nullptr)
{ {
delete tmp; delete tmp;
tmp = nullptr; tmp = NULL;
} }
} }
return (HANDLE)tmp; return (HANDLE)tmp;
@ -499,7 +462,7 @@ SOUNDTOUCHDLL_API void __cdecl bpm_destroyInstance(HANDLE h)
sth->dwMagic = 0; sth->dwMagic = 0;
if (sth->pbpm) delete sth->pbpm; if (sth->pbpm) delete sth->pbpm;
sth->pbpm = nullptr; sth->pbpm = NULL;
delete sth; delete sth;
} }
@ -562,21 +525,3 @@ SOUNDTOUCHDLL_API float __cdecl bpm_getBpm(HANDLE h)
return bpmh->pbpm->getBpm(); return bpmh->pbpm->getBpm();
} }
/// Get beat position arrays. Note: The array includes also really low beat detection values
/// in absence of clear strong beats. Consumer may wish to filter low values away.
/// - "pos" receive array of beat positions
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
SOUNDTOUCHDLL_API int __cdecl bpm_getBeats(HANDLE h, float* pos, float* strength, int count)
{
BPMHANDLE *bpmh = (BPMHANDLE *)h;
if (bpmh->dwMagic != BPMMAGIC) return 0;
return bpmh->pbpm->getBeats(pos, strength, count);
}

View File

@ -48,12 +48,12 @@
#else #else
// GNU version // GNU version
#if defined(DLL_EXPORTS) || defined(SoundTouchDLL_EXPORTS) #ifdef DLL_EXPORTS
// GCC declaration for exporting functions // GCC declaration for exporting functions
#define SOUNDTOUCHDLL_API extern "C" __attribute__((__visibility__("default"))) #define SOUNDTOUCHDLL_API extern "C" __attribute__((__visibility__("default")))
#else #else
// import function // GCC doesn't require DLL imports
#define SOUNDTOUCHDLL_API extern "C" #define SOUNDTOUCHDLL_API
#endif #endif
// Linux-replacements for Windows declarations: // Linux-replacements for Windows declarations:
@ -112,10 +112,10 @@ SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitchSemiTones(HANDLE h, float newP
/// Sets the number of channels, 1 = mono, 2 = stereo, n = multichannel /// Sets the number of channels, 1 = mono, 2 = stereo, n = multichannel
SOUNDTOUCHDLL_API int __cdecl soundtouch_setChannels(HANDLE h, unsigned int numChannels); SOUNDTOUCHDLL_API void __cdecl soundtouch_setChannels(HANDLE h, unsigned int numChannels);
/// Sets sample rate. /// Sets sample rate.
SOUNDTOUCHDLL_API int __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int srate); SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int srate);
/// Flushes the last samples from the processing pipeline to the output. /// Flushes the last samples from the processing pipeline to the output.
/// Clears also the internal processing buffers. /// Clears also the internal processing buffers.
@ -124,12 +124,12 @@ SOUNDTOUCHDLL_API int __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int sr
/// stream. This function may introduce additional blank samples in the end /// stream. This function may introduce additional blank samples in the end
/// of the sound stream, and thus it's not recommended to call this function /// of the sound stream, and thus it's not recommended to call this function
/// in the middle of a sound stream. /// in the middle of a sound stream.
SOUNDTOUCHDLL_API int __cdecl soundtouch_flush(HANDLE h); SOUNDTOUCHDLL_API void __cdecl soundtouch_flush(HANDLE h);
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into /// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object. Notice that sample rate _has_to_ be set before /// the input of the object. Notice that sample rate _has_to_ be set before
/// calling this function, otherwise throws a runtime_error exception. /// calling this function, otherwise throws a runtime_error exception.
SOUNDTOUCHDLL_API int __cdecl soundtouch_putSamples(HANDLE h, SOUNDTOUCHDLL_API void __cdecl soundtouch_putSamples(HANDLE h,
const float *samples, ///< Pointer to sample buffer. const float *samples, ///< Pointer to sample buffer.
unsigned int numSamples ///< Number of sample frames in buffer. Notice unsigned int numSamples ///< Number of sample frames in buffer. Notice
///< that in case of multi-channel sound a single ///< that in case of multi-channel sound a single
@ -225,16 +225,5 @@ SOUNDTOUCHDLL_API void __cdecl bpm_putSamples_i16(HANDLE h,
/// \return Beats-per-minute rate, or zero if detection failed. /// \return Beats-per-minute rate, or zero if detection failed.
SOUNDTOUCHDLL_API float __cdecl bpm_getBpm(HANDLE h); SOUNDTOUCHDLL_API float __cdecl bpm_getBpm(HANDLE h);
/// Get beat position arrays. Note: The array includes also really low beat detection values
/// in absence of clear strong beats. Consumer may wish to filter low values away.
/// - "pos" receive array of beat positions
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
SOUNDTOUCHDLL_API int __cdecl bpm_getBeats(HANDLE h, float *pos, float *strength, int count);
#endif // _SoundTouchDLL_h_ #endif // _SoundTouchDLL_h_

View File

@ -2,8 +2,11 @@ unit SoundTouchDLL;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// SoundTouch.dll / libSoundTouchDll.so wrapper for accessing SoundTouch // SoundTouch.dll wrapper for accessing SoundTouch routines from Delphi/Pascal
// routines from Delphi/Pascal/Lazarus //
// Module Author : Christian Budde
//
// 2014-01-12 fixes by Sandro Cumerlato <sandro.cumerlato 'at' gmail.com>
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
@ -30,8 +33,8 @@ unit SoundTouchDLL;
interface interface
//uses uses
//Windows; Windows;
type type
TSoundTouchHandle = THandle; TSoundTouchHandle = THandle;
@ -104,13 +107,6 @@ type
//< contains data for both channels. //< contains data for both channels.
); cdecl; ); cdecl;
TSoundTouchPutSamplesI16 = procedure (Handle: TSoundTouchHandle;
const Samples: Pint16; //< Pointer to sample buffer.
NumSamples: Cardinal //< Number of samples in buffer. Notice
//< that in case of stereo-sound a single sample
//< contains data for both channels.
); cdecl;
// Clears all the samples in the object's output and internal processing // Clears all the samples in the object's output and internal processing
// buffers. // buffers.
TSoundTouchClear = procedure (Handle: TSoundTouchHandle); cdecl; TSoundTouchClear = procedure (Handle: TSoundTouchHandle); cdecl;
@ -135,20 +131,16 @@ type
// Returns number of samples currently unprocessed. // Returns number of samples currently unprocessed.
TSoundTouchNumUnprocessedSamples = function (Handle: TSoundTouchHandle): Cardinal; cdecl; TSoundTouchNumUnprocessedSamples = function (Handle: TSoundTouchHandle): Cardinal; cdecl;
/// Receive ready samples from the processing pipeline. // Adjusts book-keeping so that given number of samples are removed from beginning of the
/// // sample buffer without copying them anywhere.
/// if called with outBuffer=nullptr, just reduces amount of ready samples within the pipeline. //
// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
// with 'ptrBegin' function.
TSoundTouchReceiveSamples = function (Handle: TSoundTouchHandle; TSoundTouchReceiveSamples = function (Handle: TSoundTouchHandle;
OutBuffer: PSingle; //< Buffer where to copy output samples. OutBuffer: PSingle; //< Buffer where to copy output samples.
MaxSamples: Integer //< How many samples to receive at max. MaxSamples: Integer //< How many samples to receive at max.
): Cardinal; cdecl; ): Cardinal; cdecl;
/// int16 version of soundtouch_receiveSamples(): This converts internal float samples
/// into int16 (short) return data type
TSoundTouchReceiveSamplesI16 = function (Handle: TSoundTouchHandle;
OutBuffer: int16; //< Buffer where to copy output samples.
MaxSamples: Integer //< How many samples to receive at max.
): Cardinal; cdecl;
// Returns number of samples currently available. // Returns number of samples currently available.
TSoundTouchNumSamples = function (Handle: TSoundTouchHandle): Cardinal; cdecl; TSoundTouchNumSamples = function (Handle: TSoundTouchHandle): Cardinal; cdecl;
@ -178,7 +170,6 @@ var
SoundTouchGetSetting : TSoundTouchGetSetting; SoundTouchGetSetting : TSoundTouchGetSetting;
SoundTouchNumUnprocessedSamples : TSoundTouchNumUnprocessedSamples; SoundTouchNumUnprocessedSamples : TSoundTouchNumUnprocessedSamples;
SoundTouchReceiveSamples : TSoundTouchReceiveSamples; SoundTouchReceiveSamples : TSoundTouchReceiveSamples;
SoundTouchReceiveSamplesI16 : TSoundTouchReceiveSamplesI16;
SoundTouchNumSamples : TSoundTouchNumSamples; SoundTouchNumSamples : TSoundTouchNumSamples;
SoundTouchIsEmpty : TSoundTouchIsEmpty; SoundTouchIsEmpty : TSoundTouchIsEmpty;
@ -241,9 +232,6 @@ type
property IsEmpty: Integer read GetIsEmpty; property IsEmpty: Integer read GetIsEmpty;
end; end;
// list of exported functions and procedures
function IsSoundTouchLoaded: Boolean;
implementation implementation
{ TSoundTouch } { TSoundTouch }
@ -428,23 +416,19 @@ begin
end; end;
var var
SoundTouchLibHandle: THandle; SoundTouchLibHandle: HINST;
SoundTouchDLLFile: AnsiString = 'libSoundTouchDll.so'; SoundTouchDLLFile: PAnsiChar = 'SoundTouch.dll';
//SoundTouchDLLFile: AnsiString = 'SoundTouch.dll';
// bpm detect functions. untested -- if these don't work then remove: // bpm detect functions. untested -- if these don't work then remove:
bpm_createInstance: function(chan: int32; sampleRate : int32): THandle; cdecl; bpm_createInstance: function(chan: CInt32; sampleRate : CInt32): THandle; cdecl;
bpm_destroyInstance: procedure(h: THandle); cdecl; bpm_destroyInstance: procedure(h: THandle); cdecl;
bpm_getBpm: function(h: THandle): Single; cdecl; bpm_getBpm: function(h: THandle): cfloat; cdecl;
bpm_putSamples: procedure(h: THandle; const samples: PSingle; numSamples: cardinal); cdecl; bpm_putSamples: procedure(h: THandle; const samples: pcfloat;
numSamples: cardinal); cdecl;
procedure InitDLL; procedure InitDLL;
begin begin
{$ifdef mswindows} // Windows SoundTouchLibHandle := LoadLibrary(SoundTouchDLLFile);
SoundTouchLibHandle := LoadLibrary('.\SoundTouchDll.dll');
{$else} // Unix
SoundTouchLibHandle := LoadLibrary('./libSoundTouchDll.so');
{$endif}
if SoundTouchLibHandle <> 0 then if SoundTouchLibHandle <> 0 then
try try
Pointer(SoundTouchCreateInstance) := GetProcAddress(SoundTouchLibHandle, 'soundtouch_createInstance'); Pointer(SoundTouchCreateInstance) := GetProcAddress(SoundTouchLibHandle, 'soundtouch_createInstance');
@ -489,12 +473,6 @@ begin
if SoundTouchLibHandle <> 0 then FreeLibrary(SoundTouchLibHandle); if SoundTouchLibHandle <> 0 then FreeLibrary(SoundTouchLibHandle);
end; end;
// returns 'true' if SoundTouch dynamic library has been successfully loaded, otherwise 'false'
function IsSoundTouchLoaded: Boolean;
begin;
result := SoundTouchLibHandle <> 0
end;
initialization initialization
InitDLL; InitDLL;

View File

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,3,2,0 FILEVERSION 2,1,0,0
PRODUCTVERSION 2,3,2,0 PRODUCTVERSION 2,1,0,0
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN BEGIN
VALUE "Comments", "SoundTouch Library licensed for 3rd party applications subject to LGPL license v2.1. Visit http://www.surina.net/soundtouch for more information about the SoundTouch library." VALUE "Comments", "SoundTouch Library licensed for 3rd party applications subject to LGPL license v2.1. Visit http://www.surina.net/soundtouch for more information about the SoundTouch library."
VALUE "FileDescription", "SoundTouch Dynamic Link Library" VALUE "FileDescription", "SoundTouch Dynamic Link Library"
VALUE "FileVersion", "2.3.3.0" VALUE "FileVersion", "2.1.0.0"
VALUE "InternalName", "SoundTouch" VALUE "InternalName", "SoundTouch"
VALUE "LegalCopyright", "Copyright (C) Olli Parviainen 2024" VALUE "LegalCopyright", "Copyright (C) Olli Parviainen 2018"
VALUE "OriginalFilename", "SoundTouch.dll" VALUE "OriginalFilename", "SoundTouch.dll"
VALUE "ProductName", " SoundTouch Dynamic Link Library" VALUE "ProductName", " SoundTouch Dynamic Link Library"
VALUE "ProductVersion", "2.3.3.0" VALUE "ProductVersion", "2.1.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -21,28 +21,28 @@
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{164DE61D-6391-4265-8273-30740117D356}</ProjectGuid> <ProjectGuid>{164DE61D-6391-4265-8273-30740117D356}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@ -95,8 +95,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader /> <PrecompiledHeader />
@ -107,7 +106,6 @@
<ObjectFileName>$(OutDir)</ObjectFileName> <ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName> <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@ -136,8 +134,7 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader /> <PrecompiledHeader />
@ -147,7 +144,6 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation> <AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName> <ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName> <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@ -186,8 +182,6 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<ObjectFileName>$(OutDir)</ObjectFileName> <ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName> <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MinimalRebuild />
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@ -229,8 +223,6 @@ copy $(OutDir)$(TargetName).lib ..\..\lib
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation> <AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName> <ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName> <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<MinimalRebuild />
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>

View File

@ -1,8 +1,5 @@
#!/bin/bash #!/bin/bash
# #
# This script is deprecated. Don't use this, the makefile can now compile
# the dynamic-link library 'libSoundTouchDLL.so' automatically.
#
# This script compiles SoundTouch dynamic-link library for GNU environment # This script compiles SoundTouch dynamic-link library for GNU environment
# with wrapper functions that are easier to import to Java / Mono / etc # with wrapper functions that are easier to import to Java / Mono / etc
# #
@ -19,11 +16,7 @@ if [[ $arch == *"86"* ]]; then
fi fi
fi fi
echo "*************************************************************************"
echo "NOTE: Rather use the makefile that can now build the dynamic-link library"
echo "*************************************************************************"
echo ""
echo "Building SoundTouchDLL for $arch with flags:$flags" echo "Building SoundTouchDLL for $arch with flags:$flags"
g++ -O3 -ffast-math -shared $flags -DDLL_EXPORTS -fvisibility=hidden -I../../include \ g++ -O3 -shared $flags -DDLL_EXPORTS -fvisibility=hidden -I../../include \
-I../SoundTouch -o SoundTouchDll.so SoundTouchDLL.cpp ../SoundTouch/*.cpp -I../SoundTouch -o SoundTouchDll.so SoundTouchDLL.cpp ../SoundTouch/*.cpp

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1"/> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup> </startup>
</configuration> </configuration>

View File

@ -12,7 +12,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp-example")] [assembly: AssemblyProduct("csharp-example")]
[assembly: AssemblyCopyright("Copyright © Olli Parviainen")] [assembly: AssemblyCopyright("Copyright Olli Parviainen © 2017")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]

View File

@ -8,8 +8,8 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace csharp_example.Properties { namespace csharp_example.Properties
using System; {
/// <summary> /// <summary>
@ -19,26 +19,31 @@ namespace csharp_example.Properties {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() { internal Resources()
{
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager
get { {
if (object.ReferenceEquals(resourceMan, null)) { get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("csharp_example.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("csharp_example.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
@ -51,11 +56,14 @@ namespace csharp_example.Properties {
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture
get { {
get
{
return resourceCulture; return resourceCulture;
} }
set { set
{
resourceCulture = value; resourceCulture = value;
} }
} }

View File

@ -8,17 +8,21 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace csharp_example.Properties { namespace csharp_example.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default { public static Settings Default
get { {
get
{
return defaultInstance; return defaultInstance;
} }
} }

Binary file not shown.

View File

@ -9,15 +9,14 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>csharp_example</RootNamespace> <RootNamespace>csharp_example</RootNamespace>
<AssemblyName>csharp-example</AssemblyName> <AssemblyName>csharp-example</AssemblyName>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
@ -25,7 +24,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>