Upgrade libsoxr to 0.1.3

This commit is contained in:
Steve Daulton 2018-03-08 16:26:50 +00:00
parent f7f721b52d
commit ccc29c6c76
115 changed files with 4831 additions and 2597 deletions

View File

@ -1,10 +1,11 @@
# 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.
cmake_minimum_required (VERSION 2.8 FATAL_ERROR)
cmake_minimum_required (VERSION 3.1 FATAL_ERROR)
project (soxr C)
set (DESCRIPTION_SUMMARY "High quality, one-dimensional sample-rate conversion library")
set (DESCRIPTION_SUMMARY
"High quality, one-dimensional sample-rate conversion library")
@ -12,18 +13,22 @@ set (DESCRIPTION_SUMMARY "High quality, one-dimensional sample-rate conversion l
set (PROJECT_VERSION_MAJOR 0)
set (PROJECT_VERSION_MINOR 1)
set (PROJECT_VERSION_PATCH 1)
set (PROJECT_VERSION_PATCH 3)
# For shared-object; if, since the last public release:
# * library code changed at all: ++revision
# * interfaces changed at all: ++current, revision = 0
# * interfaces added: ++age
# * interfaces removed: age = 0
# 1) library code changed at all: ++revision
# 2) interfaces changed at all: ++current, revision = 0
# 3) interfaces added: ++age
# 4) interfaces removed: age = 0
set (SO_VERSION_CURRENT 1)
set (SO_VERSION_REVISION 0)
set (SO_VERSION_REVISION 2)
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:
@ -31,30 +36,49 @@ set (SO_VERSION_AGE 1)
include (CMakeDependentOption)
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 ()
option (BUILD_TESTS "Build sanity-tests." ON)
option (BUILD_SHARED_LIBS "Build shared libraries." ON)
option (BUILD_TESTS "Build sanity-tests." ON)
option (BUILD_EXAMPLES "Build examples." OFF)
option (WITH_OPENMP "Include OpenMP threading." ON)
option (WITH_LSR_BINDINGS "Include a `libsamplerate'-like interface." ON)
cmake_dependent_option (WITH_SINGLE_PRECISION "Build with single precision (for up to 20-bit accuracy)." ON
"WITH_DOUBLE_PRECISION" ON)
cmake_dependent_option (WITH_DOUBLE_PRECISION "Build with double precision (for up to 32-bit accuracy)." ON
"WITH_SINGLE_PRECISION" ON)
cmake_dependent_option (WITH_SIMD "Use SIMD (for faster single precision)." ON
"WITH_SINGLE_PRECISION" OFF)
cmake_dependent_option (WITH_AVFFT "Use libavcodec (LGPL) for SIMD DFT." OFF
"WITH_SIMD;NOT WITH_PFFFT" OFF)
cmake_dependent_option (WITH_PFFFT "Use PFFFT (BSD-like licence) for SIMD DFT." ON
"WITH_SIMD;NOT WITH_AVFFT" OFF)
if (UNIX)
if (EXISTS ${PROJECT_SOURCE_DIR}/lsr-tests)
cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF
"WITH_LSR_BINDINGS" OFF)
endif ()
endif ()
cmake_dependent_option (BUILD_SHARED_LIBS
"Build shared (dynamic) soxr libraries." ON
"NOT WITH_DEV_GPROF" OFF)
cmake_dependent_option (WITH_VR32
"Include HQ variable-rate resampling engine." ON
"WITH_CR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S OR NOT DEFINED WITH_VR32" ON)
cmake_dependent_option (WITH_CR32
"Include HQ constant-rate resampling engine." ON
"WITH_VR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S" ON)
cmake_dependent_option (WITH_CR64
"Include VHQ constant-rate resampling engine." ON
"WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64S" ON)
cmake_dependent_option (WITH_CR64S
"Include VHQ SIMD constant-rate resampling engine." ON
"WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64" ON)
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)
@ -65,73 +89,88 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
include (CheckFunctionExists)
include (CheckIncludeFiles)
include (CheckLibraryExists)
include (SetSystemProcessor)
include (TestBigEndian)
set_system_processor ()
check_library_exists (m pow "" NEED_LIBM)
if (NEED_LIBM)
set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}")
link_libraries (m)
set (LIBM_LIBRARIES m)
endif ()
if (${BUILD_EXAMPLES})
project (${PROJECT_NAME}) # Adds c++ compiler
endif ()
if (WITH_OPENMP)
find_package (OpenMP)
endif ()
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}")
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 ()
if (WITH_SIMD)
find_package (SIMD)
if (SIMD_FOUND)
set (HAVE_SIMD 1)
endif ()
if (WITH_CR32S)
find_package (SIMD32)
set (WITH_CR32S ${SIMD32_FOUND})
endif ()
if (WITH_SINGLE_PRECISION)
set (HAVE_SINGLE_PRECISION 1)
endif ()
if (WITH_DOUBLE_PRECISION)
set (HAVE_DOUBLE_PRECISION 1)
if (WITH_CR64S)
find_package (SIMD64)
set (WITH_CR64S ${SIMD64_FOUND})
endif ()
if (WITH_AVFFT)
find_package (LibAVCodec)
find_package (LibAVCodec REQUIRED)
if (AVCODEC_FOUND)
include_directories (${AVCODEC_INCLUDE_DIRS})
link_libraries (${AVCODEC_LIBRARIES})
set (HAVE_AVFFT 1)
set (LIBS ${LIBS} ${AVCODEC_LIBRARIES})
endif ()
endif ()
if (WITH_AVFFT OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND SIMD32_FOUND AND WITH_CR32))
find_package (LibAVUtil)
if (AVUTIL_FOUND)
include_directories (${AVUTIL_INCLUDE_DIRS})
set (LIBS ${LIBS} ${AVUTIL_LIBRARIES})
endif ()
endif ()
check_function_exists (lrint HAVE_LRINT)
check_include_files (fenv.h HAVE_FENV_H)
test_big_endian (WORDS_BIGENDIAN)
macro (make_exist)
foreach (x ${ARGN})
if (NOT ${x})
set (${x} 0)
endif ()
endforeach ()
endmacro ()
make_exist (HAVE_LRINT HAVE_FENV_H WORDS_BIGENDIAN HAVE_SIMD)
make_exist (HAVE_SINGLE_PRECISION HAVE_DOUBLE_PRECISION HAVE_AVFFT)
check_include_files (stdbool.h HAVE_STDBOOL_H)
check_include_files (stdint.h HAVE_STDINT_H)
test_big_endian (HAVE_BIGENDIAN)
# Compiler configuration:
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set (PROJECT_CXX_FLAGS "-Wconversion -Wall -W -pedantic -Wundef -Wcast-align -Wpointer-arith -Wno-long-long")
set (PROJECT_C_FLAGS "${PROJECT_CXX_FLAGS} -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes")
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wconversion -Wall -Wextra \
-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")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s") # strip
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)
mark_as_advanced (VISIBILITY_HIDDEN)
if (VISIBILITY_HIDDEN)
add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY)
endif ()
@ -139,9 +178,14 @@ endif ()
if (MSVC)
add_definitions (-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS)
option (ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically." OFF)
if (ENABLE_STATIC_RUNTIME)
foreach (flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
option (BUILD_SHARED_RUNTIME "MSVC, link with runtime dynamically." ON)
if (NOT BUILD_SHARED_RUNTIME)
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}}")
endforeach ()
endif ()
@ -155,7 +199,8 @@ endif ()
# 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)
# Allow exes to find dlls:
set (BIN ${PROJECT_BINARY_DIR}/bin/)
set (EXAMPLES_BIN ${BIN})
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN})
@ -173,6 +218,10 @@ if (BUILD_SHARED_LIBS)
endif ()
endif ()
if (CMAKE_BUILD_TYPE STREQUAL "None") # As used by some distros.
add_definitions (-DNDEBUG)
endif ()
# Installation configuration:
@ -196,23 +245,16 @@ endif ()
if (APPLE)
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 ()
# Add 'make check' target for integration into GNU Autotools.
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
# Top-level:
set (PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
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}")
set (PROJECT_VERSION
${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
set (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH})
configure_file (
@ -220,7 +262,7 @@ configure_file (
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.h)
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 ()
endif ()
@ -249,26 +291,21 @@ endif ()
# Rough-and-ready distclean for anyone still doing in-tree builds:
# GNU Autotools compatibility; 'make check':
add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND})
# GNU Autotools compatibility; 'make distclean':
if (UNIX)
add_custom_target (distclean
COMMAND make clean && rm -rf
CMakeCache.txt
CMakeFiles
cmake_install.cmake
CPackConfig.cmake
CPackSourceConfig.cmake
deinstall.cmake
Makefile
soxr-config.h
src/CMakeFiles
src/cmake_install.cmake
src/libsoxr-dev.src
src/libsoxr-lsr.pc
src/libsoxr.pc
src/libsoxr.src
src/Makefile)
add_custom_target (distclean COMMAND make clean && find .
\\! -path \\*/Modules/\\* \\! -name cmp-test.cmake -a -name \\*.cmake
-o -name CMakeFiles -o -name Makefile -o -name CMakeCache.txt -o -name
Testing -o -name cmake_install.cmake -o -name install_manifest.txt -o
-path ./soxr-config.h -o -name config.h -o -name \\*.pc -o -name \\*.s32
| xargs rm -rf)
endif ()
@ -291,13 +328,8 @@ if (UNIX)
set (CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set (CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
set (CPACK_SOURCE_GENERATOR "TGZ")
set (CPACK_SOURCE_IGNORE_FILES "dist;/lsr-tests/;/Debug/;/Release/;/cpack/;\\\\.swp$;\\\\.gitignore;/\\\\.git/")
set (CPACK_SOURCE_GENERATOR "TXZ")
set (CPACK_SOURCE_IGNORE_FILES
"dist;/lsr-tests/;/Debug.*/;/Release.*/;\\\\.swp$;\\\\.git.*;/\\\\.git/")
include (CPack)
if (IS_DIRECTORY ${PROJECT_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
* Standard build
* Build customisation
* Cross-compiling with mingw (linux host)
* Cross-compilation
* 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).
* CMake: http://www.cmake.org/cmake/resources/software.html
* CMake v3.0 or newer: https://cmake.org/download/
2. Build:
@ -30,7 +31,7 @@ STANDARD BUILD
go (on MS-Windows with nmake)
or
./go (on unix-like systems)
./go (on Unix-like systems)
This should build the library and run a few sanity tests.
@ -38,14 +39,14 @@ STANDARD BUILD
3. Installation:
Note that this step may need to be performed by a system
adminstrator. Enter:
administrator. Enter:
nmake install (on MS-Windows)
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
library and its header file in your development environment.
@ -60,38 +61,74 @@ STANDARD BUILD
BUILD CUSTOMISATION
If it is necessary to customise the build, then steps 2 and 3 above may be
substituted as follows. Change directory to the one containing this file,
then enter commands along the lines of:
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, then
enter commands along the lines:
mkdir build
cd build
cmake [OPTIONS] ..
cmake -Wno-dev -DCMAKE_BUILD_TYPE=Release [OPTIONS] ..
make
make test
sudo make install
N.B. The CMAKE_BUILD_TYPE to use for library deployment is Release.
To list help on the available options, enter:
cmake -LH ..
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
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-x86_64-mingw-w64-mingw32.cmake \
-DCMAKE_INSTALL_PREFIX=install \
-DHAVE_WORDS_BIGENDIAN_EXITCODE=1 \
-DBUILD_TESTS=0 \
-DBUILD_EXAMPLES=1 \
..
make
@ -117,7 +154,30 @@ INTEGRATION WITH OTHER BUILD SYSTEMS
Autotools-based systems might find it useful to create a file called
`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).
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
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.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
along with this library; if not, see <https://www.gnu.org/licenses/>.
Notes

View File

@ -1,3 +1,25 @@
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)
* Fix conversion failure when I/O types differ but I/O rates don't.
* Fix #defines for interpolation order selection.
* Fix ineffectual SOXR_MINIMUM_PHASE and SOXR_INTERMEDIATE_PHASE in
soxr_quality_spec recipe.
* Fix soxr_delay() returning a negative number after end-of-input has been
indicated.
* Fix crash when using soxr_process() after calling soxr_clear().
* Be more POSIX compliant w.r.t. errno in the examples; fixes erroneous
reporting of errors on FreeBSD.
* Quality improvement for variable-rate.
* Various fixes/improvements to build/tests/documentation.
Version 0.1.1 (2013-03-03)
* Minor fixes/improvements to build/tests.
* Fix crash (e.g. with k3b) when null error pointer passed to src_create (lsr

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
conversion -- it may be used, for example, to resample PCM-encoded audio.
@ -8,8 +8,8 @@ should look elsewhere.
It aims to give fast¹ and very high quality² results for any constant
(rational or irrational) resampling ratio. Phase-response, preserved
bandwidth, aliasing, and rejection level parameters are all configurable;
alternatively, simple `preset' configurations may be selected. An
experimental, variable-rate resampling mode of operation is also included.
alternatively, simple `preset' configurations may be selected. A
variable-rate resampling mode of operation is also included.
The resampler is currently available either as part of `libsox' (the audio
file-format and effect library), or stand-alone as `libsoxr' (this package).
@ -46,7 +46,7 @@ size configuration parameters may be used to reduce this figure).
For build and installation instructions, see the file `INSTALL'; for
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.
² Bit-perfect within practical occupied-bandwidth limits.

View File

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

View File

@ -1,17 +0,0 @@
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt (revision 12955)
+++ CMakeLists.txt (working copy)
@@ -201,6 +201,12 @@
+# Add 'make check' target for integration into GNU Autotools.
+
+add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
+
+
+
# Top-level:
set (PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})

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.
# - 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_LIBRARIES - List of libraries when using this package.
# AVCODEC_FOUND - True if this package can be found.
# AVCODEC_INCLUDE_DIRS - where to find headers for this package.
# AVCODEC_LIBRARIES - libraries to link to when using this package.
# AVCODEC_FOUND - true iff this package can be found.
if (AVCODEC_INCLUDES)
if (AVCODEC_INCLUDE_DIRS)
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)
include (FindPackageHandleStandardArgs)
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,108 +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/
#
# Modified for libsoxr not to rely on presence of C++ compiler.
#
#=============================================================================
# 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 OpenMP_C_FLAGS)
mark_as_advanced (OpenMP_C_FLAGS)

View File

@ -1,88 +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)
set (SIMD_C_FLAG_CANDIDATES
# Microsoft Visual Studio x64
" "
# Microsoft Visual Studio x86
"/arch:SSE /fp:fast -D__SSE__"
# Gnu
"-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 ()

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[])
{
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. */
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[])
{
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. */
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */

View File

@ -72,7 +72,7 @@ int main(int argc, char const * arg[])
soxr_delete(soxr);
free(obuf), free(ibuf);
/* Diagnostics: */
fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0],
soxr_strerror(error), errno? strerror(errno) : "no error");
return error || errno;
fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error),
ferror(stdin) || ferror(stdout)? strerror(errno) : "no 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-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Example 3: extends example 2 with multiple channels, multiple datatypes,
@ -14,7 +14,7 @@
* OUTPUT-RATE Ditto
* NUM-CHANNELS Number of interleaved channels
* 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-FLAGS Quality flags (in hex) See soxr.h
* PASSBAND-END %
@ -42,21 +42,22 @@ static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len)
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 orate = n? --n, atof(*arg++) : 44100.;
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 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_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;
soxr_datatype_t const otype = ospec & 3;
soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags);
soxr_io_spec_t const io_spec = soxr_io_spec(itype, otype);
soxr_io_spec_t io_spec = soxr_io_spec(itype, otype);
soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads);
/* Allocate resampling input and output buffers in proportion to the input
@ -79,6 +80,7 @@ int main(int n, char const * arg[])
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;
/* Create a stream resampler: */
soxr = soxr_create(
@ -92,6 +94,7 @@ int main(int n, char const * arg[])
}
if (!error) { /* If all is well, run the resampler: */
engine = soxr_engine(soxr);
USE_STD_STDIO;
/* Resample in blocks: */
do odone = soxr_output(soxr, obuf, olen);
@ -104,7 +107,8 @@ int main(int n, char const * arg[])
soxr_delete(soxr);
free(obuf), free(ibuf);
/* Diagnostics: */
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n", arg0, soxr_strerror(error),
(long unsigned)clips, errno? strerror(errno) : "no error");
return error || errno;
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%s)\n",
arg0, soxr_strerror(error), (long unsigned)clips,
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine);
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. */
/* 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
* be used for input and output independently.
*
* Arguments are as example 3.
*/
#include <soxr.h>
@ -73,13 +75,17 @@ int main(int n, char const * arg[])
double const orate = n? --n, atof(*arg++) : 44100.;
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 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_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;
soxr_datatype_t const otype = ospec & 3;
soxr_quality_spec_t const 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_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags);
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);
/* 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;
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);
unsigned i;
for (i = 0; i < chans; ++i) {
ibuf_ptrs[i] = iptr;
obuf_ptrs[i] = optr;
@ -141,7 +154,8 @@ int main(int n, char const * arg[])
free(obuf), free(ibuf), free(obufs), free(ibufs);
free(obuf_ptrs), free(ibuf_ptrs);
/* Diagnostics: */
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n", arg0, soxr_strerror(error),
(long unsigned)clips, errno? strerror(errno) : "no error");
return error || errno;
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n",
arg0, soxr_strerror(error), (long unsigned)clips,
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error");
return !!error;
}

View File

@ -1,11 +1,10 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Example 5: Variable-rate resampling (N.B. experimental). A test signal
* (held in a buffer) is resampled over a wide range of octaves. Resampled
* data is sent to stdout as raw, float32 samples. Choices of 2 test-signals
* and of 2 ways of varying the sample-rate are combined in a command-line
* option:
/* Example 5: Variable-rate resampling. A test signal (held in a buffer) is
* resampled over a wide range of octaves. Resampled data is sent to stdout as
* raw, float32 samples. Choices of 2 test-signals and of 2 ways of varying
* the sample-rate are combined in a command-line option:
*
* Usage: ./5-variable-rate [0|1|2|3]
*/
@ -30,7 +29,7 @@ int main(int argc, char *arg[])
int opt = argc <= 1? 2 : (atoi(arg[1]) & 3), saw = opt & 1, fm = opt & 2;
float ibuf[10 << OCTAVES], obuf[AL(ibuf)];
int i, wl = 2 << OCTAVES;
size_t ilen = AL(ibuf), need_input = 1;
size_t ilen = AL(ibuf), need_input = 1, written;
size_t odone, total_odone, total_olen = OLEN * FS;
size_t olen1 = fm? 10 : AL(obuf); /* Small block-len if fast-changing ratio */
soxr_error_t error;
@ -70,7 +69,7 @@ int main(int argc, char *arg[])
do {
size_t len = need_input? ilen : 0;
error = soxr_process(soxr, ibuf, len, NULL, obuf, block_len, &odone);
fwrite(obuf, sizeof(float), odone, stdout);
written = fwrite(obuf, sizeof(float), odone, stdout);
/* Update counters for the current block and for the total length: */
block_len -= odone;
@ -80,7 +79,7 @@ int main(int argc, char *arg[])
* again, supplying more input samples: */
need_input = block_len != 0;
} while (need_input && !error);
} while (need_input && !error && written == odone);
/* Now that the block for the current ioratio is complete, go back
* round the main `for' loop in order to process the next block. */
@ -88,7 +87,7 @@ int main(int argc, char *arg[])
soxr_delete(soxr);
}
/* Diagnostics: */
fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0],
soxr_strerror(error), errno? strerror(errno) : "no error");
return error || errno;
fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error),
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error");
return !!error;
}

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.
if (${BUILD_EXAMPLES})
project (soxr) # Adds c++ compiler
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/[1-9]-*.[cC])
elseif (${BUILD_TESTS})
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/3*.c)
endif ()
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}")
link_libraries (${PROJECT_NAME} ${LIBM_LIBRARIES})
if (${BUILD_EXAMPLES} OR ${BUILD_TESTS})
set (SOURCES 3-options-input-fn)
if (${WITH_LSR_BINDINGS})
set (LSR_SOURCES 1a-lsr.c)
set (LSR_SOURCES 1a-lsr)
endif ()
endif ()
if (NOT BUILD_SHARED_LIBS AND OPENMP_FOUND)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_C_FLAGS}")
if (${BUILD_EXAMPLES})
list (APPEND SOURCES 1-single-block 2-stream 4-split-channels)
if (${WITH_VR32})
list (APPEND SOURCES 5-variable-rate)
endif ()
endif ()
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}")
link_libraries (${PROJECT_NAME})
foreach (fe ${SOURCES} ${LSR_SOURCES})
get_filename_component (f ${fe} NAME_WE)
@ -34,4 +32,5 @@ if (${BUILD_TESTS} AND ${WITH_LSR_BINDINGS})
endif ()
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. */
/* Common includes etc. for the examples. */
@ -17,10 +17,7 @@
#include <io.h>
#include <fcntl.h>
#define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \
_setmode(_fileno(stdin ), _O_BINARY);
/* Sometimes missing, so ensure that it is defined: */
#undef M_PI
#define M_PI 3.14159265358979323846
_setmode(_fileno(stdin ), _O_BINARY)
#else
#define USE_STD_STDIO
#endif
@ -38,8 +35,13 @@
#endif
#undef min
#undef max
#define min(x,y) ((x)<(y)?(x):(y))
#undef max
#define max(x,y) ((x)>(y)?(x):(y))
#undef AL
#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

19
lib-src/libsoxr/go Normal file → Executable file
View File

@ -1,17 +1,18 @@
#!/bin/sh
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
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
case "$1" in -j*) j="$1"; shift;; esac # Support -jX for parallel build/test
build=$1
test x$build = x && build=Release
test x"$1" = x && build=Release || build="$1"
rm -f CMakeCache.txt # Prevent interference from any in-tree build
mkdir -p $build
cd $build
mkdir -p "$build"
cd "$build"
cmake -DCMAKE_BUILD_TYPE=$build .. &&
make $j &&
(ctest $j || echo "FAILURE details in $build/Testing/Temporary/LastTest.log")
cmake -Wno-dev -DCMAKE_BUILD_TYPE="$build" ..
make $j
ctest $j || echo "FAILURE details in $build/Testing/Temporary/LastTest.log"

View File

@ -1,5 +1,5 @@
@echo off
rem SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
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
@ -11,7 +11,7 @@ del/f CMakeCache.txt
mkdir %build%
cd %build%
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% ..
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% -Wno-dev ..
if errorlevel 1 goto end
nmake

View File

@ -20,7 +20,7 @@ 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
cflags=-I$dir/src
else
echo "Examples in `pwd`; using pkg-config:"
libs=$(pkg-config --libs $1)
@ -29,7 +29,7 @@ build_examples() {
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"
cmd="$cc $cflags -o $out $f $libs -lm"
echo $cmd; $cmd
done
}

View File

@ -0,0 +1 @@
inst-check-soxr

View File

@ -1,14 +0,0 @@
Index: lib-src/libsoxr/configure
===================================================================
--- lib-src/libsoxr/configure (revision 13509)
+++ lib-src/libsoxr/configure (working copy)
@@ -10,4 +10,8 @@
# Autotools options should not be passed to this script.
-cmake -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF .
+srcdir="$@"
+srcdir="${srcdir#*--srcdir=}"
+srcdir="./${srcdir/ */}"
+
+cmake -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF "${srcdir}"

View File

@ -1,9 +1,22 @@
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
Cmake is able 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, for projects that prefer to maintain a more monolithic build
structure using the MSVC compiler, the accompanying files may be useful.
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.
* libsoxr.vcproj Builds a static lib for MSVC ver >= 9 (2008).
* soxr-config.h Pre-configured for a typical Win32 system.
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.

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>

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

View File

@ -3,9 +3,10 @@
ProjectType="Visual C++"
Version="9.00"
Name="libsoxr"
ProjectGUID="{af9ad75c-4785-4432-bac3-adab1e7f1192}"
ProjectGUID="{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}"
RootNamespace="libsoxr"
TargetFrameworkVersion="131072"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform Name="Win32" />
@ -17,63 +18,79 @@
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
WholeProgramOptimization="0"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="."
PreprocessorDefinitions="_DEBUG;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB"
StringPooling="true"
PreprocessorDefinitions="_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;SOXR_DLL;soxr_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
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"
StringPooling="true"
PreprocessorDefinitions="NDEBUG;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;SOXR_DLL;soxr_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
CompileAs="0"
DebugInformationFormat="3"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter Name="Source Files" >
<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/lsr.c" />
<File RelativePath="../src/pffft32s.c" />
<File RelativePath="../src/rate32.c" />
<File RelativePath="../src/rate32s.c" />
<File RelativePath="../src/rate64.c" />
<File RelativePath="../src/simd.c" />
<File RelativePath="../src/soxr.c" />
<File RelativePath="../src/vr32.c" />
</Filter>
<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>

View File

@ -1,49 +1,30 @@
/* 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. */
/* N.B. Pre-configured for typical MS-Windows systems. However, the normal
/* 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 HAVE_SINGLE_PRECISION 1
#define HAVE_DOUBLE_PRECISION 1
#define HAVE_AVFFT 0
#define HAVE_SIMD 1
#define HAVE_FENV_H 0
#define HAVE_LRINT 0
#define WORDS_BIGENDIAN 0
#define AVCODEC_FOUND 0
#define AVUTIL_FOUND 0
#define WITH_PFFFT 1
#include <limits.h>
#define HAVE_FENV_H 1
#define HAVE_STDBOOL_H 1
#define HAVE_STDINT_H 1
#define HAVE_LRINT 1
#define HAVE_BIGENDIAN 0
#undef bool
#undef false
#undef true
#define bool int
#define false 0
#define true 1
#define WITH_CR32 1
#define WITH_CR32S 1
#define WITH_CR64 1
#define WITH_CR64S 1
#define WITH_VR32 1
#undef int16_t
#undef int32_t
#undef int64_t
#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
#define WITH_HI_PREC_CLOCK 1
#define WITH_FLOAT_STD_PREC_CLOCK 0
#define WITH_DEV_TRACE 1
#endif

31
lib-src/libsoxr/multi-arch Executable 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. */
#if !defined soxr_config_included
#define soxr_config_included
#define HAVE_SINGLE_PRECISION @HAVE_SINGLE_PRECISION@
#define HAVE_DOUBLE_PRECISION @HAVE_DOUBLE_PRECISION@
#define HAVE_AVFFT @HAVE_AVFFT@
#define HAVE_SIMD @HAVE_SIMD@
#define HAVE_FENV_H @HAVE_FENV_H@
#define HAVE_LRINT @HAVE_LRINT@
#define WORDS_BIGENDIAN @WORDS_BIGENDIAN@
#cmakedefine01 AVCODEC_FOUND
#cmakedefine01 AVUTIL_FOUND
#cmakedefine01 WITH_PFFFT
#include <limits.h>
#cmakedefine01 HAVE_FENV_H
#cmakedefine01 HAVE_STDBOOL_H
#cmakedefine01 HAVE_STDINT_H
#cmakedefine01 HAVE_LRINT
#cmakedefine01 HAVE_BIGENDIAN
#undef bool
#undef false
#undef true
#define bool int
#define false 0
#define true 1
#cmakedefine01 WITH_CR32
#cmakedefine01 WITH_CR32S
#cmakedefine01 WITH_CR64
#cmakedefine01 WITH_CR64S
#cmakedefine01 WITH_VR32
#undef int16_t
#undef int32_t
#undef int64_t
#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
#cmakedefine01 WITH_HI_PREC_CLOCK
#cmakedefine01 WITH_FLOAT_STD_PREC_CLOCK
#cmakedefine01 WITH_DEV_TRACE
#endif

View File

@ -1,6 +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.
# Can generate vr-coefs.h but it complicates cross-compiling & non-cmake builds
if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vr-coefs.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set_property(SOURCE vr32.c
APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h)
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
COMMAND vr-coefs > ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
DEPENDS vr-coefs)
endif ()
add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB)
@ -8,28 +25,50 @@ add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB)
# Libsoxr configuration:
set (RDFT32 fft4g32)
if (WITH_AVFFT AND AVCODEC_FOUND)
if (AVCODEC_FOUND)
set (RDFT32 avfft32)
set (RDFT32S avfft32s)
elseif (WITH_PFFFT)
#set (RDFT32 pffft32)
set (RDFT32S pffft32s)
elseif (WITH_SIMD)
elseif (WITH_CR32S)
set (RDFT32S fft4g32s)
if (NOT WITH_CR32)
list (APPEND RDFT32S fft4g32)
endif ()
endif ()
if (WITH_DOUBLE_PRECISION)
set (DP_SOURCES rate64)
set (SOURCES ${PROJECT_NAME}.c data-io)
if (WITH_CR32 OR WITH_CR32S OR WITH_CR64 OR WITH_CR64S)
list (APPEND SOURCES dbesi0 filter fft4g64 cr)
endif ()
if (WITH_SINGLE_PRECISION)
set (SP_SOURCES rate32 ${RDFT32})
if (WITH_CR32)
list (APPEND SOURCES cr32 ${RDFT32})
endif ()
if (HAVE_SIMD)
set (SIMD_SOURCES rate32s ${RDFT32S} simd)
foreach (source ${SIMD_SOURCES})
set_property (SOURCE ${source} PROPERTY COMPILE_FLAGS ${SIMD_C_FLAGS})
if (WITH_CR64)
list (APPEND SOURCES cr64)
endif ()
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 ()
endif ()
@ -37,8 +76,8 @@ endif ()
# Libsoxr:
add_library (${PROJECT_NAME} ${LIB_TYPE} ${PROJECT_NAME}.c data-io dbesi0 filter fft4g64
${SP_SOURCES} vr32 ${DP_SOURCES} ${SIMD_SOURCES})
add_library (${PROJECT_NAME} ${LIB_TYPE} ${SOURCES})
target_link_libraries (${PROJECT_NAME} PRIVATE ${LIBS} ${LIBM_LIBRARIES})
set_target_properties (${PROJECT_NAME} PROPERTIES
VERSION "${SO_VERSION}"
SOVERSION ${SO_VERSION_MAJOR}
@ -61,7 +100,7 @@ if (WITH_LSR_BINDINGS)
set (LSR ${PROJECT_NAME}-lsr)
set (LSR_SO_VERSION 0.1.9)
set (LSR_SO_VERSION_MAJOR 0)
add_library (${LSR} ${LIB_TYPE} lsr)
add_library (${LSR} ${LIB_TYPE} ${LSR})
target_link_libraries (${LSR} ${PROJECT_NAME})
set_target_properties (${LSR} PROPERTIES
VERSION "${LSR_SO_VERSION}"
@ -88,23 +127,3 @@ install (TARGETS ${PROJECT_NAME} ${LSR}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR})
# Packaging (for unix-like distributions):
get_property (LIB1 TARGET ${PROJECT_NAME} PROPERTY LOCATION)
if (BUILD_SHARED_LIBS)
set (LIB1 ${LIB1}.${SO_VERSION_MAJOR} ${LIB1}.${SO_VERSION})
endif ()
list (APPEND TARGET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.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. */
#if defined SOXR_LIB
@ -18,8 +18,10 @@
#define lsx_dfst_f _soxr_dfst_f
#define lsx_dfst _soxr_dfst
#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 _soxr_init_fft_cache
#define lsx_inv_f_resp _soxr_inv_f_resp
#define lsx_kaiser_beta _soxr_kaiser_beta
#define lsx_kaiser_params _soxr_kaiser_params
#define lsx_make_lpf _soxr_make_lpf

View File

@ -1,17 +1,19 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#include <stdlib.h>
#include <math.h>
#include <libavcodec/avfft.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 * 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 int multiplier(void) {return 2;}
static void nothing(void) {}
static int flags(void) {return 0;}
typedef void (* fn_t)(void);
fn_t _soxr_rdft32_cb[] = {
(fn_t)forward_setup,
(fn_t)backward_setup,
@ -24,4 +26,8 @@ fn_t _soxr_rdft32_cb[] = {
(fn_t)_soxr_ordered_partial_convolve_f,
(fn_t)multiplier,
(fn_t)nothing,
(fn_t)malloc,
(fn_t)calloc,
(fn_t)free,
(fn_t)flags,
};

View File

@ -3,15 +3,16 @@
#include <math.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 * 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 int multiplier(void) {return 2;}
static void nothing(void) {}
static int flags(void) {return RDFT_IS_SIMD;}
typedef void (* fn_t)(void);
fn_t _soxr_rdft32s_cb[] = {
(fn_t)forward_setup,
(fn_t)backward_setup,
@ -20,8 +21,12 @@ fn_t _soxr_rdft32s_cb[] = {
(fn_t)rdft,
(fn_t)rdft,
(fn_t)rdft,
(fn_t)_soxr_ordered_convolve_simd,
(fn_t)_soxr_ordered_partial_convolve_simd,
(fn_t)ORDERED_CONVOLVE_SIMD,
(fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)multiplier,
(fn_t)nothing,
(fn_t)SIMD_ALIGNED_MALLOC,
(fn_t)SIMD_ALIGNED_CALLOC,
(fn_t)SIMD_ALIGNED_FREE,
(fn_t)flags,
};

View File

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

View File

@ -0,0 +1,314 @@
/* 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 fn_t 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,
soxr_quality_spec_t * q_spec, soxr_runtime_spec_t * 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;}
fn_t RATE_CB[] = {
(fn_t)_soxr_input,
(fn_t)_soxr_process,
(fn_t)_soxr_output,
(fn_t)_soxr_flush,
(fn_t)_soxr_close,
(fn_t)_soxr_delay,
(fn_t)_soxr_sizes,
(fn_t)rate_create,
(fn_t)0,
(fn_t)id,
};
#endif

588
lib-src/libsoxr/src/cr.c Normal file
View File

@ -0,0 +1,588 @@
/* 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 "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) {
fn_t 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);
}
(void)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,
fn_t const * RDFT_CB)
{
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_CB;
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(rate_t * p, size_t olen)
{
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 real * _soxr_input(rate_t * p, real const * samples, size_t n)
{
if (p->flushing)
return 0;
p->samples_in += (int64_t)n;
return fifo_write(&p->stages[0].fifo, (int)n, samples);
}
STATIC real const * _soxr_output(rate_t * p, real * samples, size_t * n0)
{
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(rate_t * 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(rate_t * p)
{
if (p->stages) {
fn_t 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);
(void)RDFT_CB;
}
}
#if defined SOXR_LIB
STATIC double _soxr_delay(rate_t * 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
lib-src/libsoxr/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: */
fn_t 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;
fn_t * 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(struct rate * p, size_t olen);
real * _soxr_input(struct rate * p, real const * samples, size_t n);
real const * _soxr_output(struct rate * p, real * samples, size_t * n0);
void _soxr_flush(struct rate * p);
void _soxr_close(struct rate * p);
double _soxr_delay(struct rate * p);
void _soxr_sizes(size_t * shared, size_t * channel);
#endif
#endif

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"

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"

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"

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. */
#include <limits.h>
@ -14,8 +14,8 @@
unsigned i; \
size_t j; \
T const * src = *src0; \
if (ch > 1) \
for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = (DEINTERLEAVE_TO)*src++; \
if (ch > 1) for (j = 0; j < n; ++j) \
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 for (j = 0; j < n; dest[0][j++] = (DEINTERLEAVE_TO)*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 */
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 */
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"
#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__
@ -97,13 +68,13 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
#endif
#endif
#if HAVE_DOUBLE_PRECISION
#if WITH_CR64 || WITH_CR64S
#define FLOATX double
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2
#define LSX_RINT_CLIP lsx_rint32_clip
#define RINT_CLIP rint32_clip
#define RINT rint32
#define RINT rint32D
#if defined FPU_RINT32
#define FPU_RINT
#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 lsx_rint16_clip
#define RINT_CLIP rint16_clip
#define RINT rint16
#define RINT rint16D
#if defined FPU_RINT16
#define FPU_RINT
#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 lsx_rint16_clip_dither
#define RINT_CLIP rint16_clip_dither
#define RINT rint16
#define RINT rint16D
#if defined FPU_RINT16
#define FPU_RINT
#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 LSX_RINT_CLIP_2 lsx_rint32_clip_2_f
#define LSX_RINT_CLIP lsx_rint32_clip_f
#define RINT_CLIP rint32_clip_f
#define RINT rint32
#define RINT rint32F
#if defined FPU_RINT32
#define FPU_RINT
#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 lsx_rint16_clip_f
#define RINT_CLIP rint16_clip_f
#define RINT rint16
#define RINT rint16F
#if defined FPU_RINT16
#define FPU_RINT
#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 lsx_rint16_clip_dither_f
#define RINT_CLIP rint16_clip_dither_f
#define RINT rint16
#define RINT rint16D
#if defined FPU_RINT16
#define FPU_RINT
#endif
@ -199,7 +170,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
return 0; \
} while (0)
#if HAVE_DOUBLE_PRECISION
#if WITH_CR64 || WITH_CR64S
size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0,
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
#if HAVE_SINGLE_PRECISION
#if WITH_CR32 || WITH_CR32S || WITH_VR32
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)
{

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

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"
#ifdef FFT4G_FLOAT
#define double float
#define one_half 0.5f
#if defined _MSC_VER
#define sin (float)sin
#define cos (float)cos
#define atan (float)atan
#else
#define sin sinf
#define cos cosf
#define atan atanf
#endif
#define sin(x) sinf(x)
#define cos(x) cosf(x)
#define atan(x) atanf(x)
#define cdft lsx_cdft_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)
{
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;
(void)ip0;

View File

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

View File

@ -2,15 +2,16 @@
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#include "filter.h"
#include "simd.h"
#include "util32s.h"
#include "rdft_t.h"
static void * null(void) {return 0;}
static void nothing(void) {}
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 int multiplier(void) {return 2;}
static int flags(void) {return RDFT_IS_SIMD;}
typedef void (* fn_t)(void);
fn_t _soxr_rdft32s_cb[] = {
(fn_t)null,
(fn_t)null,
@ -19,8 +20,12 @@ fn_t _soxr_rdft32s_cb[] = {
(fn_t)forward,
(fn_t)backward,
(fn_t)backward,
(fn_t)_soxr_ordered_convolve_simd,
(fn_t)_soxr_ordered_partial_convolve_simd,
(fn_t)ORDERED_CONVOLVE_SIMD,
(fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)multiplier,
(fn_t)nothing,
(fn_t)SIMD_ALIGNED_MALLOC,
(fn_t)SIMD_ALIGNED_CALLOC,
(fn_t)SIMD_ALIGNED_FREE,
(fn_t)flags,
};

View File

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

View File

@ -1,14 +1,15 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#ifndef fifo_included
#define fifo_included
#ifndef soxr_fifo_included
#define soxr_fifo_included
#if !defined FIFO_SIZE_T
#define FIFO_SIZE_T size_t
#endif
#if !defined FIFO_REALLOC
#include <stdlib.h>
#define FIFO_REALLOC(a,b,c) realloc(a,b)
#undef FIFO_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. */
#include "filter.h"
#include <math.h>
#if !defined M_PI
#define M_PI 3.14159265358979323846
#endif
#include "math-wrap.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
@ -14,7 +11,7 @@
#include "fft4g.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 DONE_WITH_FFT_CACHE done_with_fft_cache
#define FFT_CACHE_CCRW fft_cache_ccrw
@ -31,7 +28,7 @@
#include "fft4g_cache.h"
#endif
#if HAVE_SINGLE_PRECISION && !HAVE_AVFFT
#if (WITH_CR32 && !AVCODEC_FOUND) || (WITH_CR32S && !AVCODEC_FOUND && !WITH_PFFFT)
#define DFT_FLOAT float
#define DONE_WITH_FFT_CACHE done_with_fft_cache_f
#define FFT_CACHE_CCRW fft_cache_ccrw_f
@ -48,14 +45,14 @@
#include "fft4g_cache.h"
#endif
#if HAVE_DOUBLE_PRECISION || !SOXR_LIB
#if WITH_CR64 || WITH_CR64S || !SOXR_LIB
#define DFT_FLOAT double
#define ORDERED_CONVOLVE lsx_ordered_convolve
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve
#include "rdft.h"
#endif
#if HAVE_SINGLE_PRECISION
#if WITH_CR32
#define DFT_FLOAT float
#define ORDERED_CONVOLVE lsx_ordered_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 mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho);
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);
if (h) for (i = 0; i <= m / 2; ++i) {
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;
if (m - i != 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 att, /* Stop-band attenuation in dB */
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 */
{
int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1);
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 */
tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */
tr_bw /= phases, Fs /= phases;
@ -145,7 +145,7 @@ double * lsx_design_lpf(
static double safe_log(double x)
{
assert(x >= 0);
if (x)
if (x!=0)
return log(x);
lsx_debug("log(0)");
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)
--peak;
if (!phase1)
if (phase1==0)
begin = 0;
else if (phase1 == 1)
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));
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

@ -31,9 +31,14 @@ double * lsx_design_lpf(
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */
double att, /* Stop-band attenuation in dB */
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 */
void lsx_fir_to_phase(double * * h, int * len,
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

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}}},
};

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. */
/* 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. */
#define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j;
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
#define COEFS ((sample_t const *)p->coefs)
#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);
int i, num_out = (stage_occupancy(p) + 1) / 2;
sample_t * output = fifo_reserve(output_fifo, num_out);
sample_t const * __restrict input = stage_read_p(p);
int num_in = min(stage_occupancy(p), p->input_size);
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) {
int j = 0;
sample_t sum = input[0] * .5f;
CONVOLVE
output[i] = sum;
BEGINNING; CONVOLVE; END;
}
fifo_read(&p->fifo, 2 * num_out, NULL);
}
#undef _
#undef __
#undef ____
#undef BEGINNING
#undef END
#undef COEFS
#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. */
#if !defined soxr_internal_included
#define soxr_internal_included
#include "soxr-config.h"
#include "std-types.h"
#undef min
#undef max
#define min(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 linear_to_dB(x) (log10(x) * 20)
#define array_length(a) (sizeof(a)/sizeof(a[0]))
#if !defined AL
#define AL(a) array_length(a)
#endif
#define iAL(a) (int)AL(a)
#define sqr(a) ((a) * (a))
#ifdef __GNUC__
#if defined __GNUC__
#define UNUSED __attribute__ ((unused))
#else
#define UNUSED
#endif
#if defined NDEBUG
#if !WITH_DEV_TRACE
#ifdef __GNUC__
void lsx_dummy(char const *, ...);
#else
static __inline void lsx_dummy(char const * x, ...) {}
#endif
#define lsx_debug if(0) lsx_dummy
#define lsx_debug_more lsx_debug
#else
#include <stdarg.h>
#include <stdio.h>
UNUSED static void lsx_debug(char const * fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
va_end(args);
}
extern int _soxr_trace_level;
void _soxr_trace(char const * fmt, ...);
#define lsx_debug if (_soxr_trace_level > 0) _soxr_trace
#define lsx_debug_more if (_soxr_trace_level > 1) _soxr_trace
#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

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);}

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

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

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,
authored by Dr Paul Swarztrauber of NCAR, in 1985.
@ -60,8 +65,9 @@
- 1D transforms only, with 32-bit single precision.
- 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
are all acceptable lengths). Performance is best for 128<=N<=8192.
N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128,
144, 160, etc are all acceptable lengths). Performance is best for
128<=N<=8192.
- all (float*) pointers in the functions below are expected to
have an "simd-compatible" alignment, that is 16 bytes on x86 and
@ -80,6 +86,10 @@
#ifdef __cplusplus
extern "C" {
#endif
#if PFFFT_DOUBLE
#define float double
#endif
/* 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
multiple concurrent threads.
*/
static PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform);
static void pffft_destroy_setup(PFFFT_Setup *);
static
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
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.
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
be used instead (this is probably the beest strategy for small
FFTs, say for N < 16384).[/del]
fft) floats, properly aligned. If 'work' is NULL, then stack will
be used instead (this is probably the best strategy for small
FFTs, say for N < 16384).
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
@ -128,7 +141,8 @@ extern "C" {
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(...,
@ -142,7 +156,8 @@ extern "C" {
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
@ -155,23 +170,28 @@ extern "C" {
the operation performed is: dft_ab += (dft_a * fdt_b)*scaling
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 dft_a, dft_b and dft_ab pointers may alias.
the float buffers must have the correct alignment (16-byte boundary
on intel and powerpc). This function may be used to obtain such
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 */
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
}
#endif
#endif
#endif

View File

@ -1,11 +1,14 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define _soxr_simd_aligned_free free
#define _soxr_simd_aligned_malloc malloc
#define SIMD_ALIGNED_FREE free
#define SIMD_ALIGNED_MALLOC malloc
#define PFFFT_SIMD_DISABLE
#include "pffft.c"
#define PFFFT_DOUBLE 0
#include "pffft-wrap.c"
#include "filter.h"
#include "rdft_t.h"
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
static void delete_setup(void * setup) {pffft_destroy_setup(setup);}
@ -15,8 +18,8 @@ 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 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 flags(void) {return RDFT_NEEDS_SCRATCH;}
typedef void (* fn_t)(void);
fn_t _soxr_rdft32_cb[] = {
(fn_t)setup,
(fn_t)setup,
@ -29,4 +32,8 @@ fn_t _soxr_rdft32_cb[] = {
(fn_t)_soxr_ordered_partial_convolve_f,
(fn_t)multiplier,
(fn_t)pffft_reorder_back,
(fn_t)malloc,
(fn_t)calloc,
(fn_t)free,
(fn_t)flags,
};

View File

@ -1,17 +1,20 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* 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 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 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 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 flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;}
typedef void (* fn_t)(void);
fn_t _soxr_rdft32s_cb[] = {
(fn_t)setup,
(fn_t)setup,
@ -21,7 +24,11 @@ fn_t _soxr_rdft32s_cb[] = {
(fn_t)backward,
(fn_t)obackward,
(fn_t)convolve,
(fn_t)_soxr_ordered_partial_convolve_simd,
(fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)multiplier,
(fn_t)pffft_reorder_back,
(fn_t)SIMD_ALIGNED_MALLOC,
(fn_t)SIMD_ALIGNED_CALLOC,
(fn_t)SIMD_ALIGNED_FREE,
(fn_t)flags,
};

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;}
fn_t _soxr_rdft64s_cb[] = {
(fn_t)setup,
(fn_t)setup,
(fn_t)pffft_destroy_setup,
(fn_t)forward,
(fn_t)oforward,
(fn_t)backward,
(fn_t)obackward,
(fn_t)convolve,
(fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD,
(fn_t)multiplier,
(fn_t)pffft_reorder_back,
(fn_t)SIMD_ALIGNED_MALLOC,
(fn_t)SIMD_ALIGNED_CALLOC,
(fn_t)SIMD_ALIGNED_FREE,
(fn_t)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. */
/* Resample using an interpolated poly-phase FIR with length LEN.*/
/* Input must be followed by LEN-1 samples. */
/* Resample using an interpolated poly-phase FIR with length LEN. */
/* Input must be followed by FIR_LENGTH-1 samples. */
#define a (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 0,j))
#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
#if COEF_INTERP != 1 && COEF_INTERP != 2 && COEF_INTERP != 3
#error COEF_INTERP
#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)
{
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);
sample_t * output = fifo_reserve(output_fifo, max_num_out);
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 * const __restrict output = fifo_reserve(output_fifo, max_num_out);
#if defined HI_PREC_CLOCK
#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;
}
CORE(N);
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
}
#undef _
#undef a
#undef b
#undef c
#undef d
#undef CORE
#undef cc
#undef core
#undef COEF_INTERP
#undef N
#undef BEGINNING
#undef END
#undef CONVOLVE
#undef FIR_LENGTH
#undef FUNCTION

View File

@ -1,32 +1,56 @@
/* 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. */
/* Resample using a non-interpolated poly-phase FIR with length LEN.*/
/* Input must be followed by LEN-1 samples. */
/* Resample using a non-interpolated poly-phase FIR with length LEN. */
/* Input must be followed by FIR_LENGTH-1 samples. */
#define _ sum += (coef(p->shared->poly_fir_coefs, 0, FIR_LENGTH, rem, 0, j)) *at[j], ++j;
#if SIMD_AVX || SIMD_SSE || SIMD_NEON
#define N (FIR_LENGTH>>2)
#define BEGINNING v4_t sum = vZero(); \
v4_t const * const __restrict coefs = (v4_t *)COEFS + N * rem;
#define _ sum = vMac(vLdu(at+j*4), coefs[j], sum), ++j;
#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
#define BEGINNING sample_t sum = 0; \
sample_t const * const __restrict coefs = (sample_t *)COEFS + N * rem;
#define _ sum += coefs[j]*at[j], ++j;
#define END output[i] = sum
#define CORE(n) core(n)
#endif
#define core(n) \
for (i = 0; at < num_in * p->L; ++i, at += step) { \
int const div = at / p->L, rem = at % p->L; \
sample_t const * const __restrict at = input + div; \
int j = 0; BEGINNING; CONVOLVE(n); END;}
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
{
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);
sample_t * output = fifo_reserve(output_fifo, max_num_out);
int num_in = min(stage_occupancy(p), p->input_size);
if (num_in) {
sample_t const * input = stage_read_p(p);
int at = p->at.integer, step = p->step.integer;
int i, num_out = (num_in * p->L - at + step - 1) / step;
sample_t * __restrict output = fifo_reserve(output_fifo, num_out);
for (i = 0; p->at.integer < num_in * p->L; ++i, p->at.integer += p->step.integer) {
int div = p->at.integer / p->L, rem = p->at.integer % p->L;
sample_t const * at = input + div;
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
CORE(N);
assert(i == num_out);
fifo_read(&p->fifo, at / p->L, NULL);
p->at.integer = at % p->L;
}
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
fifo_read(&p->fifo, p->at.integer / p->L, NULL);
p->at.integer = p->at.integer % p->L;
}
#undef _
#undef CORE
#undef cc
#undef core
#undef N
#undef BEGINNING
#undef MIDDLE
#undef END
#undef CONVOLVE
#undef FIR_LENGTH
#undef FUNCTION

View File

@ -1,724 +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 <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "filter.h"
#if defined SOXR_LIB
#include "internal.h"
typedef void (* fn_t)(void);
extern fn_t RDFT_CB[11];
#define rdft_forward_setup (*(void * (*)(int))RDFT_CB[0])
#define rdft_backward_setup (*(void * (*)(int))RDFT_CB[1])
#define rdft_delete_setup (*(void (*)(void *))RDFT_CB[2])
#define rdft_forward (*(void (*)(int, void *, sample_t *, sample_t *))RDFT_CB[3])
#define rdft_oforward (*(void (*)(int, void *, sample_t *, sample_t *))RDFT_CB[4])
#define rdft_backward (*(void (*)(int, void *, sample_t *, sample_t *))RDFT_CB[5])
#define rdft_obackward (*(void (*)(int, void *, sample_t *, sample_t *))RDFT_CB[6])
#define rdft_convolve (*(void (*)(int, void *, sample_t *, sample_t const *))RDFT_CB[7])
#define rdft_convolve_portion (*(void (*)(int, sample_t *, sample_t const *))RDFT_CB[8])
#define rdft_multiplier (*(int (*)(void))RDFT_CB[9])
#define rdft_reorder_back (*(void (*)(int, void *, sample_t *, sample_t *))RDFT_CB[10])
#endif
#if RATE_SIMD /* Align for SIMD: */
#include "simd.h"
#if 0 /* Not using this yet. */
#define RATE_SIMD_POLY 1
#define num_coefs4 ((num_coefs + 3) & ~3)
#define coefs4_check(i) ((i) < num_coefs)
#else
#define RATE_SIMD_POLY 0
#define num_coefs4 num_coefs
#define coefs4_check(i) 1
#endif
#define aligned_free _soxr_simd_aligned_free
#define aligned_malloc _soxr_simd_aligned_malloc
#define aligned_calloc _soxr_simd_aligned_calloc
#if 0
#define FIFO_REALLOC aligned_realloc
#define FIFO_MALLOC aligned_malloc
#define FIFO_FREE aligned_free
static void * aligned_realloc(void * q, size_t nb_bytes, size_t copy_bytes) {
void * p = aligned_malloc(nb_bytes);
if (p) memcpy(p, q, copy_bytes);
aligned_free(q);
return p;
}
#endif
#else
#define RATE_SIMD_POLY 0
#define num_coefs4 num_coefs
#define coefs4_check(i) 1
#define aligned_free free
#define aligned_malloc malloc
#define aligned_calloc calloc
#endif
#define FIFO_SIZE_T int
#include "fifo.h"
typedef union { /* Int64 in parts */
#if WORDS_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 WORDS_BIGENDIAN
struct {uint32_t ms, ls;} parts;
#else
struct {uint32_t ls, ms;} parts;
#endif
uint64_t all;
} uint64p_t;
#define FLOAT_HI_PREC_CLOCK 0 /* Non-float hi-prec has ~96 bits. */
#define float_step_t long double /* __float128 is also a (slow) option */
#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)]
#define raw_coef_t double
static sample_t * prepare_coefs(raw_coef_t const * coefs, int num_coefs,
int num_phases, int interp_order, double multiplier)
{
int i, j, length = num_coefs4 * num_phases;
sample_t * result = malloc((size_t)(length * (interp_order + 1)) * sizeof(*result));
double fm1 = coefs[0], f1 = 0, f2 = 0;
for (i = num_coefs4 - 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 = coefs4_check(i) && 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: if (interp_order) assert(0);
}
#define coef_coef(x) \
coef(result, interp_order, num_coefs4, j, x, num_coefs4 - 1 - i)
coef_coef(0) = (sample_t)f0;
if (interp_order > 0) coef_coef(1) = (sample_t)b;
if (interp_order > 1) coef_coef(2) = (sample_t)c;
if (interp_order > 2) coef_coef(3) = (sample_t)d;
#undef coef_coef
f2 = f1, f1 = f0;
}
return result;
}
typedef struct {
int dft_length, num_taps, post_peak;
void * dft_forward_setup, * dft_backward_setup;
sample_t * coefs;
} dft_filter_t;
typedef struct { /* So generated filter coefs may be shared between channels */
sample_t * poly_fir_coefs;
dft_filter_t dft_filter[2];
} rate_shared_t;
typedef enum {
irrational_stage = 1,
cubic_stage,
dft_stage,
half_stage,
rational_stage
} stage_type_t;
struct stage;
typedef void (* stage_fn_t)(struct stage * input, fifo_t * output);
#define MULT32 (65536. * 65536.)
typedef union { /* Fixed point arithmetic */
struct {uint64p_t ls; int64p_t ms;} fix;
float_step_t flt;
} step_t;
typedef struct stage {
/* Common to all stage types: */
stage_type_t type;
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. */
/* For a stage with variable (run-time generated) filter coefs: */
rate_shared_t * shared;
unsigned dft_filter_num; /* Which, if any, of the 2 DFT filters to use */
sample_t * dft_scratch, * dft_out;
/* 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)
static void cubic_stage_fn(stage_t * p, fifo_t * output_fifo)
{
int i, num_in = stage_occupancy(p), max_num_out = 1 + (int)(num_in*p->out_in_ratio);
sample_t const * input = stage_read_p(p);
sample_t * output = fifo_reserve(output_fifo, max_num_out);
#define integer fix.ms.parts.ms
#define fraction fix.ms.parts.ls
#define whole fix.ms.all
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 RATE_SIMD
#define dft_out p->dft_out
#else
#define dft_out output
#endif
static void dft_stage_fn(stage_t * p, fifo_t * output_fifo)
{
sample_t * output;
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;
while (p->at.integer + p->L * num_in >= f->dft_length) {
div_t divd = div(f->dft_length - overlap - p->at.integer + p->L - 1, p->L);
sample_t 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);
if (lsx_is_power_of_2(p->L)) { /* F-domain */
int portion = f->dft_length / p->L;
memcpy(dft_out, input, (unsigned)portion * sizeof(*dft_out));
rdft_oforward(portion, f->dft_forward_setup, dft_out, p->dft_scratch);
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];
for (portion <<= 1; i < f->dft_length; i += portion, portion <<= 1) {
memcpy(dft_out + i, dft_out, (size_t)portion * sizeof(*dft_out));
dft_out[i + 1] = 0;
}
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(*dft_out));
else {
memset(dft_out, 0, (size_t)f->dft_length * sizeof(*dft_out));
for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L)
dft_out[i] = 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 RATE_SIMD
if (p->step.integer == 1)
memcpy(output, dft_out, (size_t)f->dft_length * sizeof(sample_t));
#endif
if (p->step.integer != 1) {
for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j,
i += p->step.integer)
output[j] = 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 RATE_SIMD
memcpy(output, dft_out, (size_t)(f->dft_length >> m) * sizeof(sample_t));
#endif
fifo_trim_by(output_fifo, (((1 << m) - 1) * f->dft_length + overlap) >>m);
}
}
}
#undef dft_out
/* 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, stage_t * p, int L, int M, double * multiplier,
int min_dft_size, int large_dft_size)
{
dft_filter_t * f = &p->shared->dft_filter[instance];
int num_taps = 0, dft_length = f->dft_length, i;
bool f_domain_m = abs(3-M) == 1 && Fs <= 1;
if (!dft_length) {
int k = phase == 50 && lsx_is_power_of_2(L) && Fn == L? L << 1 : 4;
double * h = lsx_design_lpf(Fp, Fs, Fn, att, &num_taps, -k, -1.);
if (phase != 50)
lsx_fir_to_phase(&h, &num_taps, &f->post_peak, phase);
else f->post_peak = num_taps / 2;
dft_length = set_dft_length(num_taps, min_dft_size, large_dft_size);
f->coefs = aligned_calloc((size_t)dft_length, sizeof(*f->coefs));
for (i = 0; i < num_taps; ++i)
f->coefs[(i + dft_length - num_taps + 1) & (dft_length - 1)]
= (sample_t)(h[i] * ((1. / dft_length) * rdft_multiplier() * L * *multiplier));
free(h);
}
#if RATE_SIMD
p->dft_out = aligned_malloc(sizeof(sample_t) * (size_t)dft_length);
#endif
#if 1 /* In fact, currently, only pffft needs this. */
p->dft_scratch = aligned_malloc(2 * sizeof(sample_t) * (size_t)dft_length);
#endif
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->type = dft_stage;
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;
}
#include "filters.h"
typedef struct {
double factor;
uint64_t samples_in, samples_out;
int num_stages;
stage_t * stages;
} rate_t;
#define pre_stage p->stages[shift]
#define arb_stage p->stages[shift + have_pre_stage]
#define post_stage p->stages[shift + have_pre_stage + have_arb_stage]
#define have_pre_stage (preM * preL != 1)
#define have_arb_stage (arbM * arbL != 1)
#define have_post_stage (postM * postL != 1)
#define TO_3dB(a) ((1.6e-6*a-7.5e-4)*a+.646)
#define LOW_Q_BW0 (1385 / 2048.) /* 0.67625 rounded to be a FP exact. */
typedef enum {
rolloff_none, rolloff_small /* <= 0.01 dB */, rolloff_medium /* <= 0.35 dB */
} rolloff_t;
static char const * rate_init(
/* Private work areas (to be supplied by the client): */
rate_t * p, /* Per audio channel. */
rate_shared_t * shared, /* Between channels (undergoing same rate change)*/
/* Public parameters: Typically */
double factor, /* Input rate divided by output rate. */
double bits, /* Required bit-accuracy (pass + stop) 16|20|28 */
double phase, /* Linear/minimum etc. filter phase. 50 */
double passband_end, /* 0dB pt. bandwidth to preserve; nyquist=1 0.913*/
double stopband_begin, /* Aliasing/imaging control; > passband_end 1 */
rolloff_t rolloff, /* Pass-band roll-off small */
bool maintain_3dB_pt, /* true */
double multiplier, /* Linear gain to apply during conversion. 1 */
/* Primarily for test/development purposes: */
bool use_hi_prec_clock, /* Increase irrational ratio accuracy. false */
int interpolator, /* Force a particular coef interpolator. -1 */
size_t max_coefs_size, /* k bytes of coefs to try to keep below. 400 */
bool noSmallIntOpt, /* Disable small integer optimisations. false */
int log2_min_dft_size,
int log2_large_dft_size)
{
double att = (bits + 1) * linear_to_dB(2.), attArb = att; /* pass + stop */
double tbw0 = 1 - passband_end, Fs_a = stopband_begin;
double arbM = factor, tbw_tighten = 1;
int n = 0, i, preL = 1, preM = 1, shift = 0, arbL = 1, postL = 1, postM = 1;
bool upsample = false, rational = false, iOpt = !noSmallIntOpt;
int mode = rolloff > rolloff_small? factor > 1 || passband_end > LOW_Q_BW0:
(int)ceil(2 + (bits - 17) / 4);
stage_t * s;
assert(factor > 0);
assert(!bits || (15 <= bits && bits <= 33));
assert(0 <= phase && phase <= 100);
assert(.53 <= passband_end);
assert(stopband_begin <= 1.2);
assert(passband_end + .005 < stopband_begin);
p->factor = factor;
if (bits) while (!n++) { /* Determine stages: */
int try, L, M, x, maxL = interpolator > 0? 1 : mode? 2048 :
(int)ceil((double)max_coefs_size * 1000. / (U100_l * sizeof(sample_t)));
double d, epsilon = 0, frac;
upsample = arbM < 1;
for (i = (int)(arbM * .5), shift = 0; i >>= 1; arbM *= .5, ++shift);
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))
epsilon = fabs((uint32_t)(frac * MULT32 + .5) / (frac * MULT32) - 1);
for (i = 1, rational = !frac; 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), shift += arbM > 2, arbM /= 1 + (arbM > 2);
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 = shift + have_pre_stage + have_arb_stage + have_post_stage;
if (!p->num_stages && multiplier != 1) {
arbL = 0;
++p->num_stages;
}
p->stages = calloc((size_t)p->num_stages + 1, sizeof(*p->stages));
for (i = 0; i < p->num_stages; ++i)
p->stages[i].shared = shared;
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);
}
for (n = 0; (size_t)n + 1 < array_length(half_firs) && att > half_firs[n].att; ++n);
for (i = 0, s = p->stages; i < shift; ++i, ++s) {
s->type = half_stage;
s->fn = half_firs[n].fn;
s->pre_post = 4 * half_firs[n].num_coefs;
s->preload = s->pre = s->pre_post >> 1;
}
if (have_pre_stage) {
if (maintain_3dB_pt && have_post_stage) { /* Trans. bands overlapping. */
double tbw3 = tbw0 * TO_3dB(att); /* FFS: consider Fs_a. */
double x = ((2.1429e-4 - 5.2083e-7 * att) * att - .015863) * att + 3.95;
x = att * pow((tbw0 - tbw3) / (postM / (factor * postL) - 1 + tbw0), x);
if (x > .035) {
tbw_tighten = ((4.3074e-3 - 3.9121e-4 * x) * x - .040009) * x + 1.0014;
lsx_debug("x=%g tbw_tighten=%g", x, tbw_tighten);
}
}
dft_stage_init(0, 1 - tbw0 * tbw_tighten, Fs_a, preM? max(preL, preM) :
arbM / arbL, att, phase, &pre_stage, preL, max(preM, 1), &multiplier,
log2_min_dft_size, log2_large_dft_size);
}
if (!bits && have_arb_stage) { /* Quick and dirty arb stage: */
arb_stage.type = cubic_stage;
arb_stage.fn = cubic_stage_fn;
arb_stage.mult = multiplier, multiplier = 1;
arb_stage.step.whole = (int64_t)(arbM * MULT32 + .5);
arb_stage.pre_post = max(3, arb_stage.step.integer);
arb_stage.preload = arb_stage.pre = 1;
arb_stage.out_in_ratio = MULT32 / (double)arb_stage.step.whole;
}
else if (have_arb_stage) { /* Higher quality arb stage: */
poly_fir_t const * f = &poly_firs[6*(upsample + !!preM) + mode - !upsample];
int order, num_coefs = (int)f->interp[0].scalar, phase_bits, phases;
size_t coefs_size;
double x = .5, at, Fp, Fs, Fn, mult = upsample? 1 : arbL / arbM;
poly_fir1_t const * f1;
Fn = !upsample && preM? x = arbM / arbL : 1;
Fp = !preM? mult : mode? .5 : 1;
Fs = 2 - Fp; /* Ignore Fs_a; it would have little benefit here. */
Fp *= 1 - tbw0;
if (rolloff > rolloff_small && mode)
Fp = !preM? mult * .5 - .125 : mult * .05 + .1;
else if (rolloff == rolloff_small)
Fp = Fs - (Fs - .148 * x - Fp * .852) * (.00813 * bits + .973);
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) {
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 * (arb_stage.phase0 = .5 * (num_coefs & 1));
order = i + (i && mode > 4);
coefs_size = (size_t)(num_coefs4 * phases * (order + 1)) * sizeof(sample_t);
} while (interpolator < 0 && i < 2 && f->interp[i+1].fn &&
coefs_size / 1000 > max_coefs_size);
if (!arb_stage.shared->poly_fir_coefs) {
int num_taps = num_coefs * phases - 1;
raw_coef_t * coefs = lsx_design_lpf(
Fp, Fs, Fn, attArb, &num_taps, phases, f->beta);
arb_stage.shared->poly_fir_coefs = prepare_coefs(
coefs, num_coefs, phases, order, multiplier);
lsx_debug("fir_len=%i phases=%i coef_interp=%i size=%.3gk",
num_coefs, phases, order, (double)coefs_size / 1000.);
free(coefs);
}
multiplier = 1;
arb_stage.type = rational? rational_stage : irrational_stage;
arb_stage.fn = f1->fn;
arb_stage.pre_post = num_coefs4 - 1;
arb_stage.preload = ((num_coefs - 1) >> 1) + (num_coefs4 - num_coefs);
arb_stage.n = num_coefs4;
arb_stage.phase_bits = phase_bits;
arb_stage.L = arbL;
arb_stage.use_hi_prec_clock = mode > 1 && use_hi_prec_clock && !rational;
#if FLOAT_HI_PREC_CLOCK
if (arb_stage.use_hi_prec_clock) {
arb_stage.at.flt = at;
arb_stage.step.flt = arbM;
arb_stage.out_in_ratio = (double)(arbL / arb_stage.step.flt);
} else
#endif
{
arb_stage.at.whole = (int64_t)(at * MULT32 + .5);
#if !FLOAT_HI_PREC_CLOCK
if (arb_stage.use_hi_prec_clock) {
arb_stage.at.fix.ls.parts.ms = 0x80000000ul;
arbM *= MULT32;
arb_stage.step.whole = (int64_t)arbM;
arbM -= (double)arb_stage.step.whole;
arbM *= MULT32 * MULT32;
arb_stage.step.fix.ls.all = (uint64_t)arbM;
} else
#endif
arb_stage.step.whole = (int64_t)(arbM * MULT32 + .5);
arb_stage.out_in_ratio = MULT32 * arbL / (double)arb_stage.step.whole;
}
}
if (have_post_stage)
dft_stage_init(1, 1 - (1 - (1 - tbw0) *
(upsample? factor * postL / postM : 1)) * tbw_tighten, Fs_a,
(double)max(postL, postM), att, phase, &post_stage, postL, postM,
&multiplier, log2_min_dft_size, log2_large_dft_size);
lsx_debug("%g: »%i⋅%i/%i⋅%i/%g⋅%i/%i",
1/factor, shift, preL, preM, arbL, arbM, postL, postM);
for (i = 0, s = p->stages; i < p->num_stages; ++i, ++s) {
fifo_create(&s->fifo, (int)sizeof(sample_t));
memset(fifo_reserve(&s->fifo, s->preload), 0, sizeof(sample_t) * (size_t)s->preload);
lsx_debug("%5i|%-5i preload=%i remL=%i o/i=%g",
s->pre, s->pre_post - s->pre, s->preload, s->at.integer, s->out_in_ratio);
}
fifo_create(&s->fifo, (int)sizeof(sample_t));
return 0;
}
static void rate_process(rate_t * p)
{
stage_t * stage = p->stages;
int i;
for (i = 0; i < p->num_stages; ++i, ++stage)
stage->fn(stage, &(stage+1)->fifo);
}
static sample_t * rate_input(rate_t * p, sample_t const * samples, size_t n)
{
p->samples_in += n;
return fifo_write(&p->stages[0].fifo, (int)n, samples);
}
static sample_t const * rate_output(rate_t * p, sample_t * samples, size_t * n)
{
fifo_t * fifo = &p->stages[p->num_stages].fifo;
p->samples_out += *n = min(*n, (size_t)fifo_occupancy(fifo));
return fifo_read(fifo, (int)*n, samples);
}
static void rate_flush(rate_t * p)
{
fifo_t * fifo = &p->stages[p->num_stages].fifo;
#if defined _MSC_VER && _MSC_VER == 1200
uint64_t samples_out = (uint64_t)(int64_t)((double)(int64_t)p->samples_in / p->factor + .5);
#else
uint64_t samples_out = (uint64_t)((double)p->samples_in / p->factor + .5);
#endif
size_t remaining = (size_t)(samples_out - p->samples_out);
sample_t * buff = calloc(1024, sizeof(*buff));
if (samples_out > p->samples_out) {
while ((size_t)fifo_occupancy(fifo) < remaining) {
rate_input(p, buff, 1024);
rate_process(p);
}
fifo_trim_to(fifo, (int)remaining);
p->samples_in = 0;
}
free(buff);
}
static void rate_close(rate_t * p)
{
rate_shared_t * shared = p->stages[0].shared;
int i;
for (i = 0; i <= p->num_stages; ++i) {
stage_t * s = &p->stages[i];
aligned_free(s->dft_scratch);
aligned_free(s->dft_out);
fifo_delete(&s->fifo);
}
if (shared) {
for (i = 0; i < 2; ++i) {
dft_filter_t * f= &shared->dft_filter[i];
aligned_free(f->coefs);
rdft_delete_setup(f->dft_forward_setup);
rdft_delete_setup(f->dft_backward_setup);
}
free(shared->poly_fir_coefs);
memset(shared, 0, sizeof(*shared));
}
free(p->stages);
}
#if defined SOXR_LIB
static double rate_delay(rate_t * p)
{
#if defined _MSC_VER && _MSC_VER == 1200
double samples_out = (double)(int64_t)p->samples_in / p->factor;
return samples_out - (double)(int64_t)p->samples_out;
#else
double samples_out = (double)p->samples_in / p->factor;
return samples_out - (double)p->samples_out;
#endif
}
static void rate_sizes(size_t * shared, size_t * channel)
{
*shared = sizeof(rate_shared_t);
*channel = sizeof(rate_t);
}
#include "soxr.h"
static char const * rate_create(
void * channel,
void * shared,
double io_ratio,
soxr_quality_spec_t * q_spec,
soxr_runtime_spec_t * r_spec,
double scale)
{
return rate_init(
channel, shared,
io_ratio,
q_spec->precision,
q_spec->phase_response,
q_spec->passband_end,
q_spec->stopband_begin,
"\1\2\0"[q_spec->flags & 3],
!!(q_spec->flags & SOXR_MAINTAIN_3DB_PT),
scale,
!!(q_spec->flags & SOXR_HI_PREC_CLOCK),
(int)(r_spec->flags & 3) - 1,
r_spec->coef_size_kbytes,
!!(r_spec->flags & SOXR_NOSMALLINTOPT),
(int)r_spec->log2_min_dft_size,
(int)r_spec->log2_large_dft_size);
}
static char const * id(void)
{
return RATE_ID;
}
fn_t RATE_CB[] = {
(fn_t)rate_input,
(fn_t)rate_process,
(fn_t)rate_output,
(fn_t)rate_flush,
(fn_t)rate_close,
(fn_t)rate_delay,
(fn_t)rate_sizes,
(fn_t)rate_create,
(fn_t)0,
(fn_t)id,
};
#endif

View File

@ -1,9 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define sample_t float
#define RATE_SIMD 0
#define RDFT_CB _soxr_rdft32_cb
#define RATE_CB _soxr_rate32_cb
#define RATE_ID "single-precision"
#include "rate.h"

View File

@ -1,9 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define sample_t float
#define RATE_SIMD 1
#define RDFT_CB _soxr_rdft32s_cb
#define RATE_CB _soxr_rate32s_cb
#define RATE_ID "single-precision-SIMD"
#include "rate.h"

View File

@ -1,9 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define sample_t double
#define RATE_SIMD 0
#define RDFT_CB _soxr_rdft64_cb
#define RATE_CB _soxr_rate64_cb
#define RATE_ID "double-precision"
#include "rate.h"

View File

@ -0,0 +1,24 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
typedef void (* fn_t)(void);
#define rdft_forward_setup (*(void * (*)(int))RDFT_CB[0])
#define rdft_backward_setup (*(void * (*)(int))RDFT_CB[1])
#define rdft_delete_setup (*(void (*)(void *))RDFT_CB[2])
#define rdft_forward (*(void (*)(int, void *, void *, void *))RDFT_CB[3])
#define rdft_oforward (*(void (*)(int, void *, void *, void *))RDFT_CB[4])
#define rdft_backward (*(void (*)(int, void *, void *, void *))RDFT_CB[5])
#define rdft_obackward (*(void (*)(int, void *, void *, void *))RDFT_CB[6])
#define rdft_convolve (*(void (*)(int, void *, void *, void const *))RDFT_CB[7])
#define rdft_convolve_portion (*(void (*)(int, void *, void const *))RDFT_CB[8])
#define rdft_multiplier (*(int (*)(void))RDFT_CB[9])
#define rdft_reorder_back (*(void (*)(int, void *, void *, void *))RDFT_CB[10])
#define rdft_malloc (*(void * (*)(size_t))RDFT_CB[11])
#define rdft_calloc (*(void * (*)(size_t, size_t))RDFT_CB[12])
#define rdft_free (*(void (*)(void *))RDFT_CB[13])
#define rdft_flags (*(int (*)(void))RDFT_CB[14])
/* Flag templates: */
#define RDFT_IS_SIMD 1
#define RDFT_NEEDS_SCRATCH 2

View File

@ -1,9 +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. */
#if defined DITHER
#define DITHERING (1./32)*(int)(((ran1>>=3)&31)-((ran2>>=3)&31))
#define DITHERING + (1./32)*(int)(((ran1>>=3)&31)-((ran2>>=3)&31))
#define DITHER_RAND (seed = 1664525UL * seed + 1013904223UL) >> 3
#define DITHER_VARS unsigned long ran1 = DITHER_RAND, ran2 = DITHER_RAND
#define SEED_ARG , unsigned long * seed0
@ -12,10 +12,11 @@
#define COPY_SEED1 unsigned long seed1 = seed
#define PASS_SEED1 , &seed1
#define PASS_SEED , &seed
#define FLOATD double
#else
#define DITHERING 0
#define DITHERING
#define DITHER_VARS
#define SEED_ARG
#define SAVE_SEED
@ -23,9 +24,12 @@
#define COPY_SEED1
#define PASS_SEED1
#define PASS_SEED
#define FLOATD FLOATX
#endif
#define DO_16 _;_;_;_;_;_;_;_;_;_;_;_;_;_;_;_
#if defined FE_INVALID && defined FPU_RINT
@ -35,8 +39,8 @@ static void RINT_CLIP(RINT_T * const dest, FLOATX const * const src,
COPY_SEED
DITHER_VARS;
for (; i < n; ++i) {
double d = src[i] + DITHERING;
dest[stride * i] = RINT(d);
FLOATD const d = src[i] DITHERING;
RINT(dest[stride * i], d);
if (fe_test_invalid()) {
fe_clear_invalid();
dest[stride * i] = d > 0? RINT_MAX : -RINT_MAX - 1;
@ -56,29 +60,29 @@ static size_t LSX_RINT_CLIP(void * * const dest0, FLOATX const * const src,
RINT_T * dest = *dest0;
COPY_SEED
#if defined FE_INVALID && defined FPU_RINT
#define _ dest[i] = RINT(src[i] + DITHERING), ++i,
fe_clear_invalid();
for (i = 0; i < (n & ~7u);) {
#define _ RINT(dest[i], src[i] DITHERING); ++i
for (i = 0; i < (n & ~15u);) {
COPY_SEED1;
DITHER_VARS;
_ _ _ _ _ _ _ _ 0;
DO_16;
if (fe_test_invalid()) {
fe_clear_invalid();
RINT_CLIP(dest, src, 1, i - 8, i, &clips PASS_SEED1);
RINT_CLIP(dest, src, 1, i - 16, i, &clips PASS_SEED1);
}
}
RINT_CLIP(dest, src, 1, i, n, &clips PASS_SEED);
#else
#define _ d = src[i] + DITHERING, dest[i++] = (RINT_T)(d > 0? d+.5 >= N? ++clips, N-1 : d+.5 : d-.5 <= -N-1? ++clips, -N:d-.5),
#define _ d = src[i] DITHERING, dest[i++] = (RINT_T)(d > 0? \
d+.5 >= N? ++clips, N-1 : d+.5 : d-.5 <= -N-1? ++clips, -N:d-.5)
const double N = 1. + RINT_MAX;
double d;
for (i = 0; i < (n & ~7u);) {
for (i = 0; i < (n & ~15u);) {
DITHER_VARS;
_ _ _ _ _ _ _ _ 0;
DO_16;
}
{
DITHER_VARS;
for (; i < n; _ 0);
for (; i < n; _);
}
#endif
SAVE_SEED;
@ -97,34 +101,34 @@ static size_t LSX_RINT_CLIP_2(void * * dest0, FLOATX const * const * srcs,
RINT_T * dest = *dest0;
COPY_SEED
#if defined FE_INVALID && defined FPU_RINT
#define _ dest[stride * i] = RINT(src[i] + DITHERING), ++i,
fe_clear_invalid();
#define _ RINT(dest[stride * i], src[i] DITHERING); ++i
for (j = 0; j < stride; ++j, ++dest) {
FLOATX const * const src = srcs[j];
for (i = 0; i < (n & ~7u);) {
for (i = 0; i < (n & ~15u);) {
COPY_SEED1;
DITHER_VARS;
_ _ _ _ _ _ _ _ 0;
DO_16;
if (fe_test_invalid()) {
fe_clear_invalid();
RINT_CLIP(dest, src, stride, i - 8, i, &clips PASS_SEED1);
RINT_CLIP(dest, src, stride, i - 16, i, &clips PASS_SEED1);
}
}
RINT_CLIP(dest, src, stride, i, n, &clips PASS_SEED);
}
#else
#define _ d = src[i] + DITHERING, dest[stride * i++] = (RINT_T)(d > 0? d+.5 >= N? ++clips, N-1 : d+.5 : d-.5 <= -N-1? ++clips, -N:d-.5),
#define _ d = src[i] DITHERING, dest[stride * i++] = (RINT_T)(d > 0? \
d+.5 >= N? ++clips, N-1 : d+.5 : d-.5 <= -N-1? ++clips, -N:d-.5)
const double N = 1. + RINT_MAX;
double d;
for (j = 0; j < stride; ++j, ++dest) {
FLOATX const * const src = srcs[j];
for (i = 0; i < (n & ~7u);) {
for (i = 0; i < (n & ~15u);) {
DITHER_VARS;
_ _ _ _ _ _ _ _ 0;
DO_16;
}
{
DITHER_VARS;
for (; i < n; _ 0);
for (; i < n; _);
}
}
#endif
@ -134,6 +138,7 @@ static size_t LSX_RINT_CLIP_2(void * * dest0, FLOATX const * const * srcs,
}
#undef _
#undef FLOATD
#undef PASS_SEED
#undef PASS_SEED1
#undef COPY_SEED1

View File

@ -1,68 +1,102 @@
/* 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. */
#if !defined soxr_rint_included
#define soxr_rint_included
#include "soxr-config.h"
#if HAVE_LRINT && LONG_MAX == 2147483647L
#include <math.h>
#define FPU_RINT32
#define rint32 lrint
#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define FPU_RINT32
static __inline int32_t rint32(double input) {
int32_t result;
__asm__ __volatile__("fistpl %0": "=m"(result): "t"(input): "st");
return result;
}
#elif defined __GNUC__ && defined __arm__
#define FPU_RINT32
static __inline int32_t rint32(double input) {
register int32_t result;
__asm__ __volatile__ ("ftosid %0, %P1": "=w"(result): "w"(input));
return result;
}
#elif defined _MSC_VER && defined _M_IX86 /* FIXME need solution for MSVC x64 */
#define FPU_RINT32
static __inline int32_t rint32(double input) {
int32_t result;
_asm {
fld input
fistp result
}
return result;
}
#else
#define rint32(x) (int32_t)((x) < 0? x - .5 : x + .5)
#endif
#include "std-types.h"
/* For x86, compiler-supplied versions of these functions (where available)
* can have poor performance (e.g. mingw32), so prefer these asm versions: */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define FPU_RINT32
#define FPU_RINT16
static __inline int16_t rint16(double input) {
int16_t result;
__asm__ __volatile__("fistps %0": "=m"(result): "t"(input): "st");
return result;
#define rint32D(a,b) __asm__ __volatile__("fistpl %0": "=m"(a): "t"(b): "st")
#define rint16D(a,b) __asm__ __volatile__("fistps %0": "=m"(a): "t"(b): "st")
#define rint32F rint32D
#define rint16F rint16D
#define FE_INVALID 1
static __inline int fe_test_invalid(void) {
int status_word;
__asm__ __volatile__("fnstsw %%ax": "=a"(status_word));
return status_word & FE_INVALID;
}
#elif defined _MSC_VER && defined _M_IX86 /* FIXME need solution for MSVC x64 */
static __inline int fe_clear_invalid(void) {
int32_t status[7];
__asm__ __volatile__("fnstenv %0": "=m"(status));
status[1] &= ~FE_INVALID;
__asm__ __volatile__("fldenv %0": : "m"(*status));
return 0;
}
#elif defined _MSC_VER && defined _M_IX86
#define FPU_RINT32
#define FPU_RINT16
static __inline int16_t rint16(double input) {
int16_t result;
_asm {
fld input
fistp result
}
return result;
#define rint_fn(N,Y,X) \
static __inline void N(Y *y, X x) {Y t; {__asm fld x __asm fistp t} *y=t;}
rint_fn(rint32d, int32_t, double)
rint_fn(rint32f, int32_t, float )
rint_fn(rint16d, int16_t, double)
rint_fn(rint16f, int16_t, float )
#define rint32D(y,x) rint32d(&(y),x)
#define rint32F(y,x) rint32f(&(y),x)
#define rint16D(y,x) rint16d(&(y),x)
#define rint16F(y,x) rint16f(&(y),x)
#define FE_INVALID 1
static __inline int fe_test_invalid(void) {
short status_word;
__asm fnstsw status_word
return status_word & FE_INVALID;
}
#else
#define rint16(x) (int16_t)((x) < 0? x - .5 : x + .5)
static __inline int fe_clear_invalid(void) {
int32_t status[7];
__asm fnstenv status
status[1] &= ~FE_INVALID;
__asm fldenv status
return 0;
}
#elif defined _MSC_VER && defined _M_X64
#include <emmintrin.h>
#include <float.h>
#define FPU_RINT32
#define FPU_RINT16
static __inline void rint32d(int32_t *y, double x) {
*y = _mm_cvtsd_si32(_mm_load_sd(&x));}
static __inline void rint32f(int32_t *y, float x) {
*y = _mm_cvtss_si32(_mm_load_ss(&x));}
static __inline void rint16d(int16_t *y, double x) {
x = x*65536+32738; *y = (int16_t)(_mm_cvtsd_si32(_mm_load_sd(&x)) >> 16);}
#define rint32D(y,x) rint32d(&(y),x)
#define rint32F(y,x) rint32f(&(y),x)
#define rint16D(y,x) rint16d(&(y),x)
#define rint16F(y,x) rint16d(&(y),(double)(x))
#define FE_INVALID 1
#define fe_test_invalid() (_statusfp() & _SW_INVALID)
#define fe_clear_invalid _clearfp /* Note: clears all. */
#elif HAVE_LRINT && LONG_MAX == 2147483647L && HAVE_FENV_H
#include <math.h>
#include <fenv.h>
#define FPU_RINT32
#define rint32D(y,x) ((y)=lrint(x))
#define rint32F(y,x) ((y)=lrintf(x))
#define fe_test_invalid() fetestexcept(FE_INVALID)
#define fe_clear_invalid() feclearexcept(FE_INVALID)
#endif
#if !defined FPU_RINT32
#define rint32D(y,x) ((y)=(int32_t)((x) < 0? x - .5 : x + .5))
#define rint32F(y,x) rint32D(y,(double)(x))
#endif
#if !defined FPU_RINT16
#define rint16D(y,x) ((y)=(int16_t)((x) < 0? x - .5 : x + .5))
#define rint16F(y,x) rint16D(y,(double)(x))
#endif
static __inline int32_t rint32(double input) {
int32_t result; rint32D(result, input); return result;}
static __inline int16_t rint16(double input) {
int16_t result; rint16D(result, input); return result;}
#endif

View File

@ -1,5 +0,0 @@
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
#define PFFT_MACROS_ONLY
#include "pffft.c"

View File

@ -1,16 +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 simd_included
#define simd_included
#include <stddef.h>
void * _soxr_simd_aligned_malloc(size_t);
void * _soxr_simd_aligned_calloc(size_t, size_t);
void _soxr_simd_aligned_free(void *);
void _soxr_ordered_convolve_simd(int n, void * not_used, float * a, const float * b);
void _soxr_ordered_partial_convolve_simd(int n, float * a, const float * b);
#endif

View File

@ -0,0 +1,198 @@
/* SoX Resampler Library Copyright (c) 2007-18 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"
#include "soxr-lsr.h"
#include "rint.h"
SRC_STATE *src_new(SRC_SRCTYPE id, int channels, SRC_ERROR * error)
{
return src_callback_new(0, id, channels, error, 0);
}
SRC_ERROR src_process(SRC_STATE *p, SRC_DATA * io)
{
size_t idone , odone;
if (!p || !io) return -1;
soxr_set_error(
p, soxr_set_io_ratio(p, 1/io->src_ratio, (size_t)io->output_frames));
soxr_process(p, io->data_in, /* hack: */
(size_t)(io->end_of_input? ~io->input_frames : io->input_frames),
&idone, io->data_out, (size_t)io->output_frames, &odone);
io->input_frames_used = (long)idone, io->output_frames_gen = (long)odone;
return -!!soxr_error(p);
}
SRC_ERROR src_set_ratio(SRC_STATE * p, double oi_ratio)
{
return -!!soxr_set_io_ratio(p, 1/oi_ratio, 0);
}
SRC_ERROR src_reset(SRC_STATE * p)
{
return -!!soxr_clear(p);
}
SRC_ERROR src_error(SRC_STATE * p)
{
return -!!soxr_error(p);
}
SRC_STATE * src_delete(SRC_STATE * p)
{
soxr_delete(p);
return 0;
}
SRC_STATE *src_callback_new(src_callback_t fn,
SRC_SRCTYPE id, int channels, SRC_ERROR * error0, void * p)
{
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + (unsigned)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);
soxr = soxr_create(0, 0, (unsigned)channels, &error, 0, &q_spec, &r_spec);
if (soxr)
error = soxr_set_input_fn(soxr, (soxr_input_fn_t)fn, p, 0);
if (error0)
*error0 = -!!error;
return soxr;
}
long src_callback_read(SRC_STATE *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);
}
SRC_ERROR src_simple(SRC_DATA * io, SRC_SRCTYPE id, int channels)
{
size_t idone, odone;
soxr_error_t error;
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + (unsigned)id, 0);
char const * e = getenv("SOXR_LSR_NUM_THREADS");
soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1));
if (!io || channels<=0 || io->input_frames<0 || io->output_frames<0) return-1;
error = soxr_oneshot(1, io->src_ratio, (unsigned)channels, io->data_in,
(size_t)io->input_frames, &idone, io->data_out, (size_t)io->output_frames,
&odone, 0, &q_spec, &r_spec);
io->input_frames_used = (long)idone, io->output_frames_gen = (long)odone;
return -!!error;
}
char const * src_get_name(SRC_SRCTYPE id)
{
static char const * const names[] = {
"LSR best sinc", "LSR medium sinc", "LSR fastest sinc",
"LSR ZOH", "LSR linear", "SoX VHQ"};
return (unsigned)id < 5u + !getenv("SOXR_LSR_STRICT")? names[id] : 0;
}
char const * src_get_description(SRC_SRCTYPE id)
{
return src_get_name(id);
}
char const * src_get_version(void)
{
return soxr_version();
}
char const * src_strerror(SRC_ERROR error)
{
return error == 1? "Placeholder." : error ? "soxr error" : soxr_strerror(0);
}
int src_is_valid_ratio(double oi_ratio)
{
return getenv("SOXR_LSR_STRICT")?
oi_ratio >= 1./256 && oi_ratio <= 256 : oi_ratio > 0;
}
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_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_int_to_float_array(int const * src, float * dest, int len)
{
assert (src && dest);
while (len--) dest[len] = (float)(src[len] * (1 / (32768. * 65536.)));
}
void src_float_to_int_array(float const * src, int * dest, int len)
{
double d, N = 32768. * 65536.; /* N.B. int32, not int! (Also above fn.) */
assert (src && dest);
while (len--) d = src[len] * N, dest[len] =
d >= N - 1? (int)(N - 1) : d < -N? (int)(-N) : rint32(d);
}

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
* under the terms of the GNU Lesser General Public License as published by
@ -37,13 +37,12 @@
#endif
typedef float SRC_SAMPLE;
#if !defined SOXR_LIB
enum SRC_SRCTYPE_e {SRC_SINC_BEST_QUALITY, SRC_SINC_MEDIUM_QUALITY,
SRC_SINC_FASTEST, SRC_ZERO_ORDER_HOLD, SRC_LINEAR};
typedef int SRC_SRCTYPE;
typedef int SRC_ERROR;
typedef long (* src_callback_t)(void *, SRC_SAMPLE * *);
typedef struct SRC_STATE SRC_STATE;
typedef struct soxr SRC_STATE;
typedef struct SRC_DATA {
SRC_SAMPLE * data_in, * data_out;
long input_frames, output_frames;
@ -51,7 +50,6 @@ typedef struct SRC_DATA {
int end_of_input;
double src_ratio;
} SRC_DATA;
#endif
SOXR SRC_STATE * src_new(SRC_SRCTYPE, int num_channels, SRC_ERROR *);
SOXR SRC_ERROR src_process (SRC_STATE *, SRC_DATA *);
SOXR SRC_ERROR src_set_ratio(SRC_STATE *, double);

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. */
#include <math.h>
@ -10,6 +10,30 @@
#include "data-io.h"
#include "internal.h"
#if AVUTIL_FOUND
#include <libavutil/cpu.h>
#endif
#if WITH_DEV_TRACE
#include <stdarg.h>
#include <stdio.h>
int _soxr_trace_level;
void _soxr_trace(char const * fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
va_end(args);
}
#endif
char const * soxr_version(void)
@ -19,6 +43,7 @@ char const * soxr_version(void)
typedef void sample_t; /* float or double */
typedef void (* fn_t)(void);
typedef fn_t control_block_t[10];
@ -67,42 +92,52 @@ struct soxr {
/* TODO: these should not be here. */
#define TO_3dB(a) ((1.6e-6*a-7.5e-4)*a+.646)
#define LOW_Q_BW0 (1385 / 2048.) /* 0.67625 rounded to be a FP exact. */
#if WITH_CR32 || WITH_CR32S || WITH_CR64 || WITH_CR64S
#include "filter.h"
#else
#define lsx_to_3dB(x) ((x)/(x))
#endif
soxr_quality_spec_t soxr_quality_spec(unsigned long recipe, unsigned long flags)
{
soxr_quality_spec_t spec, * p = &spec;
unsigned quality = recipe & 0xf;
unsigned q = recipe & 0xf; /* TODO: move to soxr-lsr.c: */
unsigned quality = q > SOXR_LSR2Q+2? SOXR_VHQ : q > SOXR_LSR2Q? SOXR_QQ : q;
double rej;
memset(p, 0, sizeof(*p));
if (quality > 13) {
if (quality > SOXR_PRECISIONQ) {
p->e = "invalid quality type";
return spec;
}
if (quality == 13)
quality = 6;
else if (quality > 10)
quality = 0;
p->phase_response = "\62\31\144"[(recipe & 0x30)>>8];
flags |= quality < SOXR_LSR0Q ? RESET_ON_CLEAR : 0;
p->phase_response = "\62\31\144"[(recipe & 0x30)>>4];
p->stopband_begin = 1;
p->precision = !quality? 0: quality < 3? 16 : quality < 8? 4 + quality * 4 : 55 - quality * 4;
p->precision =
quality == SOXR_QQ ? 0 :
quality <= SOXR_16_BITQ ? 16 :
quality <= SOXR_32_BITQ ? 4 + quality * 4 :
quality <= SOXR_LSR2Q ? 55 - quality * 4 : /* TODO: move to soxr-lsr.c */
0;
rej = p->precision * linear_to_dB(2.);
p->flags = flags;
if (quality < 8) {
p->passband_end = quality == 1? LOW_Q_BW0 : 1 - .05 / TO_3dB(rej);
if (quality <= SOXR_32_BITQ || quality == SOXR_PRECISIONQ) {
#define LOW_Q_BW0 (1385 / 2048.) /* 0.67625 rounded to be a FP exact. */
p->passband_end = quality == 1? LOW_Q_BW0 : 1 - .05 / lsx_to_3dB(rej);
if (quality <= 2)
p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM;
}
else {
else { /* TODO: move to soxr-lsr.c */
static float const bw[] = {.931f, .832f, .663f};
p->passband_end = bw[quality - 8];
if (quality - 8 == 2)
p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM;
p->passband_end = bw[quality - SOXR_LSR0Q];
if (quality == SOXR_LSR2Q) {
p->flags &= ~SOXR_ROLLOFF_NONE;
p->flags |= SOXR_ROLLOFF_LSR2Q | SOXR_PROMOTE_TO_LQ;
}
}
if (recipe & SOXR_STEEP_FILTER)
p->passband_end = 1 - .01 / TO_3dB(rej);
p->passband_end = 1 - .01 / lsx_to_3dB(rej);
return spec;
}
@ -160,39 +195,165 @@ soxr_io_spec_t soxr_io_spec(
#if HAVE_SIMD
static bool cpu_has_simd(void)
{
#if defined __x86_64__ || defined _M_X64
return true;
#elif defined __GNUC__ && defined i386
uint32_t eax, ebx, ecx, edx;
__asm__ __volatile__ (
"pushl %%ebx \n\t"
"cpuid \n\t"
"movl %%ebx, %1\n\t"
"popl %%ebx \n\t"
: "=a"(eax), "=r"(ebx), "=c"(ecx), "=d"(edx)
: "a"(1)
: "cc" );
return !!(edx & 0x06000000);
#elif defined _MSC_VER && defined _M_IX86
uint32_t d;
__asm {
xor eax, eax
inc eax
push ebx
cpuid
pop ebx
mov d, edx
}
return !!(d & 0x06000000);
#endif
return false;
}
#if (WITH_CR32S && WITH_CR32) || (WITH_CR64S && WITH_CR64)
#if defined __GNUC__ && defined __x86_64__
#define CPUID(type, eax_, ebx_, ecx_, edx_) \
__asm__ __volatile__ ( \
"cpuid \n\t" \
: "=a" (eax_), "=b" (ebx_), "=c" (ecx_), "=d" (edx_) \
: "a" (type), "c" (0));
#elif defined __GNUC__ && defined __i386__
#define CPUID(type, eax_, ebx_, ecx_, edx_) \
__asm__ __volatile__ ( \
"mov %%ebx, %%edi \n\t" \
"cpuid \n\t" \
"xchg %%edi, %%ebx \n\t" \
: "=a" (eax_), "=D" (ebx_), "=c" (ecx_), "=d" (edx_) \
: "a" (type), "c" (0));
#elif defined _M_X64 && defined _MSC_VER && _MSC_VER > 1500
void __cpuidex(int CPUInfo[4], int info_type, int ecxvalue);
#pragma intrinsic(__cpuidex)
#define CPUID(type, eax_, ebx_, ecx_, edx_) do { \
int regs[4]; \
__cpuidex(regs, type, 0); \
eax_ = regs[0], ebx_ = regs[1], ecx_ = regs[2], edx_ = regs[3]; \
} while(0)
#elif defined _M_X64 && defined _MSC_VER
void __cpuidex(int CPUInfo[4], int info_type);
#pragma intrinsic(__cpuidex)
#define CPUID(type, eax_, ebx_, ecx_, edx_) do { \
int regs[4]; \
__cpuidex(regs, type); \
eax_ = regs[0], ebx_ = regs[1], ecx_ = regs[2], edx_ = regs[3]; \
} while(0)
#elif defined _M_IX86 && defined _MSC_VER
#define CPUID(type, eax_, ebx_, ecx_, edx_) \
__asm pushad \
__asm mov eax, type \
__asm xor ecx, ecx \
__asm cpuid \
__asm mov eax_, eax \
__asm mov ebx_, ebx \
__asm mov ecx_, ecx \
__asm mov edx_, edx \
__asm popad
#endif
#endif
extern control_block_t _soxr_rate32s_cb, _soxr_rate32_cb, _soxr_rate64_cb, _soxr_vr32_cb;
#if WITH_CR32S && WITH_CR32
static bool cpu_has_simd32(void)
{
#if defined __x86_64__ || defined _M_X64
return true;
#elif defined __i386__ || defined _M_IX86
enum {SSE = 1 << 25, SSE2 = 1 << 26};
unsigned eax_, ebx_, ecx_, edx_;
CPUID(1, eax_, ebx_, ecx_, edx_);
return (edx_ & (SSE|SSE2)) != 0;
#elif defined AV_CPU_FLAG_NEON
return !!(av_get_cpu_flags() & AV_CPU_FLAG_NEON);
#else
return false;
#endif
}
static bool should_use_simd32(void)
{
char const * e;
return ((e = getenv("SOXR_USE_SIMD" )))? !!atoi(e) :
((e = getenv("SOXR_USE_SIMD32")))? !!atoi(e) : cpu_has_simd32();
}
#else
#define should_use_simd32() true
#endif
#if WITH_CR64S && WITH_CR64
#if defined __GNUC__
#define XGETBV(type, eax_, edx_) \
__asm__ __volatile__ ( \
".byte 0x0f, 0x01, 0xd0\n" \
: "=a"(eax_), "=d"(edx_) : "c" (type));
#elif defined _M_X64 && defined _MSC_FULL_VER && _MSC_FULL_VER >= 160040219
#include <immintrin.h>
#define XGETBV(type, eax_, edx_) do { \
union {uint64_t x; uint32_t y[2];} a = {_xgetbv(0)}; \
eax_ = a.y[0], edx_ = a.y[1]; \
} while(0)
#elif defined _M_IX86 && defined _MSC_VER
#define XGETBV(type, eax_, edx_) \
__asm pushad \
__asm mov ecx, type \
__asm _emit 0x0f \
__asm _emit 0x01 \
__asm _emit 0xd0 \
__asm mov eax_, eax \
__asm mov edx_, edx \
__asm popad
#else
#define XGETBV(type, eax_, edx_) eax_ = edx_ = 0
#endif
static bool cpu_has_simd64(void)
{
enum {OSXSAVE = 1 << 27, AVX = 1 << 28};
unsigned eax_, ebx_, ecx_, edx_;
CPUID(1, eax_, ebx_, ecx_, edx_);
if ((ecx_ & (OSXSAVE|AVX)) == (OSXSAVE|AVX)) {
XGETBV(0, eax_, edx_);
return (eax_ & 6) == 6;
}
return false;
}
static bool should_use_simd64(void)
{
char const * e;
return ((e = getenv("SOXR_USE_SIMD" )))? !!atoi(e) :
((e = getenv("SOXR_USE_SIMD64")))? !!atoi(e) : cpu_has_simd64();
}
#else
#define should_use_simd64() true
#endif
extern control_block_t
_soxr_rate32_cb,
_soxr_rate32s_cb,
_soxr_rate64_cb,
_soxr_rate64s_cb,
_soxr_vr32_cb;
static void runtime_num(char const * env_name,
int min, int max, unsigned * field)
{
char const * e = getenv(env_name);
if (e) {
int i = atoi(e);
if (i >= min && i <= max)
*field = (unsigned)i;
}
}
static void runtime_flag(char const * env_name,
unsigned n_bits, unsigned n_shift, unsigned long * flags)
{
char const * e = getenv(env_name);
if (e) {
int i = atoi(e);
unsigned long mask = (1UL << n_bits) - 1;
if (i >= 0 && i <= (int)mask)
*flags &= ~(mask << n_shift), *flags |= ((unsigned long)i << n_shift);
}
}
@ -204,11 +365,30 @@ soxr_t soxr_create(
soxr_quality_spec_t const * q_spec,
soxr_runtime_spec_t const * runtime_spec)
{
double io_ratio = output_rate? input_rate? input_rate / output_rate : -1 : input_rate? -1 : 0;
double io_ratio = output_rate!=0? input_rate!=0?
input_rate / output_rate : -1 : input_rate!=0? -1 : 0;
static const float datatype_full_scale[] = {1, 1, 65536.*32768, 32768};
soxr_t p = 0;
soxr_error_t error = 0;
#if WITH_DEV_TRACE
#define _(x) (char)(sizeof(x)>=10? 'a'+(char)(sizeof(x)-10):'0'+(char)sizeof(x))
char const * e = getenv("SOXR_TRACE");
_soxr_trace_level = e? atoi(e) : 0;
{
static char const arch[] = {_(char), _(short), _(int), _(long), _(long long)
, ' ', _(float), _(double), _(long double)
, ' ', _(int *), _(int (*)(int))
, ' ', HAVE_BIGENDIAN ? 'B' : 'L'
#if defined _OPENMP
, ' ', 'O', 'M', 'P'
#endif
, 0};
#undef _
lsx_debug("arch: %s", arch);
}
#endif
if (q_spec && q_spec->e) error = q_spec->e;
else if (io_spec && (io_spec->itype | io_spec->otype) >= SOXR_SPLIT * 2)
error = "invalid io datatype(s)";
@ -216,6 +396,8 @@ soxr_t soxr_create(
if (!error && !(p = calloc(sizeof(*p), 1))) error = "malloc failed";
if (p) {
control_block_t * control_block;
p->q_spec = q_spec? *q_spec : soxr_quality_spec(SOXR_HQ, 0);
if (q_spec) { /* Backwards compatibility with original API: */
@ -233,35 +415,59 @@ soxr_t soxr_create(
p->io_spec.scale = 1;
p->runtime_spec = runtime_spec? *runtime_spec : soxr_runtime_spec(1);
runtime_num("SOXR_MIN_DFT_SIZE", 8, 15, &p->runtime_spec.log2_min_dft_size);
runtime_num("SOXR_LARGE_DFT_SIZE", 8, 20, &p->runtime_spec.log2_large_dft_size);
runtime_num("SOXR_COEFS_SIZE", 100, 800, &p->runtime_spec.coef_size_kbytes);
runtime_num("SOXR_NUM_THREADS", 0, 64, &p->runtime_spec.num_threads);
runtime_flag("SOXR_COEF_INTERP", 2, 0, &p->runtime_spec.flags);
runtime_flag("SOXR_STRICT_BUF", 1, 2, &p->runtime_spec.flags);
runtime_flag("SOXR_NOSMALLINTOPT", 1, 3, &p->runtime_spec.flags);
p->io_spec.scale *= datatype_full_scale[p->io_spec.otype & 3] /
datatype_full_scale[p->io_spec.itype & 3];
p->seed = (unsigned long)time(0) ^ (unsigned long)(size_t)p;
#if HAVE_SINGLE_PRECISION
if (!HAVE_DOUBLE_PRECISION || (p->q_spec.precision <= 20 && !(p->q_spec.flags & SOXR_DOUBLE_PRECISION))
|| (p->q_spec.flags & SOXR_VR)) {
#if WITH_CR32 || WITH_CR32S || WITH_VR32
if (0
#if WITH_VR32
|| ((!WITH_CR32 && !WITH_CR32S) || (p->q_spec.flags & SOXR_VR))
#endif
#if WITH_CR32 || WITH_CR32S
|| !(WITH_CR64 || WITH_CR64S) || (p->q_spec.precision <= 20 && !(p->q_spec.flags & SOXR_DOUBLE_PRECISION))
#endif
) {
p->deinterleave = (deinterleave_t)_soxr_deinterleave_f;
p->interleave = (interleave_t)_soxr_interleave_f;
memcpy(&p->control_block,
(p->q_spec.flags & SOXR_VR)? &_soxr_vr32_cb :
#if HAVE_SIMD
cpu_has_simd()? &_soxr_rate32s_cb :
control_block =
#if WITH_VR32
((!WITH_CR32 && !WITH_CR32S) || (p->q_spec.flags & SOXR_VR))? &_soxr_vr32_cb :
#endif
&_soxr_rate32_cb, sizeof(p->control_block));
#if WITH_CR32S
!WITH_CR32 || should_use_simd32()? &_soxr_rate32s_cb :
#endif
&_soxr_rate32_cb;
}
#if HAVE_DOUBLE_PRECISION
#if WITH_CR64 || WITH_CR64S
else
#endif
#endif
#if HAVE_DOUBLE_PRECISION
#if WITH_CR64 || WITH_CR64S
{
p->deinterleave = (deinterleave_t)_soxr_deinterleave;
p->interleave = (interleave_t)_soxr_interleave;
memcpy(&p->control_block, &_soxr_rate64_cb, sizeof(p->control_block));
control_block =
#if WITH_CR64S
!WITH_CR64 || should_use_simd64()? &_soxr_rate64s_cb :
#endif
&_soxr_rate64_cb;
}
#endif
memcpy(&p->control_block, control_block, sizeof(p->control_block));
if (p->num_channels && io_ratio)
if (p->num_channels && io_ratio!=0)
error = soxr_set_io_ratio(p, io_ratio, 0);
}
if (error)
@ -304,7 +510,8 @@ static void soxr_delete0(soxr_t p)
double soxr_delay(soxr_t p)
{
return (p && !p->error && p->resamplers)? resampler_delay(p->resamplers[0]) : 0;
return
(p && !p->error && p->resamplers)? resampler_delay(p->resamplers[0]) : 0;
}
@ -378,7 +585,7 @@ soxr_error_t soxr_set_io_ratio(soxr_t p, double io_ratio, size_t slew_len)
return error;
}
return fabs(p->io_ratio - io_ratio) < 1e-15? 0 :
"Varying O/I ratio is not supported with this quality level";
"varying O/I ratio is not supported with this quality level";
}
@ -406,7 +613,8 @@ soxr_error_t soxr_clear(soxr_t p) /* TODO: this, properly. */
memcpy(p->control_block, tmp.control_block, sizeof(p->control_block));
p->deinterleave = tmp.deinterleave;
p->interleave = tmp.interleave;
return 0;
return (p->q_spec.flags & RESET_ON_CLEAR)?
soxr_set_io_ratio(p, tmp.io_ratio, 0) : 0;
}
return "invalid soxr_t pointer";
}

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
* under the terms of the GNU Lesser General Public License as published by
@ -63,9 +63,10 @@ input or output (e.g. ilen, olen). */
/* --------------------------- Version management --------------------------- */
/* E.g. #if SOXR_THIS_VERSION >= SOXR_VERSION(0,1,1) ... */
#define SOXR_VERSION(x,y,z) (((x)<<16)|((y)<<8)|(z))
#define SOXR_THIS_VERSION SOXR_VERSION(0,1,1)
#define SOXR_THIS_VERSION_STR "0.1.1"
#define SOXR_THIS_VERSION SOXR_VERSION(0,1,3)
#define SOXR_THIS_VERSION_STR "0.1.3"
@ -105,7 +106,11 @@ SOXR soxr_t soxr_create(
soxr_error_t *, /* To report any error during creation. */
soxr_io_spec_t const *, /* To specify non-default I/O formats. */
soxr_quality_spec_t const *, /* To specify non-default resampling quality.*/
soxr_runtime_spec_t const *);/* To specify non-default runtime resources. */
soxr_runtime_spec_t const *);/* To specify non-default runtime resources.
Default io_spec is per soxr_io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I)
Default quality_spec is per soxr_quality_spec(SOXR_HQ, 0)
Default runtime_spec is per soxr_runtime_spec(1) */
@ -168,7 +173,7 @@ SOXR size_t /*odone*/ soxr_output(/* Resample and output a block of data.*/
SOXR soxr_error_t soxr_error(soxr_t); /* Query error status. */
SOXR size_t * soxr_num_clips(soxr_t); /* Query int. clip counter (for R/W). */
SOXR double soxr_delay(soxr_t); /* Query current delay in output samples.*/
SOXR char const * soxr_engine(soxr_t p); /* Query resampling engine name. */
SOXR char const * soxr_engine(soxr_t); /* Query resampling engine name. */
SOXR soxr_error_t soxr_clear(soxr_t); /* Ready for fresh signal, same config. */
SOXR void soxr_delete(soxr_t); /* Free resources. */
@ -176,7 +181,9 @@ SOXR void soxr_delete(soxr_t); /* Free resources. */
/* `Short-cut', single call to resample a (probably short) signal held entirely
* in memory. See soxr_create and soxr_process above for parameter details. */
* in memory. See soxr_create and soxr_process above for parameter details.
* Note that unlike soxr_create however, the default quality spec. for
* soxr_oneshot is per soxr_quality_spec(SOXR_LQ, 0). */
SOXR soxr_error_t soxr_oneshot(
double input_rate,
@ -190,8 +197,8 @@ SOXR soxr_error_t soxr_oneshot(
/* For variable-rate resampling (experimental). See example # 5 for how to
* create a variable-rate resampler and how to use this function. */
/* For variable-rate resampling. See example # 5 for how to create a
* variable-rate resampler and how to use this function. */
SOXR soxr_error_t soxr_set_io_ratio(soxr_t, double io_ratio, size_t slew_len);
@ -242,28 +249,24 @@ struct soxr_quality_spec { /* Typically */
#define SOXR_ROLLOFF_MEDIUM 1u /* <= 0.35 dB */
#define SOXR_ROLLOFF_NONE 2u /* For Chebyshev bandwidth. */
#define SOXR_MAINTAIN_3DB_PT 4u /* Reserved for internal use. */
#define SOXR_HI_PREC_CLOCK 8u /* Increase `irrational' ratio accuracy. */
#define SOXR_DOUBLE_PRECISION 16u /* Use D.P. calcs even if precision <= 20. */
#define SOXR_VR 32u /* Experimental, variable-rate resampling. */
#define SOXR_VR 32u /* Variable-rate resampling. */
struct soxr_runtime_spec { /* Typically */
unsigned log2_min_dft_size;/* For DFT efficiency. [8,15] 10 */
unsigned log2_large_dft_size;/* For DFT efficiency. [16,20] 17 */
unsigned coef_size_kbytes; /* For SOXR_COEF_INTERP_AUTO (below). 400 */
unsigned num_threads; /* If built so. 0 means `automatic'. 1 */
void * e; /* Reserved for internal use. 0 */
unsigned long flags; /* Per the following #defines. 0 */
unsigned log2_min_dft_size; /* For DFT efficiency. [8,15] 10 */
unsigned log2_large_dft_size; /* For DFT efficiency. [8,20] 17 */
unsigned coef_size_kbytes; /* For SOXR_COEF_INTERP_AUTO (below). 400 */
unsigned num_threads; /* 0: per OMP_NUM_THREADS; 1: 1 thread. 1 */
void * e; /* Reserved for internal use. 0 */
unsigned long flags; /* Per the following #defines. 0 */
};
/* For `irrational' ratios only: */
#define SOXR_COEF_INTERP_AUTO 0u /* Auto select coef. interpolation. */
#define SOXR_COEF_INTERP_LOW 1u /* Man. select: less CPU, more memory. */
#define SOXR_COEF_INTERP_HIGH 2u /* Man. select: more CPU, less memory. */
#define SOXR_STRICT_BUFFERING 4u /* Reserved for future use. */
#define SOXR_NOSMALLINTOPT 8u /* For test purposes only. */
#define SOXR_COEF_INTERP_LOW 2u /* Man. select: less CPU, more memory. */
#define SOXR_COEF_INTERP_HIGH 3u /* Man. select: more CPU, less memory. */
@ -289,7 +292,7 @@ SOXR soxr_quality_spec_t soxr_quality_spec(
#define SOXR_24_BITQ 5
#define SOXR_28_BITQ 6
#define SOXR_32_BITQ 7
/* Libsamplerate equivalent qualities: */
/* Reserved for internal use (to be removed): */
#define SOXR_LSR0Q 8 /* 'Best sinc'. */
#define SOXR_LSR1Q 9 /* 'Medium sinc'. */
#define SOXR_LSR2Q 10 /* 'Fast sinc'. */
@ -297,8 +300,8 @@ SOXR soxr_quality_spec_t soxr_quality_spec(
#define SOXR_LINEAR_PHASE 0x00
#define SOXR_INTERMEDIATE_PHASE 0x10
#define SOXR_MINIMUM_PHASE 0x30
#define SOXR_STEEP_FILTER 0x40
#define SOXR_ALLOW_ALIASING 0x80 /* Reserved for future use. */
@ -313,7 +316,19 @@ SOXR soxr_io_spec_t soxr_io_spec(
/* --------------------------- Internal use only ---------------------------- */
/* --------------------------- Advanced use only ---------------------------- */
/* For new designs, the following functions/usage will probably not be needed.
* They might be useful when adding soxr into an existing design where values
* for the resampling-rate and/or number-of-channels parameters to soxr_create
* are not available when that function will be called. In such cases, the
* relevant soxr_create parameter(s) can be given as 0, then one or both of the
* following (as appropriate) later invoked (but prior to calling soxr_process
* or soxr_output):
*
* soxr_set_error(soxr, soxr_set_io_ratio(soxr, io_ratio, 0));
* soxr_set_error(soxr, soxr_set_num_channels(soxr, num_channels));
*/
SOXR soxr_error_t soxr_set_error(soxr_t, soxr_error_t);
SOXR soxr_error_t soxr_set_num_channels(soxr_t, unsigned);

View File

@ -0,0 +1,48 @@
/* 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_std_types_included
#define soxr_std_types_included
#include "soxr-config.h"
#include <limits.h>
#if HAVE_STDBOOL_H
#include <stdbool.h>
#else
#undef bool
#undef false
#undef true
#define bool int
#define false 0
#define true 1
#endif
#if HAVE_STDINT_H
#include <stdint.h>
#else
#undef int16_t
#undef int32_t
#undef int64_t
#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,15 +1,15 @@
/* 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. */
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "simd.h"
#include "simd-dev.h"
#define SIMD_ALIGNMENT (sizeof(float) * 4)
#include "soxr-config.h"
void * _soxr_simd_aligned_malloc(size_t size)
#define SIMD_ALIGNMENT (sizeof(float) * (1 + (PFFFT_DOUBLE|AVCODEC_FOUND)) * 4)
void * SIMD_ALIGNED_MALLOC(size_t size)
{
char * p1 = 0, * p = malloc(size + SIMD_ALIGNMENT);
if (p) {
@ -21,9 +21,9 @@ void * _soxr_simd_aligned_malloc(size_t size)
void * _soxr_simd_aligned_calloc(size_t nmemb, size_t size)
void * SIMD_ALIGNED_CALLOC(size_t nmemb, size_t size)
{
void * p = _soxr_simd_aligned_malloc(nmemb * size);
void * p = SIMD_ALIGNED_MALLOC(nmemb * size);
if (p)
memset(p, 0, nmemb * size);
return p;
@ -31,7 +31,7 @@ void * _soxr_simd_aligned_calloc(size_t nmemb, size_t size)
void _soxr_simd_aligned_free(void * p1)
void SIMD_ALIGNED_FREE(void * p1)
{
if (p1)
free(*((void * *)p1 - 1));
@ -39,11 +39,16 @@ void _soxr_simd_aligned_free(void * p1)
void _soxr_ordered_convolve_simd(int n, void * not_used, float * a, const float * b)
#define PFFT_MACROS_ONLY
#include "pffft.c"
void ORDERED_CONVOLVE_SIMD(int n, void * not_used, float * a, float const * b)
{
int i;
float ab0, ab1;
v4sf * /*RESTRICT*/ va = (v4sf *)a;
v4sf * RESTRICT va = (v4sf *)a;
v4sf const * RESTRICT vb = (v4sf const *)b;
assert(VALIGNED(a) && VALIGNED(b));
ab0 = a[0] * b[0], ab1 = a[1] * b[1];
@ -62,11 +67,11 @@ void _soxr_ordered_convolve_simd(int n, void * not_used, float * a, const float
void _soxr_ordered_partial_convolve_simd(int n, float * a, const float * b)
void ORDERED_PARTIAL_CONVOLVE_SIMD(int n, float * a, float const * b)
{
int i;
float ab0;
v4sf * /*RESTRICT*/ va = (v4sf *)a;
v4sf * RESTRICT va = (v4sf *)a;
v4sf const * RESTRICT vb = (v4sf const *)b;
assert(VALIGNED(a) && VALIGNED(b));
ab0 = a[0] * b[0];

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 PFFFT_DOUBLE 0
#include "util32s.h"
#include "util-simd.c"

View File

@ -0,0 +1,23 @@
/* 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_util32s_included
#define soxr_util32s_included
#include <stddef.h>
void * _soxr_simd32_aligned_malloc(size_t);
void * _soxr_simd32_aligned_calloc(size_t, size_t);
void _soxr_simd32_aligned_free(void *);
#define SIMD_ALIGNED_MALLOC _soxr_simd32_aligned_malloc
#define SIMD_ALIGNED_CALLOC _soxr_simd32_aligned_calloc
#define SIMD_ALIGNED_FREE _soxr_simd32_aligned_free
void _soxr_ordered_convolve_simd32(int n, void * not_used, float * a, float const * b);
void _soxr_ordered_partial_convolve_simd32(int n, float * a, float const * b);
#define ORDERED_CONVOLVE_SIMD _soxr_ordered_convolve_simd32
#define ORDERED_PARTIAL_CONVOLVE_SIMD _soxr_ordered_partial_convolve_simd32
#endif

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 PFFFT_DOUBLE 1
#include "util64s.h"
#include "util-simd.c"

View File

@ -0,0 +1,23 @@
/* 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_util64s_included
#define soxr_util64s_included
#include <stddef.h>
void * _soxr_simd64_aligned_malloc(size_t);
void * _soxr_simd64_aligned_calloc(size_t, size_t);
void _soxr_simd64_aligned_free(void *);
#define SIMD_ALIGNED_MALLOC _soxr_simd64_aligned_malloc
#define SIMD_ALIGNED_CALLOC _soxr_simd64_aligned_calloc
#define SIMD_ALIGNED_FREE _soxr_simd64_aligned_free
void _soxr_ordered_convolve_simd64(int n, void * not_used, double * a, double const * b);
void _soxr_ordered_partial_convolve_simd64(int n, double * a, double const * b);
#define ORDERED_CONVOLVE_SIMD _soxr_ordered_convolve_simd64
#define ORDERED_PARTIAL_CONVOLVE_SIMD _soxr_ordered_partial_convolve_simd64
#endif

View File

@ -0,0 +1,115 @@
/* SoX Resampler Library Copyright (c) 2013 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Generate the filter coefficients for variable-rate resampling. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.14159265358979323846 /* Since M_PI can't be relied on */
static void print(double * h, int m, double l, char const * name)
{ /* Print out a filter: */
int i, N = l? (int)(l*m)-(l>1) : m, R=(N+1)/2;
int a = !l||l>1? 0:N-R, b = l>1? R:N;
printf("static float const %s[] = {\n", name);
if (l>1) printf(" 0.f,"); else if (!l) l=1;
for (i=a; h && i<b; ++i, printf("% .9gf,%c",l*h[i-1],"\n "[(i-a)&3 && i<b]));
puts("};\n");
free(h);
}
/* Parks McClellan FIR LPF: */
#define even_adj(f) ((N&1)? 1 : cos(PI*.5*(f)))
#define W(f) (((f) < Fp+1e-9? weight : 1) * even_adj(f)) /* Weighting fn */
#define D(f) (((f) < Fp+1e-9) / even_adj(f)) /* Desired response fn */
#define F(i) ((i) <= end[0]? (i)*inc[0] : 1-(end[1]-(i))*inc[1])
#define EE(x,z) (_1 != x 1 && x E[i] > 0 && x E[i] >= x E[i z 1])
#define PEAK do {if (k<NP+1) peak[k]=i; ++k,_1=(E[i]>0)-(E[i]<0);} while (0)
typedef struct {double x, beta, gamma;} coef_t;
static double amp_response(coef_t * coef, int R, double f, int i)
{
double n = 0, d = 0, x = cos(PI*f), t;
for (; i < R; d += t = coef[i].beta / t, n += coef[i].gamma * t, ++i)
if (fabs(t = x - coef[i].x) < 1e-9) return coef[i].gamma;
return n/d;
}
static void fir(int m, double l, double Fp0, double Fs0,
double weight0, int density, char const * name)
{
double Fp=Fp0/l, Fs=Fs0/l, weight=1/weight0, inc[2], Ws=1-Fs;
int N = (int)(l*m)-(l>1), R=(N+1)/2, NP=R+1, grid_size=1+density*R+1, pass=0;
int n1 = Ws>=(2*R-1)*Fp? 1:(int)(R*Fp/(Fp+Ws)+.5), n2=NP-n1, _1, i, j, k;
int * peak = calloc(sizeof(*peak), (size_t)(NP+1)), * P=peak, end[2];
coef_t * coef = calloc(sizeof(*coef), (size_t)(NP));
float * E = calloc(sizeof(*E ), (size_t)(grid_size));
double d, n, e, f, mult, delta, sum, hi, lo, * A = (double*)E, *h=0;
if (!P || !coef || !E) goto END;
end[0] = n1 * density, end[1] = grid_size-1; /* Create prototype peaks: */
inc[0] = Fp/end[0], inc[1] = n2==1? 0 : Ws / ((n2-1)*density);
for (i=0; i<n1; P[n1-1-i] = end[0] - i*density,++i);
for (i=0; i<n2; P[n1+i] = 1+end[0] + i*density,++i);
do { /* Coefs for amp. resp.: */
for (i = 0; i<NP; coef[i].x = cos(PI*F(P[i])), ++i);
for (_1=-1, n=d=i=0; i < NP; ++i) {
for (mult = 1, j = 0; j < R; ++j) if (j != i) mult *= coef[i].x-coef[j].x;
if (mult) coef[i].beta = 1/mult; else goto END;
if (i != R) mult *= coef[i].x - coef[R].x;
f = F(P[i]), n += D(f)/mult, d += (_1=-_1)/(W(f)*mult);
}
for (delta = n/d, _1 = -1, i = 0; i < R; ++i)
f = F(P[i]), coef[i].gamma = D(f)-(_1=-_1)*delta/W(f);
for (i = 0; i <= end[1]; ++i) /* Amplitude response and error: */
f = F(i), E[i] = (float)(W(f)*(D(f) - amp_response(coef, R, f, 0)));
i = k = _1 = 0; /* Find new peaks: */
if (end[0]) if (EE(+,+) || EE(-,+)) PEAK; /* At F=0 */
for (++i, j = 0; j < 2; ++j) { /* In band j: */
for (; i < end[j]; ++i)
if ((EE(+,-) && E[i]>E[i+1]) || (EE(-,-) && E[i]<E[i+1])) PEAK;
if (!j) {PEAK; ++i; PEAK; ++i;} /* At Fp & Fs */
}
if (i==end[1]) if (EE(+,-) || EE(-,-)) PEAK; /* At F=1 */
if ((unsigned)(k = k-NP) > 1) goto END; /* Too many/few? */
P = peak + k * (fabs(E[peak[0]]) < fabs(E[peak[NP]])); /* rm 1st? */
for (lo = hi = fabs(E[P[0]]), i=1; i<NP; ++i) /* Converged?: */
e = fabs(E[P[i]]), lo = e<lo? e:lo, hi = e>hi? e:hi;
} while ((hi-lo)/hi > .001 && ++pass < 20);
/* Create impulse response from final amp. resp. coefs: */
if (!(h = malloc(sizeof(*h)*(size_t)N))) goto END;
for (i = 0; i < R; f = 2.*i/N, A[i++] = amp_response(coef,R,f,0)*even_adj(f));
for (i = 0; i < R; h[N-1-i] = h[i] = sum/N, ++i)
for (sum=*A, j=1; j<R; sum += 2*cos(2*PI*(i-(N-1)/2.)/N*j)*A[j], ++j);
END: free(coef), free(E), free(peak);
print(h, m, l, name);
}
/* Half-band IIR LPF (Mitra DSP 3/e, 13_9): */
static void iir(int N, double Fp, char const * name)
{
double d=tan(PI*.5*Fp), r=d*d, t=sqrt(1-r*r), n=(1-sqrt(t))/(1+sqrt(t))*.5;
double x=(n*n)*(n*n), Q=(((150*x+15)*x+2)*x+1)*n, q=pow(Q,.25), *h;
int i=0, j, _1;
if (!(h = malloc(sizeof(*h)*(size_t)N))) goto END;
for (; i<N; t=n*q/d, t=t*t, t=sqrt((1-t*r)*(1-t/r))/(1+t), h[i++]=(1-t)/(1+t))
for (_1=1, d=-.5, n=j=0, x=(i+1)*PI/(N+.5); j<7; ++j, _1=-_1)
n += _1*pow(Q,j*(j+1))*sin(x*(j+.5)), d += _1*pow(Q,j*j)*cos(x*j);
END: print(h, N, 0, name);
}
int main(int argc, char **argv)
{
puts("/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net");
puts(" * Licence for this file: LGPL v2.1 See LICENCE for details. */\n");
fir(241, 1, .45, .5, 160, 32, "half_fir_coefs");
fir( 24, .5, .25, .5, 1, 31, "fast_half_fir_coefs");
fir( 20, 12, .9 , 1.5, 160, 58, "coefs0_d");
fir( 12, 6, .45, 1.5, 80, 29, "coefs0_u");
iir( 15, .492, "iir_coefs");
return 0*argc*!argv;
}

View File

@ -0,0 +1,94 @@
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
static float const half_fir_coefs[] = {
0.471112154f, 0.316907549f, 0.0286963396f, -0.101927032f,
-0.0281272982f, 0.0568029535f, 0.027196876f, -0.0360795942f,
-0.0259313561f, 0.023641162f, 0.0243660538f, -0.0151238564f,
-0.0225440668f, 0.00886927471f, 0.0205146088f, -0.00411434209f,
-0.0183312132f, 0.000458525335f, 0.0160497772f, 0.00233248286f,
-0.0137265989f, -0.0044106884f, 0.011416442f, 0.005885487f,
-0.00917074467f, -0.00684373006f, 0.00703601669f, 0.00736018933f,
-0.00505250698f, -0.00750298261f, 0.00325317131f, 0.00733618346f,
-0.00166298445f, -0.00692082025f, 0.000298598848f, 0.00631493711f,
0.000831644129f, -0.0055731438f, -0.00172737872f, 0.00474591812f,
0.0023955814f, -0.0038788491f, -0.00284969263f, 0.00301194082f,
0.00310854264f, -0.00217906496f, -0.00319514679f, 0.00140761062f,
0.00313542959f, -0.000718361916f, -0.00295694328f, 0.000125607323f,
0.00268763625f, 0.000362527878f, -0.00235472525f, -0.000743552559f,
0.00198371228f, 0.00101991741f, -0.0015975797f, -0.00119820218f,
0.00121618271f, 0.0012882279f, -0.000855849209f, -0.00130214036f,
0.000529184474f, 0.00125350876f, -0.000245067778f, -0.00115647977f,
8.82118676e-06f, 0.00102502052f, 0.000177478031f, -0.000872275256f,
-0.000314572995f, 0.000710055602f, 0.000405526007f, -0.000548470439f,
-0.000455174442f, 0.000395698685f, 0.000469579667f, -0.000257895884f,
-0.000455495078f, 0.000139222702f, 0.000419883982f, -4.19753541e-05f,
-0.00036950051f, -3.32020844e-05f, 0.000310554015f, 8.7050045e-05f,
-0.000248456595f, -0.000121389974f, 0.000187662656f, 0.000138813233f,
-0.000131587954f, -0.000142374865f, 8.26090549e-05f, 0.000135318039f,
-4.21208043e-05f, -0.000120830917f, 1.06505085e-05f, 0.00010185819f,
1.20015129e-05f, -8.09558888e-05f, -2.65925299e-05f, 6.02101571e-05f,
3.42775752e-05f, -4.11911155e-05f, -3.64462477e-05f, 2.49654252e-05f,
3.46090513e-05f, -1.21078107e-05f, -3.03027209e-05f, 2.73562006e-06f,
2.51329043e-05f, 3.66157998e-06f, -2.0990973e-05f, -9.38752332e-06f,
2.07133365e-05f, 3.2060847e-05f, 1.98462364e-05f, 4.90328648e-06f,
-5.28550107e-07f,
};
static float const fast_half_fir_coefs[] = {
0.309418476f, -0.0819805418f, 0.0305513441f, -0.0101582224f,
0.00251293175f, -0.000346895324f,
};
static float const coefs0_d[] = {
0.f, 1.40520362e-05f, 2.32939994e-05f, 4.00699869e-05f, 6.18938797e-05f,
8.79406317e-05f, 0.000116304226f, 0.000143862785f, 0.000166286173f,
0.000178229431f, 0.00017374107f, 0.00014689118f, 9.25928444e-05f,
7.55567388e-06f, -0.000108723934f, -0.000253061416f, -0.000417917952f,
-0.000591117466f, -0.000756082504f, -0.000892686881f, -0.000978762367f,
-0.000992225841f, -0.00091370246f, -0.000729430325f, -0.000434153678f,
-3.36489703e-05f, 0.000453499646f, 0.000995243588f, 0.00154683724f,
0.00205322353f, 0.00245307376f, 0.0026843294f, 0.0026908874f,
0.00242986868f, 0.00187874742f, 0.00104150259f, -4.70759945e-05f,
-0.00131972748f, -0.00267834298f, -0.00399923407f, -0.00514205849f,
-0.00596200535f, -0.00632441105f, -0.00612058374f, -0.00528328869f,
-0.00380015804f, -0.0017232609f, 0.000826765169f, 0.0036632503f,
0.00654337507f, 0.00918536843f, 0.0112922007f, 0.0125801323f,
0.0128097433f, 0.0118164904f, 0.00953750551f, 0.00603133188f,
0.00148762708f, -0.00377544588f, -0.009327395f, -0.014655127f,
-0.0192047839f, -0.0224328082f, -0.0238620596f, -0.0231377935f,
-0.0200777417f, -0.0147104883f, -0.00729690011f, 0.0016694689f,
0.0114853672f, 0.02128446f, 0.0301054204f, 0.03697694f,
0.0410129138f, 0.0415093321f, 0.0380333749f, 0.0304950299f,
0.0191923285f, 0.00482304203f, -0.0115416941f, -0.0285230397f,
-0.0445368533f, -0.0579264573f, -0.0671158215f, -0.070770308f,
-0.0679502076f, -0.0582416438f, -0.0418501969f, -0.0196448429f,
0.00685658762f, 0.0355644891f, 0.0639556622f, 0.0892653703f,
0.108720484f, 0.11979613f, 0.120474745f, 0.109484562f,
0.0864946948f, 0.0522461633f, 0.00860233712f, -0.041491734f,
-0.0941444939f, -0.144742955f, -0.188255118f, -0.219589829f,
-0.233988169f, -0.227416437f, -0.196929062f, -0.140970726f,
-0.0595905561f, 0.0454527813f, 0.170708227f, 0.311175511f,
0.460568159f, 0.61168037f, 0.756833088f, 0.888367707f,
0.999151395f, 1.08305644f, 1.13537741f, 1.15315438f,
};
static float const coefs0_u[] = {
0.f, 2.4378013e-05f, 9.70782157e-05f, 0.000256572953f, 0.000527352928f,
0.000890796838f, 0.00124949518f, 0.00140604793f, 0.00107945998f,
-2.15586031e-05f, -0.00206589462f, -0.00493342625f, -0.00807135101f,
-0.0104515787f, -0.0107039866f, -0.00746258988f, 0.000109078838f,
0.0117345872f, 0.0255795186f, 0.0381690155f, 0.0448461522f,
0.0408218138f, 0.0226797758f, -0.00999595371f, -0.0533441602f,
-0.0987927774f, -0.133827418f, -0.144042973f, -0.116198269f,
-0.0416493482f, 0.0806808506f, 0.242643854f, 0.427127981f,
0.610413245f, 0.766259257f, 0.8708884f, 0.907742029f,
};
static float const iir_coefs[] = {
0.0262852045f, 0.0998310478f, 0.206865061f, 0.330224134f,
0.454420362f, 0.568578357f, 0.666944466f, 0.747869771f,
0.812324404f, 0.8626001f, 0.901427744f, 0.931486057f,
0.955191529f, 0.974661783f, 0.991776305f,
};

View File

@ -1,27 +1,21 @@
/* 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. */
/* Experimental variable-rate resampling. */
/* Variable-rate resampling. */
#include <assert.h>
#include <math.h>
#if !defined M_PI
#define M_PI 3.14159265358979323846
#endif
#if !defined M_LN2
#define M_LN2 0.69314718055994530942
#endif
#include "math-wrap.h"
#include <string.h>
#include <stdlib.h>
#include "internal.h"
#define FIFO_SIZE_T int
#define FIFO_MIN 0x8000
#include "fifo.h"
#include "vr-coefs.h"
#define FADE_LEN_BITS 9
#define PHASE_BITS_D (8 + PHASE_MORE)
#define PHASE_BITS_U (7 + PHASE_MORE)
#define PHASE_MORE 0 /* 2 improves small int, and large u, ratios. */
#define PHASE_BITS_D 10
#define PHASE_BITS_U 9
#define PHASES0_D 12
#define POLY_FIR_LEN_D 20
@ -32,50 +26,6 @@
#define PHASES_D (1 << PHASE_BITS_D)
#define PHASES_U (1 << PHASE_BITS_U)
static float const half_fir_coefs[] = {
4.7111692735253413e-1f, 3.1690797657656167e-1f, 2.8691667164678896e-2f,
-1.0192825848403946e-1f, -2.8122856237424654e-2f, 5.6804928137780292e-2f,
2.7192768359197508e-2f, -3.6082309197154230e-2f, -2.5927789156038026e-2f,
2.3644444384060669e-2f, 2.4363075319345607e-2f, -1.5127630198606428e-2f,
-2.2541790286342567e-2f, 8.8733836742880233e-3f, 2.0513077413933017e-2f,
-4.1186431656279818e-3f, -1.8330444480421631e-2f, 4.6288071358217028e-4f,
1.6049769308921290e-2f, 2.3282106680446069e-3f, -1.3727327353082214e-2f,
-4.4066375505196096e-3f, 1.1417847550661287e-2f, 5.8817724081355978e-3f,
-9.1727580349157123e-3f, -6.8404638339394346e-3f, 7.0385357033205332e-3f,
7.3574525331962567e-3f, -5.0554197628506353e-3f, -7.5008330890673153e-3f,
3.2563575907277676e-3f, 7.3346538206330259e-3f, -1.6663208501478607e-3f,
-6.9199171108861694e-3f, 3.0196567996023190e-4f, 6.3146436955438768e-3f,
8.2835711466756098e-4f, -5.5734271982033918e-3f, -1.7242765658561860e-3f,
4.7467223803576682e-3f, 2.3927523666941205e-3f, -3.8801054688632139e-3f,
-2.8472115748114728e-3f, 3.0135659731132642e-3f, 3.1064651802365259e-3f,
-2.1809660142807748e-3f, -3.1935061143485862e-3f, 1.4096923923208671e-3f,
3.1342382222281609e-3f, -7.2053095076414931e-4f, -2.9561940489039682e-3f,
1.2777585046118889e-4f, 2.6873033434313882e-3f, 3.6043554054680685e-4f,
-2.3547716396561816e-3f, -7.4160208709749312e-4f, 1.9840894915230177e-3f,
1.0181606831615856e-3f, -1.5982325266851590e-3f, -1.1966774804490967e-3f,
1.2170528733224913e-3f, 1.2869618709883193e-3f, -8.5687504489877664e-4f,
-1.3011452950496001e-3f, 5.3030588389885972e-4f, 1.2527854026453923e-3f,
-2.4622758430821288e-4f, -1.1560181289625195e-3f, 9.9661643910782316e-6f,
1.0247989665318426e-3f, 1.7639297561664703e-4f, -8.7226452073196350e-4f,
-3.1358436147401782e-4f, 7.1022054657665971e-4f, 4.0466151692224986e-4f,
-5.4877022848030636e-4f, -4.5444807961399138e-4f, 3.9609542800868769e-4f,
4.6899779918507020e-4f, -2.5835154936239735e-4f, -4.5505391611721792e-4f,
1.3970512544147175e-4f, 4.1957352577882777e-4f, -4.2458993694471047e-5f,
-3.6930861782460262e-4f, -3.2738549063278822e-5f, 3.1046609224355927e-4f,
8.6624679037202785e-5f, -2.4845427128026068e-4f, -1.2101300074995281e-4f,
1.8773208187021294e-4f, 1.3849844077872591e-4f, -1.3170611080827864e-4f,
-1.4212373327156217e-4f, 8.2758595879431528e-5f, 1.3513059684140468e-4f,
-4.2284127775471251e-5f, -1.2070298779675768e-4f, 1.0811692847491609e-5f,
1.0178008299781669e-4f, 1.1852545451857104e-5f, -8.0914539313342186e-5f,
-2.6454558961220653e-5f, 6.0208388858339534e-5f, 3.4169979203255580e-5f,
-4.1203296686185329e-5f, -3.6353143441156863e-5f, 2.4999186627094098e-5f,
3.4542829080466582e-5f, -1.2148053427488782e-5f, -3.0260855999161159e-5f,
2.7687092952335852e-6f, 2.5095689880235108e-5f, 3.6223160417538916e-6f,
-2.0960977068565079e-5f, -9.3312292092513232e-6f, 2.0711288605113663e-5f,
3.1992093654438569e-5f, 1.9772538588596925e-5f, 4.8667740603532560e-6f,
-5.3495033191567977e-7f,
};
#define CONVOLVE \
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \
@ -119,25 +69,14 @@ static float double_fir1(float const * input)
static float fast_half_fir(float const * input)
{
static const float coefs[] = {
.3094188462713818f, -.08198144615199748f, .03055232105456833f,
-.01015890277986387f, .002513237297525149f, -.0003469672050347395f,
};
int i = 0;
float sum = input[0] * .5f;
#define _ sum += (input[-(2*i+1)] + input[2*i+1]) * coefs[i], ++i;
#define _ sum += (input[-(2*i+1)] + input[2*i+1]) * fast_half_fir_coefs[i], ++i;
_ _ _ _ _ _
#undef _
return (float)sum;
}
static const float iir_coefs[] = {
.0262852045255816f, .0998310478296204f, .2068650611060755f,
.3302241336172489f, .4544203620946318f, .5685783569471244f,
.6669444657994612f, .7478697711807407f, .8123244036799226f,
.8626000999654434f, .9014277444199280f, .9314860567781748f,
.9551915287878752f, .9746617828910630f, .9917763050166036f,
};
#define IIR_FILTER _ _ _ _ _ _ _
#define _ in1=(in1-p->y[i])*iir_coefs[i]+tmp1;tmp1=p->y[i],p->y[i]=in1;++i;\
in0=(in0-p->y[i])*iir_coefs[i]+tmp0;tmp0=p->y[i],p->y[i]=in0;++i;
@ -175,77 +114,18 @@ static void half_phase(half_iir_t * p, float * buf, int len)
#undef _
}
#define raw_coef_t float
static const raw_coef_t coefs0_d[POLY_FIR_LEN_D / 2 * PHASES0_D + 1] = {
0.f, 1.4057457935754080e-5f, 2.3302768424632188e-5f, 4.0084897378442095e-5f,
6.1916773126231636e-5f, 8.7973434034929016e-5f, 1.1634847507082481e-4f,
1.4391931654629385e-4f, 1.6635470822160746e-4f, 1.7830838562749493e-4f,
1.7382737311735053e-4f, 1.4698011689178234e-4f, 9.2677933545427018e-5f,
7.6288745483685147e-6f, -1.0867156553965507e-4f, -2.5303924530322309e-4f,
-4.1793463959360433e-4f, -5.9118012513731508e-4f, -7.5619603440508576e-4f,
-8.9285245696990080e-4f, -9.7897684238178358e-4f, -9.9248131798952959e-4f,
-9.1398576537725926e-4f, -7.2972364732199553e-4f, -4.3443557115962946e-4f,
-3.3895523979487613e-5f, 4.5331297364457429e-4f, 9.9513966802111057e-4f,
1.5468348913161652e-3f, 2.0533350794358640e-3f, 2.4533031436958950e-3f,
2.6846707315385087e-3f, 2.6913237051575155e-3f, 2.4303724507982708e-3f,
1.8792817173578587e-3f, 1.0420231121204950e-3f, -4.6617252898486750e-5f,
-1.3193786988492551e-3f, -2.6781478874181100e-3f, -3.9992272197487003e-3f,
-5.1422613336274056e-3f, -5.9624224517967755e-3f, -6.3250283969908542e-3f,
-6.1213677360236101e-3f, -5.2841872043022185e-3f, -3.8011036067186429e-3f,
-1.7241752288145494e-3f, 8.2596463599396213e-4f, 3.6626436307478369e-3f,
6.5430316636724021e-3f, 9.1853404499045010e-3f, 1.1292516396583619e-2f,
1.2580791345879052e-2f, 1.2810714562937180e-2f, 1.1817712330677889e-2f,
9.5388893881204976e-3f, 6.0327678128662696e-3f, 1.4889921444742027e-3f,
-3.7742770128030593e-3f, -9.3265389310393538e-3f, -1.4654680466977541e-2f,
-1.9204813565928323e-2f, -2.2433342812570076e-2f, -2.3863084249865732e-2f,
-2.3139248817097825e-2f, -2.0079526147977360e-2f, -1.4712465100990968e-2f,
-7.2989072959128900e-3f, 1.6676055337427264e-3f, 1.1483818597217116e-2f,
2.1283378291010333e-2f, 3.0104924254589629e-2f, 3.6977102234817580e-2f,
4.1013752396638667e-2f, 4.1510805491867378e-2f, 3.8035383354576423e-2f,
3.0497421566956902e-2f, 1.9194910514469185e-2f, 4.8255960959712636e-3f,
-1.1539393212932630e-2f, -2.8521204184392364e-2f, -4.4535662544571142e-2f,
-5.7926040870466614e-2f, -6.7116245375785713e-2f, -7.0771566186484461e-2f,
-6.7952220045636696e-2f, -5.8244261062898019e-2f, -4.1853211028450271e-2f,
-1.9648003905967236e-2f, 6.8535507014343263e-3f, 3.5561844452076982e-2f,
6.3953651316164553e-2f, 8.9264185854578418e-2f, 1.0872025112127688e-1f,
1.1979689474056175e-1f, 1.2047646491371326e-1f, 1.0948710929592399e-1f,
8.6497869185231543e-2f, 5.2249701648862154e-2f, 8.6059406690018377e-3f,
-4.1488376792262582e-2f, -9.4141677945723271e-2f, -1.4474093381170536e-1f,
-1.8825408052888104e-1f, -2.1958987927558168e-1f, -2.3398931875783419e-1f,
-2.2741860176576378e-1f, -1.9693206642095332e-1f, -1.4097432039328661e-1f,
-5.9594435654526039e-2f, 4.5448949025739843e-2f, 1.7070477403312445e-1f,
3.1117273816011837e-1f, 4.6056631075658744e-1f, 6.1167961235662682e-1f,
7.5683349228721264e-1f, 8.8836924234920911e-1f, 9.9915393319190682e-1f,
1.0830597619389459e+0f, 1.1353812335460003e+0f, 1.1531583819295732e+0f,
};
static const raw_coef_t coefs0_u[POLY_FIR_LEN_U / 2 * PHASES0_U + 1] = {
0.f, 2.4376543962047211e-5f, 9.7074354091545404e-5f, 2.5656573977863553e-4f,
5.2734092391248152e-4f, 8.9078135146855391e-4f, 1.2494786883827907e-3f,
1.4060353542261659e-3f, 1.0794576035695273e-3f, -2.1547711862939183e-5f,
-2.0658693124381805e-3f, -4.9333908355966233e-3f, -8.0713165910440213e-3f,
-1.0451560117817383e-2f, -1.0703998868319438e-2f, -7.4626412699536097e-3f,
1.0898921033926621e-4f, 1.1734475997741493e-2f, 2.5579413661660957e-2f,
3.8168952738129619e-2f, 4.4846162998312754e-2f, 4.0821915377309274e-2f,
2.2679961923658700e-2f, -9.9957152600624218e-3f, -5.3343924460223908e-2f,
-9.8792607573741240e-2f, -1.3382736970823086e-1f, -1.4404307655147228e-1f,
-1.1619851747063137e-1f, -4.1649695271274462e-2f, 8.0680482815468343e-2f,
2.4264355486537642e-1f, 4.2712782955601925e-1f, 6.1041328492424185e-1f,
7.6625948559498691e-1f, 8.7088876549652772e-1f, 9.0774244518772884e-1f,
};
#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)]
#define COEF(h,l,i) ((i)<0||(i)>=(l)?0:(h)[(i)>(l)/2?(l)-(i):(i)])
static void prepare_coefs(float * coefs, int n, int phases0, int phases,
raw_coef_t const * coefs0, double multiplier)
float const * coefs0, double multiplier)
{
double k[6];
int length0 = n * phases0, length = n * phases, K0 = iAL(k)/2 - 1, i, j, pos;
raw_coef_t * coefs1 = malloc(((size_t)length / 2 + 1) * sizeof(*coefs1));
raw_coef_t * p = coefs1, f0, f1 = 0;
float * coefs1 = malloc(((size_t)length / 2 + 1) * sizeof(*coefs1));
float * p = coefs1, f0, f1 = 0;
for (j = 0; j < iAL(k); k[j] = COEF(coefs0, length0, j - K0), ++j);
for (pos = i = 0; i < length0 / 2; ++i) {
@ -254,18 +134,18 @@ static void prepare_coefs(float * coefs, int n, int phases0, int phases,
double c=(1/12.)*(k[4]-k[0]-2*(k[3]-k[1])-60*a),e=.5*(k[3]-k[1])-a-c;
for (; pos / phases == i; pos += phases0) {
double x = (double)(pos % phases) / phases;
*p++ = (raw_coef_t)(k[K0] + ((((a*x + b)*x + c)*x + d)*x + e)*x);
*p++ = (float)(k[K0] + ((((a*x + b)*x + c)*x + d)*x + e)*x);
}
for (j = 0; j < iAL(k) - 1; k[j] = k[j + 1], ++j);
k[j] = COEF(coefs0, length0, i + iAL(k) / 2 + 1);
}
if (!(length & 1))
*p++ = (raw_coef_t)k[K0];
*p++ = (float)k[K0];
assert(p - coefs1 == length / 2 + 1);
for (i = 0; i < n; ++i) for (j = phases - 1; j >= 0; --j, f1 = f0) {
pos = (n - 1 - i) * phases + j;
f0 = COEF(coefs1, length, pos) * (raw_coef_t)multiplier;
f0 = COEF(coefs1, length, pos) * (float)multiplier;
coef(coefs, 1, n, j, 0, i) = (float)f0;
coef(coefs, 1, n, j, 1, i) = (float)(f1 - f0);
}
@ -311,7 +191,7 @@ static float poly_fir1_u(float const * input, uint32_t frac)
typedef struct {
union {
int64_t all;
#if WORDS_BIGENDIAN
#if HAVE_BIGENDIAN
struct {int32_t integer; uint32_t frac;} part;
#else
struct {uint32_t frac; int32_t integer;} part;
@ -430,7 +310,7 @@ static void vr_init(rate_t * p, double default_io_ratio, int num_stages, double
}
fifo_create(&p->output_fifo, sizeof(float));
p->default_io_ratio = default_io_ratio;
if (!fade_coefs[0]) {
if (fade_coefs[0]==0) {
for (i = 0; i < iAL(fade_coefs); ++i)
fade_coefs[i] = (float)(.5 * (1 + cos(M_PI * i / (AL(fade_coefs) - 1))));
prepare_coefs(poly_fir_coefs_u, POLY_FIR_LEN_U, PHASES0_U, PHASES_U, coefs0_u, mult);
@ -481,7 +361,7 @@ static void vr_set_io_ratio(rate_t * p, double io_ratio, size_t slew_len)
}
}
else {
if (p->default_io_ratio) { /* Then this is the first call to this fn. */
if (p->default_io_ratio!=0) { /* Then this is the first call to this fn. */
int octave = (int)floor(log(io_ratio) / M_LN2);
p->current.stage_num = octave < 0? -1 : min(octave, p->num_stages0-1);
enter_new_stage(p, 0);
@ -489,7 +369,7 @@ static void vr_set_io_ratio(rate_t * p, double io_ratio, size_t slew_len)
else if (p->fade_len)
set_step(&p->fadeout, io_ratio);
set_step(&p->current, io_ratio);
if (p->default_io_ratio) FRAC(p->current.at) = FRAC(p->current.step) >> 1;
if (p->default_io_ratio!=0) FRAC(p->current.at) = FRAC(p->current.step) >> 1;
p->default_io_ratio = 0;
}
}
@ -544,7 +424,7 @@ static bool do_input_stage(rate_t * p, int stage_num, int sign, int min_stage_nu
static int vr_process(rate_t * p, int olen0)
{
assert(p->num_stages > 0);
if (p->default_io_ratio)
if (p->default_io_ratio!=0)
vr_set_io_ratio(p, p->default_io_ratio, 0);
{
float * output = fifo_reserve(&p->output_fifo, olen0);
@ -576,7 +456,7 @@ static int vr_process(rate_t * p, int olen0)
olen = min(olen, (int)(AL(buf) >> 1));
if (p->slew_len)
olen = min(olen, p->slew_len);
else if (p->new_io_ratio) {
else if (p->new_io_ratio!=0) {
set_step(&p->current, p->new_io_ratio);
set_step(&p->fadeout, p->new_io_ratio);
p->fadeout.step_step.all = p->current.step_step.all = 0;
@ -753,7 +633,7 @@ static char const * vr_create(void * channel, void * shared,double max_io_ratio,
static char const * vr_id(void)
{
return "single-precision variable-rate";
return "vr32";
}
typedef void (* fn_t)(void);

View File

@ -0,0 +1,64 @@
/* SoX Resampler Library Copyright (c) 2007-15 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details. */
/* Test 1: exercises soxr_delay and soxr_clear */
#ifdef NDEBUG /* N.B. assert used with active statements so enable always. */
#undef NDEBUG /* Must undef above assert.h or other that might include it. */
#endif
#include <soxr.h>
#include "../examples/examples-common.h"
#define ranqd1(x) ((x) = 1664525 * (x) + 1013904223) /* int32_t x */
#define franqd1(x) (float)(ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */
#define irate 9600
#define orate 4410
int main(int argc, char const * arg[])
{
soxr_error_t error;
int32_t ran = 0;
int j;
soxr_t soxr = soxr_create(irate, orate, 1, &error, NULL, NULL, NULL);
assert(!error);
for (j=0; j<2; ++j) {
float ibuf[irate], out[orate+2], obuf[orate+2], * ibuf1 = ibuf;
size_t ilen = AL(ibuf)-1, olen = AL(obuf), i, odone = 0, odone0, odone1=0;
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, 0);
for (i=0; i<irate; ibuf[i++] = franqd1(ran));
error = soxr_oneshot(irate, orate, 1, ibuf, ilen, NULL,
out, AL(out), &odone0, NULL, &q_spec, NULL);
assert(!error);
assert(odone0==orate);
for (i=0; ilen || odone1; ++i) {
double out_samples = (double)orate / irate * (double)ilen;
double delayed_samples = soxr_delay(soxr);
unsigned max_out_samples = (unsigned)(out_samples + delayed_samples + .5);
assert(delayed_samples >= 0);
fprintf(stderr, "%5u %5u %5u\n",
(unsigned)ilen, max_out_samples, (unsigned)odone);
assert(max_out_samples+odone==odone0);
error = soxr_process(soxr, ibuf1, ilen, NULL, obuf+odone, olen, &odone1);
assert(!error);
odone += odone1;
ibuf1 = NULL, ilen = 0;
olen = min(100, AL(obuf)-odone);
}
assert(odone==odone0);
for (i=0; i<odone && out[i]==obuf[i]; ++i);
assert(i==odone);
soxr_clear(soxr);
}
soxr_delete(soxr);
return 0 * argc * !arg;
}

View File

@ -1,8 +1,8 @@
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
# Licence for this file: LGPL v2.1 See LICENCE for details.
add_definitions (${PROJECT_C_FLAGS})
link_libraries (${PROJECT_NAME})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
link_libraries (${PROJECT_NAME} ${LIBM_LIBRARIES})
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c)
foreach (fe ${SOURCES})
@ -10,7 +10,10 @@ foreach (fe ${SOURCES})
add_executable (${f} ${fe})
endforeach ()
enable_testing ()
# Can't use c89 for this file:
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_property (SOURCE throughput APPEND_STRING PROPERTY COMPILE_FLAGS "-std=gnu89")
endif ()
set (sweep_to_freq 22050)
set (leader 1)
@ -20,31 +23,40 @@ math (EXPR base_rate "${sweep_to_freq} + ${sweep_to_freq}")
macro (add_vector r)
set (output ${CMAKE_CURRENT_BINARY_DIR}/ref-${r}.s32)
add_custom_command (OUTPUT ${output} DEPENDS vector-gen ${CMAKE_CURRENT_LIST_FILE}
COMMAND vector-gen ${r} ${leader} ${len} ${sweep_to_freq} 1 ${output})
COMMAND vector-gen ${r} ${leader} ${len} 0 ${sweep_to_freq} 1 ${output})
set (vectors ${output} ${vectors})
endmacro ()
macro (add_cmp_test from to bits)
set (name ${bits}-bit-perfect-${from}-${to})
add_test (NAME ${name} COMMAND ${CMAKE_COMMAND} -Dbits=${bits} -DBIN=${BIN} -DEXAMPLES_BIN=${EXAMPLES_BIN} -Dleader=${leader} -Dto=${to}
-Dfrom=${from} -Dlen=${len} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmp-test.cmake)
add_vector (${from})
add_vector (${to})
macro (add_cmp_test irate orate bits)
set (name ${bits}-bit-perfect-${irate}-${orate})
add_test (NAME ${name} COMMAND ${CMAKE_COMMAND} -Dbits=${bits} -DBIN=${BIN}
-DEXAMPLES_BIN=${EXAMPLES_BIN} -DlenToSkip=${leader} -Dorate=${orate}
-Dirate=${irate} -Dlen=${len} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmp-test.cmake)
add_vector (${irate})
add_vector (${orate})
endmacro ()
unset (test_bits)
if (WITH_SINGLE_PRECISION)
if (WITH_CR32 OR WITH_CR32S OR WITH_CR64 OR WITH_CR64S)
set (test_bits 20)
endif ()
if (WITH_DOUBLE_PRECISION)
set (test_bits ${test_bits} 24)
if (WITH_CR64 OR WITH_CR64S)
set (test_bits ${test_bits} 28)
endif ()
set (rates 192000)
if (WITH_HI_PREC_CLOCK)
set (rates ${rates} 65537)
endif ()
foreach (b ${test_bits})
foreach (r 96000 65537)
foreach (r ${rates})
add_cmp_test (${base_rate} ${r} ${b})
add_cmp_test (${r} ${base_rate} ${b})
endforeach ()
endforeach ()
add_custom_target (test-vectors ALL DEPENDS ${vectors})
if (NOT CMAKE_CROSSCOMPILING)
add_custom_target (test-vectors ALL DEPENDS ${vectors})
endif ()
add_test (1-delay-clear ${BIN}1-delay-clear)

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