Upgrade libsoxr to 0.1.3
This commit is contained in:
parent
f7f721b52d
commit
ccc29c6c76
|
@ -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 ()
|
||||
|
|
|
@ -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 libsoxr’s operation for a particular application.
|
||||
Optimal performance however, might depend on an individual end-user’s run-
|
||||
time system and the end-user’s 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
|
@ -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 ()
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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}")
|
|
@ -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}")
|
|
@ -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 ()
|
|
@ -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 ()
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
inst-check-soxr
|
|
@ -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}"
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}},
|
||||
};
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
set(TARGET_HEADERS "@TARGET_HEADERS@")
|
||||
set(TARGET_PCS "@TARGET_PCS@")
|
|
@ -1 +0,0 @@
|
|||
set(TARGET_LIBS "@TARGET_LIBS@")
|
|
@ -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);}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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];
|
|
@ -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"
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue