Update soxr to 0.1.3; make wasm compatible

This commit is contained in:
Luke Street 2022-08-03 18:10:19 -04:00
parent 6e4030212c
commit 39eb95a824
141 changed files with 9179 additions and 9529 deletions

View File

@ -73,7 +73,7 @@ endif ()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
add_subdirectory(soxr/src) add_subdirectory(soxr)
add_library(boo add_library(boo
lib/audiodev/Common.hpp lib/audiodev/Common.hpp

2
soxr/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
Release*/
Debug*/

View File

@ -1,30 +1,36 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net # SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details. # Licence for this file: LGPL v2.1 See LICENCE for details.
cmake_minimum_required (VERSION 2.8 FATAL_ERROR) cmake_minimum_required (VERSION 3.1 FATAL_ERROR)
cmake_policy(SET CMP0075 OLD) project (soxr C)
set (DESCRIPTION_SUMMARY
#project (soxr C) "High quality, one-dimensional sample-rate conversion library")
#set (DESCRIPTION_SUMMARY "High quality, one-dimensional sample-rate conversion library")
cmake_policy(SET CMP0075 NEW)
cmake_policy(SET CMP0115 OLD)
cmake_policy(SET CMP0127 OLD)
# Release versioning: # Release versioning:
set (PROJECT_VERSION_MAJOR 0) set (PROJECT_VERSION_MAJOR 0)
set (PROJECT_VERSION_MINOR 1) set (PROJECT_VERSION_MINOR 1)
set (PROJECT_VERSION_PATCH 2) set (PROJECT_VERSION_PATCH 3)
# For shared-object; if, since the last public release: # For shared-object; if, since the last public release:
# * library code changed at all: ++revision # 1) library code changed at all: ++revision
# * interfaces changed at all: ++current, revision = 0 # 2) interfaces changed at all: ++current, revision = 0
# * interfaces added: ++age # 3) interfaces added: ++age
# * interfaces removed: age = 0 # 4) interfaces removed: age = 0
set (SO_VERSION_CURRENT 1) set (SO_VERSION_CURRENT 1)
set (SO_VERSION_REVISION 1) set (SO_VERSION_REVISION 2)
set (SO_VERSION_AGE 1) set (SO_VERSION_AGE 1)
math (EXPR SO_VERSION_MAJOR "${SO_VERSION_CURRENT} - ${SO_VERSION_AGE}")
math (EXPR SO_VERSION_MINOR "${SO_VERSION_AGE}")
math (EXPR SO_VERSION_PATCH "${SO_VERSION_REVISION}")
# Main options: # Main options:
@ -32,112 +38,147 @@ set (SO_VERSION_AGE 1)
include (CMakeDependentOption) include (CMakeDependentOption)
if (NOT CMAKE_BUILD_TYPE) if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) set (CMAKE_BUILD_TYPE Release CACHE STRING
"Build type, one of: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif () endif ()
#option (BUILD_TESTS "Build sanity-tests." ON) option (BUILD_TESTS "Build sanity-tests." OFF)
#option (BUILD_SHARED_LIBS "Build shared libraries." ON) option (BUILD_EXAMPLES "Build examples." OFF)
#option (BUILD_EXAMPLES "Build examples." OFF) option (WITH_OPENMP "Include OpenMP threading." OFF)
option (WITH_LSR_BINDINGS "Include a `libsamplerate'-like interface." ON) option (WITH_LSR_BINDINGS "Include a `libsamplerate'-like interface." OFF)
cmake_dependent_option (WITH_SINGLE_PRECISION "Build with single precision (for up to 20-bit accuracy)." ON
"WITH_DOUBLE_PRECISION" ON) cmake_dependent_option (BUILD_SHARED_LIBS
cmake_dependent_option (WITH_DOUBLE_PRECISION "Build with double precision (for up to 32-bit accuracy)." ON "Build shared (dynamic) soxr libraries." OFF
"WITH_SINGLE_PRECISION" ON) "NOT WITH_DEV_GPROF" OFF)
cmake_dependent_option (WITH_SIMD "Use SIMD (for faster single precision)." ON cmake_dependent_option (WITH_VR32
"WITH_SINGLE_PRECISION" OFF) "Include HQ variable-rate resampling engine." ON
cmake_dependent_option (WITH_AVFFT "Use libavcodec (LGPL) for SIMD DFT." OFF "WITH_CR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S OR NOT DEFINED WITH_VR32" ON)
"WITH_SIMD;NOT WITH_PFFFT" OFF) cmake_dependent_option (WITH_CR32
cmake_dependent_option (WITH_PFFFT "Use PFFFT (BSD-like licence) for SIMD DFT." ON "Include HQ constant-rate resampling engine." ON
"WITH_SIMD;NOT WITH_AVFFT" OFF) "WITH_VR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S" ON)
option (SOXR_SILENT "Disable debug messages, even in debug mode" OFF) cmake_dependent_option (WITH_CR64
if (UNIX) "Include VHQ constant-rate resampling engine." ON
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/lsr-tests) "WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64S" ON)
cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF cmake_dependent_option (WITH_CR64S
"WITH_LSR_BINDINGS" OFF) "Include VHQ SIMD constant-rate resampling engine." ON
endif () "WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64" ON)
endif () cmake_dependent_option (WITH_CR32S
"Include HQ SIMD constant-rate resampling engine." ON
"WITH_VR32 OR WITH_CR64 OR WITH_CR32 OR WITH_CR64S" ON)
cmake_dependent_option (WITH_PFFFT
"Use PFFFT (BSD-like licence) for HQ SIMD DFT." ON
"WITH_CR32S;NOT WITH_AVFFT" OFF)
cmake_dependent_option (WITH_AVFFT
"Use libavcodec (LGPL) for HQ SIMD DFT." OFF
"WITH_CR32S;NOT WITH_PFFFT" OFF)
cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF
"UNIX;NOT CMAKE_CROSSCOMPILING;EXISTS ${PROJECT_SOURCE_DIR}/lsr-tests;WITH_LSR_BINDINGS" OFF)
option (WITH_HI_PREC_CLOCK "Enable high-precision time-base." ON)
option (WITH_FLOAT_STD_PREC_CLOCK
"Use floating-point for standard-precision time-base." OFF)
option (WITH_DEV_TRACE "Enable developer trace capability." ON)
option (WITH_DEV_GPROF "Enable developer grpof output." OFF)
mark_as_advanced (WITH_HI_PREC_CLOCK WITH_FLOAT_STD_PREC_CLOCK
WITH_DEV_TRACE WITH_DEV_GPROF)
# Introspection: # Introspection:
list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
include (CheckFunctionExists) include (CheckFunctionExists)
include (CheckIncludeFiles) include (CheckIncludeFiles)
include (CheckLibraryExists) include (CheckLibraryExists)
include (TestBigEndian) include (SetSystemProcessor)
if (NOT EMSCRIPTEN)
include(TestBigEndian)
endif ()
set_system_processor ()
check_library_exists (m pow "" NEED_LIBM) check_library_exists (m pow "" NEED_LIBM)
if (NEED_LIBM) if (NEED_LIBM)
set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}") set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}")
link_libraries (m) set (LIBM_LIBRARIES m)
endif () endif ()
#if (WITH_OPENMP) if (${BUILD_EXAMPLES})
# find_package (OpenMP) project (${PROJECT_NAME}) # Adds c++ compiler
# if (OPENMP_FOUND)
# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
# set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
# set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_SHARED_LINKER_FLAGS}")
# endif ()
#endif ()
if (WITH_SIMD)
find_package (SIMD)
if (SIMD_FOUND)
set (HAVE_SIMD 1)
endif ()
endif () endif ()
if (WITH_SINGLE_PRECISION) if (WITH_OPENMP)
set (HAVE_SINGLE_PRECISION 1) find_package (OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
if (MINGW) # Is this still needed?
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
endif ()
endif()
endif () endif ()
if (WITH_DOUBLE_PRECISION) if (WITH_CR32S)
set (HAVE_DOUBLE_PRECISION 1) find_package (SIMD32)
set (WITH_CR32S ${SIMD32_FOUND})
endif ()
if (WITH_CR64S)
find_package (SIMD64)
set (WITH_CR64S ${SIMD64_FOUND})
endif () endif ()
if (WITH_AVFFT) if (WITH_AVFFT)
find_package (LibAVCodec) find_package (LibAVCodec REQUIRED)
if (AVCODEC_FOUND) if (AVCODEC_FOUND)
include_directories (${AVCODEC_INCLUDE_DIRS}) include_directories (${AVCODEC_INCLUDE_DIRS})
link_libraries (${AVCODEC_LIBRARIES}) set (LIBS ${LIBS} ${AVCODEC_LIBRARIES})
set (HAVE_AVFFT 1)
endif () endif ()
endif () endif ()
if (SOXR_SILENT) if (WITH_AVFFT OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND SIMD32_FOUND AND WITH_CR32))
add_definitions (-DSOXR_SILENT=1) find_package (LibAVUtil)
if (AVUTIL_FOUND)
include_directories (${AVUTIL_INCLUDE_DIRS})
set (LIBS ${LIBS} ${AVUTIL_LIBRARIES})
endif ()
endif () endif ()
check_function_exists (lrint HAVE_LRINT) check_function_exists (lrint HAVE_LRINT)
check_include_files (fenv.h HAVE_FENV_H) check_include_files (fenv.h HAVE_FENV_H)
test_big_endian (WORDS_BIGENDIAN) check_include_files (stdbool.h HAVE_STDBOOL_H)
check_include_files (stdint.h HAVE_STDINT_H)
macro (make_exist) if (EMSCRIPTEN)
foreach (x ${ARGN}) set(HAVE_BIGENDIAN OFF)
if (NOT ${x}) else()
set (${x} 0) test_big_endian (HAVE_BIGENDIAN)
endif () endif()
endforeach ()
endmacro ()
make_exist (HAVE_LRINT HAVE_FENV_H WORDS_BIGENDIAN HAVE_SIMD)
make_exist (HAVE_SINGLE_PRECISION HAVE_DOUBLE_PRECISION HAVE_AVFFT)
# Compiler configuration: # Compiler configuration:
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set (PROJECT_CXX_FLAGS "-Wconversion -Wall -W -Wundef -Wcast-align -Wpointer-arith -Wno-long-long") set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wconversion -Wall -Wextra \
set (PROJECT_C_FLAGS "${PROJECT_CXX_FLAGS} -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes") -pedantic -Wundef -Wpointer-arith -Wno-long-long")
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wno-keyword-macro")
endif ()
if (WITH_DEV_GPROF)
set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -pg")
endif ()
# Can use std=c89, but gnu89 should give faster sinf, cosf, etc.:
set (PROJECT_C_FLAGS "${PROJECT_CXX_FLAGS} \
-std=gnu89 -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes")
if (CMAKE_BUILD_TYPE STREQUAL "Release") if (CMAKE_BUILD_TYPE STREQUAL "Release")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s") # strip set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s") # strip
endif () endif ()
cmake_dependent_option (VISIBILITY_HIDDEN "Build with -fvisibility=hidden." ON cmake_dependent_option (VISIBILITY_HIDDEN
"Build shared libraries with -fvisibility=hidden." ON
"BUILD_SHARED_LIBS" OFF) "BUILD_SHARED_LIBS" OFF)
mark_as_advanced (VISIBILITY_HIDDEN)
if (VISIBILITY_HIDDEN) if (VISIBILITY_HIDDEN)
add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY) add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY)
endif () endif ()
@ -145,9 +186,14 @@ endif ()
if (MSVC) if (MSVC)
add_definitions (-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS) add_definitions (-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS)
option (ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically." OFF) option (BUILD_SHARED_RUNTIME "MSVC, link with runtime dynamically." ON)
if (ENABLE_STATIC_RUNTIME) if (NOT BUILD_SHARED_RUNTIME)
foreach (flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) foreach (flag_var
CMAKE_C_FLAGS CMAKE_CXX_FLAGS
CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endforeach () endforeach ()
endif () endif ()
@ -161,8 +207,9 @@ endif ()
# Build configuration: # Build configuration:
if (${BUILD_SHARED_LIBS} AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows) # Allow exes to find dlls: if (${BUILD_SHARED_LIBS} AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows)
set (BIN ${CMAKE_CURRENT_BINARY_DIR}/bin/) # Allow exes to find dlls:
set (BIN ${PROJECT_BINARY_DIR}/bin/)
set (EXAMPLES_BIN ${BIN}) set (EXAMPLES_BIN ${BIN})
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN}) set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN}) set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN})
@ -179,6 +226,10 @@ if (BUILD_SHARED_LIBS)
endif () endif ()
endif () endif ()
if (CMAKE_BUILD_TYPE STREQUAL "None") # As used by some distros.
add_definitions (-DNDEBUG)
endif ()
# Installation configuration: # Installation configuration:
@ -194,7 +245,7 @@ if (NOT DEFINED INCLUDE_INSTALL_DIR)
endif () endif ()
if (NOT DEFINED DOC_INSTALL_DIR) if (NOT DEFINED DOC_INSTALL_DIR)
if (UNIX) if (UNIX)
set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/libsoxr") set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/lib${PROJECT_NAME}")
else () else ()
set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/doc") set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/doc")
endif () endif ()
@ -202,25 +253,24 @@ endif ()
if (APPLE) if (APPLE)
option (BUILD_FRAMEWORK "Build an OS X framework." OFF) option (BUILD_FRAMEWORK "Build an OS X framework." OFF)
set (FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.") set (FRAMEWORK_INSTALL_DIR
"/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
endif () endif ()
# Top-level: # Top-level:
set (PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) set (PROJECT_VERSION
math (EXPR SO_VERSION_MAJOR "${SO_VERSION_CURRENT} - ${SO_VERSION_AGE}") ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
math (EXPR SO_VERSION_MINOR "${SO_VERSION_AGE}")
math (EXPR SO_VERSION_PATCH "${SO_VERSION_REVISION}")
set (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH}) set (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH})
configure_file ( configure_file (
${CMAKE_CURRENT_SOURCE_DIR}/soxr-config.h.in ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-config.h.in
${CMAKE_CURRENT_BINARY_DIR}/soxr-config.h) ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.h)
include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${PROJECT_BINARY_DIR})
if (BUILD_TESTS OR BUILD_LSR_TESTS) if (NOT CMAKE_CROSSCOMPILING AND (BUILD_TESTS OR BUILD_LSR_TESTS))
enable_testing () enable_testing ()
endif () endif ()
@ -234,7 +284,7 @@ install (FILES
# Subdirectories: # Subdirectories:
include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories (${PROJECT_SOURCE_DIR}/src)
add_subdirectory (src) add_subdirectory (src)
if (BUILD_TESTS) if (BUILD_TESTS)
@ -249,55 +299,45 @@ endif ()
# Rough-and-ready distclean for anyone still doing in-tree builds: # GNU Autotools compatibility; 'make check':
#if (UNIX) add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND})
# add_custom_target (distclean
# COMMAND make clean && rm -rf
# CMakeCache.txt
# CMakeFiles # GNU Autotools compatibility; 'make distclean':
# cmake_install.cmake
# CPackConfig.cmake if (UNIX)
# CPackSourceConfig.cmake add_custom_target (distclean COMMAND make clean && find .
# deinstall.cmake \\! -path \\*/Modules/\\* \\! -name cmp-test.cmake -a -name \\*.cmake
# Makefile -o -name CMakeFiles -o -name Makefile -o -name CMakeCache.txt -o -name
# soxr-config.h Testing -o -name cmake_install.cmake -o -name install_manifest.txt -o
# src/CMakeFiles -path ./soxr-config.h -o -name config.h -o -name \\*.pc -o -name \\*.s32
# src/cmake_install.cmake | xargs rm -rf)
# src/libsoxr-dev.src endif ()
# src/libsoxr-lsr.pc
# src/libsoxr.pc
# src/libsoxr.src
# src/Makefile)
#endif ()
# Deinstallation: # Deinstallation:
#configure_file ( configure_file (
# "${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in" "${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in"
# "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake"
# IMMEDIATE @ONLY) IMMEDIATE @ONLY)
#add_custom_target (deinstall add_custom_target (deinstall
# COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake") COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake")
# Packaging: # Packaging:
#if (UNIX) if (UNIX)
# set (CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set (CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
# set (CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") set (CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
# set (CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") set (CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
# set (CPACK_SOURCE_GENERATOR "TXZ")
# set (CPACK_SOURCE_GENERATOR "TGZ") set (CPACK_SOURCE_IGNORE_FILES
# set (CPACK_SOURCE_IGNORE_FILES "dist;/lsr-tests/;/Debug/;/Release/;/cpack/;\\\\.swp$;\\\\.gitignore;/\\\\.git/") "dist;/lsr-tests/;/Debug.*/;/Release.*/;\\\\.swp$;\\\\.git.*;/\\\\.git/")
# include (CPack)
# include (CPack) endif ()
#
# if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cpack)
# add_subdirectory (cpack)
# endif ()
#endif ()

View File

@ -1,11 +1,12 @@
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
INSTALLATION GUIDE CONTENTS INSTALLATION GUIDE CONTENTS
* Standard build * Standard build
* Build customisation * Build customisation
* Cross-compiling with mingw (linux host) * Cross-compilation
* Integration with other build systems * Integration with other build systems
* Run-time configuration
@ -20,7 +21,7 @@ STANDARD BUILD
* A 'make' utility (most compiler installations already have one of these). * A 'make' utility (most compiler installations already have one of these).
* CMake: http://www.cmake.org/cmake/resources/software.html * CMake v3.0 or newer: https://cmake.org/download/
2. Build: 2. Build:
@ -30,7 +31,7 @@ STANDARD BUILD
go (on MS-Windows with nmake) go (on MS-Windows with nmake)
or or
./go (on unix-like systems) ./go (on Unix-like systems)
This should build the library and run a few sanity tests. This should build the library and run a few sanity tests.
@ -38,14 +39,14 @@ STANDARD BUILD
3. Installation: 3. Installation:
Note that this step may need to be performed by a system Note that this step may need to be performed by a system
adminstrator. Enter: administrator. Enter:
nmake install (on MS-Windows) nmake install (on MS-Windows)
or or
cd Release; make install (on unix) cd Release; make install (on Unix-like)
4. Configuration: 4. Preparation for use:
To use the library you may need to set up appropriate paths to the To use the library you may need to set up appropriate paths to the
library and its header file in your development environment. library and its header file in your development environment.
@ -60,38 +61,74 @@ STANDARD BUILD
BUILD CUSTOMISATION BUILD CUSTOMISATION
If it is necessary to customise the build, then steps 2 and 3 above may be If it is necessary to customise the build, then steps 2 and 3 above should be
substituted as follows. Change directory to the one containing this file, substituted as follows: change directory to the one containing this file, then
then enter commands along the lines of: enter commands along the lines:
mkdir build mkdir build
cd build cd build
cmake [OPTIONS] .. cmake -Wno-dev -DCMAKE_BUILD_TYPE=Release [OPTIONS] ..
make make
make test make test
sudo make install sudo make install
N.B. The CMAKE_BUILD_TYPE to use for library deployment is Release.
To list help on the available options, enter: To list help on the available options, enter:
cmake -LH .. cmake -LH ..
Options, if given, should be preceded with '-D', e.g. Options, if given, should be preceded with '-D', e.g.
cmake -DWITH_SIMD:BOOL=OFF .. -DBUILD_SHARED_LIBS:BOOL=OFF
CROSS-COMPILING WITH MINGW (LINUX HOST) Resampling engines
For example: As available on a given system, options for including up-to five resampling
engines are available (per above) as follows:
WITH_CR32: for constant-rate HQ resampling,
WITH_CR32S: SIMD variant of previous,
WITH_CR64: for constant-rate VHQ resampling,
WITH_CR64S: SIMD variant of previous,
WITH_VR32: for variable-rate HQ resampling.
By default, these options are all set to ON.
When both SIMD and non-SIMD engine variants are included, run-time selection
is automatic (based on CPU capability) for x86 CPUs, and can be automatic for
ARM CPUs if the 3rd-party library `libavutil' is available at libsoxr
build-time. Which engine has been selected for a specific configuration and
invocation of the library can be checked using example #3, which reports it.
See also Run-time Configuration, below.
CROSS-COMPILATION
E.g. targeting a Linux ARM system:
mkdir build
cd build
cmake -DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
..
or, also building the examples (one of which uses C++):
cmake -DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
-DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \
-DBUILD_EXAMPLES=1 \
..
E.g. with Mingw (Linux host), using a tool-chain file:
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-x86_64-mingw-w64-mingw32.cmake \ cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-x86_64-mingw-w64-mingw32.cmake \
-DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_INSTALL_PREFIX=install \
-DHAVE_WORDS_BIGENDIAN_EXITCODE=1 \
-DBUILD_TESTS=0 \
-DBUILD_EXAMPLES=1 \
.. ..
make make
@ -117,7 +154,30 @@ INTEGRATION WITH OTHER BUILD SYSTEMS
Autotools-based systems might find it useful to create a file called Autotools-based systems might find it useful to create a file called
`configure' in the directory containing this file, consisting of the line: `configure' in the directory containing this file, consisting of the line:
cmake -DBUILD_SHARED_LIBS=OFF . cmake -DBUILD_SHARED_LIBS=OFF .
(or with other build options as required). (or with other build options as required).
For MS visual studio, see msvc/README For MS Visual Studio, see msvc/README.
RUN-TIME CONFIGURATION
The libsoxr API structure soxr_runtime_spec_t allows application developers
to optimise some aspects of libsoxrs operation for a particular application.
Optimal performance however, might depend on an individual end-users run-
time system and the end-users preferences. Hence environment variables are
available to set (override) run-time parameters as follows:
Env. variable Equivalent soxr_runtime_spec_t item (see soxr.h)
------------------ -----------------------------------
SOXR_COEFS_SIZE coef_size_kbytes
SOXR_COEF_INTERP SOXR_COEF_INTERP_xxx
SOXR_LARGE_DFT_SIZE log2_large_dft_size
SOXR_MIN_DFT_SIZE log2_min_dft_size
SOXR_NUM_THREADS num_threads
Additionally, the SOXR_USE_SIMD32 and SOXR_USE_SIMD64 boolean environment
variables can be used to override automatic selection (or to provide manual
selection where automatic selection is not available) between SIMD and
non-SIMD engine variants.

View File

@ -1,4 +1,4 @@
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
This library is free software; you can redistribute it and/or modify it 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 under the terms of the GNU Lesser General Public License as published by
@ -11,8 +11,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
General Public License for more details. General Public License for more details.
You should have received a copy of the GNU Lesser General Public License 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, along with this library; if not, see <https://www.gnu.org/licenses/>.
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Notes Notes

View File

@ -1,3 +1,12 @@
Version 0.1.3 (2018-02-24)
* SIMD enhancements: SSE, AVX, Neon.
* Improve support for clang, ARM, and cross-compilation.
* Provide env. var. override of runtime parameters.
* Build fix re cmake variables AVCODEC_INCLUDE_DIRS & AVUTIL_INCLUDE_DIRS.
* Build options WITH_SINGLE_PRECISION, WITH_DOUBLE_PRECISION & WITH_SIMD have
been removed; replacement options are detailed in INSTALL, `Resampling
engines'.
Version 0.1.2 (2015-09-05) Version 0.1.2 (2015-09-05)
* Fix conversion failure when I/O types differ but I/O rates don't. * Fix conversion failure when I/O types differ but I/O rates don't.
* Fix #defines for interpolation order selection. * Fix #defines for interpolation order selection.

View File

@ -1,4 +1,4 @@
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
The SoX Resampler library `libsoxr' performs one-dimensional sample-rate The SoX Resampler library `libsoxr' performs one-dimensional sample-rate
conversion -- it may be used, for example, to resample PCM-encoded audio. conversion -- it may be used, for example, to resample PCM-encoded audio.
@ -46,7 +46,7 @@ size configuration parameters may be used to reduce this figure).
For build and installation instructions, see the file `INSTALL'; for For build and installation instructions, see the file `INSTALL'; for
copyright and licensing information, see the file `LICENCE'. copyright and licensing information, see the file `LICENCE'.
For support and new versions, see http://soxr.sourceforge.net For support and new versions, see https://soxr.sourceforge.net
________ ________
¹ For example, multi-channel resampling can utilise multiple CPU-cores. ¹ For example, multi-channel resampling can utilise multiple CPU-cores.
² Bit-perfect within practical occupied-bandwidth limits. ² Bit-perfect within practical occupied-bandwidth limits.

View File

@ -1,3 +1,3 @@
* SOXR_ALLOW_ALIASING * vr32s
* Explicit flush API fn, perhaps. * vr32 with 1-delay-clear
* More SIMD. * fir_to_phase with RDFT32

View File

@ -0,0 +1,35 @@
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Function to find C compiler feature flags
include (CheckCSourceCompiles)
include (FindPackageHandleStandardArgs)
function (FindCFlags PKG_NAME PKG_DESC TRIAL_C_FLAGS TEST_C_SOURCE)
foreach (TRIAL_C_FLAG ${TRIAL_C_FLAGS})
message (STATUS "Trying ${PKG_NAME} C flags: ${TRIAL_C_FLAG}")
unset (DETECT_${PKG_NAME}_C_FLAGS CACHE) #displayed by check_c_source_compiles
set (TMP "${CMAKE_REQUIRED_FLAGS}")
set (CMAKE_REQUIRED_FLAGS "${TRIAL_C_FLAG}")
check_c_source_compiles ("${TEST_C_SOURCE}" DETECT_${PKG_NAME}_C_FLAGS)
set (CMAKE_REQUIRED_FLAGS "${TMP}")
if (DETECT_${PKG_NAME}_C_FLAGS)
set (DETECTED_C_FLAGS "${TRIAL_C_FLAG}")
break ()
endif ()
endforeach ()
# N.B. Will not overwrite existing cache variable:
set (${PKG_NAME}_C_FLAGS "${DETECTED_C_FLAGS}"
CACHE STRING "C compiler flags for ${PKG_DESC}")
find_package_handle_standard_args (
${PKG_NAME} DEFAULT_MSG ${PKG_NAME}_C_FLAGS ${PKG_NAME}_C_FLAGS)
mark_as_advanced (${PKG_NAME}_C_FLAGS)
set (${PKG_NAME}_FOUND ${${PKG_NAME}_FOUND} PARENT_SCOPE)
endfunction ()

View File

@ -1,23 +1,23 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net # SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details. # Licence for this file: LGPL v2.1 See LICENCE for details.
# - Find AVCODEC # - Find AVCODEC
# Find the native installation of this package: includes and libraries. # Find the installation of this package: include-dirs and libraries.
# #
# AVCODEC_INCLUDES - where to find headers for this package. # AVCODEC_INCLUDE_DIRS - where to find headers for this package.
# AVCODEC_LIBRARIES - List of libraries when using this package. # AVCODEC_LIBRARIES - libraries to link to when using this package.
# AVCODEC_FOUND - True if this package can be found. # AVCODEC_FOUND - true iff this package can be found.
if (AVCODEC_INCLUDES) if (AVCODEC_INCLUDE_DIRS)
set (AVCODEC_FIND_QUIETLY TRUE) set (AVCODEC_FIND_QUIETLY TRUE)
endif (AVCODEC_INCLUDES) endif ()
find_path (AVCODEC_INCLUDES libavcodec/avcodec.h) find_path (AVCODEC_INCLUDE_DIRS libavcodec/avcodec.h)
find_library (AVCODEC_LIBRARIES NAMES avcodec) find_library (AVCODEC_LIBRARIES NAMES avcodec)
include (FindPackageHandleStandardArgs) include (FindPackageHandleStandardArgs)
find_package_handle_standard_args ( find_package_handle_standard_args (
AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDES) AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIRS)
mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDES) mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIRS)

View File

@ -0,0 +1,23 @@
# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Find AVUTIL
# Find the installation of this package: includes and libraries.
#
# AVUTIL_INCLUDE_DIRS - where to find headers for this package.
# AVUTIL_LIBRARIES - libraries to link to when using this package.
# AVUTIL_FOUND - true iff this package can be found.
if (AVUTIL_INCLUDE_DIRS)
set (AVUTIL_FIND_QUIETLY TRUE)
endif ()
find_path (AVUTIL_INCLUDE_DIRS libavutil/cpu.h)
find_library (AVUTIL_LIBRARIES NAMES avutil)
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (
AVUTIL DEFAULT_MSG AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIRS)
mark_as_advanced (AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIRS)

View File

@ -1,115 +0,0 @@
# - Finds OpenMP support
# This module can be used to detect OpenMP support in a compiler.
# If the compiler supports OpenMP, the flags required to compile with
# openmp support are set.
#
# The following variables are set:
# OpenMP_C_FLAGS - flags to add to the C compiler for OpenMP support
# OPENMP_FOUND - true if openmp is detected
#
# Supported compilers can be found at http://openmp.org/wp/openmp-compilers/
#
# Modifications for soxr:
# * don't rely on presence of C++ compiler
# * support MINGW
#
#=============================================================================
# Copyright 2009 Kitware, Inc.
# Copyright 2008-2009 André Rigland Brodtkorb <Andre.Brodtkorb@ifi.uio.no>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * The names of Kitware, Inc., the Insight Consortium, or the names of
# any consortium members, or of any contributors, may not be used to
# endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include (CheckCSourceCompiles)
include (FindPackageHandleStandardArgs)
set (OpenMP_C_FLAG_CANDIDATES
#Gnu
"-fopenmp"
#Microsoft Visual Studio
"/openmp"
#Intel windows
"-Qopenmp"
#Intel
"-openmp"
#Empty, if compiler automatically accepts openmp
" "
#Sun
"-xopenmp"
#HP
"+Oopenmp"
#IBM XL C/c++
"-qsmp"
#Portland Group
"-mp"
)
# sample openmp source code to test
set (OpenMP_C_TEST_SOURCE
"
#include <omp.h>
int main() {
#ifdef _OPENMP
return 0;
#else
breaks_on_purpose
#endif
}
")
# if these are set then do not try to find them again,
# by avoiding any try_compiles for the flags
if (DEFINED OpenMP_C_FLAGS)
set (OpenMP_C_FLAG_CANDIDATES)
endif (DEFINED OpenMP_C_FLAGS)
# check c compiler
foreach (FLAG ${OpenMP_C_FLAG_CANDIDATES})
set (SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
set (CMAKE_REQUIRED_FLAGS "${FLAG}")
unset (OpenMP_FLAG_DETECTED CACHE)
message (STATUS "Try OpenMP C flag = [${FLAG}]")
check_c_source_compiles ("${OpenMP_C_TEST_SOURCE}" OpenMP_FLAG_DETECTED)
set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
if (OpenMP_FLAG_DETECTED)
set (OpenMP_C_FLAGS_INTERNAL "${FLAG}")
break ()
endif (OpenMP_FLAG_DETECTED)
endforeach (FLAG ${OpenMP_C_FLAG_CANDIDATES})
set (OpenMP_C_FLAGS "${OpenMP_C_FLAGS_INTERNAL}"
CACHE STRING "C compiler flags for OpenMP parallization")
# handle the standard arguments for find_package
find_package_handle_standard_args (OpenMP DEFAULT_MSG
OpenMP_C_FLAGS)
if (MINGW)
set (OpenMP_SHARED_LINKER_FLAGS "${OpenMP_SHARED_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
set (OpenMP_EXE_LINKER_FLAGS "${OpenMP_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
endif ()
mark_as_advanced (OpenMP_C_FLAGS OpenMP_SHARED_LINKER_FLAGS OpenMP_EXE_LINKER_FLAGS)

View File

@ -1,94 +0,0 @@
# - Finds SIMD support
#
# The following variables are set:
# SIMD_C_FLAGS - flags to add to the C compiler for this package.
# SIMD_FOUND - true if support for this package is found.
#
#=============================================================================
# Based on FindOpenMP.cmake, which is:
#
# Copyright 2009 Kitware, Inc.
# Copyright 2008-2009 André Rigland Brodtkorb <Andre.Brodtkorb@ifi.uio.no>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * The names of Kitware, Inc., the Insight Consortium, or the names of
# any consortium members, or of any contributors, may not be used to
# endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include (CheckCSourceCompiles)
include (FindPackageHandleStandardArgs)
if (WIN32) # Safety for when mixed lib/app compilers (but performance hit)
set (GCC_WIN32_SIMD_OPTS "-mincoming-stack-boundary=2")
endif ()
set (SIMD_C_FLAG_CANDIDATES
# x64
" "
# Microsoft Visual Studio x86
"/arch:SSE /fp:fast -D__SSE__"
# Gcc x86
"-msse -mfpmath=sse ${GCC_WIN32_SIMD_OPTS}"
# Gcc x86 (old versions)
"-msse -mfpmath=sse"
)
set (SIMD_C_TEST_SOURCE
"
#include <xmmintrin.h>
int main()
{
__m128 a, b;
float vals[4] = {0};
a = _mm_loadu_ps (vals);
b = a;
b = _mm_add_ps (a,b);
_mm_storeu_ps (vals,b);
return 0;
}
")
if (DEFINED SIMD_C_FLAGS)
set (SIMD_C_FLAG_CANDIDATES)
endif ()
foreach (FLAG ${SIMD_C_FLAG_CANDIDATES})
set (SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
set (CMAKE_REQUIRED_FLAGS "${FLAG}")
unset (SIMD_FLAG_DETECTED CACHE)
message (STATUS "Try SIMD C flag = [${FLAG}]")
check_c_source_compiles ("${SIMD_C_TEST_SOURCE}" SIMD_FLAG_DETECTED)
set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
if (SIMD_FLAG_DETECTED)
set (SIMD_C_FLAGS_INTERNAL "${FLAG}")
break ()
endif ()
endforeach ()
set (SIMD_C_FLAGS "${SIMD_C_FLAGS_INTERNAL}"
CACHE STRING "C compiler flags for SIMD vectorization")
find_package_handle_standard_args (SIMD DEFAULT_MSG SIMD_C_FLAGS SIMD_C_FLAGS)
mark_as_advanced (SIMD_C_FLAGS)

View File

@ -0,0 +1,54 @@
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Finds SIMD32 support
#
# The following variables are set:
# SIMD32_C_FLAGS - flags to add to the C compiler for this package.
# SIMD32_FOUND - true if support for this package is found.
if (DEFINED SIMD32_C_FLAGS)
set (TRIAL_C_FLAGS)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set (TRIAL_C_FLAGS
# Gcc
"-mfpu=neon-vfpv4 -mcpu=cortex-a7"
"-mfpu=neon -mfloat-abi=hard"
"-mfpu=neon -mfloat-abi=softfp"
"-mfpu=neon -mfloat-abi=soft"
)
set (TEST_C_SOURCE "
#include <arm_neon.h>
int main(int c, char * * v) {
float32x4_t a = vdupq_n_f32((float)c), b = vdupq_n_f32((float)!!v);
return !vgetq_lane_u32(vceqq_f32(a,b),0);
}
")
else ()
if (WIN32) # Safety for when mixed lib/app compilers (but performance hit)
set (GCC_WIN32_SIMD32_OPTS "-mincoming-stack-boundary=2")
endif ()
set (TRIAL_C_FLAGS
# x64
" "
# MSVC x86
"/arch:SSE /fp:fast -D__SSE__"
# Gcc x86
"-msse -mfpmath=sse ${GCC_WIN32_SIMD32_OPTS}"
# Gcc x86 (old versions)
"-msse -mfpmath=sse"
)
set (TEST_C_SOURCE "
#include <xmmintrin.h>
int main(int c, char * * v) {
__m128 a = _mm_set_ss((float)c), b = _mm_set_ss((float)!!v);
return _mm_comineq_ss(a,b);
}
")
endif ()
include (FindCFlags)
FindCFlags ("SIMD32" "FLOAT-32 (single-precision) SIMD vectorization"
"${TRIAL_C_FLAGS}" "${TEST_C_SOURCE}")

View File

@ -0,0 +1,29 @@
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Finds SIMD64 support
#
# The following variables are set:
# SIMD64_C_FLAGS - flags to add to the C compiler for this package.
# SIMD64_FOUND - true if support for this package is found.
if (DEFINED SIMD64_C_FLAGS OR CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set (TRIAL_C_FLAGS)
else ()
set (TRIAL_C_FLAGS
"-mavx" # Gcc
"/arch:AVX" # MSVC
)
set (TEST_C_SOURCE "
#ifndef __AVX__
#error
#endif
#include <immintrin.h>
int main() {return 0;}
")
endif ()
include (FindCFlags)
FindCFlags ("SIMD64" "FLOAT-64 (double-precision) SIMD vectorization"
"${TRIAL_C_FLAGS}" "${TEST_C_SOURCE}")

View File

@ -0,0 +1,37 @@
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# Sets CMAKE_SYSTEM_PROCESSOR for cross-compiling.
macro (set_system_processor)
if (CMAKE_CROSSCOMPILING)
if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "unknown")
unset(CMAKE_SYSTEM_PROCESSOR)
endif ()
if (NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
include (CheckCSourceCompiles)
set (CPU_LINES
"#if defined __x86_64__ || defined _M_X64 /*\;x86_64\;*/"
"#if defined __i386__ || defined _M_IX86 /*\;x86_32\;*/"
"#if defined __arm__ || defined _M_ARM /*\;arm\;*/"
)
foreach (CPU_LINE ${CPU_LINES})
string (CONCAT CPU_SOURCE "${CPU_LINE}" "
int main() {return 0;}
#endif
")
unset (SYSTEM_PROCESSOR_DETECTED CACHE)
check_c_source_compiles ("${CPU_SOURCE}" SYSTEM_PROCESSOR_DETECTED)
if (SYSTEM_PROCESSOR_DETECTED)
list (GET CPU_LINE 1 CMAKE_SYSTEM_PROCESSOR)
message (STATUS "CMAKE_SYSTEM_PROCESSOR is ${CMAKE_SYSTEM_PROCESSOR}")
break ()
endif ()
endforeach ()
endif ()
# N.B. Will not overwrite existing cache variable:
set (CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}"
CACHE STRING "Target system processor")
endif ()
endmacro ()

View File

@ -1,15 +0,0 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Macro to determine endian type
# test_big_endian (VARIABLE)
# VARIABLE - variable to store the result to
macro (test_big_endian VARIABLE)
if ("${HAVE_${VARIABLE}}" MATCHES "^${HAVE_${VARIABLE}}$")
include (CheckCSourceRuns)
check_c_source_runs ("int main() {union {long i; char c[sizeof(long)];}
const u = {1}; return !!u.c[0];}" HAVE_${VARIABLE})
set (${VARIABLE} "${HAVE_${VARIABLE}}" CACHE INTERNAL "1 if system is big endian" FORCE)
endif ()
endmacro ()

12
soxr/dist Normal file
View File

@ -0,0 +1,12 @@
#!/bin/sh
set -e
# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# Makes the distribution tarball
test $# = 1 -o `git status -s|wc -c` = 0
rm -rf Release
./go -j4
cd Release
make package_source

View File

@ -25,7 +25,7 @@ const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */
int main(int argc, char const * arg[]) int main(int argc, char const * arg[])
{ {
double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */ double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */ double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */ size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */

View File

@ -12,7 +12,7 @@ float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */
int main(int argc, char const * arg[]) int main(int argc, char const * arg[])
{ {
double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */ double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */ double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */ size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */

View File

@ -1,4 +1,4 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Example 3: extends example 2 with multiple channels, multiple datatypes, /* Example 3: extends example 2 with multiple channels, multiple datatypes,
@ -14,7 +14,7 @@
* OUTPUT-RATE Ditto * OUTPUT-RATE Ditto
* NUM-CHANNELS Number of interleaved channels * NUM-CHANNELS Number of interleaved channels
* IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16
* OUT-DATATYPE# Ditto * OUT-DATATYPE# Ditto; or 11 for un-dithered int16
* Q-RECIPE Quality recipe (in hex) See soxr.h * Q-RECIPE Quality recipe (in hex) See soxr.h
* Q-FLAGS Quality flags (in hex) See soxr.h * Q-FLAGS Quality flags (in hex) See soxr.h
* PASSBAND-END % * PASSBAND-END %
@ -42,7 +42,7 @@ static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len)
int main(int n, char const * arg[]) int main(int n, char const * arg[])
{ {
char const * const arg0 = n? --n, *arg++ : ""; char const * const arg0 = n? --n, *arg++ : "", * engine = "";
double const irate = n? --n, atof(*arg++) : 96000.; double const irate = n? --n, atof(*arg++) : 96000.;
double const orate = n? --n, atof(*arg++) : 44100.; double const orate = n? --n, atof(*arg++) : 44100.;
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
@ -94,6 +94,7 @@ int main(int n, char const * arg[])
} }
if (!error) { /* If all is well, run the resampler: */ if (!error) { /* If all is well, run the resampler: */
engine = soxr_engine(soxr);
USE_STD_STDIO; USE_STD_STDIO;
/* Resample in blocks: */ /* Resample in blocks: */
do odone = soxr_output(soxr, obuf, olen); do odone = soxr_output(soxr, obuf, olen);
@ -106,8 +107,8 @@ int main(int n, char const * arg[])
soxr_delete(soxr); soxr_delete(soxr);
free(obuf), free(ibuf); free(obuf), free(ibuf);
/* Diagnostics: */ /* Diagnostics: */
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n", fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%s)\n",
arg0, soxr_strerror(error), (long unsigned)clips, arg0, soxr_strerror(error), (long unsigned)clips,
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine);
return !!error; return !!error;
} }

View File

@ -1,4 +1,4 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels. /* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels.
@ -13,6 +13,8 @@
* *
* Note also (not shown in the examples) that split/interleaved channels may * Note also (not shown in the examples) that split/interleaved channels may
* be used for input and output independently. * be used for input and output independently.
*
* Arguments are as example 3.
*/ */
#include <soxr.h> #include <soxr.h>
@ -73,13 +75,17 @@ int main(int n, char const * arg[])
double const orate = n? --n, atof(*arg++) : 44100.; double const orate = n? --n, atof(*arg++) : 44100.;
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
soxr_datatype_t const otype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ;
unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0;
double const passband_end = n? --n, atof(*arg++) : 0;
double const stopband_begin = n? --n, atof(*arg++) : 0;
double const phase_response = n? --n, atof(*arg++) : -1;
int const use_threads = n? --n, atoi(*arg++) : 1; int const use_threads = n? --n, atoi(*arg++) : 1;
soxr_datatype_t const otype = ospec & 3;
soxr_quality_spec_t const q_spec = soxr_quality_spec(q_recipe, q_flags); soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags);
soxr_io_spec_t const io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT); soxr_io_spec_t io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT);
soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads);
/* Allocate resampling input and output buffers in proportion to the input /* Allocate resampling input and output buffers in proportion to the input
@ -102,11 +108,18 @@ int main(int n, char const * arg[])
size_t odone, written, need_input = 1, clips = 0; size_t odone, written, need_input = 1, clips = 0;
soxr_error_t error; soxr_error_t error;
soxr_t soxr;
unsigned i;
soxr_t soxr = soxr_create( /* Overrides (if given): */
if (passband_end > 0) q_spec.passband_end = passband_end / 100;
if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100;
if (phase_response >=0) q_spec.phase_response = phase_response;
io_spec.flags = ospec & ~7u;
soxr = soxr_create(
irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec); irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec);
unsigned i;
for (i = 0; i < chans; ++i) { for (i = 0; i < chans; ++i) {
ibuf_ptrs[i] = iptr; ibuf_ptrs[i] = iptr;
obuf_ptrs[i] = optr; obuf_ptrs[i] = optr;

View File

@ -1,25 +1,23 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net # SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details. # Licence for this file: LGPL v2.1 See LICENCE for details.
if (${BUILD_EXAMPLES}) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
project (soxr) # Adds c++ compiler set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}")
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/[1-9]-*.[cC]) link_libraries (${PROJECT_NAME} ${LIBM_LIBRARIES})
elseif (${BUILD_TESTS})
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/3*.c)
endif ()
if (${BUILD_EXAMPLES} OR ${BUILD_TESTS}) if (${BUILD_EXAMPLES} OR ${BUILD_TESTS})
set (SOURCES 3-options-input-fn)
if (${WITH_LSR_BINDINGS}) if (${WITH_LSR_BINDINGS})
set (LSR_SOURCES 1a-lsr.c) set (LSR_SOURCES 1a-lsr)
endif () endif ()
endif () endif ()
if (NOT BUILD_SHARED_LIBS AND OPENMP_FOUND) if (${BUILD_EXAMPLES})
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_C_FLAGS}") list (APPEND SOURCES 1-single-block 2-stream 4-split-channels)
if (${WITH_VR32})
list (APPEND SOURCES 5-variable-rate)
endif ()
endif () endif ()
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}")
link_libraries (soxr)
foreach (fe ${SOURCES} ${LSR_SOURCES}) foreach (fe ${SOURCES} ${LSR_SOURCES})
get_filename_component (f ${fe} NAME_WE) get_filename_component (f ${fe} NAME_WE)
@ -34,4 +32,5 @@ if (${BUILD_TESTS} AND ${WITH_LSR_BINDINGS})
endif () endif ()
file (GLOB INSTALL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cCh]) file (GLOB INSTALL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cCh])
install (FILES ${INSTALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/README DESTINATION ${DOC_INSTALL_DIR}/examples) install (FILES ${INSTALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/README
DESTINATION ${DOC_INSTALL_DIR}/examples)

View File

@ -1,4 +1,4 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Common includes etc. for the examples. */ /* Common includes etc. for the examples. */
@ -17,10 +17,7 @@
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>
#define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \ #define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \
_setmode(_fileno(stdin ), _O_BINARY); _setmode(_fileno(stdin ), _O_BINARY)
/* Sometimes missing, so ensure that it is defined: */
#undef M_PI
#define M_PI 3.14159265358979323846
#else #else
#define USE_STD_STDIO #define USE_STD_STDIO
#endif #endif
@ -38,8 +35,13 @@
#endif #endif
#undef min #undef min
#undef max
#define min(x,y) ((x)<(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y))
#undef max
#define max(x,y) ((x)>(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y))
#undef AL
#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */ #define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */
#undef M_PI /* Sometimes missing, so ensure that it is defined: */
#define M_PI 3.14159265358979323846

18
soxr/go Normal file
View File

@ -0,0 +1,18 @@
#!/bin/sh
set -e
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
case "$1" in -j*) j="$1"; shift;; esac # Support -jX for parallel build/test
test x"$1" = x && build=Release || build="$1"
rm -f CMakeCache.txt # Prevent interference from any in-tree build
mkdir -p "$build"
cd "$build"
cmake -Wno-dev -DCMAKE_BUILD_TYPE="$build" ..
make $j
ctest $j || echo "FAILURE details in $build/Testing/Temporary/LastTest.log"

27
soxr/go.bat Normal file
View File

@ -0,0 +1,27 @@
@echo off
rem SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
rem Licence for this file: LGPL v2.1 See LICENCE for details.
set build=%1
if x%build% == x set build=Release
rem Prevent interference from any in-tree build
del/f CMakeCache.txt
mkdir %build%
cd %build%
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% -Wno-dev ..
if errorlevel 1 goto end
nmake
if errorlevel 1 goto end
nmake test
if errorlevel 1 goto error
goto end
:error
echo FAILURE details in Testing\Temporary\LastTest.log
:end

25
soxr/inst-check Normal file
View File

@ -0,0 +1,25 @@
#!/bin/sh
set -e
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# Sanity-check of library installed on unix-like system
# This script checks the installation of the entire library (including lsr).
#
# Distros using three separate packages can do the following (in order):
#
# * Install soxr pkg (i.e. basically, just the shared object)
# * ./inst-check-soxr
# * Install soxr-lsr pkg (i.e. basically, just the shared object)
# * ./inst-check-soxr-lsr
# * Install the -dev pkg (i.e. examples, headers, & pkg-config)
# * ./inst-check PATH-OF-INSTALLED-EXAMPLES-DIR (e.g. /usr/share/doc/libsoxr/examples)
# Where are the example source files:
src=$1
test x$src = x && src=/usr/local/share/doc/libsoxr/examples
dir="$(dirname $(readlink -f $0))"
$dir/inst-check-soxr $src
$dir/inst-check-soxr-lsr $src

52
soxr/inst-check-soxr Normal file
View File

@ -0,0 +1,52 @@
#!/bin/sh
set -e
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# Sanity-check of sub-library installed on unix-like system
arg="$1" # path to installed examples (if dev pkg installed); otherwise omitted
dir="$(dirname $(readlink -f $0))"
# Find the examples:
src="$arg"
test x"$src" = x && src="$dir/examples"
cd $src
# Somewhere to put the binaries:
tmp=`mktemp -d`
build_examples() {
if [ x"$arg" = x ]; then
echo "Examples in `pwd`; using local headers:" # for when dev pkg not installed
libs=-l$1
cflags=-I$dir/src
else
echo "Examples in `pwd`; using pkg-config:"
libs=$(pkg-config --libs $1)
cflags=$(pkg-config --cflags $1)
fi
for f in ?$2-*.[cC]; do
cc=cc; echo $f | grep -q C$ && cc=c++
out=$tmp/`echo $f | sed "s/.[cC]$//"`
cmd="$cc $cflags -o $out $f $libs -lm"
echo $cmd; $cmd
done
}
# Determine library:
if [ `basename $0` = inst-check-soxr ]; then
build_examples soxr
gen="dd if=/dev/urandom count=1000"
$tmp/1-single-block 1 2 .
$gen 2> /dev/null | $tmp/2-stream 2>&1 >$tmp/stdout
$gen 2> /dev/null | $tmp/3-options-input-fn 6 7 2 2 0 2>&1 >$tmp/stdout
$gen 2> /dev/null | $tmp/4-split-channels 7 6 2 2 3 2>&1 >$tmp/stdout # Clipping expected here
$gen 2> /dev/null | $tmp/5-variable-rate 2>&1 >$tmp/stdout
else
build_examples soxr-lsr a # lsr has 'a' suffix on example number.
$tmp/1a-lsr 1 2 .
fi
# Tidy up:
rm -rf $tmp

52
soxr/inst-check-soxr-lsr Normal file
View File

@ -0,0 +1,52 @@
#!/bin/sh
set -e
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# Sanity-check of sub-library installed on unix-like system
arg="$1" # path to installed examples (if dev pkg installed); otherwise omitted
dir="$(dirname $(readlink -f $0))"
# Find the examples:
src="$arg"
test x"$src" = x && src="$dir/examples"
cd $src
# Somewhere to put the binaries:
tmp=`mktemp -d`
build_examples() {
if [ x"$arg" = x ]; then
echo "Examples in `pwd`; using local headers:" # for when dev pkg not installed
libs=-l$1
cflags=-I$dir/src
else
echo "Examples in `pwd`; using pkg-config:"
libs=$(pkg-config --libs $1)
cflags=$(pkg-config --cflags $1)
fi
for f in ?$2-*.[cC]; do
cc=cc; echo $f | grep -q C$ && cc=c++
out=$tmp/`echo $f | sed "s/.[cC]$//"`
cmd="$cc $cflags -o $out $f $libs -lm"
echo $cmd; $cmd
done
}
# Determine library:
if [ `basename $0` = inst-check-soxr ]; then
build_examples soxr
gen="dd if=/dev/urandom count=1000"
$tmp/1-single-block 1 2 .
$gen 2> /dev/null | $tmp/2-stream 2>&1 >$tmp/stdout
$gen 2> /dev/null | $tmp/3-options-input-fn 6 7 2 2 0 2>&1 >$tmp/stdout
$gen 2> /dev/null | $tmp/4-split-channels 7 6 2 2 3 2>&1 >$tmp/stdout # Clipping expected here
$gen 2> /dev/null | $tmp/5-variable-rate 2>&1 >$tmp/stdout
else
build_examples soxr-lsr a # lsr has 'a' suffix on example number.
$tmp/1a-lsr 1 2 .
fi
# Tidy up:
rm -rf $tmp

View File

@ -0,0 +1,50 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
find_package (FFTW)
if (FFTW_FOUND)
include_directories (${FFTW_INCLUDE_DIRS})
link_libraries (${FFTW_LIBRARIES})
set (HAVE_FFTW3 1)
endif ()
find_package (sndfile)
if (SNDFILE_FOUND)
include_directories (${SNDFILE_INCLUDE_DIRS})
link_libraries (${SNDFILE_LIBRARIES})
set (HAVE_SNDFILE 1)
endif ()
check_function_exists (lrintf HAVE_LRINTF)
check_function_exists (alarm HAVE_ALARM)
check_function_exists (signal HAVE_SIGNAL)
check_include_files (sys/times.h HAVE_SYS_TIMES_H)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
include_directories (${CMAKE_CURRENT_BINARY_DIR})
add_library (tests_lib STATIC util calc_snr)
link_libraries (tests_lib ${PROJECT_NAME}-lsr ${LIBM_LIBRARIES})
enable_testing ()
set (tests
callback_hang_test callback_test downsample_test
float_short_test misc_test multi_channel_test
reset_test simple_test termination_test varispeed_test)
if (WITH_CR64 OR WITH_CR64S)
set (tests ${tests} snr_bw_test)
endif ()
foreach (test ${tests})
add_executable (${test} ${test})
add_test (lsr-${test} ${BIN}${test})
set_property (TEST lsr-${test} PROPERTY ENVIRONMENT "SOXR_LSR_STRICT=1")
endforeach ()
add_executable (multichan_throughput_test multichan_throughput_test)
add_executable (throughput_test throughput_test )
add_executable (sndfile-resample sndfile-resample)

340
soxr/lsr-tests/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

8
soxr/lsr-tests/README Normal file
View File

@ -0,0 +1,8 @@
The C source and header files in this directory have been copied from
the `libsamplerate' project and are copyrighted by its authors -- see
the notices within the files and the file `COPYING' for details.
They are used here to test libsoxr's optional libsamplerate-like
wrapper. The only modifications made are to the file `snr_bw_test.c' to
remove reliance on certain frequency response troughs that are specific
to libsamplerate.

242
soxr/lsr-tests/calc_snr.c Normal file
View File

@ -0,0 +1,242 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 "config.h"
#include "util.h"
#if (HAVE_FFTW3 == 1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fftw3.h>
#define MAX_SPEC_LEN (1<<18)
#define MAX_PEAKS 10
static void log_mag_spectrum (double *input, int len, double *magnitude) ;
static void smooth_mag_spectrum (double *magnitude, int len) ;
static double find_snr (const double *magnitude, int len, int expected_peaks) ;
typedef struct
{ double peak ;
int index ;
} PEAK_DATA ;
double
calculate_snr (float *data, int len, int expected_peaks)
{ static double magnitude [MAX_SPEC_LEN] ;
static double datacopy [MAX_SPEC_LEN] ;
double snr = 200.0 ;
int k ;
if (len > MAX_SPEC_LEN)
{ printf ("%s : line %d : data length too large.\n", __FILE__, __LINE__) ;
exit (1) ;
} ;
for (k = 0 ; k < len ; k++)
datacopy [k] = data [k] ;
/* Pad the data just a little to speed up the FFT. */
while ((len & 0x1F) && len < MAX_SPEC_LEN)
{ datacopy [len] = 0.0 ;
len ++ ;
} ;
log_mag_spectrum (datacopy, len, magnitude) ;
smooth_mag_spectrum (magnitude, len / 2) ;
snr = find_snr (magnitude, len, expected_peaks) ;
return snr ;
} /* calculate_snr */
/*==============================================================================
** There is a slight problem with trying to measure SNR with the method used
** here; the side lobes of the windowed FFT can look like a noise/aliasing peak.
** The solution is to smooth the magnitude spectrum by wiping out troughs
** between adjacent peaks as done here.
** This removes side lobe peaks without affecting noise/aliasing peaks.
*/
static void linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller) ;
static void
smooth_mag_spectrum (double *mag, int len)
{ PEAK_DATA peaks [2] ;
int k ;
memset (peaks, 0, sizeof (peaks)) ;
/* Find first peak. */
for (k = 1 ; k < len - 1 ; k++)
{ if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1])
{ peaks [0].peak = mag [k] ;
peaks [0].index = k ;
break ;
} ;
} ;
/* Find subsequent peaks ans smooth between peaks. */
for (k = peaks [0].index + 1 ; k < len - 1 ; k++)
{ if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1])
{ peaks [1].peak = mag [k] ;
peaks [1].index = k ;
if (peaks [1].peak > peaks [0].peak)
linear_smooth (mag, &peaks [1], &peaks [0]) ;
else
linear_smooth (mag, &peaks [0], &peaks [1]) ;
peaks [0] = peaks [1] ;
} ;
} ;
} /* smooth_mag_spectrum */
static void
linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller)
{ int k ;
if (smaller->index < larger->index)
{ for (k = smaller->index + 1 ; k < larger->index ; k++)
mag [k] = (mag [k] < mag [k - 1]) ? 0.999 * mag [k - 1] : mag [k] ;
}
else
{ for (k = smaller->index - 1 ; k >= larger->index ; k--)
mag [k] = (mag [k] < mag [k + 1]) ? 0.999 * mag [k + 1] : mag [k] ;
} ;
} /* linear_smooth */
/*==============================================================================
*/
static int
peak_compare (const void *vp1, const void *vp2)
{ const PEAK_DATA *peak1, *peak2 ;
peak1 = (const PEAK_DATA*) vp1 ;
peak2 = (const PEAK_DATA*) vp2 ;
return (peak1->peak < peak2->peak) ? 1 : -1 ;
} /* peak_compare */
static double
find_snr (const double *magnitude, int len, int expected_peaks)
{ PEAK_DATA peaks [MAX_PEAKS] ;
int k, peak_count = 0 ;
double snr ;
memset (peaks, 0, sizeof (peaks)) ;
/* Find the MAX_PEAKS largest peaks. */
for (k = 1 ; k < len - 1 ; k++)
{ if (magnitude [k - 1] < magnitude [k] && magnitude [k] >= magnitude [k + 1])
{ if (peak_count < MAX_PEAKS)
{ peaks [peak_count].peak = magnitude [k] ;
peaks [peak_count].index = k ;
peak_count ++ ;
qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ;
}
else if (magnitude [k] > peaks [MAX_PEAKS - 1].peak)
{ peaks [MAX_PEAKS - 1].peak = magnitude [k] ;
peaks [MAX_PEAKS - 1].index = k ;
qsort (peaks, MAX_PEAKS, sizeof (PEAK_DATA), peak_compare) ;
} ;
} ;
} ;
if (peak_count < expected_peaks)
{ printf ("\n%s : line %d : bad peak_count (%d), expected %d.\n\n", __FILE__, __LINE__, peak_count, expected_peaks) ;
return -1.0 ;
} ;
/* Sort the peaks. */
qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ;
snr = peaks [0].peak ;
for (k = 1 ; k < peak_count ; k++)
if (fabs (snr - peaks [k].peak) > 10.0)
return fabs (peaks [k].peak) ;
return snr ;
} /* find_snr */
static void
log_mag_spectrum (double *input, int len, double *magnitude)
{ fftw_plan plan = NULL ;
double maxval ;
int k ;
if (input == NULL || magnitude == NULL)
return ;
plan = fftw_plan_r2r_1d (len, input, magnitude, FFTW_R2HC, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT) ;
if (plan == NULL)
{ printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ;
exit (1) ;
} ;
fftw_execute (plan) ;
fftw_destroy_plan (plan) ;
/* (k < N/2 rounded up) */
maxval = 0.0 ;
for (k = 1 ; k < len / 2 ; k++)
{ magnitude [k] = sqrt (magnitude [k] * magnitude [k] + magnitude [len - k - 1] * magnitude [len - k - 1]) ;
maxval = (maxval < magnitude [k]) ? magnitude [k] : maxval ;
} ;
memset (magnitude + len / 2, 0, len / 2 * sizeof (magnitude [0])) ;
/* Don't care about DC component. Make it zero. */
magnitude [0] = 0.0 ;
/* log magnitude. */
for (k = 0 ; k < len ; k++)
{ magnitude [k] = magnitude [k] / maxval ;
magnitude [k] = (magnitude [k] < 1e-15) ? -200.0 : 20.0 * log10 (magnitude [k]) ;
} ;
return ;
} /* log_mag_spectrum */
#else /* ! (HAVE_LIBFFTW && HAVE_LIBRFFTW) */
double
calculate_snr (float *data, int len, int expected_peaks)
{ double snr = 200.0 ;
data = data ;
len = len ;
expected_peaks = expected_peaks ;
return snr ;
} /* calculate_snr */
#endif

View File

@ -0,0 +1,131 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#if HAVE_ALARM && HAVE_SIGNAL && HAVE_SIGALRM
#include <signal.h>
#include <samplerate.h>
#include "util.h"
#define SHORT_BUFFER_LEN 512
#define LONG_BUFFER_LEN (1 << 14)
typedef struct
{ double ratio ;
int count ;
} SRC_PAIR ;
static void callback_hang_test (int converter) ;
static void alarm_handler (int number) ;
static long input_callback (void *cb_data, float **data) ;
int
main (void)
{
/* Set up SIGALRM handler. */
signal (SIGALRM, alarm_handler) ;
puts ("") ;
callback_hang_test (SRC_ZERO_ORDER_HOLD) ;
callback_hang_test (SRC_LINEAR) ;
callback_hang_test (SRC_SINC_FASTEST) ;
puts ("") ;
return 0 ;
} /* main */
static void
callback_hang_test (int converter)
{ static float output [LONG_BUFFER_LEN] ;
static SRC_PAIR pairs [] =
{
{ 1.2, 5 }, { 1.1, 1 }, { 1.0, 1 }, { 3.0, 1 }, { 2.0, 1 }, { 0.3, 1 },
{ 1.2, 0 }, { 1.1, 10 }, { 1.0, 1 }
} ;
SRC_STATE *src_state ;
double src_ratio = 1.0 ;
int k, error ;
printf ("\tcallback_hang_test (%-28s) ....... ", src_get_name (converter)) ;
fflush (stdout) ;
/* Perform sample rate conversion. */
src_state = src_callback_new (input_callback, converter, 1, &error, NULL) ;
if (src_state == NULL)
{ printf ("\n\nLine %d : src_callback_new () failed : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
for (k = 0 ; k < ARRAY_LEN (pairs) ; k++)
{ alarm (1) ;
src_ratio = pairs [k].ratio ;
src_callback_read (src_state, src_ratio, pairs [k].count, output) ;
} ;
src_state = src_delete (src_state) ;
alarm (0) ;
puts ("ok") ;
return ;
} /* callback_hang_test */
static void
alarm_handler (int number)
{
(void) number ;
printf ("\n\n Error : Hang inside src_callback_read() detected. Exiting!\n\n") ;
exit (1) ;
} /* alarm_handler */
static long
input_callback (void *cb_data, float **data)
{
static float buffer [20] ;
(void) cb_data ;
*data = buffer ;
return ARRAY_LEN (buffer) ;
} /* input_callback */
#else
int
main (void)
{
puts ("\tCan't run this test on this platform.") ;
return 0 ;
} /* main */
#endif

View File

@ -0,0 +1,243 @@
/*
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN 10000
#define CB_READ_LEN 256
static void callback_test (int converter, double ratio) ;
static void end_of_stream_test (int converter) ;
int
main (void)
{ static double src_ratios [] =
{ 1.0, 0.099, 0.1, 0.33333333, 0.789, 1.0001, 1.9, 3.1, 9.9
} ;
int k ;
puts ("") ;
puts (" Zero Order Hold interpolator :") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
callback_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
puts (" Linear interpolator :") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
callback_test (SRC_LINEAR, src_ratios [k]) ;
puts (" Sinc interpolator :") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
callback_test (SRC_SINC_FASTEST, src_ratios [k]) ;
puts ("") ;
puts (" End of stream test :") ;
end_of_stream_test (SRC_ZERO_ORDER_HOLD) ;
end_of_stream_test (SRC_LINEAR) ;
end_of_stream_test (SRC_SINC_FASTEST) ;
puts ("") ;
return 0 ;
} /* main */
/*=====================================================================================
*/
typedef struct
{ int channels ;
long count, total ;
int end_of_data ;
float data [BUFFER_LEN] ;
} TEST_CB_DATA ;
static long
test_callback_func (void *cb_data, float **data)
{ TEST_CB_DATA *pcb_data ;
long frames ;
if ((pcb_data = cb_data) == NULL)
return 0 ;
if (data == NULL)
return 0 ;
if (pcb_data->total - pcb_data->count > CB_READ_LEN)
frames = CB_READ_LEN / pcb_data->channels ;
else
frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ;
*data = pcb_data->data + pcb_data->count ;
pcb_data->count += frames ;
return frames ;
} /* test_callback_func */
static void
callback_test (int converter, double src_ratio)
{ static TEST_CB_DATA test_callback_data ;
static float output [BUFFER_LEN] ;
SRC_STATE *src_state ;
long read_count, read_total ;
int error ;
printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ;
fflush (stdout) ;
test_callback_data.channels = 2 ;
test_callback_data.count = 0 ;
test_callback_data.end_of_data = 0 ;
test_callback_data.total = ARRAY_LEN (test_callback_data.data) ;
if ((src_state = src_callback_new (test_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
read_total = 0 ;
do
{ /* We will be throwing away output data, so just grab as much as possible. */
read_count = ARRAY_LEN (output) / test_callback_data.channels ;
read_count = src_callback_read (src_state, src_ratio, read_count, output) ;
read_total += read_count ;
}
while (read_count > 0) ;
if ((error = src_error (src_state)) != 0)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_state = src_delete (src_state) ;
if (fabs (read_total / src_ratio - ARRAY_LEN (test_callback_data.data)) > 2.0)
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
printf (" input len : %d\n", ARRAY_LEN (test_callback_data.data)) ;
printf (" output len : %ld (should be %g +/- 2)\n\n", read_total,
floor (0.5 + src_ratio * ARRAY_LEN (test_callback_data.data))) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* callback_test */
/*=====================================================================================
*/
static long
eos_callback_func (void *cb_data, float **data)
{
TEST_CB_DATA *pcb_data ;
long frames ;
if (data == NULL)
return 0 ;
if ((pcb_data = cb_data) == NULL)
return 0 ;
/*
** Return immediately if there is no more data.
** In this case, the output pointer 'data' will not be set and
** valgrind should not warn about it.
*/
if (pcb_data->end_of_data)
return 0 ;
if (pcb_data->total - pcb_data->count > CB_READ_LEN)
frames = CB_READ_LEN / pcb_data->channels ;
else
frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ;
*data = pcb_data->data + pcb_data->count ;
pcb_data->count += frames ;
/*
** Set end_of_data so that the next call to the callback function will
** return zero ocunt without setting the 'data' pointer.
*/
if (pcb_data->total < 2 * pcb_data->count)
pcb_data->end_of_data = 1 ;
return frames ;
} /* eos_callback_data */
static void
end_of_stream_test (int converter)
{ static TEST_CB_DATA test_callback_data ;
static float output [BUFFER_LEN] ;
SRC_STATE *src_state ;
double src_ratio = 0.3 ;
long read_count, read_total ;
int error ;
printf ("\t%-30s ........... ", src_get_name (converter)) ;
fflush (stdout) ;
test_callback_data.channels = 2 ;
test_callback_data.count = 0 ;
test_callback_data.end_of_data = 0 ;
test_callback_data.total = ARRAY_LEN (test_callback_data.data) ;
if ((src_state = src_callback_new (eos_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
read_total = 0 ;
do
{ /* We will be throwing away output data, so just grab as much as possible. */
read_count = ARRAY_LEN (output) / test_callback_data.channels ;
read_count = src_callback_read (src_state, src_ratio, read_count, output) ;
read_total += read_count ;
}
while (read_count > 0) ;
if ((error = src_error (src_state)) != 0)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_state = src_delete (src_state) ;
if (test_callback_data.end_of_data == 0)
{ printf ("\n\nLine %d : test_callback_data.end_of_data should not be 0."
" This is a bug in the test.\n\n", __LINE__) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* end_of_stream_test */

View File

@ -0,0 +1,23 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Find FFTW
# Find the native installation of this package: includes and libraries.
#
# FFTW_INCLUDES - where to find headers for this package.
# FFTW_LIBRARIES - List of libraries when using this package.
# FFTW_FOUND - True if this package can be found.
if (FFTW_INCLUDES)
set (FFTW_FIND_QUIETLY TRUE)
endif (FFTW_INCLUDES)
find_path (FFTW_INCLUDES fftw3.h)
find_library (FFTW_LIBRARIES NAMES fftw3)
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (
FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES)
mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES)

View File

@ -0,0 +1,23 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
# - Find SNDFILE
# Find the native installation of this package: includes and libraries.
#
# SNDFILE_INCLUDES - where to find headers for this package.
# SNDFILE_LIBRARIES - List of libraries when using this package.
# SNDFILE_FOUND - True if this package can be found.
if (SNDFILE_INCLUDES)
set (SNDFILE_FIND_QUIETLY TRUE)
endif (SNDFILE_INCLUDES)
find_path (SNDFILE_INCLUDES sndfile.h)
find_library (SNDFILE_LIBRARIES NAMES sndfile)
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (
SNDFILE DEFAULT_MSG SNDFILE_LIBRARIES SNDFILE_INCLUDES)
mark_as_advanced (SNDFILE_LIBRARIES SNDFILE_INCLUDES)

View File

@ -0,0 +1,24 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxsrc_lsr_tests_config_included
#define soxsrc_lsr_tests_config_included
#cmakedefine01 HAVE_ALARM
#cmakedefine01 HAVE_FFTW3
#cmakedefine01 HAVE_LRINTF
#cmakedefine01 HAVE_LRINT
#cmakedefine01 HAVE_SIGNAL
#cmakedefine01 HAVE_SNDFILE
#cmakedefine01 HAVE_SYS_TIMES_H
#if HAVE_SIGNAL
#include <signal.h>
#if defined SIGALRM
#define HAVE_SIGALRM 1
#else
#define HAVE_SIGALRM 0
#endif
#endif
#endif

View File

@ -0,0 +1,61 @@
/*
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <samplerate.h>
#include "util.h"
static void
downsample_test (int converter)
{ static float in [1000], out [10] ;
SRC_DATA data ;
printf (" downsample_test (%-28s) ....... ", src_get_name (converter)) ;
fflush (stdout) ;
data.src_ratio = 1.0 / 255.0 ;
data.input_frames = ARRAY_LEN (in) ;
data.output_frames = ARRAY_LEN (out) ;
data.data_in = in ;
data.data_out = out ;
if (src_simple (&data, converter, 1))
{ puts ("src_simple failed.") ;
exit (1) ;
} ;
puts ("ok") ;
} /* downsample_test */
int
main (void)
{
puts ("") ;
downsample_test (SRC_ZERO_ORDER_HOLD) ;
downsample_test (SRC_LINEAR) ;
downsample_test (SRC_SINC_FASTEST) ;
downsample_test (SRC_SINC_MEDIUM_QUALITY) ;
downsample_test (SRC_SINC_BEST_QUALITY) ;
puts ("") ;
return 0 ;
} /* main */

281
soxr/lsr-tests/float_cast.h Normal file
View File

@ -0,0 +1,281 @@
/*
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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 program 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 program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Version 1.5 */
#ifndef FLOAT_CAST_HEADER
#define FLOAT_CAST_HEADER
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
** from float to int is very slow. To meet the C specs, the code produced by
** most C compilers targeting Pentium needs to change the FPU rounding mode
** before the float to int conversion is performed.
**
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
** is this flushing of the pipeline which is so slow.
**
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
** llrint and llrintf which fix this problem as a side effect.
**
** On Unix-like systems, the configure process should have detected the
** presence of these functions. If they weren't found we have to replace them
** here with a standard C cast.
*/
/*
** The C99 prototypes for lrint and lrintf are as follows:
**
** long int lrintf (float x) ;
** long int lrint (double x) ;
*/
#include "config.h"
/*
** The presence of the required functions are detected during the configure
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
** the config.h file.
*/
#define HAVE_LRINT_REPLACEMENT 0
#if (HAVE_LRINT && HAVE_LRINTF)
/*
** These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
** engage them. If optimisation is enabled, these functions will be
** inlined. With optimisation switched off, you have to link in the
** maths library using -lm.
*/
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#elif (defined (__CYGWIN__))
#include <math.h>
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
/*
** The native CYGWIN lrint and lrintf functions are buggy:
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
** and slow.
** These functions (pulled from the Public Domain MinGW math.h header)
** replace the native versions.
*/
static inline long double2int (double in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* double2int */
static inline long float2int (float in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* float2int */
#elif (defined (WIN64) || defined(_WIN64))
/* Win64 section should be places before Win32 one, because
** most likely both WIN32 and WIN64 will be defined in 64-bit case.
*/
#include <math.h>
/* Win64 doesn't seem to have these functions, nor inline assembly.
** Therefore implement inline versions of these functions here.
*/
#include <emmintrin.h>
#include <mmintrin.h>
__inline long int
lrint(double flt)
{
return _mm_cvtsd_si32(_mm_load_sd(&flt));
}
__inline long int
lrintf(float flt)
{
return _mm_cvtss_si32(_mm_load_ss(&flt));
}
#elif (defined (WIN32) || defined (_WIN32))
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
/*
** Win32 doesn't seem to have these functions.
** Therefore implement inline versions of these functions here.
*/
__inline long int
lrint (double flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
__inline long int
lrintf (float flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
#elif (defined (__MWERKS__) && defined (macintosh))
/* This MacOS 9 solution was provided by Stephane Letz */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline int
float2int (register float in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* float2int */
inline int
double2int (register double in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* double2int */
#elif (defined (__MACH__) && defined (__APPLE__))
/* For Apple MacOSX. */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline static long
float2int (register float in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrintf */
inline static long
double2int (register double in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrint */
#else
#ifndef __sgi
#warning "Don't have the functions lrint() and lrintf()."
#warning "Replacing these functions with a standard C cast."
#endif
#include <math.h>
#define lrint(dbl) ((long) (dbl))
#define lrintf(flt) ((long) (flt))
#endif
#endif /* FLOAT_CAST_HEADER */

View File

@ -0,0 +1,192 @@
/*
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN 10000
static void float_to_short_test (void) ;
static void short_to_float_test (void) ;
static void float_to_int_test (void) ;
static void int_to_float_test (void) ;
int
main (void)
{
puts ("") ;
float_to_short_test () ;
short_to_float_test () ;
float_to_int_test () ;
int_to_float_test () ;
puts ("") ;
return 0 ;
} /* main */
/*=====================================================================================
*/
static void
float_to_short_test (void)
{
static float fpos [] =
{ 0.95, 0.99, 1.0, 1.01, 1.1, 2.0, 11.1, 111.1, 2222.2, 33333.3
} ;
static float fneg [] =
{ -0.95, -0.99, -1.0, -1.01, -1.1, -2.0, -11.1, -111.1, -2222.2, -33333.3
} ;
static short out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ;
int k ;
printf ("\tfloat_to_short_test ............................. ") ;
src_float_to_short_array (fpos, out, ARRAY_LEN (fpos)) ;
for (k = 0 ; k < ARRAY_LEN (fpos) ; k++)
if (out [k] < 30000)
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
exit (1) ;
} ;
src_float_to_short_array (fneg, out, ARRAY_LEN (fneg)) ;
for (k = 0 ; k < ARRAY_LEN (fneg) ; k++)
if (out [k] > -30000)
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* float_to_short_test */
/*-------------------------------------------------------------------------------------
*/
static void
short_to_float_test (void)
{
static short input [BUFFER_LEN] ;
static short output [BUFFER_LEN] ;
static float temp [BUFFER_LEN] ;
int k ;
printf ("\tshort_to_float_test ............................. ") ;
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
input [k] = (k * 0x8000) / ARRAY_LEN (input) ;
src_short_to_float_array (input, temp, ARRAY_LEN (temp)) ;
src_float_to_short_array (temp, output, ARRAY_LEN (output)) ;
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
if (ABS (input [k] - output [k]) > 0)
{ printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* short_to_float_test */
/*=====================================================================================
*/
static void
float_to_int_test (void)
{
static float fpos [] =
{ 0.95, 0.99, 1.0, 1.01, 1.1, 2.0, 11.1, 111.1, 2222.2, 33333.3
} ;
static float fneg [] =
{ -0.95, -0.99, -1.0, -1.01, -1.1, -2.0, -11.1, -111.1, -2222.2, -33333.3
} ;
static int out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ;
int k ;
printf ("\tfloat_to_int_test ............................... ") ;
src_float_to_int_array (fpos, out, ARRAY_LEN (fpos)) ;
for (k = 0 ; k < ARRAY_LEN (fpos) ; k++)
if (out [k] < 30000 * 0x10000)
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
exit (1) ;
} ;
src_float_to_int_array (fneg, out, ARRAY_LEN (fneg)) ;
for (k = 0 ; k < ARRAY_LEN (fneg) ; k++)
if (out [k] > -30000 * 0x1000)
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* float_to_int_test */
/*-------------------------------------------------------------------------------------
*/
static void
int_to_float_test (void)
{
static int input [BUFFER_LEN] ;
static int output [BUFFER_LEN] ;
static float temp [BUFFER_LEN] ;
int k ;
printf ("\tint_to_float_test ............................... ") ;
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
input [k] = (k * 0x80000000) / ARRAY_LEN (input) ;
src_int_to_float_array (input, temp, ARRAY_LEN (temp)) ;
src_float_to_int_array (temp, output, ARRAY_LEN (output)) ;
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
if (ABS (input [k] - output [k]) > 0)
{ printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* int_to_float_test */

175
soxr/lsr-tests/misc_test.c Normal file
View File

@ -0,0 +1,175 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <samplerate.h>
#include "util.h"
static void name_test (void) ;
static void error_test (void) ;
static void src_ratio_test (void) ;
static void zero_input_test (int converter) ;
int
main (void)
{
puts ("") ;
printf (" version : %s\n\n", src_get_version ()) ;
/* Current max converter is SRC_LINEAR. */
name_test () ;
error_test () ;
src_ratio_test () ;
zero_input_test (SRC_ZERO_ORDER_HOLD) ;
zero_input_test (SRC_LINEAR) ;
zero_input_test (SRC_SINC_FASTEST) ;
puts ("") ;
return 0 ;
} /* main */
static void
name_test (void)
{ const char *name ;
int k = 0 ;
puts (" name_test :") ;
while (1)
{ name = src_get_name (k) ;
if (name == NULL)
break ;
printf ("\tName %d : %s\n", k, name) ;
printf ("\tDesc %d : %s\n", k, src_get_description (k)) ;
k ++ ;
} ;
puts ("") ;
return ;
} /* name_test */
/*------------------------------------------------------------------------------
*/
typedef struct
{ double ratio ;
int should_pass ;
} RATIO_TEST ;
static RATIO_TEST ratio_test [] =
{ { 1.0 / 256.1, 0 },
{ 1.0 / 256.0, 1 },
{ 1.0, 1 },
{ 256.0, 1 },
{ 256.1, 0 },
{ -1.0, 0 }
} ;
static void
src_ratio_test (void)
{ int k ;
puts (" src_ratio_test (SRC ratio must be in range [1/256, 256]):" ) ;
for (k = 0 ; k < ARRAY_LEN (ratio_test) ; k++)
{ if (ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) == 0)
{ printf ("\n\nLine %d : SRC ratio %f should have passed.\n\n", __LINE__, ratio_test [k].ratio) ;
exit (1) ;
} ;
if (! ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) != 0)
{ printf ("\n\nLine %d : SRC ratio %f should not have passed.\n\n", __LINE__, ratio_test [k].ratio) ;
exit (1) ;
} ;
printf ("\t SRC ratio (%9.5f) : %s ................... ok\n", ratio_test [k].ratio,
(ratio_test [k].should_pass ? "pass" : "fail")) ;
} ;
puts ("") ;
return ;
} /* src_ratio_test */
static void
error_test (void)
{ const char *errorstr ;
int k, errors = 0 ;
puts (" error_test :") ;
for (k = 0 ; 1 ; k++)
{ errorstr = src_strerror (k) ;
printf ("\t%-2d : %s\n", k, errorstr) ;
if (errorstr == NULL)
{ errors ++ ;
continue ;
} ;
if (strstr (errorstr, "Placeholder.") == errorstr)
break ;
} ;
if (errors != 0)
{ printf ("\n\nLine %d : Missing error numbers above.\n\n", __LINE__) ;
exit (1) ;
} ;
puts ("") ;
return ;
} /* error_test */
static void
zero_input_test (int converter)
{ SRC_DATA data ;
SRC_STATE *state ;
float out [100] ;
int error ;
printf (" %s (%-26s) ........ ", __func__, src_get_name (converter)) ;
fflush (stdout) ;
if ((state = src_new (converter, 1, &error)) == NULL)
{ printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
data.data_in = (float *) 0xdeadbeef ;
data.input_frames = 0 ;
data.data_out = out ;
data.output_frames = ARRAY_LEN (out) ;
data.end_of_input = 0 ;
data.src_ratio = 1.0 ;
if ((error = src_process (state, &data)))
{ printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
state = src_delete (state) ;
puts ("ok") ;
} /* zero_input_test */

View File

@ -0,0 +1,364 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN 50000
#define BLOCK_LEN (12)
#define MAX_CHANNELS 10
static void simple_test (int converter, int channel_count, double target_snr) ;
static void process_test (int converter, int channel_count, double target_snr) ;
static void callback_test (int converter, int channel_count, double target_snr) ;
int
main (void)
{ double target ;
int k ;
puts ("\n Zero Order Hold interpolator :") ;
target = 38.0 ;
for (k = 1 ; k <= 3 ; k++)
{ simple_test (SRC_ZERO_ORDER_HOLD, k, target) ;
process_test (SRC_ZERO_ORDER_HOLD, k, target) ;
callback_test (SRC_ZERO_ORDER_HOLD, k, target) ;
} ;
puts ("\n Linear interpolator :") ;
target = 79.0 ;
for (k = 1 ; k <= 3 ; k++)
{ simple_test (SRC_LINEAR, k, target) ;
process_test (SRC_LINEAR, k, target) ;
callback_test (SRC_LINEAR, k, target) ;
} ;
puts ("\n Sinc interpolator :") ;
target = 100.0 ;
for (k = 1 ; k <= MAX_CHANNELS ; k++)
{ simple_test (SRC_SINC_FASTEST, k, target) ;
process_test (SRC_SINC_FASTEST, k, target) ;
callback_test (SRC_SINC_FASTEST, k, target) ;
} ;
puts ("") ;
return 0 ;
} /* main */
/*==============================================================================
*/
static float input_serial [BUFFER_LEN * MAX_CHANNELS] ;
static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
static float output_serial [BUFFER_LEN * MAX_CHANNELS] ;
static void
simple_test (int converter, int channel_count, double target_snr)
{ SRC_DATA src_data ;
double freq, snr ;
int ch, error, frames ;
printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ;
fflush (stdout) ;
assert (channel_count <= MAX_CHANNELS) ;
memset (input_serial, 0, sizeof (input_serial)) ;
memset (input_interleaved, 0, sizeof (input_interleaved)) ;
memset (output_interleaved, 0, sizeof (output_interleaved)) ;
memset (output_serial, 0, sizeof (output_serial)) ;
frames = BUFFER_LEN ;
/* Calculate channel_count separate windowed sine waves. */
for (ch = 0 ; ch < channel_count ; ch++)
{ freq = (200.0 + 33.333333333 * ch) / 44100.0 ;
gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
} ;
/* Interleave the data in preparation for SRC. */
interleave_data (input_serial, input_interleaved, frames, channel_count) ;
/* Choose a converstion ratio <= 1.0. */
src_data.src_ratio = 0.95 ;
src_data.data_in = input_interleaved ;
src_data.input_frames = frames ;
src_data.data_out = output_interleaved ;
src_data.output_frames = frames ;
if ((error = src_simple (&src_data, converter, channel_count)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2)
{ printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__,
src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ;
printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ;
printf ("\tinput_len : %ld\n", src_data.input_frames) ;
printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ;
exit (1) ;
} ;
/* De-interleave data so SNR can be calculated for each channel. */
deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
for (ch = 0 ; ch < channel_count ; ch++)
{ snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
if (snr < target_snr)
{ printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
exit (1) ;
} ;
} ;
puts ("ok") ;
return ;
} /* simple_test */
/*==============================================================================
*/
static void
process_test (int converter, int channel_count, double target_snr)
{ SRC_STATE *src_state ;
SRC_DATA src_data ;
double freq, snr ;
int ch, error, frames, current_in, current_out ;
printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ;
fflush (stdout) ;
assert (channel_count <= MAX_CHANNELS) ;
memset (input_serial, 0, sizeof (input_serial)) ;
memset (input_interleaved, 0, sizeof (input_interleaved)) ;
memset (output_interleaved, 0, sizeof (output_interleaved)) ;
memset (output_serial, 0, sizeof (output_serial)) ;
frames = BUFFER_LEN ;
/* Calculate channel_count separate windowed sine waves. */
for (ch = 0 ; ch < channel_count ; ch++)
{ freq = (400.0 + 11.333333333 * ch) / 44100.0 ;
gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
} ;
/* Interleave the data in preparation for SRC. */
interleave_data (input_serial, input_interleaved, frames, channel_count) ;
/* Perform sample rate conversion. */
if ((src_state = src_new (converter, channel_count, &error)) == NULL)
{ printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_data.end_of_input = 0 ; /* Set this later. */
/* Choose a converstion ratio < 1.0. */
src_data.src_ratio = 0.95 ;
src_data.data_in = input_interleaved ;
src_data.data_out = output_interleaved ;
current_in = current_out = 0 ;
while (1)
{ src_data.input_frames = MAX (MIN (BLOCK_LEN, frames - current_in), 0) ;
src_data.output_frames = MAX (MIN (BLOCK_LEN, frames - current_out), 0) ;
if ((error = src_process (src_state, &src_data)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
if (src_data.end_of_input && src_data.output_frames_gen == 0)
break ;
current_in += src_data.input_frames_used ;
current_out += src_data.output_frames_gen ;
src_data.data_in += src_data.input_frames_used * channel_count ;
src_data.data_out += src_data.output_frames_gen * channel_count ;
src_data.end_of_input = (current_in >= frames) ? 1 : 0 ;
} ;
src_state = src_delete (src_state) ;
if (fabs (current_out - src_data.src_ratio * current_in) > 2)
{ printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__,
current_out, (int) floor (src_data.src_ratio * current_in)) ;
printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ;
printf ("\tinput_len : %d\n", frames) ;
printf ("\toutput_len : %d\n\n", current_out) ;
exit (1) ;
} ;
/* De-interleave data so SNR can be calculated for each channel. */
deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
for (ch = 0 ; ch < channel_count ; ch++)
{ snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
if (snr < target_snr)
{ printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
exit (1) ;
} ;
} ;
puts ("ok") ;
return ;
} /* process_test */
/*==============================================================================
*/
typedef struct
{ int channels ;
long total_frames ;
long current_frame ;
float *data ;
} TEST_CB_DATA ;
static long
test_callback_func (void *cb_data, float **data)
{ TEST_CB_DATA *pcb_data ;
long frames ;
if ((pcb_data = cb_data) == NULL)
return 0 ;
if (data == NULL)
return 0 ;
*data = pcb_data->data + (pcb_data->current_frame * pcb_data->channels) ;
if (pcb_data->total_frames - pcb_data->current_frame < BLOCK_LEN)
frames = pcb_data->total_frames - pcb_data->current_frame ;
else
frames = BLOCK_LEN ;
pcb_data->current_frame += frames ;
return frames ;
} /* test_callback_func */
static void
callback_test (int converter, int channel_count, double target_snr)
{ TEST_CB_DATA test_callback_data ;
SRC_STATE *src_state = NULL ;
double freq, snr, src_ratio ;
int ch, error, frames, read_total, read_count ;
printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ;
fflush (stdout) ;
assert (channel_count <= MAX_CHANNELS) ;
memset (input_serial, 0, sizeof (input_serial)) ;
memset (input_interleaved, 0, sizeof (input_interleaved)) ;
memset (output_interleaved, 0, sizeof (output_interleaved)) ;
memset (output_serial, 0, sizeof (output_serial)) ;
memset (&test_callback_data, 0, sizeof (test_callback_data)) ;
frames = BUFFER_LEN ;
/* Calculate channel_count separate windowed sine waves. */
for (ch = 0 ; ch < channel_count ; ch++)
{ freq = (200.0 + 33.333333333 * ch) / 44100.0 ;
gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
} ;
/* Interleave the data in preparation for SRC. */
interleave_data (input_serial, input_interleaved, frames, channel_count) ;
/* Perform sample rate conversion. */
src_ratio = 0.95 ;
test_callback_data.channels = channel_count ;
test_callback_data.total_frames = frames ;
test_callback_data.current_frame = 0 ;
test_callback_data.data = input_interleaved ;
if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
read_total = 0 ;
while (read_total < frames)
{ read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ;
if (read_count <= 0)
break ;
read_total += read_count ;
} ;
if ((error = src_error (src_state)) != 0)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_state = src_delete (src_state) ;
if (fabs (read_total - src_ratio * frames) > 2)
{ printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__,
read_total, (int) floor (src_ratio * frames)) ;
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
printf ("\tinput_len : %d\n", frames) ;
printf ("\toutput_len : %d\n\n", read_total) ;
exit (1) ;
} ;
/* De-interleave data so SNR can be calculated for each channel. */
deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
for (ch = 0 ; ch < channel_count ; ch++)
{ snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
if (snr < target_snr)
{ printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
exit (1) ;
} ;
} ;
puts ("ok") ;
return ;
} /* callback_test */

View File

@ -0,0 +1,216 @@
/*
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <samplerate.h>
#include "config.h"
#include "util.h"
#include "float_cast.h"
#define BUFFER_LEN (1<<17)
static float input [BUFFER_LEN] ;
static float output [BUFFER_LEN] ;
static long
throughput_test (int converter, int channels, long best_throughput)
{ SRC_DATA src_data ;
clock_t start_time, clock_time ;
double duration ;
long total_frames = 0, throughput ;
int error ;
printf (" %-30s %2d ", src_get_name (converter), channels) ;
fflush (stdout) ;
src_data.data_in = input ;
src_data.input_frames = ARRAY_LEN (input) / channels ;
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) / channels ;
src_data.src_ratio = 0.99 ;
sleep (2) ;
start_time = clock () ;
do
{
if ((error = src_simple (&src_data, converter, channels)) != 0)
{ puts (src_strerror (error)) ;
exit (1) ;
} ;
total_frames += src_data.output_frames_gen ;
clock_time = clock () - start_time ;
duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
}
while (duration < 5.0) ;
if (src_data.input_frames_used != src_data.input_frames)
{ printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ;
exit (1) ;
} ;
if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
printf (" input len : %d\n", ARRAY_LEN (input) / channels) ;
printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
exit (1) ;
} ;
throughput = lrint (floor (total_frames / duration)) ;
if (best_throughput == 0)
{ best_throughput = MAX (throughput, best_throughput) ;
printf ("%5.2f %10ld\n", duration, throughput) ;
}
else
{ best_throughput = MAX (throughput, best_throughput) ;
printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ;
}
return best_throughput ;
} /* throughput_test */
static void
single_run (void)
{ const int max_channels = 10 ;
int k ;
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
puts (
"\n"
" Converter Channels Duration Throughput\n"
" ---------------------------------------------------------------------"
) ;
for (k = 1 ; k <= max_channels / 2 ; k++)
throughput_test (SRC_SINC_FASTEST, k, 0) ;
puts ("") ;
for (k = 1 ; k <= max_channels / 2 ; k++)
throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ;
puts ("") ;
for (k = 1 ; k <= max_channels ; k++)
throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ;
puts ("") ;
return ;
} /* single_run */
static void
multi_run (int run_count)
{ int k, ch ;
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
puts (
"\n"
" Converter Channels Duration Throughput Best Throughput\n"
" ----------------------------------------------------------------------------------------"
) ;
for (ch = 1 ; ch <= 5 ; ch++)
{ long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ;
for (k = 0 ; k < run_count ; k++)
{ sinc_fastest = throughput_test (SRC_SINC_FASTEST, ch, sinc_fastest) ;
sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, sinc_medium) ;
sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, ch, sinc_best) ;
puts ("") ;
/* Let the CPU cool down. We might be running on a laptop. */
sleep (10) ;
} ;
puts (
"\n"
" Converter Best Throughput\n"
" ------------------------------------------------"
) ;
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ;
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ;
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ;
} ;
puts ("") ;
} /* multi_run */
static void
usage_exit (const char * argv0)
{ const char * cptr ;
if ((cptr = strrchr (argv0, '/')) != NULL)
argv0 = cptr ;
printf (
"Usage :\n"
" %s - Single run of the throughput test.\n"
" %s --best-of N - Do N runs of test a print bext result.\n"
"\n",
argv0, argv0) ;
exit (0) ;
} /* usage_exit */
int
main (int argc, char ** argv)
{ double freq ;
memset (input, 0, sizeof (input)) ;
freq = 0.01 ;
gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
if (argc == 1)
single_run () ;
else if (argc == 3 && strcmp (argv [1], "--best-of") == 0)
{ int run_count = atoi (argv [2]) ;
if (run_count < 1 || run_count > 20)
{ printf ("Please be sensible. Run count should be in range (1, 10].\n") ;
exit (1) ;
} ;
multi_run (run_count) ;
}
else
usage_exit (argv [0]) ;
puts (
" Duration is in seconds.\n"
" Throughput is in frames/sec (more is better).\n"
) ;
return 0 ;
} /* main */

238
soxr/lsr-tests/reset_test.c Normal file
View File

@ -0,0 +1,238 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN 2048
#define CB_READ_LEN 256
static void process_reset_test (int converter) ;
static void callback_reset_test (int converter) ;
static float data_one [BUFFER_LEN] ;
static float data_zero [BUFFER_LEN] ;
int
main (void)
{
puts ("") ;
process_reset_test (SRC_ZERO_ORDER_HOLD) ;
process_reset_test (SRC_LINEAR) ;
process_reset_test (SRC_SINC_FASTEST) ;
callback_reset_test (SRC_ZERO_ORDER_HOLD) ;
callback_reset_test (SRC_LINEAR) ;
callback_reset_test (SRC_SINC_FASTEST) ;
puts ("") ;
return 0 ;
} /* main */
static void
process_reset_test (int converter)
{ static float output [BUFFER_LEN] ;
SRC_STATE *src_state ;
SRC_DATA src_data ;
int k, error ;
printf ("\tprocess_reset_test (%-28s) ....... ", src_get_name (converter)) ;
fflush (stdout) ;
for (k = 0 ; k < BUFFER_LEN ; k++)
{ data_one [k] = 1.0 ;
data_zero [k] = 0.0 ;
} ;
/* Get a converter. */
if ((src_state = src_new (converter, 1, &error)) == NULL)
{ printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
/* Process a bunch of 1.0 valued samples. */
src_data.data_in = data_one ;
src_data.data_out = output ;
src_data.input_frames = BUFFER_LEN ;
src_data.output_frames = BUFFER_LEN ;
src_data.src_ratio = 0.9 ;
src_data.end_of_input = 1 ;
if ((error = src_process (src_state, &src_data)) != 0)
{ printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
/* Reset the state of the converter.*/
src_reset (src_state) ;
/* Now process some zero data. */
src_data.data_in = data_zero ;
src_data.data_out = output ;
src_data.input_frames = BUFFER_LEN ;
src_data.output_frames = BUFFER_LEN ;
src_data.src_ratio = 0.9 ;
src_data.end_of_input = 1 ;
if ((error = src_process (src_state, &src_data)) != 0)
{ printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
/* Finally make sure that the output data is zero ie reset was sucessful. */
for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
if (output [k] != 0.0)
{ printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n", __LINE__, k, output [k]) ;
exit (1) ;
} ;
/* Make sure that this function has been exported. */
src_set_ratio (src_state, 1.0) ;
/* Delete converter. */
src_state = src_delete (src_state) ;
puts ("ok") ;
} /* process_reset_test */
/*==============================================================================
*/
typedef struct
{ int channels ;
long count, total ;
float *data ;
} TEST_CB_DATA ;
static long
test_callback_func (void *cb_data, float **data)
{ TEST_CB_DATA *pcb_data ;
long frames ;
if ((pcb_data = cb_data) == NULL)
return 0 ;
if (data == NULL)
return 0 ;
if (pcb_data->total - pcb_data->count > 0)
frames = pcb_data->total - pcb_data->count ;
else
frames = 0 ;
*data = pcb_data->data + pcb_data->count ;
pcb_data->count += frames ;
return frames ;
} /* test_callback_func */
static void
callback_reset_test (int converter)
{ static TEST_CB_DATA test_callback_data ;
static float output [BUFFER_LEN] ;
SRC_STATE *src_state ;
double src_ratio = 1.1 ;
long read_count, read_total ;
int k, error ;
printf ("\tcallback_reset_test (%-28s) ....... ", src_get_name (converter)) ;
fflush (stdout) ;
for (k = 0 ; k < ARRAY_LEN (data_one) ; k++)
{ data_one [k] = 1.0 ;
data_zero [k] = 0.0 ;
} ;
if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
/* Process a bunch of 1.0 valued samples. */
test_callback_data.channels = 1 ;
test_callback_data.count = 0 ;
test_callback_data.total = ARRAY_LEN (data_one) ;
test_callback_data.data = data_one ;
read_total = 0 ;
do
{ read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ;
read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ;
read_total += read_count ;
}
while (read_count > 0) ;
/* Check for errors. */
if ((error = src_error (src_state)) != 0)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
/* Reset the state of the converter.*/
src_reset (src_state) ;
/* Process a bunch of 0.0 valued samples. */
test_callback_data.channels = 1 ;
test_callback_data.count = 0 ;
test_callback_data.total = ARRAY_LEN (data_zero) ;
test_callback_data.data = data_zero ;
/* Now process some zero data. */
read_total = 0 ;
do
{ read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ;
read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ;
read_total += read_count ;
}
while (read_count > 0) ;
/* Check for errors. */
if ((error = src_error (src_state)) != 0)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
/* Finally make sure that the output data is zero ie reset was sucessful. */
for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
if (output [k] != 0.0)
{ printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n\n", __LINE__, k, output [k]) ;
save_oct_float ("output.dat", data_one, ARRAY_LEN (data_one), output, ARRAY_LEN (output)) ;
exit (1) ;
} ;
/* Make sure that this function has been exported. */
src_set_ratio (src_state, 1.0) ;
/* Delete converter. */
src_state = src_delete (src_state) ;
puts ("ok") ;
} /* callback_reset_test */

View File

@ -0,0 +1,117 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN 2048
static void simple_test (int converter, double ratio) ;
int
main (void)
{ static double src_ratios [] =
{ 1.0001, 0.099, 0.1, 0.33333333, 0.789, 1.9, 3.1, 9.9
} ;
int k ;
puts ("") ;
puts (" Zero Order Hold interpolator :") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
simple_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
puts (" Linear interpolator :") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
simple_test (SRC_LINEAR, src_ratios [k]) ;
puts (" Sinc interpolator :") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
simple_test (SRC_SINC_FASTEST, src_ratios [k]) ;
puts ("") ;
return 0 ;
} /* main */
static void
simple_test (int converter, double src_ratio)
{ static float input [BUFFER_LEN], output [BUFFER_LEN] ;
SRC_DATA src_data ;
int input_len, output_len, error, terminate ;
printf ("\tsimple_test (SRC ratio = %6.4f) ........... ", src_ratio) ;
fflush (stdout) ;
/* Calculate maximun input and output lengths. */
if (src_ratio >= 1.0)
{ output_len = BUFFER_LEN ;
input_len = (int) floor (BUFFER_LEN / src_ratio) ;
}
else
{ input_len = BUFFER_LEN ;
output_len = (int) floor (BUFFER_LEN * src_ratio) ;
} ;
/* Reduce input_len by 10 so output is longer than necessary. */
input_len -= 10 ;
if (output_len > BUFFER_LEN)
{ printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ;
exit (1) ;
} ;
memset (&src_data, 0, sizeof (src_data)) ;
src_data.data_in = input ;
src_data.input_frames = input_len ;
src_data.src_ratio = src_ratio ;
src_data.data_out = output ;
src_data.output_frames = BUFFER_LEN ;
if ((error = src_simple (&src_data, converter, 1)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ;
if (fabs (src_data.output_frames_gen - src_ratio * input_len) > 2 * terminate)
{ printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__,
src_data.output_frames_gen, (int) floor (src_ratio * input_len)) ;
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* simple_test */

View File

@ -0,0 +1,332 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#if (HAVE_SNDFILE)
#include <samplerate.h>
#include <sndfile.h>
#define DEFAULT_CONVERTER SRC_SINC_MEDIUM_QUALITY
#define BUFFER_LEN 4096 /*-(1<<16)-*/
static void usage_exit (const char *progname) ;
static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain) ;
static double apply_gain (float * data, long frames, int channels, double max, double gain) ;
int
main (int argc, char *argv [])
{ SNDFILE *infile, *outfile = NULL ;
SF_INFO sfinfo ;
sf_count_t count ;
double src_ratio = -1.0, gain = 1.0 ;
int new_sample_rate = -1, k, converter, max_speed = SF_FALSE ;
if (argc == 2 && strcmp (argv [1], "--version") == 0)
{ char buffer [64], *cptr ;
if ((cptr = strrchr (argv [0], '/')) != NULL)
argv [0] = cptr + 1 ;
if ((cptr = strrchr (argv [0], '\\')) != NULL)
argv [0] = cptr + 1 ;
sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
printf ("%s (%s,%s)\n", argv [0], src_get_version (), buffer) ;
exit (0) ;
} ;
if (argc != 5 && argc != 7 && argc != 8)
usage_exit (argv [0]) ;
/* Set default converter. */
converter = DEFAULT_CONVERTER ;
for (k = 1 ; k < argc - 2 ; k++)
{ if (strcmp (argv [k], "--max-speed") == 0)
max_speed = SF_TRUE ;
else if (strcmp (argv [k], "-to") == 0)
{ k ++ ;
new_sample_rate = atoi (argv [k]) ;
}
else if (strcmp (argv [k], "-by") == 0)
{ k ++ ;
src_ratio = atof (argv [k]) ;
}
else if (strcmp (argv [k], "-c") == 0)
{ k ++ ;
converter = atoi (argv [k]) ;
}
else
usage_exit (argv [0]) ;
} ;
if (new_sample_rate <= 0 && src_ratio <= 0.0)
usage_exit (argv [0]) ;
if (src_get_name (converter) == NULL)
{ printf ("Error : bad converter number.\n") ;
usage_exit (argv [0]) ;
} ;
if (strcmp (argv [argc - 2], argv [argc - 1]) == 0)
{ printf ("Error : input and output file names are the same.\n") ;
exit (1) ;
} ;
if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL)
{ printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ;
exit (1) ;
} ;
printf ("Input File : %s\n", argv [argc - 2]) ;
printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
printf ("Input Frames : %ld\n\n", (long) sfinfo.frames) ;
if (new_sample_rate > 0)
{ src_ratio = (1.0 * new_sample_rate) / sfinfo.samplerate ;
sfinfo.samplerate = new_sample_rate ;
}
else if (src_is_valid_ratio (src_ratio))
sfinfo.samplerate = (int) floor (sfinfo.samplerate * src_ratio) ;
else
{ printf ("Not able to determine new sample rate. Exiting.\n") ;
sf_close (infile) ;
exit (1) ;
} ;
if (fabs (src_ratio - 1.0) < 1e-20)
{ printf ("Target samplerate and input samplerate are the same. Exiting.\n") ;
sf_close (infile) ;
exit (0) ;
} ;
printf ("SRC Ratio : %f\n", src_ratio) ;
printf ("Converter : %s\n\n", src_get_name (converter)) ;
if (src_is_valid_ratio (src_ratio) == 0)
{ printf ("Error : Sample rate change out of valid range.\n") ;
sf_close (infile) ;
exit (1) ;
} ;
/* Delete the output file length to zero if already exists. */
remove (argv [argc - 1]) ;
printf ("Output file : %s\n", argv [argc - 1]) ;
printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
do
{ sf_close (outfile) ;
if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
{ printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ;
sf_close (infile) ;
exit (1) ;
} ;
if (max_speed)
{ /* This is mainly for the comparison program tests/src-evaluate.c */
sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
}
else
{ /* Update the file header after every write. */
sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
} ;
sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
count = sample_rate_convert (infile, outfile, converter, src_ratio, sfinfo.channels, &gain) ;
}
while (count < 0) ;
printf ("Output Frames : %ld\n\n", (long) count) ;
sf_close (infile) ;
sf_close (outfile) ;
return 0 ;
} /* main */
/*==============================================================================
*/
static sf_count_t
sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain)
{ static float input [BUFFER_LEN] ;
static float output [BUFFER_LEN] ;
SRC_STATE *src_state ;
SRC_DATA src_data ;
int error ;
double max = 0.0 ;
sf_count_t output_count = 0 ;
sf_seek (infile, 0, SEEK_SET) ;
sf_seek (outfile, 0, SEEK_SET) ;
/* Initialize the sample rate converter. */
if ((src_state = src_new (converter, channels, &error)) == NULL)
{ printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
exit (1) ;
} ;
src_data.end_of_input = 0 ; /* Set this later. */
/* Start with zero to force load in while loop. */
src_data.input_frames = 0 ;
src_data.data_in = input ;
src_data.src_ratio = src_ratio ;
src_data.data_out = output ;
src_data.output_frames = BUFFER_LEN /channels ;
while (1)
{
/* If the input buffer is empty, refill it. */
if (src_data.input_frames == 0)
{ src_data.input_frames = sf_readf_float (infile, input, BUFFER_LEN / channels) ;
src_data.data_in = input ;
/* The last read will not be a full buffer, so snd_of_input. */
if (src_data.input_frames < BUFFER_LEN / channels)
src_data.end_of_input = SF_TRUE ;
} ;
if ((error = src_process (src_state, &src_data)))
{ printf ("\nError : %s\n", src_strerror (error)) ;
exit (1) ;
} ;
/* Terminate if done. */
if (src_data.end_of_input && src_data.output_frames_gen == 0)
break ;
max = apply_gain (src_data.data_out, src_data.output_frames_gen, channels, max, *gain) ;
/* Write output. */
sf_writef_float (outfile, output, src_data.output_frames_gen) ;
output_count += src_data.output_frames_gen ;
src_data.data_in += src_data.input_frames_used * channels ;
src_data.input_frames -= src_data.input_frames_used ;
} ;
src_state = src_delete (src_state) ;
if (max > 1.0)
{ *gain = 1.0 / max ;
printf ("\nOutput has clipped. Restarting conversion to prevent clipping.\n\n") ;
return -1 ;
} ;
return output_count ;
} /* sample_rate_convert */
static double
apply_gain (float * data, long frames, int channels, double max, double gain)
{
long k ;
for (k = 0 ; k < frames * channels ; k++)
{ data [k] *= gain ;
if (fabs (data [k]) > max)
max = fabs (data [k]) ;
} ;
return max ;
} /* apply_gain */
static void
usage_exit (const char *progname)
{ char lsf_ver [128] ;
const char *cptr ;
int k ;
if ((cptr = strrchr (progname, '/')) != NULL)
progname = cptr + 1 ;
if ((cptr = strrchr (progname, '\\')) != NULL)
progname = cptr + 1 ;
sf_command (NULL, SFC_GET_LIB_VERSION, lsf_ver, sizeof (lsf_ver)) ;
printf ("\n"
" A Sample Rate Converter using libsndfile for file I/O and Secret \n"
" Rabbit Code (aka libsamplerate) for performing the conversion.\n"
" It works on any file format supported by libsndfile with any \n"
" number of channels (limited only by host memory).\n"
"\n"
" %s\n"
" %s\n"
"\n"
" Usage : \n"
" %s -to <new sample rate> [-c <number>] <input file> <output file>\n"
" %s -by <amount> [-c <number>] <input file> <output file>\n"
"\n", src_get_version (), lsf_ver, progname, progname) ;
puts (
" The optional -c argument allows the converter type to be chosen from\n"
" the following list :"
"\n"
) ;
for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++)
printf (" %d : %s%s\n", k, cptr, k == DEFAULT_CONVERTER ? " (default)" : "") ;
puts ("") ;
exit (1) ;
} /* usage_exit */
/*==============================================================================
*/
#else /* (HAVE_SNFILE == 0) */
/* Alternative main function when libsndfile is not available. */
int
main (void)
{ puts (
"\n"
"****************************************************************\n"
" This example program was compiled without libsndfile \n"
" (http://www.mega-nerd.com/libsndfile/).\n"
" It is therefore completely broken and non-functional.\n"
"****************************************************************\n"
"\n"
) ;
return 0 ;
} /* main */
#endif

View File

@ -0,0 +1,401 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#if (HAVE_FFTW3)
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN 50000
#define MAX_FREQS 4
#define MAX_RATIOS 6
#define MAX_SPEC_LEN (1<<15)
#ifndef M_PI
#define M_PI 3.14159265358979323846264338
#endif
enum
{ BOOLEAN_FALSE = 0,
BOOLEAN_TRUE = 1
} ;
typedef struct
{ int freq_count ;
double freqs [MAX_FREQS] ;
double src_ratio ;
int pass_band_peaks ;
double snr ;
double peak_value ;
} SINGLE_TEST ;
typedef struct
{ int converter ;
int tests ;
int do_bandwidth_test ;
SINGLE_TEST test_data [10] ;
} CONVERTER_TEST ;
static double snr_test (SINGLE_TEST *snr_test_data, int number, int converter, int verbose) ;
static double find_peak (float *output, int output_len) ;
static double bandwidth_test (int converter, int verbose) ;
int
main (int argc, char *argv [])
{ CONVERTER_TEST snr_test_data [] =
{
{ SRC_ZERO_ORDER_HOLD,
8,
BOOLEAN_FALSE,
{ { 1, { 0.01111111111 }, 3.0, 1, 28.0, 1.0 },
{ 1, { 0.01111111111 }, 0.6, 1, 36.0, 1.0 },
{ 1, { 0.01111111111 }, 0.3, 1, 36.0, 1.0 },
{ 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
{ 1, { 0.01111111111 }, 1.001, 1, 38.0, 1.0 },
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 14.0, .96 },
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 12.0, .96 },
{ 1, { 0.3511111111 }, 1.33, 1, 10.0, 1.0 }
}
},
{ SRC_LINEAR,
8,
BOOLEAN_FALSE,
{ { 1, { 0.01111111111 }, 3.0, 1, 73.0, 1.0 },
{ 1, { 0.01111111111 }, 0.6, 1, 73.0, 1.0 },
{ 1, { 0.01111111111 }, 0.3, 1, 73.0, 1.0 },
{ 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
{ 1, { 0.01111111111 }, 1.001, 1, 77.0, 1.0 },
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 16.0, 0.96 },
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 26.0, 0.96 },
{ 1, { 0.3511111111 }, 1.33, 1, 14.4, 0.99 }
}
},
{ SRC_SINC_FASTEST,
9,
BOOLEAN_TRUE,
{ { 1, { 0.01111111111 }, 3.0, 1, 100.0, 1.0 },
{ 1, { 0.01111111111 }, 0.6, 1, 99.0, 1.0 },
{ 1, { 0.01111111111 }, 0.3, 1, 100.0, 1.0 },
{ 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
{ 1, { 0.01111111111 }, 1.001, 1, 100.0, 1.0 },
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 97.0, 1.0 },
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 100.0, 0.5 },
{ 2, { 0.011111, 0.45 }, 0.6, 1, 97.0, 0.5 },
{ 1, { 0.3511111111 }, 1.33, 1, 97.0, 1.0 }
}
},
{ SRC_SINC_MEDIUM_QUALITY,
9,
BOOLEAN_TRUE,
{ { 1, { 0.01111111111 }, 3.0, 1, 130.0, 1.0 },
{ 1, { 0.01111111111 }, 0.6, 1, 132.0, 1.0 },
{ 1, { 0.01111111111 }, 0.3, 1, 135.0, 1.0 },
{ 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 },
{ 1, { 0.01111111111 }, 1.001, 1, 133.0, 1.0 },
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 127.0, 1.0 },
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 124.0, 0.5 },
{ 2, { 0.011111, 0.45 }, 0.6, 1, 126.0, 0.5 },
{ 1, { 0.43111111111 }, 1.33, 1, 121.0, 1.0 }
}
},
{ SRC_SINC_BEST_QUALITY,
9,
BOOLEAN_TRUE,
{ { 1, { 0.01111111111 }, 3.0, 1, 147.0, 1.0 },
{ 1, { 0.01111111111 }, 0.6, 1, 147.0, 1.0 },
{ 1, { 0.01111111111 }, 0.3, 1, 147.0, 1.0 },
{ 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 },
{ 1, { 0.01111111111 }, 1.001, 1, 146.0, 1.0 },
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 147.0, 1.0 },
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 148.0, 0.5 },
{ 2, { 0.011111, 0.45 }, 0.6, 1, 145.0, 0.5 },
{ 1, { 0.43111111111 }, 1.33, 1, 145.0, 1.0 }
}
},
} ; /* snr_test_data */
double best_snr, snr, freq3dB ;
int j, k, converter, verbose = 0 ;
if (argc == 2 && strcmp (argv [1], "--verbose") == 0)
verbose = 1 ;
puts ("") ;
for (j = 0 ; j < ARRAY_LEN (snr_test_data) ; j++)
{ best_snr = 5000.0 ;
converter = snr_test_data [j].converter ;
printf (" Converter %d : %s\n", converter, src_get_name (converter)) ;
printf (" %s\n", src_get_description (converter)) ;
for (k = 0 ; k < snr_test_data [j].tests ; k++)
{ snr = snr_test (&(snr_test_data [j].test_data [k]), k, converter, verbose) ;
if (best_snr > snr)
best_snr = snr ;
} ;
printf (" Worst case Signal-to-Noise Ratio : %.2f dB.\n", best_snr) ;
if (snr_test_data [j].do_bandwidth_test == BOOLEAN_FALSE)
{ puts (" Bandwith test not performed on this converter.\n") ;
continue ;
}
freq3dB = bandwidth_test (converter, verbose) ;
printf (" Measured -3dB rolloff point : %5.2f %%.\n\n", freq3dB) ;
} ;
return 0 ;
} /* main */
/*==============================================================================
*/
static double
snr_test (SINGLE_TEST *test_data, int number, int converter, int verbose)
{ static float data [BUFFER_LEN + 1] ;
static float output [MAX_SPEC_LEN] ;
SRC_STATE *src_state ;
SRC_DATA src_data ;
double output_peak, snr ;
int k, output_len, input_len, error ;
if (verbose != 0)
{ printf ("\tSignal-to-Noise Ratio Test %d.\n"
"\t=====================================\n", number) ;
printf ("\tFrequencies : [ ") ;
for (k = 0 ; k < test_data->freq_count ; k++)
printf ("%6.4f ", test_data->freqs [k]) ;
printf ("]\n\tSRC Ratio : %8.4f\n", test_data->src_ratio) ;
}
else
{ printf ("\tSignal-to-Noise Ratio Test %d : ", number) ;
fflush (stdout) ;
} ;
/* Set up the output array. */
if (test_data->src_ratio >= 1.0)
{ output_len = MAX_SPEC_LEN ;
input_len = (int) ceil (MAX_SPEC_LEN / test_data->src_ratio) ;
if (input_len > BUFFER_LEN)
input_len = BUFFER_LEN ;
}
else
{ input_len = BUFFER_LEN ;
output_len = (int) ceil (BUFFER_LEN * test_data->src_ratio) ;
output_len &= ((-1) << 4) ;
if (output_len > MAX_SPEC_LEN)
output_len = MAX_SPEC_LEN ;
input_len = (int) ceil (output_len / test_data->src_ratio) ;
} ;
memset (output, 0, sizeof (output)) ;
/* Generate input data array. */
gen_windowed_sines (test_data->freq_count, test_data->freqs, 1.0, data, input_len) ;
/* Perform sample rate conversion. */
if ((src_state = src_new (converter, 1, &error)) == NULL)
{ printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_data.end_of_input = 1 ; /* Only one buffer worth of input. */
src_data.data_in = data ;
src_data.input_frames = input_len ;
src_data.src_ratio = test_data->src_ratio ;
src_data.data_out = output ;
src_data.output_frames = output_len ;
if ((error = src_process (src_state, &src_data)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_state = src_delete (src_state) ;
if (verbose != 0)
printf ("\tOutput Len : %ld\n", src_data.output_frames_gen) ;
if (abs (src_data.output_frames_gen - output_len) > 4)
{ printf ("\n\nLine %d : output data length should be %d.\n\n", __LINE__, output_len) ;
exit (1) ;
} ;
/* Check output peak. */
output_peak = find_peak (output, src_data.output_frames_gen) ;
if (verbose != 0)
printf ("\tOutput Peak : %6.4f\n", output_peak) ;
if (fabs (output_peak - test_data->peak_value) > 0.01)
{ printf ("\n\nLine %d : output peak (%6.4f) should be %6.4f\n\n", __LINE__, output_peak, test_data->peak_value) ;
save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, output_len) ;
exit (1) ;
} ;
/* Calculate signal-to-noise ratio. */
snr = calculate_snr (output, src_data.output_frames_gen, test_data->pass_band_peaks) ;
if (snr < 0.0)
{ /* An error occurred. */
save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, src_data.output_frames_gen) ;
exit (1) ;
} ;
if (verbose != 0)
printf ("\tSNR Ratio : %.2f dB\n", snr) ;
if (snr < test_data->snr)
{ printf ("\n\nLine %d : SNR (%5.2f) should be > %6.2f dB\n\n", __LINE__, snr, test_data->snr) ;
exit (1) ;
} ;
if (verbose != 0)
puts ("\t-------------------------------------\n\tPass\n") ;
else
puts ("Pass") ;
return snr ;
} /* snr_test */
static double
find_peak (float *data, int len)
{ double peak = 0.0 ;
int k = 0 ;
for (k = 0 ; k < len ; k++)
if (fabs (data [k]) > peak)
peak = fabs (data [k]) ;
return peak ;
} /* find_peak */
static double
find_attenuation (double freq, int converter, int verbose)
{ static float input [BUFFER_LEN] ;
static float output [2 * BUFFER_LEN] ;
SRC_DATA src_data ;
double output_peak ;
int error ;
gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
src_data.end_of_input = 1 ; /* Only one buffer worth of input. */
src_data.data_in = input ;
src_data.input_frames = BUFFER_LEN ;
src_data.src_ratio = 1.999 ;
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) ;
if ((error = src_simple (&src_data, converter, 1)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
output_peak = find_peak (output, ARRAY_LEN (output)) ;
if (verbose)
printf ("\tFreq : %6f InPeak : %6f OutPeak : %6f Atten : %6.2f dB\n",
freq, 1.0, output_peak, 20.0 * log10 (1.0 / output_peak)) ;
return 20.0 * log10 (1.0 / output_peak) ;
} /* find_attenuation */
static double
bandwidth_test (int converter, int verbose)
{ double f1, f2, a1, a2 ;
double freq, atten ;
f1 = 0.35 ;
a1 = find_attenuation (f1, converter, verbose) ;
f2 = 0.495 ;
a2 = find_attenuation (f2, converter, verbose) ;
if (a1 > 3.0 || a2 < 3.0)
{ printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ;
exit (1) ;
} ;
while (a2 - a1 > 1.0)
{ freq = f1 + 0.5 * (f2 - f1) ;
atten = find_attenuation (freq, converter, verbose) ;
if (atten < 3.0)
{ f1 = freq ;
a1 = atten ;
}
else
{ f2 = freq ;
a2 = atten ;
} ;
} ;
freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ;
return 200.0 * freq ;
} /* bandwidth_test */
#else /* (HAVE_FFTW3) == 0 */
/* Alternative main function when librfftw is not available. */
int
main (void)
{ puts ("\n"
"****************************************************************\n"
" This test cannot be run without FFTW (http://www.fftw.org/).\n"
" Both the real and the complex versions of the library are\n"
" required.") ;
puts ("****************************************************************\n") ;
return 0 ;
} /* main */
#endif

View File

@ -0,0 +1,339 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <samplerate.h>
#include "util.h"
#define SHORT_BUFFER_LEN 2048
#define LONG_BUFFER_LEN ((1 << 16) - 20)
static void simple_test (int converter) ;
static void stream_test (int converter, double ratio) ;
static void init_term_test (int converter, double ratio) ;
static int next_block_length (int reset) ;
int
main (void)
{ static double src_ratios [] =
{ 0.999900, 1.000100, 0.789012, 1.200000, 0.333333, 3.100000,
0.125000, 8.000000, 0.099900, 9.990000, 0.100000, 10.00000
} ;
int k ;
puts ("\n Zero Order Hold interpolator:") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
init_term_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
puts ("") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
puts ("\n Linear interpolator:") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
init_term_test (SRC_LINEAR, src_ratios [k]) ;
puts ("") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
stream_test (SRC_LINEAR, src_ratios [k]) ;
puts ("\n Sinc interpolator:") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
init_term_test (SRC_SINC_FASTEST, src_ratios [k]) ;
puts ("") ;
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
stream_test (SRC_SINC_FASTEST, src_ratios [k]) ;
puts ("") ;
simple_test (SRC_SINC_FASTEST) ;
return 0 ;
} /* main */
static void
simple_test (int converter)
{
int ilen = 199030, olen = 1000, error ;
{
float in [ilen] ;
float out [olen] ;
double ratio = (1.0 * olen) / ilen ;
SRC_DATA src_data =
{ in, out,
ilen, olen,
0, 0, 0,
ratio
} ;
error = src_simple (&src_data, converter, 1) ;
if (error)
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
} ;
return ;
} /* simple_test */
static void
init_term_test (int converter, double src_ratio)
{ static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ;
SRC_DATA src_data ;
int k, input_len, output_len, error, terminate ;
printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ;
fflush (stdout) ;
/* Calculate maximun input and output lengths. */
if (src_ratio >= 1.0)
{ output_len = SHORT_BUFFER_LEN ;
input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ;
}
else
{ input_len = SHORT_BUFFER_LEN ;
output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ;
} ;
/* Reduce input_len by 10 so output is longer than necessary. */
input_len -= 10 ;
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
input [k] = 1.0 ;
if (output_len > SHORT_BUFFER_LEN)
{ printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ;
exit (1) ;
} ;
src_data.data_in = input ;
src_data.input_frames = input_len ;
src_data.src_ratio = src_ratio ;
src_data.data_out = output ;
src_data.output_frames = SHORT_BUFFER_LEN ;
if ((error = src_simple (&src_data, converter, 1)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ;
if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate)
{ printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ;
printf ("\tterminate : %d\n", terminate) ;
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
printf ("\tinput_len : %d\n"
"\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ;
printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ;
exit (1) ;
} ;
if (abs (src_data.input_frames_used - input_len) > 1)
{ printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n",
__LINE__, input_len, src_data.input_frames_used) ;
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ;
exit (1) ;
} ;
if (fabs (output [0]) < 0.1)
{ printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ;
printf ("\toutput [0] == %f\n\n", output [0]) ;
exit (1) ;
}
puts ("ok") ;
return ;
} /* init_term_test */
static void
stream_test (int converter, double src_ratio)
{ static float input [LONG_BUFFER_LEN], output [LONG_BUFFER_LEN] ;
SRC_STATE *src_state ;
SRC_DATA src_data ;
int input_len, output_len, current_in, current_out ;
int k, error, terminate ;
printf ("\tstream_test (SRC ratio = %7.4f) .......... ", src_ratio) ;
fflush (stdout) ;
/* Erik */
for (k = 0 ; k < LONG_BUFFER_LEN ; k++) input [k] = k * 1.0 ;
/* Calculate maximun input and output lengths. */
if (src_ratio >= 1.0)
{ output_len = LONG_BUFFER_LEN ;
input_len = (int) floor (LONG_BUFFER_LEN / src_ratio) ;
}
else
{ input_len = LONG_BUFFER_LEN ;
output_len = (int) floor (LONG_BUFFER_LEN * src_ratio) ;
} ;
/* Reduce input_len by 10 so output is longer than necessary. */
input_len -= 20 ;
if (output_len > LONG_BUFFER_LEN)
{ printf ("\n\nLine %d : output_len > LONG_BUFFER_LEN\n\n", __LINE__) ;
exit (1) ;
} ;
current_in = current_out = 0 ;
/* Perform sample rate conversion. */
if ((src_state = src_new (converter, 1, &error)) == NULL)
{ printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_data.end_of_input = 0 ; /* Set this later. */
src_data.data_in = input ;
src_data.src_ratio = src_ratio ;
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) / 10 ;
terminate = 1 + (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ;
while (1)
{
src_data.input_frames = next_block_length (0) ;
src_data.input_frames = MIN (src_data.input_frames, input_len - current_in) ;
src_data.output_frames = ARRAY_LEN (output) - current_out ;
/*-Erik MIN (src_data.output_frames, output_len - current_out) ;-*/
src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ;
if ((error = src_process (src_state, &src_data)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
exit (1) ;
} ;
if (src_data.end_of_input && src_data.output_frames_gen == 0)
break ;
if (src_data.input_frames_used > src_data.input_frames)
{ printf ("\n\nLine %d : input_frames_used > input_frames\n\n", __LINE__) ;
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
printf (" src_data.input_frames_used : %ld\n", src_data.input_frames_used) ;
printf (" src_data.output_frames : %ld\n", src_data.output_frames) ;
printf (" src_data.output_frames_gen : %ld\n\n", src_data.output_frames_gen) ;
exit (1) ;
} ;
if (src_data.input_frames_used < 0)
{ printf ("\n\nLine %d : input_frames_used (%ld) < 0\n\n", __LINE__, src_data.input_frames_used) ;
exit (1) ;
} ;
if (src_data.output_frames_gen < 0)
{ printf ("\n\nLine %d : output_frames_gen (%ld) < 0\n\n", __LINE__, src_data.output_frames_gen) ;
exit (1) ;
} ;
current_in += src_data.input_frames_used ;
current_out += src_data.output_frames_gen ;
if (current_in > input_len + terminate)
{ printf ("\n\nLine %d : current_in (%d) > input_len (%d + %d)\n\n", __LINE__, current_in, input_len, terminate) ;
exit (1) ;
} ;
if (current_out > output_len)
{ printf ("\n\nLine %d : current_out (%d) > output_len (%d)\n\n", __LINE__, current_out, output_len) ;
exit (1) ;
} ;
if (src_data.input_frames_used > input_len)
{ printf ("\n\nLine %d : input_frames_used (%ld) > %d\n\n", __LINE__, src_data.input_frames_used, input_len) ;
exit (1) ;
} ;
if (src_data.output_frames_gen > output_len)
{ printf ("\n\nLine %d : output_frames_gen (%ld) > %d\n\n", __LINE__, src_data.output_frames_gen, output_len) ;
exit (1) ;
} ;
if (src_data.data_in == NULL && src_data.output_frames_gen == 0)
break ;
src_data.data_in += src_data.input_frames_used ;
src_data.data_out += src_data.output_frames_gen ;
} ;
src_state = src_delete (src_state) ;
if (fabs (current_out - src_ratio * input_len) > terminate)
{ printf ("\n\nLine %d : bad output data length %d should be %2.1f +/- %d.\n", __LINE__,
current_out, src_ratio * input_len, terminate) ;
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
printf ("\tinput_len : %d\n\tinput_used : %d\n", input_len, current_in) ;
printf ("\toutput_len : %d\n\toutput_gen : %d\n\n", output_len, current_out) ;
exit (1) ;
} ;
if (current_in != input_len)
{ printf ("\n\nLine %d : unused input.\n", __LINE__) ;
printf ("\tinput_len : %d\n", input_len) ;
printf ("\tinput_frames_used : %d\n\n", current_in) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* stream_test */
static int
next_block_length (int reset)
{ static int block_lengths [] = /* Should be an odd length. */
{ /*-2, 500, 5, 400, 10, 300, 20, 200, 50, 100, 70 -*/
5, 400, 10, 300, 20, 200, 50, 100, 70
} ;
static int block_len_index = 0 ;
if (reset)
block_len_index = 0 ;
else
block_len_index = (block_len_index + 1) % ARRAY_LEN (block_lengths) ;
return block_lengths [block_len_index] ;
} /* next_block_length */

View File

@ -0,0 +1,212 @@
/*
** Copyright (C) 2004-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <samplerate.h>
#include "config.h"
#include "util.h"
#include "float_cast.h"
#define BUFFER_LEN (1<<16)
static float input [BUFFER_LEN] ;
static float output [BUFFER_LEN] ;
static long
throughput_test (int converter, long best_throughput)
{ SRC_DATA src_data ;
clock_t start_time, clock_time ;
double duration ;
long total_frames = 0, throughput ;
int error ;
printf (" %-30s ", src_get_name (converter)) ;
fflush (stdout) ;
src_data.data_in = input ;
src_data.input_frames = ARRAY_LEN (input) ;
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) ;
src_data.src_ratio = 0.99 ;
sleep (2) ;
start_time = clock () ;
do
{
if ((error = src_simple (&src_data, converter, 1)) != 0)
{ puts (src_strerror (error)) ;
exit (1) ;
} ;
total_frames += src_data.output_frames_gen ;
clock_time = clock () - start_time ;
duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
}
while (duration < 3.0) ;
if (src_data.input_frames_used != ARRAY_LEN (input))
{ printf ("\n\nLine %d : input frames used %ld should be %d\n", __LINE__, src_data.input_frames_used, ARRAY_LEN (input)) ;
exit (1) ;
} ;
if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
printf (" input len : %d\n", ARRAY_LEN (input)) ;
printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
exit (1) ;
} ;
throughput = lrint (floor (total_frames / duration)) ;
if (best_throughput == 0)
{ best_throughput = MAX (throughput, best_throughput) ;
printf ("%5.2f %10ld\n", duration, throughput) ;
}
else
{ best_throughput = MAX (throughput, best_throughput) ;
printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ;
}
return best_throughput ;
} /* throughput_test */
static void
single_run (void)
{
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
puts (
"\n"
" Converter Duration Throughput\n"
" -----------------------------------------------------------"
) ;
throughput_test (SRC_ZERO_ORDER_HOLD, 0) ;
throughput_test (SRC_LINEAR, 0) ;
throughput_test (SRC_SINC_FASTEST, 0) ;
throughput_test (SRC_SINC_MEDIUM_QUALITY, 0) ;
throughput_test (SRC_SINC_BEST_QUALITY, 0) ;
puts ("") ;
return ;
} /* single_run */
static void
multi_run (int run_count)
{ long zero_order_hold = 0, linear = 0 ;
long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ;
int k ;
puts (
"\n"
" Converter Duration Throughput Best Throughput\n"
" --------------------------------------------------------------------------------"
) ;
for (k = 0 ; k < run_count ; k++)
{ zero_order_hold = throughput_test (SRC_ZERO_ORDER_HOLD, zero_order_hold) ;
linear = throughput_test (SRC_LINEAR, linear) ;
sinc_fastest = throughput_test (SRC_SINC_FASTEST, sinc_fastest) ;
sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, sinc_medium) ;
sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, sinc_best) ;
puts ("") ;
/* Let the CPU cool down. We might be running on a laptop. */
sleep (10) ;
} ;
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
puts (
"\n"
" Converter Best Throughput\n"
" ------------------------------------------------"
) ;
printf (" %-30s %10ld\n", src_get_name (SRC_ZERO_ORDER_HOLD), zero_order_hold) ;
printf (" %-30s %10ld\n", src_get_name (SRC_LINEAR), linear) ;
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ;
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ;
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ;
puts ("") ;
} /* multi_run */
static void
usage_exit (const char * argv0)
{ const char * cptr ;
if ((cptr = strrchr (argv0, '/')) != NULL)
argv0 = cptr ;
printf (
"Usage :\n"
" %s - Single run of the throughput test.\n"
" %s --best-of N - Do N runs of test a print bext result.\n"
"\n",
argv0, argv0) ;
exit (0) ;
} /* usage_exit */
int
main (int argc, char ** argv)
{ double freq ;
memset (input, 0, sizeof (input)) ;
freq = 0.01 ;
gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
if (argc == 1)
single_run () ;
else if (argc == 3 && strcmp (argv [1], "--best-of") == 0)
{ int run_count = atoi (argv [2]) ;
if (run_count < 1 || run_count > 20)
{ printf ("Please be sensible. Run count should be in range (1, 10].\n") ;
exit (1) ;
} ;
multi_run (run_count) ;
}
else
usage_exit (argv [0]) ;
puts (
" Duration is in seconds.\n"
" Throughput is in samples/sec (more is better).\n"
) ;
return 0 ;
} /* main */

230
soxr/lsr-tests/util.c Normal file
View File

@ -0,0 +1,230 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "util.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846264338
#endif
void
gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len)
{ int k, freq ;
double amplitude, phase ;
amplitude = max / freq_count ;
for (k = 0 ; k < output_len ; k++)
output [k] = 0.0 ;
for (freq = 0 ; freq < freq_count ; freq++)
{ phase = 0.9 * M_PI / freq_count ;
if (freqs [freq] <= 0.0 || freqs [freq] >= 0.5)
{ printf ("\n%s : Error : freq [%d] == %g is out of range. Should be < 0.5.\n", __FILE__, freq, freqs [freq]) ;
exit (1) ;
} ;
for (k = 0 ; k < output_len ; k++)
output [k] += amplitude * sin (freqs [freq] * (2 * k) * M_PI + phase) ;
} ;
/* Apply Hanning Window. */
for (k = 0 ; k < output_len ; k++)
output [k] *= 0.5 - 0.5 * cos ((2 * k) * M_PI / (output_len - 1)) ;
/* data [k] *= 0.3635819 - 0.4891775 * cos ((2 * k) * M_PI / (output_len - 1))
+ 0.1365995 * cos ((4 * k) * M_PI / (output_len - 1))
- 0.0106411 * cos ((6 * k) * M_PI / (output_len - 1)) ;
*/
return ;
} /* gen_windowed_sines */
void
save_oct_float (char *filename, float *input, int in_len, float *output, int out_len)
{ FILE *file ;
int k ;
printf ("Dumping input and output data to file : %s.\n\n", filename) ;
if (! (file = fopen (filename, "w")))
return ;
fprintf (file, "# Not created by Octave\n") ;
fprintf (file, "# name: input\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", in_len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < in_len ; k++)
fprintf (file, "% g\n", input [k]) ;
fprintf (file, "# name: output\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", out_len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < out_len ; k++)
fprintf (file, "% g\n", output [k]) ;
fclose (file) ;
return ;
} /* save_oct_float */
void
save_oct_double (char *filename, double *input, int in_len, double *output, int out_len)
{ FILE *file ;
int k ;
printf ("Dumping input and output data to file : %s.\n\n", filename) ;
if (! (file = fopen (filename, "w")))
return ;
fprintf (file, "# Not created by Octave\n") ;
fprintf (file, "# name: input\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", in_len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < in_len ; k++)
fprintf (file, "% g\n", input [k]) ;
fprintf (file, "# name: output\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", out_len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < out_len ; k++)
fprintf (file, "% g\n", output [k]) ;
fclose (file) ;
return ;
} /* save_oct_double */
void
interleave_data (const float *in, float *out, int frames, int channels)
{ int fr, ch ;
for (fr = 0 ; fr < frames ; fr++)
for (ch = 0 ; ch < channels ; ch++)
out [ch + channels * fr] = in [fr + frames * ch] ;
return ;
} /* interleave_data */
void
deinterleave_data (const float *in, float *out, int frames, int channels)
{ int fr, ch ;
for (ch = 0 ; ch < channels ; ch++)
for (fr = 0 ; fr < frames ; fr++)
out [fr + frames * ch] = in [ch + channels * fr] ;
return ;
} /* deinterleave_data */
void
reverse_data (float *data, int datalen)
{ int left, right ;
float temp ;
left = 0 ;
right = datalen - 1 ;
while (left < right)
{ temp = data [left] ;
data [left] = data [right] ;
data [right] = temp ;
left ++ ;
right -- ;
} ;
} /* reverse_data */
const char *
get_cpu_name (void)
{
const char *name = "Unknown", *search = NULL ;
static char buffer [512] ;
FILE * file = NULL ;
int is_pipe = 0 ;
#if defined (__linux__)
file = fopen ("/proc/cpuinfo", "r") ;
search = "model name" ;
#elif defined (__APPLE__)
file = popen ("/usr/sbin/system_profiler -detailLevel full SPHardwareDataType", "r") ;
search = "Processor Name" ;
is_pipe = 1 ;
#elif defined (__FreeBSD__)
file = popen ("sysctl -a", "r") ;
search = "hw.model" ;
is_pipe = 1 ;
#else
file = NULL ;
#endif
if (file == NULL)
return name ;
if (search == NULL)
{ printf ("Error : search is NULL in function %s.\n", __func__) ;
return name ;
} ;
while (fgets (buffer, sizeof (buffer), file) != NULL)
if (strstr (buffer, search))
{ char *src, *dest ;
if ((src = strchr (buffer, ':')) != NULL)
{ src ++ ;
while (isspace (src [0]))
src ++ ;
name = src ;
/* Remove consecutive spaces. */
src ++ ;
for (dest = src ; src [0] ; src ++)
{ if (isspace (src [0]) && isspace (dest [-1]))
continue ;
dest [0] = src [0] ;
dest ++ ;
} ;
dest [0] = 0 ;
break ;
} ;
} ;
if (is_pipe)
pclose (file) ;
else
fclose (file) ;
return name ;
} /* get_cpu_name */

50
soxr/lsr-tests/util.h Normal file
View File

@ -0,0 +1,50 @@
/*
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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.
*/
#define ABS(a) (((a) < 0) ? - (a) : (a))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
void gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len) ;
void save_oct_float (char *filename, float *input, int in_len, float *output, int out_len) ;
void save_oct_double (char *filename, double *input, int in_len, double *output, int out_len) ;
void interleave_data (const float *in, float *out, int frames, int channels) ;
void deinterleave_data (const float *in, float *out, int frames, int channels) ;
void reverse_data (float *data, int datalen) ;
double calculate_snr (float *data, int len, int expected_peaks) ;
const char * get_cpu_name (void) ;
#if OS_IS_WIN32
/*
** Extra Win32 hacks.
**
** Despite Microsoft claim of windows being POSIX compatibile it has '_sleep'
** instead of 'sleep'.
*/
#define sleep _sleep
#endif

View File

@ -0,0 +1,152 @@
/*
** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program 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.
**
** This program 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 <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <samplerate.h>
#include "util.h"
#define BUFFER_LEN (1 << 16)
static void varispeed_test (int converter, double target_snr) ;
int
main (void)
{
puts ("") ;
printf (" Zero Order Hold interpolator : ") ;
varispeed_test (SRC_ZERO_ORDER_HOLD, 10.0) ;
printf (" Linear interpolator : ") ;
varispeed_test (SRC_LINEAR, 10.0) ;
printf (" Sinc interpolator : ") ;
varispeed_test (SRC_SINC_FASTEST, 115.0) ;
puts ("") ;
return 0 ;
} /* main */
static void
varispeed_test (int converter, double target_snr)
{ static float input [BUFFER_LEN], output [BUFFER_LEN] ;
double sine_freq, snr ;
SRC_STATE *src_state ;
SRC_DATA src_data ;
int input_len, error ;
memset (input, 0, sizeof (input)) ;
input_len = ARRAY_LEN (input) / 2 ;
sine_freq = 0.0111 ;
gen_windowed_sines (1, &sine_freq, 1.0, input, input_len) ;
/* Perform sample rate conversion. */
if ((src_state = src_new (converter, 1, &error)) == NULL)
{ printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_data.end_of_input = 1 ;
src_data.data_in = input ;
src_data.input_frames = input_len ;
src_data.src_ratio = 3.0 ;
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) ;
if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
if ((error = src_process (src_state, &src_data)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
exit (1) ;
} ;
if (src_data.input_frames_used != input_len)
{ printf ("\n\nLine %d : unused input.\n", __LINE__) ;
printf ("\tinput_len : %d\n", input_len) ;
printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ;
exit (1) ;
} ;
/* Copy the last output to the input. */
memcpy (input, output, sizeof (input)) ;
reverse_data (input, src_data.output_frames_gen) ;
if ((error = src_reset (src_state)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
src_data.end_of_input = 1 ;
src_data.data_in = input ;
input_len = src_data.input_frames = src_data.output_frames_gen ;
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) ;
if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
exit (1) ;
} ;
if ((error = src_process (src_state, &src_data)))
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
exit (1) ;
} ;
if (src_data.input_frames_used != input_len)
{ printf ("\n\nLine %d : unused input.\n", __LINE__) ;
printf ("\tinput_len : %d\n", input_len) ;
printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ;
exit (1) ;
} ;
src_state = src_delete (src_state) ;
snr = calculate_snr (output, src_data.output_frames_gen, 1) ;
if (target_snr > snr)
{ printf ("\n\nLine %d : snr (%3.1f) does not meet target (%3.1f)\n\n", __LINE__, snr, target_snr) ;
save_oct_float ("varispeed.mat", input, src_data.input_frames, output, src_data.output_frames_gen) ;
exit (1) ;
} ;
puts ("ok") ;
return ;
} /* varispeed_test */

22
soxr/msvc/README Normal file
View File

@ -0,0 +1,22 @@
SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
Cmake is the recommended way to configure, build (as either a DLL or a static
library), and install libsoxr for general use on MS-Windows, as on other OSs.
However, building within MS Visual Studio is also possible, as exemplified by
the accompanying files:
* soxr-config.h Pre-configured for a modern Win32 system.
* libsoxr.vcproj Builds the library as a DLL, per above.
* libsoxr.sln, Build an example exe using the above.
example1.vcproj
The following notes apply to adaptation of these files:
* For a system without AVX support, set WITH_CR64S to 0 in
soxr-config.h and exclude the three files ...64s.c from the build.
* If changing libsoxr.vcproj to build a static library, then also
remove the preprocessor definition: SOXR_DLL.

82
soxr/msvc/example1.vcproj Normal file
View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="example1"
ProjectGUID="{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}"
RootNamespace="soxr"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform Name="Win32" />
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\src"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\src"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File RelativePath="..\examples\1-single-block.c" />
</Files>
<Globals>
</Globals>
</VisualStudioProject>

29
soxr/msvc/libsoxr.sln Normal file
View File

@ -0,0 +1,29 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example1", "example1.vcproj", "{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}"
ProjectSection(ProjectDependencies) = postProject
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB} = {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsoxr", "libsoxr.vcproj", "{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|Win32 = Release|Win32
Debug|Win32 = Debug|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Release|Win32.ActiveCfg = Release|Win32
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Release|Win32.Build.0 = Release|Win32
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Debug|Win32.ActiveCfg = Debug|Win32
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Debug|Win32.Build.0 = Debug|Win32
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Release|Win32.ActiveCfg = Release|Win32
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Release|Win32.Build.0 = Release|Win32
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Debug|Win32.ActiveCfg = Debug|Win32
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Debug|Win32.Build.0 = Debug|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

97
soxr/msvc/libsoxr.vcproj Normal file
View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libsoxr"
ProjectGUID="{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}"
RootNamespace="libsoxr"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform Name="Win32" />
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="."
PreprocessorDefinitions="_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;SOXR_DLL;soxr_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="."
PreprocessorDefinitions="NDEBUG;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;SOXR_DLL;soxr_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File RelativePath="..\src\cr.c" />
<File RelativePath="..\src\cr32.c" />
<File RelativePath="..\src\cr32s.c" />
<File RelativePath="..\src\cr64.c" />
<File RelativePath="..\src\cr64s.c" />
<File RelativePath="..\src\data-io.c" />
<File RelativePath="..\src\dbesi0.c" />
<File RelativePath="..\src\fft4g32.c" />
<File RelativePath="..\src\fft4g64.c" />
<File RelativePath="..\src\filter.c" />
<File RelativePath="..\src\pffft32s.c" />
<File RelativePath="..\src\pffft64s.c" />
<File RelativePath="..\src\util32s.c" />
<File RelativePath="..\src\util64s.c" />
<File RelativePath="..\src\soxr.c" />
<File RelativePath="..\src\vr32.c" />
</Files>
<Globals>
</Globals>
</VisualStudioProject>

30
soxr/msvc/soxr-config.h Normal file
View File

@ -0,0 +1,30 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* N.B. Pre-configured for modern MS-Windows systems. However, the normal
* procedure is to use the cmake configuration and build system. See INSTALL. */
#if !defined soxr_config_included
#define soxr_config_included
#define AVCODEC_FOUND 0
#define AVUTIL_FOUND 0
#define WITH_PFFFT 1
#define HAVE_FENV_H 1
#define HAVE_STDBOOL_H 1
#define HAVE_STDINT_H 1
#define HAVE_LRINT 1
#define HAVE_BIGENDIAN 0
#define WITH_CR32 1
#define WITH_CR32S 1
#define WITH_CR64 1
#define WITH_CR64S 1
#define WITH_VR32 1
#define WITH_HI_PREC_CLOCK 1
#define WITH_FLOAT_STD_PREC_CLOCK 0
#define WITH_DEV_TRACE 1
#endif

31
soxr/multi-arch Normal file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -e
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
rm -f CMakeCache.txt # Prevent interference from any in-tree build
j=-j4
build=Release
for n in \
cc: \
clang: \
arm-linux-gnueabi-gcc:Linux \
x86_64-w64-mingw32-gcc:Windows \
i686-w64-mingw32-gcc:Windows \
; do
compiler=$(echo $n | sed 's/:.*//')
system=$(echo $n | sed 's/.*://')
dir=$build-$compiler
which $compiler > /dev/null || echo $compiler not found && (
echo "***" $dir
mkdir -p $dir
cd $dir
cmake -DCMAKE_BUILD_TYPE=$build -DCMAKE_C_COMPILER=$compiler -DCMAKE_SYSTEM_NAME="$system" -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF ..
make $j && [ /$system = / ] && ctest -j || true
cd tests
../../tests/throughput-test && SOXR_THROUGHPUT_GAIN=.6 ../../tests/throughput-test 2 3 || true
)
done

View File

@ -1,46 +1,27 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxr_config_included #if !defined soxr_config_included
#define soxr_config_included #define soxr_config_included
#define HAVE_SINGLE_PRECISION @HAVE_SINGLE_PRECISION@ #cmakedefine01 AVCODEC_FOUND
#define HAVE_DOUBLE_PRECISION @HAVE_DOUBLE_PRECISION@ #cmakedefine01 AVUTIL_FOUND
#define HAVE_AVFFT @HAVE_AVFFT@ #cmakedefine01 WITH_PFFFT
#define HAVE_SIMD @HAVE_SIMD@
#define HAVE_FENV_H @HAVE_FENV_H@
#define HAVE_LRINT @HAVE_LRINT@
#define WORDS_BIGENDIAN @WORDS_BIGENDIAN@
#include <limits.h> #cmakedefine01 HAVE_FENV_H
#cmakedefine01 HAVE_STDBOOL_H
#cmakedefine01 HAVE_STDINT_H
#cmakedefine01 HAVE_LRINT
#cmakedefine01 HAVE_BIGENDIAN
#undef bool #cmakedefine01 WITH_CR32
#undef false #cmakedefine01 WITH_CR32S
#undef true #cmakedefine01 WITH_CR64
#define bool int #cmakedefine01 WITH_CR64S
#define false 0 #cmakedefine01 WITH_VR32
#define true 1
#undef int16_t #cmakedefine01 WITH_HI_PREC_CLOCK
#undef int32_t #cmakedefine01 WITH_FLOAT_STD_PREC_CLOCK
#undef int64_t #cmakedefine01 WITH_DEV_TRACE
#undef uint32_t
#undef uint64_t
#define int16_t short
#if LONG_MAX > 2147483647L
#define int32_t int
#define int64_t long
#elif LONG_MAX < 2147483647L
#error this library requires that 'long int' has at least 32-bits
#else
#define int32_t long
#if defined _MSC_VER
#define int64_t __int64
#else
#define int64_t long long
#endif
#endif
#define uint32_t unsigned int32_t
#define uint64_t unsigned int64_t
#endif #endif

View File

@ -1,4 +1,4 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net # SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details. # Licence for this file: LGPL v2.1 See LICENCE for details.
@ -7,90 +7,89 @@
if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vr-coefs.h) if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vr-coefs.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
set_property(SOURCE vr32.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h) set_property(SOURCE vr32.c
APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h)
add_executable (vr-coefs vr-coefs.c) add_executable (vr-coefs vr-coefs.c)
target_link_libraries (vr-coefs ${LIBM_LIBRARIES})
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
COMMAND vr-coefs > ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h COMMAND vr-coefs > ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
DEPENDS vr-coefs) DEPENDS vr-coefs)
endif () endif ()
# Minimalist boo configuration:
add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB -DSOXR_SILENT=1)
include (CheckFunctionExists)
include (CheckIncludeFiles)
set(WITH_LSR_BINDINGS OFF) add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB)
set(WITH_SINGLE_PRECISION ON)
set(WITH_DOUBLE_PRECISION OFF)
set(WITH_SIMD ON)
set(HAVE_SINGLE_PRECISION "1")
set(HAVE_DOUBLE_PRECISION "0")
set(HAVE_AVFFT "0")
set(HAVE_SIMD "1")
check_function_exists (lrint HAVE_LRINT)
if(NOT HAVE_LRINT)
set(HAVE_LRINT "0")
endif()
check_include_files (fenv.h HAVE_FENV_H)
if(NOT HAVE_FENV_H)
set(HAVE_FENV_H "0")
endif()
set(WORDS_BIGENDIAN "0")
configure_file (
${CMAKE_CURRENT_SOURCE_DIR}/../soxr-config.h.in
${CMAKE_CURRENT_BINARY_DIR}/soxr-config.h)
include_directories (${CMAKE_CURRENT_BINARY_DIR})
# Libsoxr configuration: # Libsoxr configuration:
set (RDFT32 fft4g32.c) set (RDFT32 fft4g32)
if (WITH_AVFFT AND AVCODEC_FOUND) if (AVCODEC_FOUND)
set (RDFT32 avfft32.c) set (RDFT32 avfft32)
set (RDFT32S avfft32s.c) set (RDFT32S avfft32s)
elseif (WITH_PFFFT) elseif (WITH_PFFFT)
#set (RDFT32 pffft32.c) #set (RDFT32 pffft32)
set (RDFT32S pffft32s.c) set (RDFT32S pffft32s)
elseif (WITH_SIMD) elseif (WITH_CR32S)
set (RDFT32S fft4g32s.c) set (RDFT32S fft4g32s)
if (NOT WITH_CR32)
list (APPEND RDFT32S fft4g32)
endif ()
endif () endif ()
if (WITH_DOUBLE_PRECISION) set (SOURCES ${PROJECT_NAME}.c data-io)
set (DP_SOURCES rate64.c)
if (WITH_CR32 OR WITH_CR32S OR WITH_CR64 OR WITH_CR64S)
list (APPEND SOURCES dbesi0 filter fft4g64 cr)
endif () endif ()
if (WITH_SINGLE_PRECISION) if (WITH_CR32)
set (SP_SOURCES rate32.c ${RDFT32}) list (APPEND SOURCES cr32 ${RDFT32})
endif () endif ()
if (HAVE_SIMD) if (WITH_CR64)
set (SIMD_SOURCES rate32s.c vr32s.c ${RDFT32S} simd.c) list (APPEND SOURCES cr64)
foreach (source ${SIMD_SOURCES}) endif ()
set_property (SOURCE ${source} PROPERTY COMPILE_FLAGS ${SIMD_C_FLAGS})
if (WITH_VR32)
list (APPEND SOURCES vr32)
endif ()
if (WITH_CR32S)
foreach (source cr32s ${RDFT32S} util32s)
list (APPEND SOURCES ${source})
set_property (SOURCE ${source}
APPEND_STRING PROPERTY COMPILE_FLAGS ${SIMD32_C_FLAGS})
endforeach ()
endif ()
if (WITH_CR64S)
foreach (source cr64s pffft64s util64s)
list (APPEND SOURCES ${source})
set_property (SOURCE ${source}
APPEND_STRING PROPERTY COMPILE_FLAGS ${SIMD64_C_FLAGS})
endforeach () endforeach ()
else ()
set (SIMD_SOURCES vr32.c)
endif () endif ()
# Libsoxr: # Libsoxr:
add_library (soxr ${LIB_TYPE} soxr.c data-io.c dbesi0.c filter.c fft4g64.c add_library (${PROJECT_NAME} ${LIB_TYPE} ${SOURCES})
${SP_SOURCES} ${DP_SOURCES} ${SIMD_SOURCES}) target_link_libraries (${PROJECT_NAME} PRIVATE ${LIBS} ${LIBM_LIBRARIES})
set_target_properties (soxr PROPERTIES set_target_properties (${PROJECT_NAME} PROPERTIES
VERSION "${SO_VERSION}" VERSION "${SO_VERSION}"
SOVERSION ${SO_VERSION_MAJOR} SOVERSION ${SO_VERSION_MAJOR}
INSTALL_NAME_DIR ${LIB_INSTALL_DIR} INSTALL_NAME_DIR ${LIB_INSTALL_DIR}
LINK_INTERFACE_LIBRARIES "" LINK_INTERFACE_LIBRARIES ""
PUBLIC_HEADER "soxr.h") PUBLIC_HEADER "${PROJECT_NAME}.h")
if (BUILD_FRAMEWORK) if (BUILD_FRAMEWORK)
set_target_properties (soxr PROPERTIES FRAMEWORK TRUE) set_target_properties (${PROJECT_NAME} PROPERTIES FRAMEWORK TRUE)
elseif (NOT WIN32) elseif (NOT WIN32)
# set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/soxr.pc) set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc)
# configure_file (${CMAKE_CURRENT_SOURCE_DIR}/soxr.pc.in ${TARGET_PCS}) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${TARGET_PCS})
# install (FILES ${CMAKE_CURRENT_BINARY_DIR}/soxr.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif () endif ()
@ -98,11 +97,11 @@ endif ()
# LSR bindings: # LSR bindings:
if (WITH_LSR_BINDINGS) if (WITH_LSR_BINDINGS)
set (LSR soxr-lsr) set (LSR ${PROJECT_NAME}-lsr)
set (LSR_SO_VERSION 0.1.9) set (LSR_SO_VERSION 0.1.9)
set (LSR_SO_VERSION_MAJOR 0) set (LSR_SO_VERSION_MAJOR 0)
add_library (${LSR} ${LIB_TYPE} lsr) add_library (${LSR} ${LIB_TYPE} ${LSR})
target_link_libraries (${LSR} soxr) target_link_libraries (${LSR} ${PROJECT_NAME})
set_target_properties (${LSR} PROPERTIES set_target_properties (${LSR} PROPERTIES
VERSION "${LSR_SO_VERSION}" VERSION "${LSR_SO_VERSION}"
SOVERSION ${LSR_SO_VERSION_MAJOR} SOVERSION ${LSR_SO_VERSION_MAJOR}
@ -112,9 +111,9 @@ if (WITH_LSR_BINDINGS)
if (BUILD_FRAMEWORK) if (BUILD_FRAMEWORK)
set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE) set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE)
elseif (NOT WIN32) elseif (NOT WIN32)
# set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc") set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc")
# configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc)
# install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif () endif ()
endif () endif ()
@ -122,29 +121,9 @@ endif ()
# Installation (from build from source): # Installation (from build from source):
#install (TARGETS soxr ${LSR} install (TARGETS ${PROJECT_NAME} ${LSR}
# FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR} FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
# LIBRARY DESTINATION ${LIB_INSTALL_DIR} LIBRARY DESTINATION ${LIB_INSTALL_DIR}
# RUNTIME DESTINATION ${BIN_INSTALL_DIR} RUNTIME DESTINATION ${BIN_INSTALL_DIR}
# ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
# PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}) PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR})
# Packaging (for unix-like distributions):
#get_property (LIB1 TARGET soxr PROPERTY LOCATION)
#if (BUILD_SHARED_LIBS)
# set (LIB1 ${LIB1}.${SO_VERSION_MAJOR} ${LIB1}.${SO_VERSION})
#endif ()
#list (APPEND TARGET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/soxr.h")
#if (WITH_LSR_BINDINGS)
# get_property (LIB2 TARGET ${LSR} PROPERTY LOCATION)
# if (BUILD_SHARED_LIBS)
# set (LIB2 ${LIB2}.${LSR_SO_VERSION_MAJOR} ${LIB2}.${LSR_SO_VERSION})
# endif ()
# list (APPEND TARGET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.h")
#endif ()
#set (TARGET_LIBS ${LIB1} ${LIB2})
#configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libsoxr.src.in ${CMAKE_CURRENT_BINARY_DIR}/libsoxr.src)
#configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libsoxr-dev.src.in ${CMAKE_CURRENT_BINARY_DIR}/libsoxr-dev.src)

View File

@ -1,4 +1,4 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#if defined SOXR_LIB #if defined SOXR_LIB
@ -18,8 +18,10 @@
#define lsx_dfst_f _soxr_dfst_f #define lsx_dfst_f _soxr_dfst_f
#define lsx_dfst _soxr_dfst #define lsx_dfst _soxr_dfst
#define lsx_fir_to_phase _soxr_fir_to_phase #define lsx_fir_to_phase _soxr_fir_to_phase
#define lsx_f_resp _soxr_f_resp
#define lsx_init_fft_cache_f _soxr_init_fft_cache_f #define lsx_init_fft_cache_f _soxr_init_fft_cache_f
#define lsx_init_fft_cache _soxr_init_fft_cache #define lsx_init_fft_cache _soxr_init_fft_cache
#define lsx_inv_f_resp _soxr_inv_f_resp
#define lsx_kaiser_beta _soxr_kaiser_beta #define lsx_kaiser_beta _soxr_kaiser_beta
#define lsx_kaiser_params _soxr_kaiser_params #define lsx_kaiser_params _soxr_kaiser_params
#define lsx_make_lpf _soxr_make_lpf #define lsx_make_lpf _soxr_make_lpf

View File

@ -1,27 +1,33 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include <stdlib.h>
#include <math.h> #include <math.h>
#include <libavcodec/avfft.h> #include <libavcodec/avfft.h>
#include "filter.h" #include "filter.h"
#include "rdft_t.h"
static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);} static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);}
static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);} static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);}
static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;} static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;}
static int multiplier(void) {return 2;} static int multiplier(void) {return 2;}
static void nothing(void) {} static void nothing(void) {}
static int flags(void) {return 0;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft32_cb = {
fn_t _soxr_rdft32_cb[] = { forward_setup,
(fn_t)forward_setup, backward_setup,
(fn_t)backward_setup, av_rdft_end,
(fn_t)av_rdft_end, rdft,
(fn_t)rdft, rdft,
(fn_t)rdft, rdft,
(fn_t)rdft, rdft,
(fn_t)rdft, _soxr_ordered_convolve_f,
(fn_t)_soxr_ordered_convolve_f, _soxr_ordered_partial_convolve_f,
(fn_t)_soxr_ordered_partial_convolve_f, multiplier,
(fn_t)multiplier, nothing,
(fn_t)nothing, malloc,
calloc,
free,
flags,
}; };

View File

@ -3,25 +3,30 @@
#include <math.h> #include <math.h>
#include <libavcodec/avfft.h> #include <libavcodec/avfft.h>
#include "simd.h" #include "util32s.h"
#include "rdft_t.h"
static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);} static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);}
static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);} static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);}
static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;} static void rdft(int length, void * setup, void * H, void * scratch) {av_rdft_calc(setup, H); (void)length; (void)scratch;}
static int multiplier(void) {return 2;} static int multiplier(void) {return 2;}
static void nothing(void) {} static void nothing2(int u1, void *u2, void *u3, void *u4) {(void)u1; (void)u2; (void)u3; (void)u4;}
static int flags(void) {return RDFT_IS_SIMD;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft32s_cb = {
fn_t _soxr_rdft32s_cb[] = { forward_setup,
(fn_t)forward_setup, backward_setup,
(fn_t)backward_setup, av_rdft_end,
(fn_t)av_rdft_end, rdft,
(fn_t)rdft, rdft,
(fn_t)rdft, rdft,
(fn_t)rdft, rdft,
(fn_t)rdft, ORDERED_CONVOLVE_SIMD,
(fn_t)_soxr_ordered_convolve_simd, ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)_soxr_ordered_partial_convolve_simd, multiplier,
(fn_t)multiplier, nothing2,
(fn_t)nothing, SIMD_ALIGNED_MALLOC,
SIMD_ALIGNED_CALLOC,
SIMD_ALIGNED_FREE,
flags,
}; };

26
soxr/src/cb_t.h Normal file
View File

@ -0,0 +1,26 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
typedef struct {
void * (*input)(void *, void * samples, size_t n);
void (*process)(void *, size_t);
void const * (*output)(void *, void * samples, size_t * n);
void (*flush)(void *);
void (*close)(void *);
double (*delay)(void *);
void (*sizes)(size_t * shared, size_t * channel);
char const * (*create)(void * channel, void * shared, double io_ratio, void * q_spec, void * r_spec, double scale);
void (*set_io_ratio)(void *, double io_ratio, size_t len);
char const * (*id)(void);
} control_block_t;
#define resampler_input p->control_block.input
#define resampler_process p->control_block.process
#define resampler_output p->control_block.output
#define resampler_flush p->control_block.flush
#define resampler_close p->control_block.close
#define resampler_delay p->control_block.delay
#define resampler_sizes p->control_block.sizes
#define resampler_create p->control_block.create
#define resampler_set_io_ratio p->control_block.set_io_ratio
#define resampler_id p->control_block.id

View File

@ -3,8 +3,8 @@
/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */ /* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */
#if !defined ccrw2_included #if !defined soxr_ccrw2_included
#define ccrw2_included #define soxr_ccrw2_included
#if defined SOXR_LIB #if defined SOXR_LIB
#include "internal.h" #include "internal.h"

316
soxr/src/cr-core.c Normal file
View File

@ -0,0 +1,316 @@
/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details.
*
* Constant-rate resampling engine-specific code. */
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "filter.h"
#if defined SOXR_LIB
#include "internal.h"
#include "cr.h"
#if CORE_TYPE & CORE_DBL
typedef double sample_t;
#if CORE_TYPE & CORE_SIMD_DFT
#define RDFT_CB _soxr_rdft64s_cb
#else
#define RDFT_CB _soxr_rdft64_cb
#endif
#else
typedef float sample_t;
#if CORE_TYPE & CORE_SIMD_DFT
#define RDFT_CB _soxr_rdft32s_cb
#else
#define RDFT_CB _soxr_rdft32_cb
#endif
#endif
#if CORE_TYPE & (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
#if CORE_TYPE & CORE_DBL
#include "util64s.h"
#include "dev64s.h"
#else
#include "util32s.h"
#include "dev32s.h"
#endif
#endif
extern rdft_cb_table RDFT_CB;
#else
#define RDFT_CB 0
#endif
static void cubic_stage_fn(stage_t * p, fifo_t * output_fifo)
{
sample_t const * input = stage_read_p(p);
int num_in = min(stage_occupancy(p), p->input_size);
int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio);
sample_t * output = fifo_reserve(output_fifo, max_num_out);
for (i = 0; p->at.integer < num_in; ++i, p->at.whole += p->step.whole) {
sample_t const * s = input + p->at.integer;
double x = p->at.fraction * (1 / MULT32);
double b = .5*(s[1]+s[-1])-*s, a = (1/6.)*(s[2]-s[1]+s[-1]-*s-4*b);
double c = s[1]-*s-a-b;
output[i] = (sample_t)(p->mult * (((a*x + b)*x + c)*x + *s));
}
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
fifo_read(&p->fifo, p->at.integer, NULL);
p->at.integer = 0;
}
#if defined __AVX__
#define DEFINED_AVX 1
#else
#define DEFINED_AVX 0
#endif
#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86
#define DEFINED_X86 1
#else
#define DEFINED_X86 0
#endif
#if defined __arm__
#define DEFINED_ARM 1
#else
#define DEFINED_ARM 0
#endif
#if CORE_TYPE & CORE_DBL
#define SIMD_AVX ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_AVX)
#define SIMD_SSE 0
#else
#define SIMD_SSE ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_X86)
#define SIMD_AVX 0
#endif
#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_ARM)
#include "half-coefs.h"
#if !(CORE_TYPE & CORE_SIMD_HALF)
#define FUNCTION_H h7
#define CONVOLVE ____ __ _
#include "half-fir.h"
#endif
#define FUNCTION_H h8
#define CONVOLVE ____ ____
#include "half-fir.h"
#define FUNCTION_H h9
#define CONVOLVE ____ ____ _
#include "half-fir.h"
#if CORE_TYPE & CORE_DBL
#define FUNCTION_H h10
#define CONVOLVE ____ ____ __
#include "half-fir.h"
#define FUNCTION_H h11
#define CONVOLVE ____ ____ __ _
#include "half-fir.h"
#define FUNCTION_H h12
#define CONVOLVE ____ ____ ____
#include "half-fir.h"
#define FUNCTION_H h13
#define CONVOLVE ____ ____ ____ _
#include "half-fir.h"
#endif
static half_fir_info_t const half_firs[] = {
#if !(CORE_TYPE & CORE_SIMD_HALF)
{ 7, half_fir_coefs_7 , h7 , 0 , 120.65f},
#endif
{ 8, half_fir_coefs_8 , h8 , 0 , 136.51f},
{ 9, half_fir_coefs_9 , h9 , 0 , 152.32f},
#if CORE_TYPE & CORE_DBL
{10, half_fir_coefs_10, h10, 0 , 168.08f},
{11, half_fir_coefs_11, h11, 0 , 183.79f},
{12, half_fir_coefs_12, h12, 0 , 199.46f},
{13, half_fir_coefs_13, h13, 0 , 215.12f},
#endif
};
#undef SIMD_AVX
#undef SIMD_NEON
#undef SIMD_SSE
#if CORE_TYPE & CORE_DBL
#define SIMD_AVX ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_AVX)
#define SIMD_SSE 0
#else
#define SIMD_SSE ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_X86)
#define SIMD_AVX 0
#endif
#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_ARM)
#define COEFS (sample_t * __restrict)p->shared->poly_fir_coefs
#define VAR_LENGTH p->n
#define VAR_CONVOLVE(n) while (j < (n)) _
#define VAR_POLY_PHASE_BITS p->phase_bits
#define FUNCTION vpoly0
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir0.h"
#define FUNCTION vpoly1
#define COEF_INTERP 1
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir.h"
#define FUNCTION vpoly2
#define COEF_INTERP 2
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir.h"
#define FUNCTION vpoly3
#define COEF_INTERP 3
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir.h"
#if !(CORE_TYPE & CORE_SIMD_POLY)
#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
#define FUNCTION U100_0
#define FIR_LENGTH U100_l
#define CONVOLVE(n) poly_fir_convolve_U100
#include "poly-fir0.h"
#define u100_l 11
#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _
#define FUNCTION u100_0
#define FIR_LENGTH u100_l
#define CONVOLVE(n) poly_fir_convolve_u100
#include "poly-fir0.h"
#define FUNCTION u100_1
#define COEF_INTERP 1
#define PHASE_BITS 8
#define FIR_LENGTH u100_l
#define CONVOLVE(n) poly_fir_convolve_u100
#include "poly-fir.h"
#define FUNCTION u100_2
#define COEF_INTERP 2
#define PHASE_BITS 6
#define FIR_LENGTH u100_l
#define CONVOLVE(n) poly_fir_convolve_u100
#include "poly-fir.h"
#endif
#define u100_1_b 8
#define u100_2_b 6
static poly_fir_t const poly_firs[] = {
{-1, {{0, vpoly0}, { 7.2f, vpoly1}, {5.0f, vpoly2}}},
{-1, {{0, vpoly0}, { 9.4f, vpoly1}, {6.7f, vpoly2}}},
{-1, {{0, vpoly0}, {12.4f, vpoly1}, {7.8f, vpoly2}}},
{-1, {{0, vpoly0}, {13.6f, vpoly1}, {9.3f, vpoly2}}},
{-1, {{0, vpoly0}, {10.5f, vpoly2}, {8.4f, vpoly3}}},
{-1, {{0, vpoly0}, {11.85f,vpoly2}, {9.0f, vpoly3}}},
{-1, {{0, vpoly0}, { 8.0f, vpoly1}, {5.3f, vpoly2}}},
{-1, {{0, vpoly0}, { 8.6f, vpoly1}, {5.7f, vpoly2}}},
{-1, {{0, vpoly0}, {10.6f, vpoly1}, {6.75f,vpoly2}}},
{-1, {{0, vpoly0}, {12.6f, vpoly1}, {8.6f, vpoly2}}},
{-1, {{0, vpoly0}, { 9.6f, vpoly2}, {7.6f, vpoly3}}},
{-1, {{0, vpoly0}, {11.4f, vpoly2}, {8.65f,vpoly3}}},
#if CORE_TYPE & CORE_SIMD_POLY
{10.62f, {{0, vpoly0}, {0, 0}, {0, 0}}},
{-1, {{0, vpoly0}, {u100_1_b, vpoly1}, {u100_2_b, vpoly2}}},
#else
{10.62f, {{U100_l, U100_0}, {0, 0}, {0, 0}}},
{11.28f, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}},
#endif
{-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}},
{-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}},
{-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}},
{-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}},
{-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}},
};
static cr_core_t const cr_core = {
#if CORE_TYPE & CORE_SIMD_POLY
{SIMD_ALIGNED_MALLOC, SIMD_ALIGNED_CALLOC, SIMD_ALIGNED_FREE},
#else
{malloc, calloc, free},
#endif
half_firs, array_length(half_firs),
0, 0,
cubic_stage_fn,
poly_firs, &RDFT_CB
};
#if defined SOXR_LIB
#include "soxr.h"
static char const * rate_create(void * channel, void * shared, double io_ratio,
void * q_spec, void * r_spec, double scale)
{
return _soxr_init(channel, shared, io_ratio, q_spec, r_spec, scale,
&cr_core, CORE_TYPE);
}
static char const * id(void) {return CORE_STR;}
#include "cb_t.h"
control_block_t RATE_CB = {
_soxr_input,
_soxr_process,
_soxr_output,
_soxr_flush,
_soxr_close,
_soxr_delay,
_soxr_sizes,
rate_create,
0,
id,
};
#endif

600
soxr/src/cr.c Normal file
View File

@ -0,0 +1,600 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details.
*
* Constant-rate resampling common code. */
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include "filter.h"
#if defined SOXR_LIB
#include "internal.h"
#define STATIC
#endif
#include "cr.h"
#define num_coefs4 ((core_flags&CORE_SIMD_POLY)? ((num_coefs+3)&~3) : num_coefs)
#define coef_coef(C,T,x) \
C((T*)result, interp_order, num_coefs4, j, x, num_coefs4 - 1 - i)
#define STORE(C,T) { \
if (interp_order > 2) coef_coef(C,T,3) = (T)d; \
if (interp_order > 1) coef_coef(C,T,2) = (T)c; \
if (interp_order > 0) coef_coef(C,T,1) = (T)b; \
coef_coef(C,T,0) = (T)f0;}
static real * prepare_poly_fir_coefs(double const * coefs, int num_coefs,
int num_phases, int interp_order, double multiplier,
core_flags_t core_flags, alloc_t const * mem)
{
int i, j, length = num_coefs4 * num_phases * (interp_order + 1);
real * result = mem->calloc(1,(size_t)length << LOG2_SIZEOF_REAL(core_flags));
double fm1 = coefs[0], f1 = 0, f2 = 0;
for (i = num_coefs - 1; i >= 0; --i)
for (j = num_phases - 1; j >= 0; --j) {
double f0 = fm1, b = 0, c = 0, d = 0; /* = 0 to kill compiler warning */
int pos = i * num_phases + j - 1;
fm1 = pos > 0 ? coefs[pos - 1] * multiplier : 0;
switch (interp_order) {
case 1: b = f1 - f0; break;
case 2: b = f1 - (.5 * (f2+f0) - f1) - f0; c = .5 * (f2+f0) - f1; break;
case 3: c=.5*(f1+fm1)-f0;d=(1/6.)*(f2-f1+fm1-f0-4*c);b=f1-f0-d-c; break;
default: assert(!interp_order);
}
switch (core_flags & 3) {
case 0: if (WITH_CR32 ) STORE(coef , float ); break;
case 1: if (WITH_CR64 ) STORE(coef , double); break;
case 2: if (WITH_CR32S) STORE(coef4, float ); break;
default:if (WITH_CR64S) STORE(coef4, double); break;
}
f2 = f1, f1 = f0;
}
return result;
}
#undef STORE
#undef coef_coef
#define IS_FLOAT32 (WITH_CR32 || WITH_CR32S) && \
(!(WITH_CR64 || WITH_CR64S) || sizeof_real == sizeof(float))
#define WITH_FLOAT64 WITH_CR64 || WITH_CR64S
static void dft_stage_fn(stage_t * p, fifo_t * output_fifo)
{
real * output, * dft_out;
int i, j, num_in = max(0, fifo_occupancy(&p->fifo));
rate_shared_t const * s = p->shared;
dft_filter_t const * f = &s->dft_filter[p->dft_filter_num];
int const overlap = f->num_taps - 1;
if (p->at.integer + p->L * num_in >= f->dft_length) {
rdft_cb_table const * const RDFT_CB = p->rdft_cb;
size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(p->core_flags);
div_t divd = div(f->dft_length - overlap - p->at.integer + p->L - 1, p->L);
real const * input = fifo_read_ptr(&p->fifo);
fifo_read(&p->fifo, divd.quot, NULL);
num_in -= divd.quot;
output = fifo_reserve(output_fifo, f->dft_length);
dft_out = (p->core_flags & CORE_SIMD_DFT)? p->dft_out : output;
if (lsx_is_power_of_2(p->L)) { /* F-domain */
int portion = f->dft_length / p->L;
memcpy(dft_out, input, (unsigned)portion * sizeof_real);
rdft_oforward(portion, f->dft_forward_setup, dft_out, p->dft_scratch);
if (IS_FLOAT32) {
#define dft_out ((float *)dft_out)
for (i = portion + 2; i < (portion << 1); i += 2) /* Mirror image. */
dft_out[i] = dft_out[(portion << 1) - i],
dft_out[i+1] = -dft_out[(portion << 1) - i + 1];
dft_out[portion] = dft_out[1];
dft_out[portion + 1] = 0;
dft_out[1] = dft_out[0];
#undef dft_out
}
else if (WITH_FLOAT64) {
#define dft_out ((double *)dft_out)
for (i = portion + 2; i < (portion << 1); i += 2) /* Mirror image. */
dft_out[i] = dft_out[(portion << 1) - i],
dft_out[i+1] = -dft_out[(portion << 1) - i + 1];
dft_out[portion] = dft_out[1];
dft_out[portion + 1] = 0;
dft_out[1] = dft_out[0];
#undef dft_out
}
for (portion <<= 1; i < f->dft_length; i += portion, portion <<= 1) {
memcpy((char *)dft_out + (size_t)i * sizeof_real, dft_out, (size_t)portion * sizeof_real);
if (IS_FLOAT32)
#define dft_out ((float *)dft_out)
dft_out[i + 1] = 0;
#undef dft_out
else if (WITH_FLOAT64)
#define dft_out ((double *)dft_out)
dft_out[i + 1] = 0;
#undef dft_out
}
if (p->step.integer > 0) {
rdft_reorder_back(f->dft_length, f->dft_backward_setup, dft_out, p->dft_scratch);
}
} else {
if (p->L == 1)
memcpy(dft_out, input, (size_t)f->dft_length * sizeof_real);
else {
memset(dft_out, 0, (size_t)f->dft_length * sizeof_real);
if (IS_FLOAT32)
for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L)
((float *)dft_out)[i] = ((float *)input)[j];
else if (WITH_FLOAT64)
for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L)
((double *)dft_out)[i] = ((double *)input)[j];
p->at.integer = p->L - 1 - divd.rem;
}
if (p->step.integer > 0)
rdft_forward(f->dft_length, f->dft_forward_setup, dft_out, p->dft_scratch);
else
rdft_oforward(f->dft_length, f->dft_forward_setup, dft_out, p->dft_scratch);
}
if (p->step.integer > 0) {
rdft_convolve(f->dft_length, f->dft_backward_setup, dft_out, f->coefs);
rdft_backward(f->dft_length, f->dft_backward_setup, dft_out, p->dft_scratch);
if ((p->core_flags & CORE_SIMD_DFT) && p->step.integer == 1)
memcpy(output, dft_out, (size_t)f->dft_length * sizeof_real);
if (p->step.integer != 1) {
if (IS_FLOAT32)
for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j,
i += p->step.integer)
((float *)output)[j] = ((float *)dft_out)[i];
else if (WITH_FLOAT64)
for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j,
i += p->step.integer)
((double *)output)[j] = ((double *)dft_out)[i];
p->remM = i - (f->dft_length - overlap);
fifo_trim_by(output_fifo, f->dft_length - j);
}
else fifo_trim_by(output_fifo, overlap);
}
else { /* F-domain */
int m = -p->step.integer;
rdft_convolve_portion(f->dft_length >> m, dft_out, f->coefs);
rdft_obackward(f->dft_length >> m, f->dft_backward_setup, dft_out, p->dft_scratch);
if (p->core_flags & CORE_SIMD_DFT)
memcpy(output, dft_out, (size_t)(f->dft_length >> m) * sizeof_real);
fifo_trim_by(output_fifo, (((1 << m) - 1) * f->dft_length + overlap) >>m);
}
(rdft_cb_table const *)RDFT_CB;
}
p->input_size = (f->dft_length - p->at.integer + p->L - 1) / p->L;
}
/* Set to 4 x nearest power of 2 or half of that */
/* if danger of causing too many cache misses. */
static int set_dft_length(int num_taps, int min, int large)
{
double d = log((double)num_taps) / log(2.);
return 1 << range_limit((int)(d + 2.77), min, max((int)(d + 1.77), large));
}
static void dft_stage_init(
unsigned instance, double Fp, double Fs, double Fn, double att,
double phase_response, stage_t * p, int L, int M, double * multiplier,
unsigned min_dft_size, unsigned large_dft_size, core_flags_t core_flags,
rdft_cb_table const * rdft_table)
{
rdft_cb_table const * const RDFT_CB = rdft_table;
dft_filter_t * f = &p->shared->dft_filter[instance];
int num_taps = 0, dft_length = f->dft_length, i, offset;
bool f_domain_m = abs(3-M) == 1 && Fs <= 1;
size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(core_flags);
if (!dft_length) {
int k = phase_response == 50 && lsx_is_power_of_2(L) && Fn == L? L << 1 : 4;
double m, * h = lsx_design_lpf(Fp, Fs, Fn, att, &num_taps, -k, -1.);
if (phase_response != 50)
lsx_fir_to_phase(&h, &num_taps, &f->post_peak, phase_response);
else f->post_peak = num_taps / 2;
dft_length = set_dft_length(num_taps, (int)min_dft_size, (int)large_dft_size);
f->coefs = rdft_calloc((size_t)dft_length, sizeof_real);
offset = dft_length - num_taps + 1;
m = (1. / dft_length) * rdft_multiplier() * L * *multiplier;
if (IS_FLOAT32) for (i = 0; i < num_taps; ++i)
((float *)f->coefs)[(i + offset) & (dft_length - 1)] =(float)(h[i] * m);
else if (WITH_FLOAT64) for (i = 0; i < num_taps; ++i)
((double *)f->coefs)[(i + offset) & (dft_length - 1)] = h[i] * m;
free(h);
}
if (rdft_flags() & RDFT_IS_SIMD)
p->dft_out = rdft_malloc(sizeof_real * (size_t)dft_length);
if (rdft_flags() & RDFT_NEEDS_SCRATCH)
p->dft_scratch = rdft_malloc(2 * sizeof_real * (size_t)dft_length);
if (!f->dft_length) {
void * coef_setup = rdft_forward_setup(dft_length);
int Lp = lsx_is_power_of_2(L)? L : 1;
int Mp = f_domain_m? M : 1;
f->dft_forward_setup = rdft_forward_setup(dft_length / Lp);
f->dft_backward_setup = rdft_backward_setup(dft_length / Mp);
if (Mp == 1)
rdft_forward(dft_length, coef_setup, f->coefs, p->dft_scratch);
else
rdft_oforward(dft_length, coef_setup, f->coefs, p->dft_scratch);
rdft_delete_setup(coef_setup);
f->num_taps = num_taps;
f->dft_length = dft_length;
lsx_debug("fir_len=%i dft_length=%i Fp=%g Fs=%g Fn=%g att=%g %i/%i",
num_taps, dft_length, Fp, Fs, Fn, att, L, M);
}
*multiplier = 1;
p->out_in_ratio = (double)L / M;
p->core_flags = core_flags;
p->rdft_cb = rdft_table;
p->fn = dft_stage_fn;
p->preload = f->post_peak / L;
p->at.integer = f->post_peak % L;
p->L = L;
p->step.integer = f_domain_m? -M/2 : M;
p->dft_filter_num = instance;
p->block_len = f->dft_length - (f->num_taps - 1);
p->phase0 = p->at.integer / p->L;
p->input_size = (f->dft_length - p->at.integer + p->L - 1) / p->L;
}
static struct half_fir_info const * find_half_fir(
struct half_fir_info const * firs, size_t len, double att)
{
size_t i;
for (i = 0; i + 1 < len && att > firs[i].att; ++i);
return &firs[i];
}
#define have_pre_stage (preM * preL != 1)
#define have_arb_stage (arbM * arbL != 1)
#define have_post_stage (postM * postL != 1)
#include "soxr.h"
STATIC char const * _soxr_init(
rate_t * const p, /* Per audio channel. */
rate_shared_t * const shared, /* By channels undergoing same rate change. */
double const io_ratio, /* Input rate divided by output rate. */
soxr_quality_spec_t const * const q_spec,
soxr_runtime_spec_t const * const r_spec,
double multiplier, /* Linear gain to apply during conversion. */
cr_core_t const * const core,
core_flags_t const core_flags)
{
size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(core_flags);
double const tolerance = 1 + 1e-5;
double bits = q_spec->precision;
rolloff_t const rolloff = (rolloff_t)(q_spec->flags & 3);
int interpolator = (int)(r_spec->flags & 3) - 1;
double const Fp0 = q_spec->passband_end, Fs0 = q_spec->stopband_begin;
double const phase_response = q_spec->phase_response, tbw0 = Fs0-Fp0;
bool const maintain_3dB_pt = !!(q_spec->flags & SOXR_MAINTAIN_3DB_PT);
double tbw_tighten = 1, alpha;
#define tighten(x) (Fs0-(Fs0-(x))*tbw_tighten)
double arbM = io_ratio, Fn1, Fp1 = Fp0, Fs1 = Fs0, bits1 = min(bits,33);
double att = (bits1 + 1) * linear_to_dB(2.), attArb = att; /* +1: pass+stop */
int preL = 1, preM = 1, shr = 0, arbL = 1, postL = 1, postM = 1;
bool upsample=false, rational=false, iOpt=!(r_spec->flags&SOXR_NOSMALLINTOPT);
bool lq_bits= (q_spec->flags & SOXR_PROMOTE_TO_LQ)? bits <= 16 : bits == 16;
bool lq_Fp0 = (q_spec->flags & SOXR_PROMOTE_TO_LQ)? Fp0<=lq_bw0 : Fp0==lq_bw0;
int n = 0, i, mode = lq_bits && rolloff == rolloff_medium? io_ratio > 1 ||
phase_response != 50 || !lq_Fp0 || Fs0 != 1 : ((int)ceil(bits1) - 6) / 4;
struct half_fir_info const * half_fir_info;
stage_t * s;
if (io_ratio < 1 && Fs0 - 1 > 1 - Fp0 / tolerance)
return "imaging greater than rolloff";
if (.002 / tolerance > tbw0 || tbw0 > .5 * tolerance)
return "transition bandwidth not in [0.2,50] % of nyquist";
if (.5 / tolerance > Fp0 || Fs0 > 1.5 * tolerance)
return "transition band not within [50,150] % of nyquist";
if (bits!=0 && (15 > bits || bits > 33))
return "precision not in [15,33] bits";
if (io_ratio <= 0)
return "resampling factor not positive";
if (0 > phase_response || phase_response > 100)
return "phase response not in [0=min-phase,100=max-phase] %";
p->core = core;
p->io_ratio = io_ratio;
if (bits!=0) while (!n++) { /* Determine stages: */
int try, L, M, x, maxL = interpolator > 0? 1 : mode? 2048 :
(int)ceil(r_spec->coef_size_kbytes * 1000. / (U100_l * (int)sizeof_real));
double d, epsilon = 0, frac;
upsample = arbM < 1;
for (i = (int)(.5 * arbM), shr = 0; i >>= 1; arbM *= .5, ++shr);
preM = upsample || (arbM > 1.5 && arbM < 2);
postM = 1 + (arbM > 1 && preM), arbM /= postM;
preL = 1 + (!preM && arbM < 2) + (upsample && mode), arbM *= preL;
if ((frac = arbM - (int)arbM)!=0)
epsilon = fabs(floor(frac * MULT32 + .5) / (frac * MULT32) - 1);
for (i = 1, rational = frac==0; i <= maxL && !rational; ++i) {
d = frac * i, try = (int)(d + .5);
if ((rational = fabs(try / d - 1) <= epsilon)) { /* No long doubles! */
if (try == i)
arbM = ceil(arbM), shr += x = arbM > 3, arbM /= 1 + x;
else arbM = i * (int)arbM + try, arbL = i;
}
}
L = preL * arbL, M = (int)(arbM * postM), x = (L|M)&1, L >>= !x, M >>= !x;
if (iOpt && postL == 1 && (d = preL * arbL / arbM) > 4 && d != 5) {
for (postL = 4, i = (int)(d / 16); (i >>= 1) && postL < 256; postL <<= 1);
arbM = arbM * postL / arbL / preL, arbL = 1, n = 0;
} else if (rational && (max(L, M) < 3 + 2 * iOpt || L * M < 6 * iOpt))
preL = L, preM = M, arbM = arbL = postM = 1;
if (!mode && (!rational || !n))
++mode, n = 0;
}
p->num_stages = shr + have_pre_stage + have_arb_stage + have_post_stage;
if (!p->num_stages && multiplier != 1) {
bits = arbL = 0; /* Use cubic_stage in this case. */
++p->num_stages;
}
p->stages = calloc((size_t)p->num_stages + 1, sizeof(*p->stages));
if (!p->stages)
return "out of memory";
for (i = 0; i < p->num_stages; ++i) {
p->stages[i].num = i;
p->stages[i].shared = shared;
p->stages[i].input_size = 8192;
}
p->stages[0].is_input = true;
alpha = postM / (io_ratio * (postL << 0));
if ((n = p->num_stages) > 1) { /* Att. budget: */
if (have_arb_stage)
att += linear_to_dB(2.), attArb = att, --n;
att += linear_to_dB((double)n);
}
half_fir_info = find_half_fir(core->half_firs, core->half_firs_len, att);
for (i = 0, s = p->stages; i < shr; ++i, ++s) {
s->fn = half_fir_info->fn;
s->coefs = half_fir_info->coefs;
s->n = half_fir_info->num_coefs;
s->pre_post = 4 * s->n;
s->preload = s->pre = s->pre_post >> 1;
}
if (have_pre_stage) {
if (maintain_3dB_pt && have_post_stage) { /* Trans. bands overlapping. */
double x = tbw0 * lsx_inv_f_resp(-3., att);
x = -lsx_f_resp(x / (max(2 * alpha - Fs0, alpha) - Fp0), att);
if (x > .035) {
tbw_tighten = ((4.3074e-3 - 3.9121e-4 * x) * x - .040009) * x + 1.0014;
lsx_debug("tbw_tighten=%g (%gdB)", tbw_tighten, x);
}
}
Fn1 = preM? max(preL, preM) : arbM / arbL;
dft_stage_init(0, tighten(Fp1), Fs1, Fn1, att, phase_response, s++, preL,
max(preM, 1), &multiplier, r_spec->log2_min_dft_size,
r_spec->log2_large_dft_size, core_flags, core->rdft_cb);
Fp1 /= Fn1, Fs1 /= Fn1;
}
if (bits==0 && have_arb_stage) { /* `Quick' cubic arb stage: */
s->fn = core->cubic_stage_fn;
s->mult = multiplier, multiplier = 1;
s->step.whole = (int64_t)(arbM * MULT32 + .5);
s->pre_post = max(3, s->step.integer);
s->preload = s->pre = 1;
s->out_in_ratio = MULT32 / (double)s->step.whole;
}
else if (have_arb_stage) { /* Higher quality arb stage: */
static const float rolloffs[] = {-.01f, -.3f, 0, -.103f};
poly_fir_t const * f = &core->poly_firs[6*(upsample+!!preM)+mode-!upsample];
int order, num_coefs = (int)f->interp[0].scalar, phase_bits, phases;
size_t coefs_size;
double at, Fp = Fp1, Fs, Fn, mult = upsample? 1 : arbM / arbL;
poly_fir1_t const * f1;
if (!upsample && preM)
Fn = 2 * mult, Fs = 3 + fabs(Fs1 - 1);
else Fn = 1, Fs = 2 - (mode? Fp1 + (Fs1 - Fp1) * .7 : Fs1);
if (mode)
Fp = Fs - (Fs - Fp) / (1 - lsx_inv_f_resp(rolloffs[rolloff], attArb));
i = (interpolator < 0? !rational : max(interpolator, !rational)) - 1;
do {
f1 = &f->interp[++i];
assert(f1->fn);
if (i)
arbM /= arbL, arbL = 1, rational = false;
phase_bits = (int)ceil(f1->scalar - log(mult)/log(2.));
phases = !rational? (1 << phase_bits) : arbL;
if (f->interp[0].scalar==0) {
int phases0 = max(phases, 19), n0 = 0;
lsx_design_lpf(Fp, Fs, -Fn, attArb, &n0, phases0, f->beta);
num_coefs = n0 / phases0 + 1, num_coefs += num_coefs & !preM;
}
if ((num_coefs & 1) && rational && (arbL & 1))
phases <<= 1, arbL <<= 1, arbM *= 2;
at = arbL * (s->phase0 = .5 * (num_coefs & 1));
order = i + (i && mode > 4);
coefs_size = (size_t)(num_coefs4 * phases * (order+1)) * sizeof_real;
} while (interpolator < 0 && i < 2 && f->interp[i+1].fn &&
coefs_size / 1000 > r_spec->coef_size_kbytes);
if (!s->shared->poly_fir_coefs) {
int num_taps = num_coefs * phases - 1;
double * coefs = lsx_design_lpf(
Fp, Fs, Fn, attArb, &num_taps, phases, f->beta);
s->shared->poly_fir_coefs = prepare_poly_fir_coefs(
coefs, num_coefs, phases, order, multiplier, core_flags, &core->mem);
lsx_debug("fir_len=%i phases=%i coef_interp=%i size=%.3gk",
num_coefs, phases, order, (double)coefs_size / 1000.);
free(coefs);
}
multiplier = 1;
s->fn = f1->fn;
s->pre_post = num_coefs4 - 1;
s->preload = ((num_coefs - 1) >> 1) + (num_coefs4 - num_coefs);
s->n = num_coefs4;
s->phase_bits = phase_bits;
s->L = arbL;
s->use_hi_prec_clock =
mode>1 && (q_spec->flags & SOXR_HI_PREC_CLOCK) && !rational;
#if WITH_FLOAT_STD_PREC_CLOCK
if (order && !s->use_hi_prec_clock) {
s->at.flt = at;
s->step.flt = arbM;
s->out_in_ratio = (double)(arbL / s->step.flt);
} else
#endif
{
s->at.whole = (int64_t)(at * MULT32 + .5);
#if WITH_HI_PREC_CLOCK
if (s->use_hi_prec_clock) {
double M = arbM * MULT32;
s->at.fix.ls.parts.ms = 0x80000000ul;
s->step.whole = (int64_t)M;
M -= (double)s->step.whole;
M *= MULT32 * MULT32;
s->step.fix.ls.all = (uint64_t)M;
} else
#endif
s->step.whole = (int64_t)(arbM * MULT32 + .5);
s->out_in_ratio = MULT32 * arbL / (double)s->step.whole;
}
++s;
}
if (have_post_stage)
dft_stage_init(1, tighten(Fp0 / (upsample? alpha : 1)), upsample? max(2 -
Fs0 / alpha, 1) : Fs0, (double)max(postL, postM), att, phase_response,
s++, postL, postM, &multiplier, r_spec->log2_min_dft_size,
r_spec->log2_large_dft_size, core_flags, core->rdft_cb);
lsx_debug("%g: >>%i %i/%i %i/%g %i/%i (%x)", 1/io_ratio,
shr, preL, preM, arbL, arbM, postL, postM, core_flags);
for (i = 0, s = p->stages; i < p->num_stages; ++i, ++s) {
fifo_create(&s->fifo, (int)sizeof_real);
memset(fifo_reserve(&s->fifo, s->preload), 0,
sizeof_real * (size_t)s->preload);
lsx_debug_more("%5i|%-5i preload=%i remL=%i",
s->pre, s->pre_post-s->pre, s->preload, s->at.integer);
}
fifo_create(&s->fifo, (int)sizeof_real);
return 0;
}
static bool stage_process(stage_t * stage, bool flushing)
{
fifo_t * fifo = &stage->fifo;
bool done = false;
int want;
while (!done && (want = stage->input_size - fifo_occupancy(fifo)) > 0) {
if (stage->is_input) {
if (flushing)
memset(fifo_reserve(fifo, want), 0, fifo->item_size * (size_t)want);
else done = true;
}
else done = stage_process(stage - 1, flushing);
}
stage->fn(stage, &stage[1].fifo);
return done && fifo_occupancy(fifo) < stage->input_size;
}
STATIC void _soxr_process(void * P, size_t olen)
{
rate_t *p = P;
int const n = p->flushing? min(-(int)p->samples_out, (int)olen) : (int)olen;
stage_t * stage = &p->stages[p->num_stages];
fifo_t * fifo = &stage->fifo;
bool done = false;
while (!done && fifo_occupancy(fifo) < (int)n)
done = stage->is_input || stage_process(stage - 1, p->flushing);
}
STATIC void * _soxr_input(void * P, void * samples, size_t n)
{
rate_t *p = P;
if (p->flushing)
return 0;
p->samples_in += (int64_t)n;
return fifo_write(&p->stages[0].fifo, (int)n, samples);
}
STATIC void const * _soxr_output(void * P, void * samples, size_t * n0)
{
rate_t *p = P;
fifo_t * fifo = &p->stages[p->num_stages].fifo;
int n = p->flushing? min(-(int)p->samples_out, (int)*n0) : (int)*n0;
p->samples_out += n = min(n, fifo_occupancy(fifo));
return fifo_read(fifo, (int)(*n0 = (size_t)n), samples);
}
STATIC void _soxr_flush(void * P)
{
rate_t *p = P;
if (p->flushing) return;
p->samples_out -= (int64_t)((double)p->samples_in / p->io_ratio + .5);
p->samples_in = 0;
p->flushing = true;
}
STATIC void _soxr_close(void * P)
{
rate_t *p = P;
if (p->stages) {
rdft_cb_table const * const RDFT_CB = p->core->rdft_cb;
rate_shared_t * shared = p->stages[0].shared;
int i;
for (i = 0; i <= p->num_stages; ++i) {
stage_t * s = &p->stages[i];
rdft_free(s->dft_scratch);
rdft_free(s->dft_out);
fifo_delete(&s->fifo);
}
if (shared) {
for (i = 0; i < 2; ++i) {
dft_filter_t * f= &shared->dft_filter[i];
rdft_free(f->coefs);
rdft_delete_setup(f->dft_forward_setup);
rdft_delete_setup(f->dft_backward_setup);
}
p->core->mem.free(shared->poly_fir_coefs);
memset(shared, 0, sizeof(*shared));
}
free(p->stages);
(rdft_cb_table const *)RDFT_CB;
}
}
#if defined SOXR_LIB
STATIC double _soxr_delay(void * P)
{
rate_t *p = P;
return (double)p->samples_in / p->io_ratio - (double)p->samples_out;
}
STATIC void _soxr_sizes(size_t * shared, size_t * channel)
{
*shared = sizeof(rate_shared_t);
*channel = sizeof(rate_t);
}
#endif

178
soxr/src/cr.h Normal file
View File

@ -0,0 +1,178 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxr_cr_included
#define soxr_cr_included
#define FIFO_SIZE_T int
#include "fifo.h"
typedef void real; /* float or double */
struct stage;
typedef void (* stage_fn_t)(struct stage * input, fifo_t * output);
typedef struct half_fir_info {
int num_coefs;
real const * coefs;
stage_fn_t fn, dfn;
float att;
} half_fir_info_t;
typedef struct {float scalar; stage_fn_t fn;} poly_fir1_t;
typedef struct {float beta; poly_fir1_t interp[3];} poly_fir_t;
#define U100_l 42
#define MULT32 (65536. * 65536.)
/* Conceptually: coef_p is &coefs[num_phases][fir_len][interp_order+1]: */
#define coef(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) (coef_p)[\
(fir_len) * ((interp_order) + 1) * (phase_num) + \
((interp_order) + 1) * (fir_coef_num) + \
((interp_order) - (coef_interp_num))]
/* Conceptually: coef_p is &coefs[num_phases][fir_len/4][interp_order+1][4]: */
#define coef4(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) (coef_p)[\
(fir_len) * ((interp_order) + 1) * (phase_num) + \
((interp_order) + 1) * ((fir_coef_num) & ~3) + \
4 * ((interp_order) - (coef_interp_num)) + \
((fir_coef_num) & 3)]
typedef union { /* Int64 in parts */
#if HAVE_BIGENDIAN
struct {int32_t ms; uint32_t ls;} parts;
#else
struct {uint32_t ls; int32_t ms;} parts;
#endif
int64_t all;
} int64p_t;
typedef union { /* Uint64 in parts */
#if HAVE_BIGENDIAN
struct {uint32_t ms, ls;} parts;
#else
struct {uint32_t ls, ms;} parts;
#endif
uint64_t all;
} uint64p_t;
typedef struct {
int dft_length, num_taps, post_peak;
void * dft_forward_setup, * dft_backward_setup;
real * coefs;
} dft_filter_t;
typedef struct { /* So generated filter coefs may be shared between channels */
real * poly_fir_coefs;
dft_filter_t dft_filter[2];
} rate_shared_t;
typedef double float_step_t; /* Or long double or __float128. */
typedef union { /* Fixed point arithmetic */
struct {uint64p_t ls; int64p_t ms;} fix; /* Hi-prec has ~96 bits. */
float_step_t flt;
} step_t;
#define integer fix.ms.parts.ms
#define fraction fix.ms.parts.ls
#define whole fix.ms.all
#define CORE_DBL 1
#define CORE_SIMD_POLY 2
#define CORE_SIMD_HALF 4
#define CORE_SIMD_DFT 8
#define LOG2_SIZEOF_REAL(core_flags) (2 + ((core_flags) & 1))
typedef int core_flags_t;
#if defined SOXR_LIB
#include "rdft_t.h"
#else
typedef void fn_t;
#endif
typedef struct stage {
int num;
/* Common to all stage types: */
core_flags_t core_flags;
stage_fn_t fn;
fifo_t fifo;
int pre; /* Number of past samples to store */
int pre_post; /* pre + number of future samples to store */
int preload; /* Number of zero samples to pre-load the fifo */
double out_in_ratio; /* For buffer management. */
int input_size;
bool is_input;
/* For a stage with variable (run-time generated) filter coefs: */
rdft_cb_table const * rdft_cb;
rate_shared_t * shared;
unsigned dft_filter_num; /* Which, if any, of the 2 DFT filters to use */
real * dft_scratch;
float * dft_out;
real const * coefs;
/* For a stage with variable L/M: */
step_t at, step;
bool use_hi_prec_clock;
int L, remM;
int n, phase_bits, block_len;
double mult, phase0;
} stage_t;
#define stage_occupancy(s) max(0, fifo_occupancy(&(s)->fifo) - (s)->pre_post)
#define stage_read_p(s) ((sample_t *)fifo_read_ptr(&(s)->fifo) + (s)->pre)
#define lq_bw0 (1385/2048.) /* ~.67625, FP exact. */
typedef enum {rolloff_small, rolloff_medium, rolloff_none} rolloff_t;
typedef struct {
void * (* alloc)(size_t);
void * (* calloc)(size_t, size_t);
void (* free)(void *);
} alloc_t;
typedef struct {
alloc_t mem;
half_fir_info_t const * half_firs;
size_t half_firs_len;
half_fir_info_t const * doub_firs;
size_t doub_firs_len;
stage_fn_t cubic_stage_fn;
poly_fir_t const * poly_firs;
rdft_cb_table * rdft_cb;
} cr_core_t;
typedef struct rate rate_t;
struct rate {
cr_core_t const * core;
double io_ratio;
int64_t samples_in, samples_out;
int num_stages, flushing;
stage_t * stages;
};
#if defined SOXR_LIB
#include "soxr.h"
char const * _soxr_init(
rate_t * const p, /* Per audio channel. */
rate_shared_t * const shared, /* Between channels (undergoing same rate change)*/
double const io_ratio, /* Input rate divided by output rate. */
soxr_quality_spec_t const * const q_spec,
soxr_runtime_spec_t const * const r_spec,
double multiplier, /* Linear gain to apply during conversion. 1 */
cr_core_t const * const core,
core_flags_t const);
void _soxr_process(void * p, size_t olen);
void * _soxr_input(void * p, void * samples, size_t n);
void const * _soxr_output(void * p, void * samples, size_t * n0);
void _soxr_flush(void * p);
void _soxr_close(void * p);
double _soxr_delay(void * p);
void _soxr_sizes(size_t * shared, size_t * channel);
#endif
#endif

8
soxr/src/cr32.c Normal file
View File

@ -0,0 +1,8 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define RATE_CB _soxr_rate32_cb
#define CORE_STR "cr32"
#define CORE_TYPE 0
#include "cr-core.c"

8
soxr/src/cr32s.c Normal file
View File

@ -0,0 +1,8 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define RATE_CB _soxr_rate32s_cb
#define CORE_STR "cr32s"
#define CORE_TYPE (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
#include "cr-core.c"

8
soxr/src/cr64.c Normal file
View File

@ -0,0 +1,8 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define RATE_CB _soxr_rate64_cb
#define CORE_STR "cr64"
#define CORE_TYPE CORE_DBL
#include "cr-core.c"

8
soxr/src/cr64s.c Normal file
View File

@ -0,0 +1,8 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define RATE_CB _soxr_rate64s_cb
#define CORE_STR "cr64s"
#define CORE_TYPE (CORE_DBL|CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
#include "cr-core.c"

View File

@ -1,4 +1,4 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include <limits.h> #include <limits.h>
@ -14,8 +14,8 @@
unsigned i; \ unsigned i; \
size_t j; \ size_t j; \
T const * src = *src0; \ T const * src = *src0; \
if (ch > 1) \ if (ch > 1) for (j = 0; j < n; ++j) \
for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = (DEINTERLEAVE_TO)*src++; \ for (i = 0; i < ch; ++i) dest[i][j] = (DEINTERLEAVE_TO)*src++; \
else if (flag) memcpy(dest[0], src, n * sizeof(T)), src = &src[n]; \ else if (flag) memcpy(dest[0], src, n * sizeof(T)), src = &src[n]; \
else for (j = 0; j < n; dest[0][j++] = (DEINTERLEAVE_TO)*src++); \ else for (j = 0; j < n; dest[0][j++] = (DEINTERLEAVE_TO)*src++); \
*src0 = src; \ *src0 = src; \
@ -23,7 +23,7 @@
#if HAVE_DOUBLE_PRECISION #if WITH_CR64 || WITH_CR64S
void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */ void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */
soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch)
{ {
@ -40,7 +40,7 @@ void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */
#if HAVE_SINGLE_PRECISION #if WITH_CR32 || WITH_CR32S || WITH_VR32
void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch)
{ {
@ -60,35 +60,6 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#include "rint.h" #include "rint.h"
#if HAVE_FENV_H
#include <fenv.h>
#define fe_test_invalid() fetestexcept(FE_INVALID)
#define fe_clear_invalid() feclearexcept(FE_INVALID)
#elif defined _MSC_VER
#define FE_INVALID 1
#if defined _WIN64
#include <float.h>
#define fe_test_invalid() (_statusfp() & _SW_INVALID)
#define fe_clear_invalid _clearfp /* FIXME clears all */
#else
static __inline int fe_test_invalid()
{
short status_word;
__asm fnstsw status_word
return status_word & FE_INVALID;
}
static __inline int fe_clear_invalid()
{
int16_t status[14];
__asm fnstenv status
status[2] &= ~FE_INVALID;
__asm fldenv status
return 0;
}
#endif
#endif
#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ #if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__
@ -97,13 +68,13 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#endif #endif
#endif #endif
#if HAVE_DOUBLE_PRECISION #if WITH_CR64 || WITH_CR64S
#define FLOATX double #define FLOATX double
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2 #define LSX_RINT_CLIP_2 lsx_rint32_clip_2
#define LSX_RINT_CLIP lsx_rint32_clip #define LSX_RINT_CLIP lsx_rint32_clip
#define RINT_CLIP rint32_clip #define RINT_CLIP rint32_clip
#define RINT rint32 #define RINT rint32D
#if defined FPU_RINT32 #if defined FPU_RINT32
#define FPU_RINT #define FPU_RINT
#endif #endif
@ -114,7 +85,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2 #define LSX_RINT_CLIP_2 lsx_rint16_clip_2
#define LSX_RINT_CLIP lsx_rint16_clip #define LSX_RINT_CLIP lsx_rint16_clip
#define RINT_CLIP rint16_clip #define RINT_CLIP rint16_clip
#define RINT rint16 #define RINT rint16D
#if defined FPU_RINT16 #if defined FPU_RINT16
#define FPU_RINT #define FPU_RINT
#endif #endif
@ -125,7 +96,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither #define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither
#define LSX_RINT_CLIP lsx_rint16_clip_dither #define LSX_RINT_CLIP lsx_rint16_clip_dither
#define RINT_CLIP rint16_clip_dither #define RINT_CLIP rint16_clip_dither
#define RINT rint16 #define RINT rint16D
#if defined FPU_RINT16 #if defined FPU_RINT16
#define FPU_RINT #define FPU_RINT
#endif #endif
@ -139,13 +110,13 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#if HAVE_SINGLE_PRECISION #if WITH_CR32 || WITH_CR32S || WITH_VR32
#define FLOATX float #define FLOATX float
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2_f #define LSX_RINT_CLIP_2 lsx_rint32_clip_2_f
#define LSX_RINT_CLIP lsx_rint32_clip_f #define LSX_RINT_CLIP lsx_rint32_clip_f
#define RINT_CLIP rint32_clip_f #define RINT_CLIP rint32_clip_f
#define RINT rint32 #define RINT rint32F
#if defined FPU_RINT32 #if defined FPU_RINT32
#define FPU_RINT #define FPU_RINT
#endif #endif
@ -156,7 +127,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_f #define LSX_RINT_CLIP_2 lsx_rint16_clip_2_f
#define LSX_RINT_CLIP lsx_rint16_clip_f #define LSX_RINT_CLIP lsx_rint16_clip_f
#define RINT_CLIP rint16_clip_f #define RINT_CLIP rint16_clip_f
#define RINT rint16 #define RINT rint16F
#if defined FPU_RINT16 #if defined FPU_RINT16
#define FPU_RINT #define FPU_RINT
#endif #endif
@ -167,7 +138,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither_f #define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither_f
#define LSX_RINT_CLIP lsx_rint16_clip_dither_f #define LSX_RINT_CLIP lsx_rint16_clip_dither_f
#define RINT_CLIP rint16_clip_dither_f #define RINT_CLIP rint16_clip_dither_f
#define RINT rint16 #define RINT rint16D
#if defined FPU_RINT16 #if defined FPU_RINT16
#define FPU_RINT #define FPU_RINT
#endif #endif
@ -199,7 +170,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
return 0; \ return 0; \
} while (0) } while (0)
#if HAVE_DOUBLE_PRECISION #if WITH_CR64 || WITH_CR64S
size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0, size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0,
double const * const * src, size_t n, unsigned ch, unsigned long * seed) double const * const * src, size_t n, unsigned ch, unsigned long * seed)
{ {
@ -225,7 +196,7 @@ size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0,
} }
#endif #endif
#if HAVE_SINGLE_PRECISION #if WITH_CR32 || WITH_CR32S || WITH_VR32
size_t /* clips */ _soxr_interleave_f(soxr_datatype_t data_type, void * * dest0, size_t /* clips */ _soxr_interleave_f(soxr_datatype_t data_type, void * * dest0,
float const * const * src, size_t n, unsigned ch, unsigned long * seed) float const * const * src, size_t n, unsigned ch, unsigned long * seed)
{ {

54
soxr/src/dev32s.h Normal file
View File

@ -0,0 +1,54 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxr_dev32s_included
#define soxr_dev32s_included
#if defined __GNUC__
#define SIMD_INLINE(T) static __inline T __attribute__((always_inline))
#define vAlign __attribute__((aligned (16)))
#elif defined _MSC_VER
#define SIMD_INLINE(T) static __forceinline T
#define vAlign __declspec(align(16))
#endif
#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86
#include <xmmintrin.h>
#define vZero() _mm_setzero_ps()
#define vSet1(a) _mm_set_ss(a)
#define vMul(a,b) _mm_mul_ps(a,b)
#define vAdd(a,b) _mm_add_ps(a,b)
#define vMac(a,b,c) vAdd(vMul(a,b),c)
#define vLds(a) _mm_set1_ps(a)
#define vLd(a) _mm_load_ps(a)
#define vLdu(a) _mm_loadu_ps(a)
typedef __m128 v4_t;
SIMD_INLINE(void) vStorSum(float * a, v4_t b) {
v4_t t = vAdd(_mm_movehl_ps(b, b), b);
_mm_store_ss(a, vAdd(t, _mm_shuffle_ps(t,t,1)));}
#elif defined __arm__
#include <arm_neon.h>
#define vZero() vdupq_n_f32(0)
#define vMul(a,b) vmulq_f32(a,b)
#define vAdd(a,b) vaddq_f32(a,b)
#define vMac(a,b,c) vmlaq_f32(c,a,b)
#define vLds(a) vld1q_dup_f32(&(a))
#define vLd(a) vld1q_f32(a)
#define vLdu(a) vld1q_f32(a)
typedef float32x4_t v4_t;
SIMD_INLINE(void) vStorSum(float * a, v4_t b) {
float32x2_t t = vadd_f32(vget_high_f32(b), vget_low_f32(b));
*a = vget_lane_f32(vpadd_f32(t, t), 0);}
#endif
#endif

42
soxr/src/dev64s.h Normal file
View File

@ -0,0 +1,42 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxr_dev64s_included
#define soxr_dev64s_included
#if defined __GNUC__
#define SIMD_INLINE(T) static __inline T __attribute__((always_inline))
#define vAlign __attribute__((aligned (32)))
#elif defined _MSC_VER
#define SIMD_INLINE(T) static __forceinline T
#define vAlign __declspec(align(32))
#else
#define SIMD_INLINE(T) static __inline T
#endif
#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86
#include <immintrin.h>
#if defined __AVX__
#define vZero() _mm256_setzero_pd()
#define vSet1(a) _mm256_set_pd(0,0,0,a)
#define vMul(a,b) _mm256_mul_pd(a,b)
#define vAdd(a,b) _mm256_add_pd(a,b)
#define vMac(a,b,c) vAdd(vMul(a,b),c) /* Note: gcc -mfma will `fuse' these */
#define vLds(a) _mm256_set1_pd(a)
#define vLd(a) _mm256_load_pd(a)
#define vLdu(a) _mm256_loadu_pd(a)
typedef __m256d v4_t;
SIMD_INLINE(void) vStorSum(double * a, v4_t b) {
b = _mm256_hadd_pd(b, _mm256_permute2f128_pd(b,b,1));
_mm_store_sd(a, _mm256_castpd256_pd128(_mm256_hadd_pd(b,b)));}
#endif
#endif
#endif

View File

@ -282,22 +282,16 @@ Appendix :
*/ */
#include <math.h> #include "math-wrap.h"
#include "fft4g.h" #include "fft4g.h"
#ifdef FFT4G_FLOAT #ifdef FFT4G_FLOAT
#define double float #define double float
#define one_half 0.5f #define one_half 0.5f
#if defined _MSC_VER #define sin(x) sinf(x)
#define sin (float)sin #define cos(x) cosf(x)
#define cos (float)cos #define atan(x) atanf(x)
#define atan (float)atan
#else
#define sin sinf
#define cos cosf
#define atan atanf
#endif
#define cdft lsx_cdft_f #define cdft lsx_cdft_f
#define rdft lsx_rdft_f #define rdft lsx_rdft_f
@ -818,7 +812,7 @@ static void bitrv2(int n, int *ip0, double *a)
static void bitrv2conj(int n, int *ip0, double *a) static void bitrv2conj(int n, int *ip0, double *a)
{ {
int j, j1, k, k1, l, m, m2, ip[256]; int j, j1, k, k1, l, m, m2, ip[512];
double xr, xi, yr, yi; double xr, xi, yr, yi;
(void)ip0; (void)ip0;

View File

@ -1,27 +1,38 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include <stdlib.h>
#include "filter.h" #include "filter.h"
#define FFT4G_FLOAT #define FFT4G_FLOAT
#include "fft4g.c" #include "fft4g.c"
#include "soxr-config.h"
static void * null(void) {return 0;} #if WITH_CR32
static void forward (int length, void * setup, double * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;} #include "rdft_t.h"
static void backward(int length, void * setup, double * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;} static void * null(int u1) {(void)u1; return 0;}
static void forward (int length, void * setup, void * H, void * scratch) {lsx_safe_rdft_f(length, 1, H); (void)setup; (void)scratch;}
static void backward(int length, void * setup, void * H, void * scratch) {lsx_safe_rdft_f(length, -1, H); (void)setup; (void)scratch;}
static int multiplier(void) {return 2;} static int multiplier(void) {return 2;}
static void nothing(void) {} static void nothing(void *u1) {(void)u1;}
static void nothing2(int u1, void *u2, void *u3, void *u4) {(void)u1; (void)u2; (void)u3; (void)u4;}
static int flags(void) {return 0;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft32_cb = {
fn_t _soxr_rdft32_cb[] = { null,
(fn_t)null, null,
(fn_t)null, nothing,
(fn_t)nothing, forward,
(fn_t)forward, forward,
(fn_t)forward, backward,
(fn_t)backward, backward,
(fn_t)backward, _soxr_ordered_convolve_f,
(fn_t)_soxr_ordered_convolve_f, _soxr_ordered_partial_convolve_f,
(fn_t)_soxr_ordered_partial_convolve_f, multiplier,
(fn_t)multiplier, nothing2,
(fn_t)nothing, malloc,
calloc,
free,
flags,
}; };
#endif

View File

@ -2,25 +2,30 @@
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include "filter.h" #include "filter.h"
#include "simd.h" #include "util32s.h"
#include "rdft_t.h"
static void * null(void) {return 0;} static void * null(void) {return 0;}
static void nothing(void) {} static void nothing(void) {}
static void forward (int length, void * setup, float * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;} static void forward (int length, void * setup, float * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;}
static void backward(int length, void * setup, float * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;} static void backward(int length, void * setup, float * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;}
static int multiplier(void) {return 2;} static int multiplier(void) {return 2;}
static int flags(void) {return RDFT_IS_SIMD;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft32s_cb = {
fn_t _soxr_rdft32s_cb[] = { null,
(fn_t)null, null,
(fn_t)null, nothing,
(fn_t)nothing, forward,
(fn_t)forward, forward,
(fn_t)forward, backward,
(fn_t)backward, backward,
(fn_t)backward, ORDERED_CONVOLVE_SIMD,
(fn_t)_soxr_ordered_convolve_simd, ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)_soxr_ordered_partial_convolve_simd, multiplier,
(fn_t)multiplier, nothing,
(fn_t)nothing, SIMD_ALIGNED_MALLOC,
SIMD_ALIGNED_CALLOC,
SIMD_ALIGNED_FREE,
flags,
}; };

View File

@ -1,29 +1,36 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include <stdlib.h>
#include "filter.h" #include "filter.h"
#include "fft4g.c" #include "fft4g.c"
#include "soxr-config.h" #include "soxr-config.h"
#if HAVE_DOUBLE_PRECISION #if WITH_CR64
static void * null(void) {return 0;} #include "rdft_t.h"
static void nothing(void) {} static void * null(int u1) {(void)u1; return 0;}
static void forward (int length, void * setup, double * H) {lsx_safe_rdft(length, 1, H); (void)setup;} static void nothing(void *u1) {(void)u1;}
static void backward(int length, void * setup, double * H) {lsx_safe_rdft(length, -1, H); (void)setup;} static void nothing2(int u1, void *u2, void *u3, void *u4) {(void)u1; (void)u2; (void)u3; (void)u4;}
static void forward (int length, void * setup, void * H, void * scratch) {lsx_safe_rdft(length, 1, H); (void)setup; (void)scratch;}
static void backward(int length, void * setup, void * H, void * scratch) {lsx_safe_rdft(length, -1, H); (void)setup; (void)scratch;}
static int multiplier(void) {return 2;} static int multiplier(void) {return 2;}
static int flags(void) {return 0;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft64_cb = {
fn_t _soxr_rdft64_cb[] = { null,
(fn_t)null, null,
(fn_t)null, nothing,
(fn_t)nothing, forward,
(fn_t)forward, forward,
(fn_t)forward, backward,
(fn_t)backward, backward,
(fn_t)backward, _soxr_ordered_convolve,
(fn_t)_soxr_ordered_convolve, _soxr_ordered_partial_convolve,
(fn_t)_soxr_ordered_partial_convolve, multiplier,
(fn_t)multiplier, nothing2,
(fn_t)nothing, malloc,
calloc,
free,
flags,
}; };
#endif #endif

View File

@ -1,14 +1,15 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#ifndef fifo_included #ifndef soxr_fifo_included
#define fifo_included #define soxr_fifo_included
#if !defined FIFO_SIZE_T #if !defined FIFO_SIZE_T
#define FIFO_SIZE_T size_t #define FIFO_SIZE_T size_t
#endif #endif
#if !defined FIFO_REALLOC #if !defined FIFO_REALLOC
#include <stdlib.h>
#define FIFO_REALLOC(a,b,c) realloc(a,b) #define FIFO_REALLOC(a,b,c) realloc(a,b)
#undef FIFO_FREE #undef FIFO_FREE
#define FIFO_FREE free #define FIFO_FREE free

View File

@ -1,12 +1,9 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include "filter.h" #include "filter.h"
#include <math.h> #include "math-wrap.h"
#if !defined M_PI
#define M_PI 3.14159265358979323846
#endif
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -14,7 +11,7 @@
#include "fft4g.h" #include "fft4g.h"
#include "ccrw2.h" #include "ccrw2.h"
#if 1 || HAVE_DOUBLE_PRECISION /* Always need this, for lsx_fir_to_phase. */ #if 1 || WITH_CR64 || WITH_CR64S /* Always need this, for lsx_fir_to_phase. */
#define DFT_FLOAT double #define DFT_FLOAT double
#define DONE_WITH_FFT_CACHE done_with_fft_cache #define DONE_WITH_FFT_CACHE done_with_fft_cache
#define FFT_CACHE_CCRW fft_cache_ccrw #define FFT_CACHE_CCRW fft_cache_ccrw
@ -31,7 +28,7 @@
#include "fft4g_cache.h" #include "fft4g_cache.h"
#endif #endif
#if HAVE_SINGLE_PRECISION && !HAVE_AVFFT #if (WITH_CR32 && !AVCODEC_FOUND) || (WITH_CR32S && !AVCODEC_FOUND && !WITH_PFFFT)
#define DFT_FLOAT float #define DFT_FLOAT float
#define DONE_WITH_FFT_CACHE done_with_fft_cache_f #define DONE_WITH_FFT_CACHE done_with_fft_cache_f
#define FFT_CACHE_CCRW fft_cache_ccrw_f #define FFT_CACHE_CCRW fft_cache_ccrw_f
@ -48,14 +45,14 @@
#include "fft4g_cache.h" #include "fft4g_cache.h"
#endif #endif
#if HAVE_DOUBLE_PRECISION || !SOXR_LIB #if WITH_CR64 || WITH_CR64S || !SOXR_LIB
#define DFT_FLOAT double #define DFT_FLOAT double
#define ORDERED_CONVOLVE lsx_ordered_convolve #define ORDERED_CONVOLVE lsx_ordered_convolve
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve #define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve
#include "rdft.h" #include "rdft.h"
#endif #endif
#if HAVE_SINGLE_PRECISION #if WITH_CR32
#define DFT_FLOAT float #define DFT_FLOAT float
#define ORDERED_CONVOLVE lsx_ordered_convolve_f #define ORDERED_CONVOLVE lsx_ordered_convolve_f
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f #define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f
@ -96,12 +93,12 @@ double * lsx_make_lpf(
double * h = malloc((size_t)num_taps * sizeof(*h)); double * h = malloc((size_t)num_taps * sizeof(*h));
double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho); double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho);
assert(Fc >= 0 && Fc <= 1); assert(Fc >= 0 && Fc <= 1);
lsx_debug("make_lpf(n=%i Fc=%.7g β=%g ρ=%g scale=%g)", lsx_debug("make_lpf(n=%i Fc=%.7g beta=%g rho=%g scale=%g)",
num_taps, Fc, beta, rho, scale); num_taps, Fc, beta, rho, scale);
if (h) for (i = 0; i <= m / 2; ++i) { if (h) for (i = 0; i <= m / 2; ++i) {
double z = i - .5 * m, x = z * M_PI, y = z * mult1; double z = i - .5 * m, x = z * M_PI, y = z * mult1;
h[i] = x? sin(Fc * x) / x : Fc; h[i] = x!=0? sin(Fc * x) / x : Fc;
h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult; h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult;
if (m - i != i) if (m - i != i)
h[m - i] = h[i]; h[m - i] = h[i];
@ -123,12 +120,15 @@ double * lsx_design_lpf(
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */ double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */
double att, /* Stop-band attenuation in dB */ double att, /* Stop-band attenuation in dB */
int * num_taps, /* 0: value will be estimated */ int * num_taps, /* 0: value will be estimated */
int k, /* >0: number of phases; <0: num_taps 1 (mod -k) */ int k, /* >0: number of phases; <0: num_taps = 1 (mod -k) */
double beta) /* <0: value will be estimated */ double beta) /* <0: value will be estimated */
{ {
int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1); int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1);
double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75; double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75;
lsx_debug_more("./sinctest %-12.7g %-12.7g %g 0 %-5g %i %i 50 %g %g -4 >1",
Fp, Fs, Fn, att, *num_taps, k, beta, rho);
Fp /= fabs(Fn), Fs /= fabs(Fn); /* Normalise to Fn = 1 */ Fp /= fabs(Fn), Fs /= fabs(Fn); /* Normalise to Fn = 1 */
tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */ tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */
tr_bw /= phases, Fs /= phases; tr_bw /= phases, Fs /= phases;
@ -145,7 +145,7 @@ double * lsx_design_lpf(
static double safe_log(double x) static double safe_log(double x)
{ {
assert(x >= 0); assert(x >= 0);
if (x) if (x!=0)
return log(x); return log(x);
lsx_debug("log(0)"); lsx_debug("log(0)");
return -26; return -26;
@ -222,7 +222,7 @@ void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase)
while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0) while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0)
--peak; --peak;
if (!phase1) if (phase1==0)
begin = 0; begin = 0;
else if (phase1 == 1) else if (phase1 == 1)
begin = peak - *len / 2; begin = peak - *len / 2;
@ -243,3 +243,35 @@ void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase)
work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1)); work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1));
free(pi_wraps), free(work); free(pi_wraps), free(work);
} }
#define F_x(F,expr) static double F(double x) {return expr;}
F_x(sinePhi, ((2.0517e-07*x-1.1303e-04)*x+.023154)*x+.55924 )
F_x(sinePsi, ((9.0667e-08*x-5.6114e-05)*x+.013658)*x+1.0977 )
F_x(sinePow, log(.5)/log(sin(x*.5)) )
#define dB_to_linear(x) exp((x) * (M_LN10 * 0.05))
double lsx_f_resp(double t, double a)
{
double x;
if (t > (a <= 160? .8 : .82)) {
double a1 = a+15;
double p = .00035*a+.375;
double w = 1/(1-.597)*asin(pow((a1-10.6)/a1,1/p));
double c = 1+asin(pow(1-a/a1,1/p))/w;
return a1*(pow(sin((c-t)*w),p)-1);
}
if (t > .5)
x = sinePsi(a), x = pow(sin((1-t) * x), sinePow(x));
else
x = sinePhi(a), x = 1 - pow(sin(t * x), sinePow(x));
return linear_to_dB(x);
}
double lsx_inv_f_resp(double drop, double a)
{
double x = sinePhi(a), s;
drop = dB_to_linear(drop);
s = drop > .5 ? 1 - drop : drop;
x = asin(pow(s, 1/sinePow(x))) / x;
return drop > .5? x : 1 -x;
}

View File

@ -16,10 +16,10 @@ void lsx_safe_rdft(int len, int type, double * d);
void lsx_safe_cdft(int len, int type, double * d); void lsx_safe_cdft(int len, int type, double * d);
void lsx_safe_rdft_f(int len, int type, float * d); void lsx_safe_rdft_f(int len, int type, float * d);
void lsx_safe_cdft_f(int len, int type, float * d); void lsx_safe_cdft_f(int len, int type, float * d);
void lsx_ordered_convolve(int n, void * not_used, double * a, const double * b); void lsx_ordered_convolve(int n, void * not_used, void * a, const void * b);
void lsx_ordered_convolve_f(int n, void * not_used, float * a, const float * b); void lsx_ordered_convolve_f(int n, void * not_used, void * a, const void * b);
void lsx_ordered_partial_convolve(int n, double * a, const double * b); void lsx_ordered_partial_convolve(int n, void * a, const void * b);
void lsx_ordered_partial_convolve_f(int n, float * a, const float * b); void lsx_ordered_partial_convolve_f(int n, void * a, const void * b);
double lsx_kaiser_beta(double att, double tr_bw); double lsx_kaiser_beta(double att, double tr_bw);
double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho,
@ -31,9 +31,14 @@ double * lsx_design_lpf(
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */ double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */
double att, /* Stop-band attenuation in dB */ double att, /* Stop-band attenuation in dB */
int * num_taps, /* 0: value will be estimated */ int * num_taps, /* 0: value will be estimated */
int k, /* >0: number of phases; <0: num_taps 1 (mod -k) */ int k, /* >0: number of phases; <0: num_taps = 1 (mod -k) */
double beta); /* <0: value will be estimated */ double beta); /* <0: value will be estimated */
void lsx_fir_to_phase(double * * h, int * len, void lsx_fir_to_phase(double * * h, int * len,
int * post_len, double phase0); int * post_len, double phase0);
double lsx_f_resp(double t, double a);
double lsx_inv_f_resp(double drop, double a);
#define lsx_to_3dB(a) (1 - lsx_inv_f_resp(-3., a))
#endif #endif

View File

@ -1,151 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#include "half_coefs.h"
#define FUNCTION h8
#define CONVOLVE _ _ _ _ _ _ _ _
#define h8_l 8
#define COEFS half_fir_coefs_8
#include "half-fir.h"
#define FUNCTION h9
#define CONVOLVE _ _ _ _ _ _ _ _ _
#define h9_l 9
#define COEFS half_fir_coefs_9
#include "half-fir.h"
#define FUNCTION h10
#define CONVOLVE _ _ _ _ _ _ _ _ _ _
#define h10_l 10
#define COEFS half_fir_coefs_10
#include "half-fir.h"
#define FUNCTION h11
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _
#define h11_l 11
#define COEFS half_fir_coefs_11
#include "half-fir.h"
#define FUNCTION h12
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _
#define h12_l 12
#define COEFS half_fir_coefs_12
#include "half-fir.h"
#define FUNCTION h13
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _ _
#define h13_l 13
#define COEFS half_fir_coefs_13
#include "half-fir.h"
static struct {int num_coefs; stage_fn_t fn; float att;} const half_firs[] = {
{ 8, h8 , 136.51f},
{ 9, h9 , 152.32f},
{10, h10, 168.07f},
{11, h11, 183.78f},
{12, h12, 199.44f},
{13, h13, 212.75f},
};
#define HI_PREC_CLOCK
#define VAR_LENGTH p->n
#define VAR_CONVOLVE while (j < FIR_LENGTH) _
#define VAR_POLY_PHASE_BITS p->phase_bits
#define FUNCTION vpoly0
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "poly-fir0.h"
#define FUNCTION vpoly1
#define COEF_INTERP 1
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "poly-fir.h"
#define FUNCTION vpoly2
#define COEF_INTERP 2
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "poly-fir.h"
#define FUNCTION vpoly3
#define COEF_INTERP 3
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "poly-fir.h"
#undef HI_PREC_CLOCK
#define U100_l 42
#if RATE_SIMD_POLY
#define U100_l_EXTRA _ _
#define u100_l_EXTRA _
#define U100_l_EXTRA_LENGTH 2
#define u100_l_EXTRA_LENGTH 1
#else
#define U100_l_EXTRA
#define u100_l_EXTRA
#define U100_l_EXTRA_LENGTH 0
#define u100_l_EXTRA_LENGTH 0
#endif
#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ U100_l_EXTRA
#define FUNCTION U100_0
#define FIR_LENGTH (U100_l + U100_l_EXTRA_LENGTH)
#define CONVOLVE poly_fir_convolve_U100
#include "poly-fir0.h"
#define u100_l 11
#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _ u100_l_EXTRA
#define FUNCTION u100_0
#define FIR_LENGTH (u100_l + u100_l_EXTRA_LENGTH)
#define CONVOLVE poly_fir_convolve_u100
#include "poly-fir0.h"
#define FUNCTION u100_1
#define COEF_INTERP 1
#define PHASE_BITS 8
#define FIR_LENGTH (u100_l + u100_l_EXTRA_LENGTH)
#define CONVOLVE poly_fir_convolve_u100
#include "poly-fir.h"
#define u100_1_b 8
#define FUNCTION u100_2
#define COEF_INTERP 2
#define PHASE_BITS 6
#define FIR_LENGTH (u100_l + u100_l_EXTRA_LENGTH)
#define CONVOLVE poly_fir_convolve_u100
#include "poly-fir.h"
#define u100_2_b 6
typedef struct {float scalar; stage_fn_t fn;} poly_fir1_t;
typedef struct {float beta; poly_fir1_t interp[3];} poly_fir_t;
static poly_fir_t const poly_firs[] = {
{-1, {{0, vpoly0}, { 7.2f, vpoly1}, {5.0f, vpoly2}}},
{-1, {{0, vpoly0}, { 9.4f, vpoly1}, {6.7f, vpoly2}}},
{-1, {{0, vpoly0}, {12.4f, vpoly1}, {7.8f, vpoly2}}},
{-1, {{0, vpoly0}, {13.6f, vpoly1}, {9.3f, vpoly2}}},
{-1, {{0, vpoly0}, {10.5f, vpoly2}, {8.4f, vpoly3}}},
{-1, {{0, vpoly0}, {11.85f,vpoly2}, {9.0f, vpoly3}}},
{-1, {{0, vpoly0}, { 8.0f, vpoly1}, {5.3f, vpoly2}}},
{-1, {{0, vpoly0}, { 8.6f, vpoly1}, {5.7f, vpoly2}}},
{-1, {{0, vpoly0}, {10.6f, vpoly1}, {6.75f,vpoly2}}},
{-1, {{0, vpoly0}, {12.6f, vpoly1}, {8.6f, vpoly2}}},
{-1, {{0, vpoly0}, { 9.6f, vpoly2}, {7.6f, vpoly3}}},
{-1, {{0, vpoly0}, {11.4f, vpoly2}, {8.65f,vpoly3}}},
{10.62f, {{U100_l, U100_0}, {0, 0}, {0, 0}}},
{11.28f, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}},
{-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}},
{-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}},
{-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}},
{-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}},
{-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}},
};

75
soxr/src/half-coefs.h Normal file
View File

@ -0,0 +1,75 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if defined __GNUC__
#pragma GCC system_header
#elif defined __SUNPRO_C
#pragma disable_warn
#elif defined _MSC_VER
#pragma warning(push, 1)
#endif
#if CORE_TYPE & CORE_SIMD_HALF
#define VALIGN vAlign
#else
#define VALIGN
#endif
#if !(CORE_TYPE & CORE_SIMD_HALF)
static VALIGN const sample_t half_fir_coefs_7[] = {
3.1062656496657370e-01, -8.4998810699955796e-02, 3.4007044621123500e-02,
-1.2839903789829387e-02, 3.9899380181723145e-03, -8.9355202017945374e-04,
1.0918292424806546e-04,
};
#endif
static VALIGN const sample_t half_fir_coefs_8[] = {
3.1154652365332069e-01, -8.7344917685739543e-02, 3.6814458353637280e-02,
-1.5189204581464479e-02, 5.4540855610738801e-03, -1.5643862626630416e-03,
3.1816575906323303e-04, -3.4799449225005688e-05,
};
static VALIGN const sample_t half_fir_coefs_9[] = {
3.1227034755311189e-01, -8.9221517147969526e-02, 3.9139704015071934e-02,
-1.7250558515852023e-02, 6.8589440230476112e-03, -2.3045049636430419e-03,
6.0963740543348963e-04, -1.1323803957431231e-04, 1.1197769991000046e-05,
};
#if CORE_TYPE & CORE_DBL
static VALIGN const sample_t half_fir_coefs_10[] = {
3.1285456012000523e-01, -9.0756740799292787e-02, 4.1096398104193160e-02,
-1.9066319572525220e-02, 8.1840569787684902e-03, -3.0766876176359834e-03,
9.6396524429277980e-04, -2.3585679989922018e-04, 4.0252189026627833e-05,
-3.6298196342497932e-06,
};
static VALIGN const sample_t half_fir_coefs_11[] = {
3.1333588822574199e-01, -9.2035898673019811e-02, 4.2765169698406408e-02,
-2.0673580894964429e-02, 9.4225426824512421e-03, -3.8563379950013192e-03,
1.3634742159642453e-03, -3.9874150714431009e-04, 9.0586723632664806e-05,
-1.4285617244076783e-05, 1.1834642946400529e-06,
};
static VALIGN const sample_t half_fir_coefs_12[] = {
3.1373928463345568e-01, -9.3118180335301962e-02, 4.4205005881659098e-02,
-2.2103860986973051e-02, 1.0574689371162864e-02, -4.6276428065385065e-03,
1.7936153397572132e-03, -5.9617527051353237e-04, 1.6314517495669067e-04,
-3.4555126770115446e-05, 5.0617615610782593e-06, -3.8768958592971409e-07,
};
static VALIGN const sample_t half_fir_coefs_13[] = {
3.1408224847888910e-01, -9.4045836332667387e-02, 4.5459878763259978e-02,
-2.3383369012219993e-02, 1.1644273044890753e-02, -5.3806714579057013e-03,
2.2429072878264022e-03, -8.2204347506606424e-04, 2.5724946477840893e-04,
-6.6072709864248668e-05, 1.3099163296288644e-05, -1.7907147069136000e-06,
1.2750825595240592e-07,
};
#endif
#undef VALIGN
#if defined __SUNPRO_C
#pragma enable_warn
#elif defined _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,25 +1,61 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Down-sample by a factor of 2 using a FIR with odd length (LEN).*/ /* Decimate by 2 using a FIR with odd length (LEN). */
/* Input must be preceded and followed by LEN >> 1 samples. */ /* Input must be preceded and followed by LEN >> 1 samples. */
#define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j; #define COEFS ((sample_t const *)p->coefs)
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
#if SIMD_SSE
#define BEGINNING v4_t sum, q1, q2, t
#define ____ \
q1 = _mm_shuffle_ps(t=vLdu(input+2*j),vLdu(input+2*j+4),_MM_SHUFFLE(3,1,3,1)); \
q2 = _mm_shuffle_ps(vLdu(input-2*j-4),vLdu(input-2*j-8),_MM_SHUFFLE(1,3,1,3)); \
sum = vAdd(j? sum : vMul(vSet1(.5), t), vMul(vAdd(q1, q2), vLd(COEFS+j))); \
j += 4;
#define __ \
q1 = _mm_shuffle_ps(vLdu(input+2*j), vLdu(input-2*j-4), _MM_SHUFFLE(1,3,3,1)); \
q2 = _mm_loadl_pi(q2, (__m64*)(COEFS+j)), q2 = _mm_movelh_ps(q2, q2); \
sum = vAdd(sum, vMul(q1, q2)); \
j += 2;
#define _ \
q1 = _mm_add_ss(_mm_load_ss(input+2*j+1), _mm_load_ss(input-2*j-1)); \
sum = _mm_add_ss(sum, _mm_mul_ss(q1, _mm_load_ss(COEFS+j))); \
++j;
#define END vStorSum(output+i, sum)
/* #elif SIMD_AVX; No good solution found. */
/* #elif SIMD_NEON; No need: gcc -O3 does a good job by itself. */
#else
#define BEGINNING sample_t sum = input[0] * .5f
#define ____ __ __
#define __ _ _
#define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j;
#define END output[i] = sum
#endif
static void FUNCTION_H(stage_t * p, fifo_t * output_fifo)
{ {
sample_t const * input = stage_read_p(p); sample_t const * __restrict input = stage_read_p(p);
int i, num_out = (stage_occupancy(p) + 1) / 2; int num_in = min(stage_occupancy(p), p->input_size);
sample_t * output = fifo_reserve(output_fifo, num_out); int i, num_out = (num_in + 1) >> 1;
sample_t * __restrict output = fifo_reserve(output_fifo, num_out);
for (i = 0; i < num_out; ++i, input += 2) { for (i = 0; i < num_out; ++i, input += 2) {
int j = 0; int j = 0;
sample_t sum = input[0] * .5f; BEGINNING; CONVOLVE; END;
CONVOLVE
output[i] = sum;
} }
fifo_read(&p->fifo, 2 * num_out, NULL); fifo_read(&p->fifo, 2 * num_out, NULL);
} }
#undef _ #undef _
#undef __
#undef ____
#undef BEGINNING
#undef END
#undef COEFS #undef COEFS
#undef CONVOLVE #undef CONVOLVE
#undef FUNCTION #undef FUNCTION_H

View File

@ -1,57 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if defined __GNUC__
#pragma GCC system_header
#elif defined __SUNPRO_C
#pragma disable_warn
#elif defined _MSC_VER
#pragma warning(push, 1)
#endif
static const sample_t half_fir_coefs_8[] = {
0.3115465451887802, -0.08734497241282892, 0.03681452335604365,
-0.01518925831569441, 0.005454118437408876, -0.001564400922162005,
0.0003181701445034203, -3.48001341225749e-5,
};
static const sample_t half_fir_coefs_9[] = {
0.3122703613711853, -0.08922155288172305, 0.03913974805854332,
-0.01725059723447163, 0.006858970092378141, -0.002304518467568703,
0.0006096426006051062, -0.0001132393923815236, 1.119795386287666e-5,
};
static const sample_t half_fir_coefs_10[] = {
0.3128545521327376, -0.09075671986104322, 0.04109637155154835,
-0.01906629512749895, 0.008184039342054333, -0.0030766775017262,
0.0009639607022414314, -0.0002358552746579827, 4.025184282444155e-5,
-3.629779111541012e-6,
};
static const sample_t half_fir_coefs_11[] = {
0.3133358837508807, -0.09203588680609488, 0.04276515428384758,
-0.02067356614745591, 0.00942253142371517, -0.003856330993895144,
0.001363470684892284, -0.0003987400965541919, 9.058629923971627e-5,
-1.428553070915318e-5, 1.183455238783835e-6,
};
static const sample_t half_fir_coefs_12[] = {
0.3137392991811407, -0.0931182192961332, 0.0442050575271454,
-0.02210391200618091, 0.01057473015666001, -0.00462766983973885,
0.001793630226239453, -0.0005961819959665878, 0.0001631475979359577,
-3.45557865639653e-5, 5.06188341942088e-6, -3.877010943315563e-7,
};
static const sample_t half_fir_coefs_13[] = {
0.3140822554324578, -0.0940458550886253, 0.04545990399121566,
-0.02338339450796002, 0.01164429409071052, -0.005380686021429845,
0.002242915773871009, -0.000822047600000082, 0.0002572510962395222,
-6.607320708956279e-5, 1.309926399120154e-5, -1.790719575255006e-6,
1.27504961098836e-7,
};
#if defined __SUNPRO_C
#pragma enable_warn
#elif defined _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,46 +1,84 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxr_internal_included #if !defined soxr_internal_included
#define soxr_internal_included #define soxr_internal_included
#include "soxr-config.h" #include "std-types.h"
#undef min #undef min
#undef max #undef max
#define min(a, b) ((a) <= (b) ? (a) : (b)) #define min(a, b) ((a) <= (b) ? (a) : (b))
#define max(a, b) ((a) >= (b) ? (a) : (b)) #define max(a, b) ((a) >= (b) ? (a) : (b))
#define range_limit(x, lower, upper) (min(max(x, lower), upper)) #define range_limit(x, lower, upper) (min(max(x, lower), upper))
#define linear_to_dB(x) (log10(x) * 20) #define linear_to_dB(x) (log10(x) * 20)
#define array_length(a) (sizeof(a)/sizeof(a[0])) #define array_length(a) (sizeof(a)/sizeof(a[0]))
#if !defined AL
#define AL(a) array_length(a) #define AL(a) array_length(a)
#endif
#define iAL(a) (int)AL(a) #define iAL(a) (int)AL(a)
#define sqr(a) ((a) * (a)) #define sqr(a) ((a) * (a))
#ifdef __GNUC__
#if defined __GNUC__
#define UNUSED __attribute__ ((unused)) #define UNUSED __attribute__ ((unused))
#else #else
#define UNUSED #define UNUSED
#endif #endif
#if defined NDEBUG || SOXR_SILENT
#if !WITH_DEV_TRACE
#ifdef __GNUC__ #ifdef __GNUC__
void lsx_dummy(char const *, ...); void lsx_dummy(char const *, ...);
#else #else
static __inline void lsx_dummy(char const * x, ...) {} static __inline void lsx_dummy(char const * x, ...) {}
#endif #endif
#define lsx_debug if(0) lsx_dummy #define lsx_debug if(0) lsx_dummy
#define lsx_debug_more lsx_debug
#else #else
#include <stdarg.h> extern int _soxr_trace_level;
#include <stdio.h> void _soxr_trace(char const * fmt, ...);
UNUSED static void lsx_debug(char const * fmt, ...) #define lsx_debug if (_soxr_trace_level > 0) _soxr_trace
{ #define lsx_debug_more if (_soxr_trace_level > 1) _soxr_trace
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
va_end(args);
}
#endif #endif
/* soxr_quality_spec_t.flags: */
#define SOXR_ROLLOFF_LSR2Q 3u /* Reserved for internal use. */
#define SOXR_ROLLOFF_MASK 3u /* For masking these bits. */
#define SOXR_MAINTAIN_3DB_PT 4u /* Reserved for internal use. */
#define SOXR_PROMOTE_TO_LQ 64u /* Reserved for internal use. */
/* soxr_runtime_spec_t.flags: */
#define SOXR_STRICT_BUFFERING 4u /* Reserved for future use. */
#define SOXR_NOSMALLINTOPT 8u /* For test purposes only. */
/* soxr_quality_spec recipe: */
#define SOXR_PRECISIONQ 11 /* Quality specified by the precision parameter. */
#define SOXR_PHASE_MASK 0x30 /* For masking these bits. */
/* soxr_quality_spec flags: */
#define RESET_ON_CLEAR (1u<<31)
#endif #endif

View File

@ -1,2 +0,0 @@
set(TARGET_HEADERS "@TARGET_HEADERS@")
set(TARGET_PCS "@TARGET_PCS@")

View File

@ -1 +0,0 @@
set(TARGET_LIBS "@TARGET_LIBS@")

View File

@ -1,114 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Wrapper mostly compatible with `libsamplerate'. */
#include <assert.h>
#include <stdlib.h>
#include "soxr.h"
/* Runtime casts: */
typedef struct io_t {
float *in,*out; long ilen,olen,idone,odone; int eoi; double oi_ratio;} io_t;
#define SRC_DATA io_t
typedef struct soxr SRC_STATE;
#define src_callback_t soxr_input_fn_t
#define SRC_ERROR soxr_error_t
#define SRC_SRCTYPE unsigned
#include "soxr-lsr.h"
#include "rint.h"
soxr_error_t src_simple(io_t * p, unsigned id, int channels)
{
size_t idone, odone;
soxr_error_t error;
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + id, 0);
char const * e = getenv("SOXR_LSR_NUM_THREADS");
soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1));
assert (channels > 0);
assert (p->ilen >= 0);
assert (p->olen >= 0);
error = soxr_oneshot(1, p->oi_ratio, (unsigned)channels,
p->in, (size_t)p->ilen, &idone, p->out, (size_t)p->olen, &odone,
0, &q_spec, &r_spec);
p->idone = (long)idone, p->odone = (long)odone;
return error;
}
soxr_t src_callback_new(soxr_input_fn_t fn, unsigned id, int channels, SRC_ERROR * error0, void * p)
{
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + id, 0);
char const * e = getenv("SOXR_LSR_NUM_THREADS");
soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1));
soxr_error_t error;
soxr_t soxr = 0;
assert (channels > 0);
/* To minimise latency e.g. for real-time playback:
if (id == 2)
r_spec.log2_large_dft_size = r_spec.log2_min_dft_size = 8;
*/
soxr = soxr_create(0, 0, (unsigned)channels, &error, 0, &q_spec, &r_spec);
if (soxr)
error = soxr_set_input_fn(soxr, fn, p, 0);
if (error0)
*(int *)error0 = (int)(ptrdiff_t)error;
return soxr;
}
soxr_error_t src_process(soxr_t p, io_t * io)
{
if (!p || !io) return "null pointer";
soxr_set_error(p, soxr_set_io_ratio(p, 1/io->oi_ratio, (size_t)io->olen));
{ size_t idone , odone;
soxr_process(p, io->in, (size_t)(io->eoi? ~io->ilen : io->ilen), /* hack */
&idone, io->out, (size_t)io->olen, &odone);
io->idone = (long)idone, io->odone = (long)odone;
return soxr_error(p); }
}
long src_callback_read(soxr_t p, double oi_ratio, long olen, float * obuf)
{
if (!p || olen < 0) return -1;
soxr_set_error(p, soxr_set_io_ratio(p, 1/oi_ratio, (size_t)olen));
return (long)soxr_output(p, obuf, (size_t)olen);
}
void src_float_to_short_array(float const * src, short * dest, int len)
{
double d, N = 1. + SHRT_MAX;
assert (src && dest);
while (len--) d = src[len] * N, dest[len] = (short)(d > N - 1? (short)(N - 1) : d < -N? (short)-N : rint16(d));
}
void src_short_to_float_array(short const * src, float * dest, int len)
{
assert (src && dest);
while (len--) dest[len] = (float)(src[len] * (1 / (1. + SHRT_MAX)));
}
void src_float_to_int_array(float const * src, int * dest, int len)
{
double d, N = 32768. * 65536.; /* N.B. int32, not int! (Also next fn.) */
assert (src && dest);
while (len--) d = src[len] * N, dest[len] = d >= N - 1? (int)(N - 1) : d < -N? (int)(-N) : rint32(d);
}
void src_int_to_float_array(int const * src, float * dest, int len)
{
assert (src && dest);
while (len--) dest[len] = (float)(src[len] * (1 / (32768. * 65536.)));
}
static char const * const names[] = {"LSR best sinc", "LSR medium sinc", "LSR fastest sinc", "LSR ZOH", "LSR linear", "SoX VHQ"};
char const * src_get_name(unsigned n) {return n < 5u + !getenv("SOXR_LSR_STRICT")? names[n] : 0;}
char const * src_get_description(unsigned id) {return src_get_name(id);}
char const * src_get_version(void) {return soxr_version();}
char const * src_strerror(soxr_error_t error) {return error == (soxr_error_t)1? "Placeholder." : sizeof(int) >= sizeof(char *) || !error ? soxr_strerror(error) : "soxr error";}
int src_is_valid_ratio(double oi_ratio) {return getenv("SOXR_LSR_STRICT")? oi_ratio >= 1./256 && oi_ratio <= 256 : oi_ratio > 0;}
soxr_error_t src_error(soxr_t p) {return soxr_error(p);}
soxr_error_t src_reset(soxr_t p) {return soxr_clear(p);}
soxr_t src_delete(soxr_t p) {soxr_delete(p); return 0;}
soxr_error_t src_set_ratio(soxr_t p, double oi_ratio) {return soxr_set_io_ratio(p, 1/oi_ratio, 0);}
soxr_t src_new(unsigned id, int channels, SRC_ERROR * error) {return src_callback_new(0, id, channels, error, 0);}

31
soxr/src/math-wrap.h Normal file
View File

@ -0,0 +1,31 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined soxr_math_wrap_included
#define soxr_math_wrap_included
#include <math.h>
#if defined __STRICT_ANSI__
#define sinf(x) (float)sin ((double)(x))
#define cosf(x) (float)cos ((double)(x))
#define atanf(x) (float)atan((double)(x))
#endif
#if !defined M_PI
#define M_PI 3.141592653589793238462643383279502884
#endif
#if !defined M_LN10
#define M_LN10 2.302585092994045684017991454684364208
#endif
#if !defined M_SQRT2
#define M_SQRT2 1.414213562373095048801688724209698079
#endif
#if !defined M_LN2
#define M_LN2 0.693147180559945309417232121458176568
#endif
#endif

40
soxr/src/pffft-avx.h Normal file
View File

@ -0,0 +1,40 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* AVX support macros */
#if !defined soxr_avx_included
#define soxr_avx_included
#include <immintrin.h>
typedef __m256d v4sf;
#define VZERO() _mm256_setzero_pd()
#define VMUL(a,b) _mm256_mul_pd(a,b)
#define VADD(a,b) _mm256_add_pd(a,b)
#define VMADD(a,b,c) VADD(VMUL(a,b),c) /* Note: gcc -mfma will `fuse' these */
#define VSUB(a,b) _mm256_sub_pd(a,b)
#define LD_PS1(p) _mm256_set1_pd(p)
#define INTERLEAVE2(in1, in2, out1, out2) {v4sf \
t1 = _mm256_unpacklo_pd(in1, in2), \
t2 = _mm256_unpackhi_pd(in1, in2); \
out1 = _mm256_permute2f128_pd(t1,t2,0x20); \
out2 = _mm256_permute2f128_pd(t1,t2,0x31); }
#define UNINTERLEAVE2(in1, in2, out1, out2) {v4sf \
t1 = _mm256_permute2f128_pd(in1,in2,0x20), \
t2 = _mm256_permute2f128_pd(in1,in2,0x31); \
out1 = _mm256_unpacklo_pd(t1, t2); \
out2 = _mm256_unpackhi_pd(t1, t2);}
#define VTRANSPOSE4(x0,x1,x2,x3) {v4sf \
t0 = _mm256_shuffle_pd(x0,x1, 0x0), \
t2 = _mm256_shuffle_pd(x0,x1, 0xf), \
t1 = _mm256_shuffle_pd(x2,x3, 0x0), \
t3 = _mm256_shuffle_pd(x2,x3, 0xf); \
x0 = _mm256_permute2f128_pd(t0,t1, 0x20); \
x1 = _mm256_permute2f128_pd(t2,t3, 0x20); \
x2 = _mm256_permute2f128_pd(t0,t1, 0x31); \
x3 = _mm256_permute2f128_pd(t2,t3, 0x31);}
#define VSWAPHL(a,b) _mm256_permute2f128_pd(b, a, 0x30)
#define VALIGNED(ptr) ((((long)(ptr)) & 0x1F) == 0)
#endif

110
soxr/src/pffft-wrap.c Normal file
View File

@ -0,0 +1,110 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#if !defined PFFT_MACROS_ONLY
#include "math-wrap.h"
#if PFFFT_DOUBLE
#include "util64s.h"
#else
#include "util32s.h"
#define sin(x) sinf(x)
#define cos(x) cosf(x)
#endif
#define pffft_aligned_free SIMD_ALIGNED_FREE
#define pffft_aligned_malloc SIMD_ALIGNED_MALLOC
#define pffft_aligned_calloc SIMD_ALIGNED_CALLOC
#undef inline
#define inline __inline
#endif
#include "pffft.c"
#if !defined PFFT_MACROS_ONLY
#if !defined PFFFT_SIMD_DISABLE
static void pffft_zconvolve(PFFFT_Setup *s, const float *a, const float *b, float *ab) {
int i, Ncvec = s->Ncvec;
const v4sf * /*RESTRICT*/ va = (const v4sf*)a;
const v4sf * RESTRICT vb = (const v4sf*)b;
v4sf * /*RESTRICT*/ vab = (v4sf*)ab;
float ar, ai, br, bi;
#ifdef __arm__
__builtin_prefetch(va);
__builtin_prefetch(vb);
__builtin_prefetch(va+2);
__builtin_prefetch(vb+2);
__builtin_prefetch(va+4);
__builtin_prefetch(vb+4);
__builtin_prefetch(va+6);
__builtin_prefetch(vb+6);
#endif
assert(VALIGNED(a) && VALIGNED(b) && VALIGNED(ab));
ar = ((v4sf_union*)va)[0].f[0];
ai = ((v4sf_union*)va)[1].f[0];
br = ((v4sf_union*)vb)[0].f[0];
bi = ((v4sf_union*)vb)[1].f[0];
for (i=0; i < Ncvec; i += 2) {
v4sf ar, ai, br, bi;
ar = va[2*i+0]; ai = va[2*i+1];
br = vb[2*i+0]; bi = vb[2*i+1];
VCPLXMUL(ar, ai, br, bi);
vab[2*i+0] = ar;
vab[2*i+1] = ai;
ar = va[2*i+2]; ai = va[2*i+3];
br = vb[2*i+2]; bi = vb[2*i+3];
VCPLXMUL(ar, ai, br, bi);
vab[2*i+2] = ar;
vab[2*i+3] = ai;
}
if (s->transform == PFFFT_REAL) {
((v4sf_union*)vab)[0].f[0] = ar*br;
((v4sf_union*)vab)[1].f[0] = ai*bi;
}
}
#else
static void pffft_zconvolve(PFFFT_Setup *s, const float *a, const float *b, float *ab) {
int i, Ncvec = s->Ncvec;
if (s->transform == PFFFT_REAL) {
/* take care of the fftpack ordering */
ab[0] = a[0]*b[0];
ab[2*Ncvec-1] = a[2*Ncvec-1]*b[2*Ncvec-1];
++ab; ++a; ++b; --Ncvec;
}
for (i=0; i < Ncvec; ++i) {
float ar, ai, br, bi;
ar = a[2*i+0]; ai = a[2*i+1];
br = b[2*i+0]; bi = b[2*i+1];
VCPLXMUL(ar, ai, br, bi);
ab[2*i+0] = ar;
ab[2*i+1] = ai;
}
}
#endif
#include <string.h>
static void pffft_reorder_back(int length, void * setup, float * data, float * work)
{
memcpy(work, data, (unsigned)length * sizeof(*work));
pffft_zreorder(setup, work, data, PFFFT_BACKWARD);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,9 @@
/* Copyright (c) 2011 Julien Pommier ( pommier@modartt.com ) /* https://bitbucket.org/jpommier/pffft/raw/483453d8f7661058e74aa4e7cf5c27bcd7887e7a/pffft.h
* with minor changes for libsoxr. */
#if !defined PFFT_MACROS_ONLY
/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com )
Based on original fortran 77 code from FFTPACKv4 from NETLIB, Based on original fortran 77 code from FFTPACKv4 from NETLIB,
authored by Dr Paul Swarztrauber of NCAR, in 1985. authored by Dr Paul Swarztrauber of NCAR, in 1985.
@ -60,8 +65,9 @@
- 1D transforms only, with 32-bit single precision. - 1D transforms only, with 32-bit single precision.
- supports only transforms for inputs of length N of the form - supports only transforms for inputs of length N of the form
N=(2^a)*(3^b), a >= 5 and b >=0 (32, 48, 64, 96, 128, 144 etc N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128,
are all acceptable lengths). Performance is best for 128<=N<=8192. 144, 160, etc are all acceptable lengths). Performance is best for
128<=N<=8192.
- all (float*) pointers in the functions below are expected to - all (float*) pointers in the functions below are expected to
have an "simd-compatible" alignment, that is 16 bytes on x86 and have an "simd-compatible" alignment, that is 16 bytes on x86 and
@ -80,6 +86,10 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif
#if PFFFT_DOUBLE
#define float double
#endif #endif
/* opaque struct holding internal stuff (precomputed twiddle factors) /* opaque struct holding internal stuff (precomputed twiddle factors)
@ -99,8 +109,10 @@ extern "C" {
PFFFT_Setup structure is read-only so it can safely be shared by PFFFT_Setup structure is read-only so it can safely be shared by
multiple concurrent threads. multiple concurrent threads.
*/ */
static PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform); static
static void pffft_destroy_setup(PFFFT_Setup *); PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform);
static
void pffft_destroy_setup(PFFFT_Setup *);
/* /*
Perform a Fourier transform , The z-domain data is stored in the Perform a Fourier transform , The z-domain data is stored in the
most efficient order for transforming it back, or using it for most efficient order for transforming it back, or using it for
@ -113,13 +125,14 @@ extern "C" {
Typically you will want to scale the backward transform by 1/N. Typically you will want to scale the backward transform by 1/N.
The 'work' pointer should point to an area of N (2*N for complex The 'work' pointer should point to an area of N (2*N for complex
fft) floats, properly aligned. [del]If 'work' is NULL, then stack will fft) floats, properly aligned. If 'work' is NULL, then stack will
be used instead (this is probably the beest strategy for small be used instead (this is probably the best strategy for small
FFTs, say for N < 16384).[/del] FFTs, say for N < 16384).
input and output may alias. input and output may alias.
*/ */
static void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); static
void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
/* /*
Similar to pffft_transform, but makes sure that the output is Similar to pffft_transform, but makes sure that the output is
@ -128,7 +141,8 @@ extern "C" {
input and output may alias. input and output may alias.
*/ */
static void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); static
void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
/* /*
call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(..., call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(...,
@ -142,7 +156,8 @@ extern "C" {
input and output should not alias. input and output should not alias.
*/ */
static void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction); static
void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction);
/* /*
Perform a multiplication of the frequency components of dft_a and Perform a multiplication of the frequency components of dft_a and
@ -155,23 +170,28 @@ extern "C" {
the operation performed is: dft_ab += (dft_a * fdt_b)*scaling the operation performed is: dft_ab += (dft_a * fdt_b)*scaling
The dft_a, dft_b and dft_ab pointers may alias. The dft_a, dft_b and dft_ab pointers may alias.
void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling);
*/ */
void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling);
/* /*
the operation performed is: dft_ab = (dft_a * fdt_b) the float buffers must have the correct alignment (16-byte boundary
on intel and powerpc). This function may be used to obtain such
The dft_a, dft_b and dft_ab pointers may alias. correctly aligned buffers.
*/ */
static void pffft_zconvolve(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab); #if 0
void *pffft_aligned_malloc(size_t nb_bytes);
void pffft_aligned_free(void *);
/* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */ /* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */
int pffft_simd_size(void); int pffft_simd_size();
#endif
static void pffft_reorder_back(int length, void * setup, float * data, float * work); #undef float
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif
#endif

View File

@ -1,11 +1,14 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#define _soxr_simd_aligned_free free #define SIMD_ALIGNED_FREE free
#define _soxr_simd_aligned_malloc malloc #define SIMD_ALIGNED_MALLOC malloc
#define PFFFT_SIMD_DISABLE #define PFFFT_SIMD_DISABLE
#include "pffft.c" #define PFFFT_DOUBLE 0
#include "pffft-wrap.c"
#include "filter.h" #include "filter.h"
#include "rdft_t.h"
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
static void delete_setup(void * setup) {pffft_destroy_setup(setup);} static void delete_setup(void * setup) {pffft_destroy_setup(setup);}
@ -15,18 +18,22 @@ static void backward (int length, void * setup, float * H, float * scratch) {pff
static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;} static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;}
static int multiplier(void) {return 1;} static int multiplier(void) {return 1;}
static int flags(void) {return RDFT_NEEDS_SCRATCH;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft32_cb = {
fn_t _soxr_rdft32_cb[] = { setup,
(fn_t)setup, setup,
(fn_t)setup, delete_setup,
(fn_t)delete_setup, forward,
(fn_t)forward, oforward,
(fn_t)oforward, backward,
(fn_t)backward, obackward,
(fn_t)obackward, convolve,
(fn_t)convolve, _soxr_ordered_partial_convolve_f,
(fn_t)_soxr_ordered_partial_convolve_f, multiplier,
(fn_t)multiplier, pffft_reorder_back,
(fn_t)pffft_reorder_back, malloc,
calloc,
free,
flags,
}; };

View File

@ -1,27 +1,34 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
#include "pffft.c" #define PFFFT_DOUBLE 0
#include "pffft-wrap.c"
#include "rdft_t.h"
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
static void forward (int length, void * setup, float * h, float * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;} static void forward (int length, void * setup, float * h, float * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
static void oforward (int length, void * setup, float * h, float * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;} static void oforward (int length, void * setup, float * h, float * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
static void backward (int length, void * setup, float * H, float * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} static void backward (int length, void * setup, float * H, float * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;} static void convolve(int length, void * setup, float * H, float const * with) {pffft_zconvolve(setup, H, with, H); (void)length;}
static int multiplier(void) {return 1;} static int multiplier(void) {return 1;}
static int flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;}
typedef void (* fn_t)(void); rdft_cb_table _soxr_rdft32s_cb = {
fn_t _soxr_rdft32s_cb[] = { setup,
(fn_t)setup, setup,
(fn_t)setup, pffft_destroy_setup,
(fn_t)pffft_destroy_setup, forward,
(fn_t)forward, oforward,
(fn_t)oforward, backward,
(fn_t)backward, obackward,
(fn_t)obackward, convolve,
(fn_t)convolve, ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)_soxr_ordered_partial_convolve_simd, multiplier,
(fn_t)multiplier, pffft_reorder_back,
(fn_t)pffft_reorder_back, SIMD_ALIGNED_MALLOC,
SIMD_ALIGNED_CALLOC,
SIMD_ALIGNED_FREE,
flags,
}; };

34
soxr/src/pffft64s.c Normal file
View File

@ -0,0 +1,34 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define PFFFT_DOUBLE 1
#include "pffft-wrap.c"
#include "rdft_t.h"
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
static void forward (int length, void * setup, double * h, double * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
static void oforward (int length, void * setup, double * h, double * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
static void backward (int length, void * setup, double * H, double * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
static void obackward(int length, void * setup, double * H, double * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
static void convolve(int length, void * setup, double * H, double const * with) {pffft_zconvolve(setup, H, with, H); (void)length;}
static int multiplier(void) {return 1;}
static int flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;}
rdft_cb_table _soxr_rdft64s_cb = {
setup,
setup,
pffft_destroy_setup,
forward,
oforward,
backward,
obackward,
convolve,
ORDERED_PARTIAL_CONVOLVE_SIMD,
multiplier,
pffft_reorder_back,
SIMD_ALIGNED_MALLOC,
SIMD_ALIGNED_CALLOC,
SIMD_ALIGNED_FREE,
flags,
};

View File

@ -1,97 +1,149 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net /* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */ * Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Resample using an interpolated poly-phase FIR with length LEN.*/ /* Resample using an interpolated poly-phase FIR with length LEN. */
/* Input must be followed by LEN-1 samples. */ /* Input must be followed by FIR_LENGTH-1 samples. */
#define a (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 0,j)) #if COEF_INTERP != 1 && COEF_INTERP != 2 && COEF_INTERP != 3
#define b (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 1,j))
#define c (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 2,j))
#define d (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 3,j))
#if COEF_INTERP == 0
#define _ sum += a *in[j], ++j;
#elif COEF_INTERP == 1
#define _ sum += (b *x + a)*in[j], ++j;
#elif COEF_INTERP == 2
#define _ sum += ((c *x + b)*x + a)*in[j], ++j;
#elif COEF_INTERP == 3
#define _ sum += (((d*x + c)*x + b)*x + a)*in[j], ++j;
#else
#error COEF_INTERP #error COEF_INTERP
#endif #endif
#if SIMD_AVX || SIMD_SSE || SIMD_NEON
#define N (FIR_LENGTH>>2)
#if COEF_INTERP == 1
#define _ sum=vMac(vMac(b,X,a),vLdu(in+j*4),sum), ++j;
#elif COEF_INTERP == 2
#define _ sum=vMac(vMac(vMac(c,X,b),X,a),vLdu(in+j*4),sum), ++j;
#else
#define _ sum=vMac(vMac(vMac(vMac(d,X,c),X,b),X,a),vLdu(in+j*4),sum), ++j;
#endif
#define a coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-0)]
#define b coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-1)]
#define c coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-2)]
#define d coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-3)]
#define BEGINNING v4_t X = vLds(x), sum = vZero(); \
v4_t const * const __restrict coefs = (v4_t *)COEFS
#define END vStorSum(output+i, sum)
#define cc(n) case n: core(n); break
#define CORE(n) switch (n) {cc(2); cc(3); cc(4); cc(5); cc(6); default: core(n);}
#else
#define N FIR_LENGTH
#if COEF_INTERP == 1
#define _ sum += (b*x + a)*in[j], ++j;
#elif COEF_INTERP == 2
#define _ sum += ((c*x + b)*x + a)*in[j], ++j;
#else
#define _ sum += (((d*x + c)*x + b)*x + a)*in[j], ++j;
#endif
#define a (coef(COEFS, COEF_INTERP, N, phase, 0,j))
#define b (coef(COEFS, COEF_INTERP, N, phase, 1,j))
#define c (coef(COEFS, COEF_INTERP, N, phase, 2,j))
#define d (coef(COEFS, COEF_INTERP, N, phase, 3,j))
#define BEGINNING sample_t sum = 0
#define END output[i] = sum
#define CORE(n) core(n)
#endif
#define floatPrecCore(n) { \
float_step_t at = p->at.flt; \
for (i = 0; (int)at < num_in; ++i, at += p->step.flt) { \
sample_t const * const __restrict in = input + (int)at; \
float_step_t frac = at - (int)at; \
int phase = (int)(frac * (1 << PHASE_BITS)); \
sample_t x = (sample_t)(frac * (1 << PHASE_BITS) - phase); \
int j = 0; \
BEGINNING; CONVOLVE(n); END; \
} \
fifo_read(&p->fifo, (int)at, NULL); \
p->at.flt = at - (int)at; } /* Could round to 1 in some cirmcumstances. */
#define highPrecCore(n) { \
step_t at; at.fix = p->at.fix; \
for (i = 0; at.integer < num_in; ++i, \
at.fix.ls.all += p->step.fix.ls.all, \
at.whole += p->step.whole + (at.fix.ls.all < p->step.fix.ls.all)) { \
sample_t const * const __restrict in = input + at.integer; \
uint32_t frac = at.fraction; \
int phase = (int)(frac >> (32 - PHASE_BITS)); /* High-order bits */ \
/* Low-order bits, scaled to [0,1): */ \
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32)); \
int j = 0; \
BEGINNING; CONVOLVE(n); END; \
} \
fifo_read(&p->fifo, at.integer, NULL); \
p->at.whole = at.fraction; \
p->at.fix.ls = at.fix.ls; }
#define stdPrecCore(n) { \
int64p_t at; at.all = p->at.whole; \
for (i = 0; at.parts.ms < num_in; ++i, at.all += p->step.whole) { \
sample_t const * const __restrict in = input + at.parts.ms; \
uint32_t const frac = at.parts.ls; \
int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */ \
/* Low-order bits, scaled to [0,1): */ \
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32)); \
int j = 0; \
BEGINNING; CONVOLVE(n); END; \
} \
fifo_read(&p->fifo, at.parts.ms, NULL); \
p->at.whole = at.parts.ls; }
#if WITH_FLOAT_STD_PREC_CLOCK
#define SPCORE floatPrecCore
#else
#define SPCORE stdPrecCore
#endif
#if WITH_HI_PREC_CLOCK
#define core(n) if (p->use_hi_prec_clock) highPrecCore(n) else SPCORE(n)
#else
#define core(n) SPCORE(n)
#endif
static void FUNCTION(stage_t * p, fifo_t * output_fifo) static void FUNCTION(stage_t * p, fifo_t * output_fifo)
{ {
sample_t const * input = stage_read_p(p); sample_t const * input = stage_read_p(p);
int i, num_in = stage_occupancy(p), max_num_out = 1 + (int)(num_in*p->out_in_ratio); int num_in = min(stage_occupancy(p), p->input_size);
sample_t * output = fifo_reserve(output_fifo, max_num_out); int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio);
sample_t * const __restrict output = fifo_reserve(output_fifo, max_num_out);
#if defined HI_PREC_CLOCK CORE(N);
#if FLOAT_HI_PREC_CLOCK
if (p->use_hi_prec_clock) {
float_step_t at = p->at.flt;
for (i = 0; (int)at < num_in; ++i, at += p->step.flt) {
sample_t const * in = input + (int)at;
float_step_t frac = at - (int)at;
int phase = (int)(frac * (1 << PHASE_BITS));
#if COEF_INTERP > 0
sample_t x = (sample_t)(frac * (1 << PHASE_BITS) - phase);
#endif
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
}
fifo_read(&p->fifo, (int)at, NULL);
p->at.flt = at - (int)at;
} else
#else
if (p->use_hi_prec_clock) {
for (i = 0; p->at.integer < num_in; ++i,
p->at.fix.ls.all += p->step.fix.ls.all,
p->at.whole += p->step.whole + (p->at.fix.ls.all < p->step.fix.ls.all)) {
sample_t const * in = input + p->at.integer;
uint32_t frac = p->at.fraction;
int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */
#if COEF_INTERP > 0 /* low-order bits, scaled to [0,1) */
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32));
#endif
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
}
fifo_read(&p->fifo, p->at.integer, NULL);
p->at.integer = 0;
} else
#endif
#endif
{
for (i = 0; p->at.integer < num_in; ++i, p->at.whole += p->step.whole) {
sample_t const * in = input + p->at.integer;
uint32_t frac = p->at.fraction;
int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */
#if COEF_INTERP > 0 /* low-order bits, scaled to [0,1) */
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32));
#endif
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
}
fifo_read(&p->fifo, p->at.integer, NULL);
p->at.integer = 0;
}
assert(max_num_out - i >= 0); assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i); fifo_trim_by(output_fifo, max_num_out - i);
} }
#undef _ #undef _
#undef a #undef a
#undef b #undef b
#undef c #undef c
#undef d #undef d
#undef CORE
#undef cc
#undef core
#undef COEF_INTERP #undef COEF_INTERP
#undef N
#undef BEGINNING
#undef END
#undef CONVOLVE #undef CONVOLVE
#undef FIR_LENGTH #undef FIR_LENGTH
#undef FUNCTION #undef FUNCTION

Some files were not shown because too many files have changed in this diff Show More