From f510d21218635f3af2879091018652a9a335eb4a Mon Sep 17 00:00:00 2001 From: lllucius Date: Tue, 5 Nov 2013 04:24:24 +0000 Subject: [PATCH] Update libsoxr to 0.1.1 --- lib-src/audacity-patches.txt | 6 +- lib-src/libsoxr/CMakeLists.txt | 577 +-- lib-src/libsoxr/Doxyfile.in | 208 - lib-src/libsoxr/INSTALL | 63 +- lib-src/libsoxr/LICENCE | 2 +- lib-src/libsoxr/NEWS | 24 + lib-src/libsoxr/README | 103 +- .../cmake/Modules/FindLibAVCodec.cmake | 46 +- .../libsoxr/cmake/Modules/FindOpenMP.cmake | 199 +- lib-src/libsoxr/cmake/Modules/FindSIMD.cmake | 141 +- .../libsoxr/cmake/Modules/TestBigEndian.cmake | 30 +- lib-src/libsoxr/configure | 13 - lib-src/libsoxr/deinstall.cmake.in | 4 +- lib-src/libsoxr/doc/README | 3 - lib-src/libsoxr/doc/footer.html | 4 - lib-src/libsoxr/doc/header.html | 31 - lib-src/libsoxr/doc/logo.png | Bin 3992 -> 0 bytes lib-src/libsoxr/doc/stylesheet.css | 395 -- lib-src/libsoxr/examples/1-single-block.c | 98 +- lib-src/libsoxr/examples/1a-lsr.c | 40 + .../examples/{2-stream.c => 2-stream.C} | 156 +- lib-src/libsoxr/examples/2a-stream.c | 64 - .../examples/2b-stream-with-input-fn.c | 67 - lib-src/libsoxr/examples/3-options-input-fn.c | 207 +- lib-src/libsoxr/examples/3a-options.c | 83 - .../examples/3b-options-with-input-fn.c | 85 - lib-src/libsoxr/examples/4-split-channels.c | 294 +- lib-src/libsoxr/examples/5-variable-rate.c | 188 +- lib-src/libsoxr/examples/CMakeLists.txt | 58 +- lib-src/libsoxr/examples/README | 38 +- lib-src/libsoxr/examples/examples-common.h | 90 +- lib-src/libsoxr/go | 32 +- lib-src/libsoxr/go.bat | 54 +- lib-src/libsoxr/inst-check | 25 + lib-src/libsoxr/inst-check-soxr | 52 + lib-src/libsoxr/lsr-tests/CMakeLists.txt | 49 - lib-src/libsoxr/lsr-tests/COPYING | 340 -- lib-src/libsoxr/lsr-tests/README | 8 - lib-src/libsoxr/lsr-tests/calc_snr.c | 242 -- .../libsoxr/lsr-tests/callback_hang_test.c | 131 - lib-src/libsoxr/lsr-tests/callback_test.c | 243 -- .../lsr-tests/cmake/Modules/FindFFTW.cmake | 23 - .../lsr-tests/cmake/Modules/Findsndfile.cmake | 23 - lib-src/libsoxr/lsr-tests/config.h.in | 24 - lib-src/libsoxr/lsr-tests/downsample_test.c | 61 - lib-src/libsoxr/lsr-tests/float_cast.h | 281 -- lib-src/libsoxr/lsr-tests/float_short_test.c | 192 - lib-src/libsoxr/lsr-tests/misc_test.c | 175 - .../libsoxr/lsr-tests/multi_channel_test.c | 364 -- .../lsr-tests/multichan_throughput_test.c | 216 - lib-src/libsoxr/lsr-tests/reset_test.c | 238 -- lib-src/libsoxr/lsr-tests/simple_test.c | 117 - lib-src/libsoxr/lsr-tests/sndfile-resample.c | 332 -- lib-src/libsoxr/lsr-tests/snr_bw_test.c | 401 -- lib-src/libsoxr/lsr-tests/termination_test.c | 339 -- lib-src/libsoxr/lsr-tests/throughput_test.c | 212 - lib-src/libsoxr/lsr-tests/util.c | 230 -- lib-src/libsoxr/lsr-tests/util.h | 50 - lib-src/libsoxr/lsr-tests/varispeed_test.c | 152 - lib-src/libsoxr/msvc/README | 18 +- lib-src/libsoxr/msvc/soxr-config.h | 26 +- lib-src/libsoxr/soxr-config.h.in | 6 +- lib-src/libsoxr/src/CMakeLists.txt | 222 +- lib-src/libsoxr/src/aliases.h | 74 +- lib-src/libsoxr/src/avfft32.c | 54 +- lib-src/libsoxr/src/avfft32s.c | 54 +- lib-src/libsoxr/src/ccrw2.h | 148 +- lib-src/libsoxr/src/data-io.c | 501 +-- lib-src/libsoxr/src/data-io.h | 78 +- lib-src/libsoxr/src/dbesi0.c | 298 +- lib-src/libsoxr/src/fft4g.c | 2704 ++++++------- lib-src/libsoxr/src/fft4g.h | 46 +- lib-src/libsoxr/src/fft4g32.c | 54 +- lib-src/libsoxr/src/fft4g32s.c | 52 +- lib-src/libsoxr/src/fft4g64.c | 58 +- lib-src/libsoxr/src/fft4g_cache.h | 184 +- lib-src/libsoxr/src/fifo.h | 248 +- lib-src/libsoxr/src/filter.c | 490 +-- lib-src/libsoxr/src/filter.h | 78 +- lib-src/libsoxr/src/filters.h | 302 +- lib-src/libsoxr/src/half-fir.h | 50 +- lib-src/libsoxr/src/half_coefs.h | 114 +- lib-src/libsoxr/src/internal.h | 92 +- lib-src/libsoxr/src/libsoxr-dev.src.in | 4 +- lib-src/libsoxr/src/libsoxr-lsr.pc.in | 11 - lib-src/libsoxr/src/libsoxr.pc.in | 11 - lib-src/libsoxr/src/libsoxr.src.in | 2 +- lib-src/libsoxr/src/lsr.c | 228 +- lib-src/libsoxr/src/pffft.c | 3458 ++++++++--------- lib-src/libsoxr/src/pffft.h | 354 +- lib-src/libsoxr/src/pffft32.c | 62 +- lib-src/libsoxr/src/pffft32s.c | 54 +- lib-src/libsoxr/src/poly-fir.h | 196 +- lib-src/libsoxr/src/poly-fir0.h | 64 +- lib-src/libsoxr/src/rate.h | 1458 ++++--- lib-src/libsoxr/src/rate32.c | 18 +- lib-src/libsoxr/src/rate32s.c | 18 +- lib-src/libsoxr/src/rate64.c | 18 +- lib-src/libsoxr/src/rdft.h | 62 +- lib-src/libsoxr/src/rint-clip.h | 306 +- lib-src/libsoxr/src/rint.h | 136 +- lib-src/libsoxr/src/samplerate.h | 2 +- lib-src/libsoxr/src/simd-dev.h | 10 +- lib-src/libsoxr/src/simd.c | 168 +- lib-src/libsoxr/src/simd.h | 32 +- lib-src/libsoxr/src/soxr-lsr.h | 158 +- lib-src/libsoxr/src/soxr-lsr.pc.in | 5 + lib-src/libsoxr/src/soxr.c | 1277 +++--- lib-src/libsoxr/src/soxr.h | 647 +-- lib-src/libsoxr/src/soxr.pc.in | 5 + lib-src/libsoxr/src/vr32.c | 1542 ++++---- lib-src/libsoxr/tests/CMakeLists.txt | 100 +- lib-src/libsoxr/tests/README | 2 +- lib-src/libsoxr/tests/cmp-test.cmake | 58 +- lib-src/libsoxr/tests/eg-test | 58 +- lib-src/libsoxr/tests/io-test | 80 +- lib-src/libsoxr/tests/large-ratio | 43 +- lib-src/libsoxr/tests/vector-cmp.c | 106 +- lib-src/libsoxr/tests/vector-gen.c | 112 +- 119 files changed, 9812 insertions(+), 14927 deletions(-) delete mode 100644 lib-src/libsoxr/Doxyfile.in create mode 100644 lib-src/libsoxr/NEWS delete mode 100755 lib-src/libsoxr/configure delete mode 100644 lib-src/libsoxr/doc/README delete mode 100644 lib-src/libsoxr/doc/footer.html delete mode 100644 lib-src/libsoxr/doc/header.html delete mode 100644 lib-src/libsoxr/doc/logo.png delete mode 100644 lib-src/libsoxr/doc/stylesheet.css create mode 100644 lib-src/libsoxr/examples/1a-lsr.c rename lib-src/libsoxr/examples/{2-stream.c => 2-stream.C} (95%) delete mode 100644 lib-src/libsoxr/examples/2a-stream.c delete mode 100644 lib-src/libsoxr/examples/2b-stream-with-input-fn.c delete mode 100644 lib-src/libsoxr/examples/3a-options.c delete mode 100644 lib-src/libsoxr/examples/3b-options-with-input-fn.c create mode 100755 lib-src/libsoxr/inst-check create mode 100755 lib-src/libsoxr/inst-check-soxr delete mode 100644 lib-src/libsoxr/lsr-tests/CMakeLists.txt delete mode 100644 lib-src/libsoxr/lsr-tests/COPYING delete mode 100644 lib-src/libsoxr/lsr-tests/README delete mode 100644 lib-src/libsoxr/lsr-tests/calc_snr.c delete mode 100644 lib-src/libsoxr/lsr-tests/callback_hang_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/callback_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/cmake/Modules/FindFFTW.cmake delete mode 100644 lib-src/libsoxr/lsr-tests/cmake/Modules/Findsndfile.cmake delete mode 100644 lib-src/libsoxr/lsr-tests/config.h.in delete mode 100644 lib-src/libsoxr/lsr-tests/downsample_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/float_cast.h delete mode 100644 lib-src/libsoxr/lsr-tests/float_short_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/misc_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/multi_channel_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/multichan_throughput_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/reset_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/simple_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/sndfile-resample.c delete mode 100644 lib-src/libsoxr/lsr-tests/snr_bw_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/termination_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/throughput_test.c delete mode 100644 lib-src/libsoxr/lsr-tests/util.c delete mode 100644 lib-src/libsoxr/lsr-tests/util.h delete mode 100644 lib-src/libsoxr/lsr-tests/varispeed_test.c delete mode 100644 lib-src/libsoxr/src/libsoxr-lsr.pc.in delete mode 100644 lib-src/libsoxr/src/libsoxr.pc.in create mode 100644 lib-src/libsoxr/src/soxr-lsr.pc.in create mode 100644 lib-src/libsoxr/src/soxr.pc.in diff --git a/lib-src/audacity-patches.txt b/lib-src/audacity-patches.txt index 37ec09ef5..9c360b9c4 100644 --- a/lib-src/audacity-patches.txt +++ b/lib-src/audacity-patches.txt @@ -117,12 +117,10 @@ libsoxr The SoX Resampler library performs one-dimensional sample-rate conversion, by Rob Sykes. http://sourceforge.net/p/soxr/wiki/Home/ -Version in Audacity SVN: 0.0.5 +Version in Audacity SVN: 0.1.1 Patches: * "libsoxr/configure" file: modified cmake params - * modified .vcproj file in win\Projects\libsoxr - -Upstream Version: 0.0.5 (although no file downloads are available yet) +Upstream Version: 0.1.1 libvamp ------- diff --git a/lib-src/libsoxr/CMakeLists.txt b/lib-src/libsoxr/CMakeLists.txt index ed2ae298e..8a24952a4 100644 --- a/lib-src/libsoxr/CMakeLists.txt +++ b/lib-src/libsoxr/CMakeLists.txt @@ -1,280 +1,297 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -cmake_minimum_required (VERSION 2.8 FATAL_ERROR) - -project (soxr C) -set (DESCRIPTION_SUMMARY "One-dimensional sample-rate conversion library") - - - -# Release versioning: - -set (PROJECT_VERSION_MAJOR 0) -set (PROJECT_VERSION_MINOR 0) -set (PROJECT_VERSION_PATCH 5) - -# 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 - -set (SO_VERSION_CURRENT 0) -set (SO_VERSION_REVISION 0) -set (SO_VERSION_AGE 0) - - - -# Main options: - -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) -endif () - -option (BUILD_TESTS "Build sanity-tests." OFF) -option (BUILD_SHARED_LIBS "Build shared libraries." 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) - cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF - "WITH_LSR_BINDINGS" OFF) -endif () - - - -# Introspection: - -list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) - -include (CheckFunctionExists) -include (CheckIncludeFiles) -include (CheckLibraryExists) -include (TestBigEndian) - -check_library_exists (m pow "" NEED_LIBM) -if (NEED_LIBM) - set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}") - link_libraries (m) -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}") -endif () - -if (WITH_SIMD) - find_package (SIMD) - if (SIMD_FOUND) - set (HAVE_SIMD 1) - endif () -endif () - -if (WITH_SINGLE_PRECISION) - set (HAVE_SINGLE_PRECISION 1) -endif () - -if (WITH_DOUBLE_PRECISION) - set (HAVE_DOUBLE_PRECISION 1) -endif () - -if (WITH_AVFFT) - find_package (LibAVCodec) - if (AVCODEC_FOUND) - include_directories (${AVCODEC_INCLUDE_DIRS}) - link_libraries (${AVCODEC_LIBRARIES}) - set (HAVE_AVFFT 1) - endif () -endif () - -if (EXISTS ${PROJECT_SOURCE_DIR}/src/vr32.c) - set (HAVE_VR 1) -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 HAVE_VR) -make_exist (HAVE_SINGLE_PRECISION HAVE_DOUBLE_PRECISION HAVE_AVFFT) - - - -# 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_BUILD_TYPE STREQUAL "Release") - set (CMAKE_SHARED_LINKER_FLAGS "-s") # strip - endif () - #option (VISIBILITY_HIDDEN "Build with -fvisibility=hidden." ON) - if (VISIBILITY_HIDDEN) - add_definitions (-fvisibility=hidden) - endif () -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) - string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endforeach () - endif () - # By default, do not warn when built on machines using only VS Express: - if (NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - set (CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) - endif () -endif () - - - -# Build configuration: - -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}) - set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN}) -else () - set (BIN ./) - set (EXAMPLES_BIN ../examples/) -endif () - -set (LIB_TYPE STATIC) -if (BUILD_SHARED_LIBS) - set (LIB_TYPE SHARED) - if (MSVC) - add_definitions (-DSOXR_DLL) - endif () -endif () - - - -# Installation configuration: - -set (LIB_SUFFIX "" CACHE STRING "Define suffix of libraries directory name (32 or 64).") -set (BIN_INSTALL_DIR "bin" CACHE PATH "The subdirectory to the binaries." FORCE) -set (LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The subdirectory to the libraries." FORCE) -set (INCLUDE_INSTALL_DIR "include" CACHE PATH "The subdirectory to the headers." FORCE) - -if (APPLE) - option (BUILD_FRAMEWORK "Build an OS X framework." OFF) - set (FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.") -endif () - - - -# 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 (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH}) - -configure_file ( - ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-config.h.in - ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.h) -include_directories (${PROJECT_BINARY_DIR}) - -if (BUILD_TESTS OR BUILD_LSR_TESTS) - enable_testing () -endif () - - - -# Subdirectories: - -include_directories (${PROJECT_SOURCE_DIR}/src) - -add_subdirectory (src) -if (BUILD_TESTS) - add_subdirectory (tests) -endif () -if (BUILD_LSR_TESTS) - add_subdirectory (lsr-tests) -endif () -if (BUILD_EXAMPLES OR BUILD_TESTS) - add_subdirectory (examples) -endif () - - - -# Rough-and-ready distclean for anyone still doing in-tree builds: - -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) -endif () - - - -# Deinstallation: - -configure_file ( - "${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake" - IMMEDIATE @ONLY) - -add_custom_target (deinstall - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake") - - - -# Packaging: - -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 "TBZ2") - set (CPACK_SOURCE_IGNORE_FILES "/Debug/;/Release/;/cpack/;\\\\.swp$;\\\\.gitignore") - - include (CPack) - - if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/cpack) - add_subdirectory (cpack) - endif () -endif () +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +cmake_minimum_required (VERSION 2.8 FATAL_ERROR) + +project (soxr C) +set (DESCRIPTION_SUMMARY "High quality, one-dimensional sample-rate conversion library") + + + +# Release versioning: + +set (PROJECT_VERSION_MAJOR 0) +set (PROJECT_VERSION_MINOR 1) +set (PROJECT_VERSION_PATCH 1) + +# 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 + +set (SO_VERSION_CURRENT 1) +set (SO_VERSION_REVISION 0) +set (SO_VERSION_AGE 1) + + + +# Main options: + +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) +endif () + +option (BUILD_TESTS "Build sanity-tests." ON) +option (BUILD_SHARED_LIBS "Build shared libraries." 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 () + + + +# Introspection: + +list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) + +include (CheckFunctionExists) +include (CheckIncludeFiles) +include (CheckLibraryExists) +include (TestBigEndian) + +check_library_exists (m pow "" NEED_LIBM) +if (NEED_LIBM) + set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}") + link_libraries (m) +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}") +endif () + +if (WITH_SIMD) + find_package (SIMD) + if (SIMD_FOUND) + set (HAVE_SIMD 1) + endif () +endif () + +if (WITH_SINGLE_PRECISION) + set (HAVE_SINGLE_PRECISION 1) +endif () + +if (WITH_DOUBLE_PRECISION) + set (HAVE_DOUBLE_PRECISION 1) +endif () + +if (WITH_AVFFT) + find_package (LibAVCodec) + if (AVCODEC_FOUND) + include_directories (${AVCODEC_INCLUDE_DIRS}) + link_libraries (${AVCODEC_LIBRARIES}) + set (HAVE_AVFFT 1) + 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) + + + +# 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_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 + "BUILD_SHARED_LIBS" OFF) + if (VISIBILITY_HIDDEN) + add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY) + endif () +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) + string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endforeach () + endif () + # By default, do not warn when built on machines using only VS Express: + if (NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) + set (CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) + endif () +endif () + + + +# Build configuration: + +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}) + set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN}) +else () + set (BIN ./) + set (EXAMPLES_BIN ../examples/) +endif () + +set (LIB_TYPE STATIC) +if (BUILD_SHARED_LIBS) + set (LIB_TYPE SHARED) + if (MSVC) + add_definitions (-DSOXR_DLL) + endif () +endif () + + + +# Installation configuration: + +if (NOT DEFINED BIN_INSTALL_DIR) + set (BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin") +endif () +if (NOT DEFINED LIB_INSTALL_DIR) + set (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") +endif () +if (NOT DEFINED INCLUDE_INSTALL_DIR) + set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include") +endif () +if (NOT DEFINED DOC_INSTALL_DIR) + if (UNIX) + set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/lib${PROJECT_NAME}") + else () + set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/doc") + endif () +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.") +endif () + + + +# 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 (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH}) + +configure_file ( + ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-config.h.in + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.h) +include_directories (${PROJECT_BINARY_DIR}) + +if (BUILD_TESTS OR BUILD_LSR_TESTS) + enable_testing () +endif () + +install (FILES + ${CMAKE_CURRENT_SOURCE_DIR}/README + ${CMAKE_CURRENT_SOURCE_DIR}/LICENCE + ${CMAKE_CURRENT_SOURCE_DIR}/NEWS + DESTINATION ${DOC_INSTALL_DIR}) + + + +# Subdirectories: + +include_directories (${PROJECT_SOURCE_DIR}/src) + +add_subdirectory (src) +if (BUILD_TESTS) + add_subdirectory (tests) +endif () +if (BUILD_LSR_TESTS) + add_subdirectory (lsr-tests) +endif () +if (BUILD_EXAMPLES OR BUILD_TESTS) + add_subdirectory (examples) +endif () + + + +# Rough-and-ready distclean for anyone still doing in-tree builds: + +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) +endif () + + + +# Deinstallation: + +configure_file ( + "${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target (deinstall + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake") + + + +# Packaging: + +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/") + + include (CPack) + + if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/cpack) + add_subdirectory (cpack) + endif () +endif () diff --git a/lib-src/libsoxr/Doxyfile.in b/lib-src/libsoxr/Doxyfile.in deleted file mode 100644 index 96b86d06e..000000000 --- a/lib-src/libsoxr/Doxyfile.in +++ /dev/null @@ -1,208 +0,0 @@ -# Doxyfile 1.3.4 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = lib${PROJECT_NAME} -PROJECT_NUMBER = ${PROJECT_VERSION} -OUTPUT_DIRECTORY = doc -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = NO -STRIP_FROM_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 2 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = YES -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -GENERATE_TODOLIST = NO -GENERATE_TESTLIST = NO -GENERATE_BUGLIST = NO -GENERATE_DEPRECATEDLIST= NO -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = @CMAKE_SOURCE_DIR@/src -FILE_PATTERNS = @PROJECT_NAME@.h -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = @CMAKE_SOURCE_DIR@/doc/header.html -HTML_FOOTER = @CMAKE_SOURCE_DIR@/doc/footer.html -HTML_STYLESHEET = @CMAKE_SOURCE_DIR@/doc/stylesheet.css -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = YES -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = letter -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = DO_NOT_DOCUMENT \ - DOXYGEN \ - WITH_MP4 \ - WITH_ASF -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = YES -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 0 -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/lib-src/libsoxr/INSTALL b/lib-src/libsoxr/INSTALL index 541281579..c2c7675b3 100644 --- a/lib-src/libsoxr/INSTALL +++ b/lib-src/libsoxr/INSTALL @@ -1,4 +1,15 @@ -SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net +SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + +INSTALLATION GUIDE CONTENTS + +* Standard build +* Build customisation +* Cross-compiling with mingw (linux host) +* Integration with other build systems + + + +STANDARD BUILD 1. Prerequisites: @@ -42,10 +53,13 @@ SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net 5. Installation test - To test the installation, build and run the first example programme (see - examples/README). + To test the installation, build and run some of the example programmes + (see examples/README). + +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: @@ -64,3 +78,46 @@ To list help on the available options, enter: Options, if given, should be preceded with '-D', e.g. cmake -DWITH_SIMD:BOOL=OFF .. + + + +CROSS-COMPILING WITH MINGW (LINUX HOST) + +For example: + + 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 + +where ~/Toolchain-x86_64-mingw-w64-mingw32.cmake might contain: + + SET(CMAKE_SYSTEM_NAME Windows) + SET(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) + SET(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) + SET(CMAKE_RC_COMPILER /usr/bin/x86_64-w64-mingw32-windres) + SET(CMAKE_Fortran_COMPILER /usr/bin/x86_64-w64-mingw32-gfortran) + SET(CMAKE_AR:FILEPATH /usr/bin/x86_64-w64-mingw32-ar) + SET(CMAKE_RANLIB:FILEPATH /usr/bin/x86_64-w64-mingw32-ranlib) + SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + SET(QT_BINARY_DIR /usr/x86_64-w64-mingw32/bin /usr/bin) + SET(Boost_COMPILER -gcc47) + + + +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 . +(or with other build options as required). + +For MS visual studio, see msvc/README diff --git a/lib-src/libsoxr/LICENCE b/lib-src/libsoxr/LICENCE index ded4ca3f7..1c618785e 100644 --- a/lib-src/libsoxr/LICENCE +++ b/lib-src/libsoxr/LICENCE @@ -1,4 +1,4 @@ -SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net +SoX Resampler Library Copyright (c) 2007-13 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 diff --git a/lib-src/libsoxr/NEWS b/lib-src/libsoxr/NEWS new file mode 100644 index 000000000..64f8ffac6 --- /dev/null +++ b/lib-src/libsoxr/NEWS @@ -0,0 +1,24 @@ +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 + bindings only). + * Fix broken resampling in many cases with SIMD and anti_aliasing_pc < 100. + * For clarity, renamed and slightly changed usage of three parameters in + soxr_quality_spec_t (ABI compatible, API incompatible). An application not + setting these parameters directly need make no change; otherwise, changes + should be made per the following example (as shown, compatibility with both + old/new APIs is maintained). See also the comments on these parameters in + soxr.h. N.B. ABI compatibility with the 0.1.0 API may be removed in a + future release. + #if !defined SOXR_VERSION /* Deprecated, 0.1.0 API */ + q_spec.phase = minimum_phase? 0 : 50; + q_spec.bw_pc = cutoff * 100; + q_spec.anti_aliasing_pc = anti_aliasing * 100; + #else /* 0.1.1 API */ Explanation: + q_spec.phase_response = minimum_phase? 0 : 50; Renamed. + q_spec.passband_end = cutoff; Renamed, no longer %. + q_spec.stopband_begin = 2 - anti_aliasing; Renamed, no longer %, no + #endif longer mirrored in Fs. + +Version 0.1.0 (2013-01-19) + * First public release. diff --git a/lib-src/libsoxr/README b/lib-src/libsoxr/README index f357ef2f8..1f9921dc7 100644 --- a/lib-src/libsoxr/README +++ b/lib-src/libsoxr/README @@ -1,50 +1,53 @@ -SoX Resampler Library Copyright (c) 2007-12 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. -For higher-dimensional resampling, such as for visual-image processing, you -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. - -The resampler is currently available either as part of `libsox' (the audio -file-format and effect library), or stand-alone as `libsoxr' (this package). -The interfaces to libsox and libsoxr are slightly different, with that of -libsoxr designed specifically for resampling. An application requiring -support for other effects, or for reading-from or writing-to audio files or -devices, should use libsox (or other libraries such as libsndfile or -libavformat). - -Libsoxr provides a simple API that allows interfacing using the most -commonly-used sample formats and buffering schemes: sample-formats may be -either floating-point or integer, and multiple channels either interleaved -or split in separate buffers. The API is documented in the header file -`soxr.h', together with sample code found in the 'examples' directory. - -For compatibility with the popular `libsamplerate' library, the header file -`soxr-lsr.h' is provided and may be used as an alternative API.³ Note -however, that libsoxr does not provide a full emulation of libsamplerate -and that using this approach, only a sub-set of libsoxr's features are -available. - -The design was inspired by Laurent De Soras' paper `The Quest For The -Perfect Resampler', http://ldesoras.free.fr/doc/articles/resampler-en.pdf; -in essence, it combines Julius O. Smith's `Bandlimited Interpolation' -technique (https://ccrma.stanford.edu/~jos/resample/resample.pdf) with FFT- -based over-sampling. - -Note that for real-time resampling, libsoxr may have a higher latency -than non-FFT based resamplers. For example, when using the `High Quality' -configuration to resample between 44100Hz and 48000Hz, the latency is -around 1000 output samples, i.e. roughly 20ms. - -For build and installation instructions, see the file `INSTALL'; for -copyright and licensing information, see the file `LICENCE'. -________ -¹ For example, multi-channel resampling can utilise multiple CPU-cores. -² Bit-perfect within practical occupied-bandwidth limits. -³ For details of that API, see http://www.mega-nerd.com/SRC/api.html. +SoX Resampler Library Copyright (c) 2007-13 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. +For higher-dimensional resampling, such as for visual-image processing, you +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. + +The resampler is currently available either as part of `libsox' (the audio +file-format and effect library), or stand-alone as `libsoxr' (this package). +The interfaces to libsox and libsoxr are slightly different, with that of +libsoxr designed specifically for resampling. An application requiring +support for other effects, or for reading-from or writing-to audio files or +devices, should use libsox (or other libraries such as libsndfile or +libavformat). + +Libsoxr provides a simple API that allows interfacing using the most +commonly-used sample formats and buffering schemes: sample-formats may be +either floating-point or integer, and multiple channels either interleaved +or split in separate buffers. The API is documented in the header file +`soxr.h', together with sample code found in the 'examples' directory. + +For compatibility with the popular `libsamplerate' library, the header file +`soxr-lsr.h' is provided and may be used as an alternative API.³ Note +however, that libsoxr does not provide a full emulation of libsamplerate +and that using this approach, only a sub-set of libsoxr's features are +available. + +The design was inspired by Laurent De Soras' paper `The Quest For The +Perfect Resampler', http://ldesoras.free.fr/doc/articles/resampler-en.pdf; +in essence, it combines Julius O. Smith's `Bandlimited Interpolation' +technique (https://ccrma.stanford.edu/~jos/resample/resample.pdf) with FFT- +based over-sampling. + +Note that for real-time resampling, libsoxr may have a higher latency +than non-FFT based resamplers. For example, when using the `High Quality' +configuration to resample between 44100Hz and 48000Hz, the latency is +around 1000 output samples, i.e. roughly 20ms (though passband and FFT- +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 example, multi-channel resampling can utilise multiple CPU-cores. +² Bit-perfect within practical occupied-bandwidth limits. +³ For details of that API, see http://www.mega-nerd.com/SRC/api.html. diff --git a/lib-src/libsoxr/cmake/Modules/FindLibAVCodec.cmake b/lib-src/libsoxr/cmake/Modules/FindLibAVCodec.cmake index e3669a1f0..add33c3e6 100644 --- a/lib-src/libsoxr/cmake/Modules/FindLibAVCodec.cmake +++ b/lib-src/libsoxr/cmake/Modules/FindLibAVCodec.cmake @@ -1,23 +1,23 @@ -# SoX Resampler Library Copyright (c) 2007-12 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. -# -# 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. - -if (AVCODEC_INCLUDES) - set (AVCODEC_FIND_QUIETLY TRUE) -endif (AVCODEC_INCLUDES) - -find_path (AVCODEC_INCLUDES libavcodec/avcodec.h) - -find_library (AVCODEC_LIBRARIES NAMES avcodec) - -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args ( - AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDES) - -mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDES) +# SoX Resampler Library Copyright (c) 2007-13 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. +# +# 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. + +if (AVCODEC_INCLUDES) + set (AVCODEC_FIND_QUIETLY TRUE) +endif (AVCODEC_INCLUDES) + +find_path (AVCODEC_INCLUDES libavcodec/avcodec.h) + +find_library (AVCODEC_LIBRARIES NAMES avcodec) + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args ( + AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDES) + +mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDES) diff --git a/lib-src/libsoxr/cmake/Modules/FindOpenMP.cmake b/lib-src/libsoxr/cmake/Modules/FindOpenMP.cmake index f0aedbde9..654dc30a1 100644 --- a/lib-src/libsoxr/cmake/Modules/FindOpenMP.cmake +++ b/lib-src/libsoxr/cmake/Modules/FindOpenMP.cmake @@ -1,91 +1,108 @@ -# - 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/ - -#============================================================================= -# Copyright 2009 Kitware, Inc. -# Copyright 2008-2009 André Rigland Brodtkorb -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -# -# Modified for libsoxr not to rely on presence of C++ compiler. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -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 -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) +# - 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 +# +# 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 +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) diff --git a/lib-src/libsoxr/cmake/Modules/FindSIMD.cmake b/lib-src/libsoxr/cmake/Modules/FindSIMD.cmake index 93cef32cf..6484bbd17 100644 --- a/lib-src/libsoxr/cmake/Modules/FindSIMD.cmake +++ b/lib-src/libsoxr/cmake/Modules/FindSIMD.cmake @@ -1,53 +1,88 @@ -# - 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. - -include (CheckCSourceCompiles) -include (FindPackageHandleStandardArgs) - -set (SIMD_C_FLAG_CANDIDATES - #Microsoft Visual Studio - "/arch:SSE /fp:fast -D__SSE__" - #Gnu - "-msse -mfpmath=sse" -) - -set (SIMD_C_TEST_SOURCE -" -#include -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) +# - 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 +# +# 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 +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) diff --git a/lib-src/libsoxr/cmake/Modules/TestBigEndian.cmake b/lib-src/libsoxr/cmake/Modules/TestBigEndian.cmake index 5c5bde215..7f65cc004 100644 --- a/lib-src/libsoxr/cmake/Modules/TestBigEndian.cmake +++ b/lib-src/libsoxr/cmake/Modules/TestBigEndian.cmake @@ -1,15 +1,15 @@ -# SoX Resampler Library Copyright (c) 2007-12 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 () +# 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 () diff --git a/lib-src/libsoxr/configure b/lib-src/libsoxr/configure deleted file mode 100755 index 0c71041f2..000000000 --- a/lib-src/libsoxr/configure +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Wrapper to allow easier integration with projects using autotools. - -# Such projects will probably be using static libs so should pass -# -DBUILD_SHARED_LIBS=OFF amongst any other options needed. - -# Autotools options should not be passed to this script. - -cmake -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF . diff --git a/lib-src/libsoxr/deinstall.cmake.in b/lib-src/libsoxr/deinstall.cmake.in index a0174185e..307be5018 100644 --- a/lib-src/libsoxr/deinstall.cmake.in +++ b/lib-src/libsoxr/deinstall.cmake.in @@ -1,4 +1,4 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net # Licence for this file: LGPL v2.1 See LICENCE for details. if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") @@ -12,7 +12,7 @@ foreach (file ${files}) message (STATUS "Deinstalling \"${dest}\"") if (EXISTS "${dest}" OR IS_SYMLINK "${dest}") execute_process ( - COMMAND @CMAKE_COMMAND@ -E remove "${dest}" + COMMAND "@CMAKE_COMMAND@" -E remove "${dest}" OUTPUT_VARIABLE rm_out RESULT_VARIABLE rm_retval ) diff --git a/lib-src/libsoxr/doc/README b/lib-src/libsoxr/doc/README deleted file mode 100644 index aa9c0d104..000000000 --- a/lib-src/libsoxr/doc/README +++ /dev/null @@ -1,3 +0,0 @@ -Not convinced that this is going anywhere useful. - -Run "make docs" in the parent directory to generate the API documentation. diff --git a/lib-src/libsoxr/doc/footer.html b/lib-src/libsoxr/doc/footer.html deleted file mode 100644 index 9b151ee89..000000000 --- a/lib-src/libsoxr/doc/footer.html +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/lib-src/libsoxr/doc/header.html b/lib-src/libsoxr/doc/header.html deleted file mode 100644 index c9994e7ab..000000000 --- a/lib-src/libsoxr/doc/header.html +++ /dev/null @@ -1,31 +0,0 @@ - - $title ($projectname) - - - -
- - - - - -
- - -
- - - - - -

The SoX Resampler $projectnumber ($title)

- -
-
-
-
diff --git a/lib-src/libsoxr/doc/logo.png b/lib-src/libsoxr/doc/logo.png deleted file mode 100644 index 62c0e28db0506102d1149e6a8f4a79e69d3b5b88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3992 zcmV;J4`=X+P)Px&08mU+MF0T+0{{g9022TK4gdlM2>=fP1ONa4GY9}51Ogcl0RaF2J`Vv25C9Yd z1_2TP8w3DF3;`(_023Aj1{VP$76kwb0aFMH1|b0#8v!XK04pp2C=m<-Bm*TU10XN~ zB_aq5FasMn0uLboY7Gz!GXXLv0AN1=Av*#t77_pw6cIWAY8Dj@D-Rq!2_qX82pthL zKmdCd7Zp(jCRzbCO#p6S0xK9A7g`1$Q3p629vou;bwm;$I~5!r9V1`>f+!mzX#j6e z4ly1e9#9f1c>ruI9yu={A|fOqhX81P0ELbKWQGBPQyUp@5HT$!D3}0TCMYIq5KKE71T@F*7jW06FFWEKDvn?*JV&HZyQ0ICUm4I5{_#A~=~ND}gN=ktiuX zKs}5sG=MNU*Bk(lEJ;R4MWQe%`x^nDGBSxdHKsB{r#B>mLMom*Jy20kmq0O-K|i@a zG@(g9*gyb$S1qwfF}g-8U0+N5lx5$S zJ>j4L@seEMnPKCdTKS$h{GLSrr2zV$RN%G%@}_U;s&U?~bN{VR{_8`&v^gRW#8Xq{M3lx z-*x=icHQ5h;@_3}+JxWWw*KcL``nr9<%<2^k>=&p|LAl7>1_V!gZ}2P|LKqY>6!oe zP5u|8xKQoBsK<|NW%>{;L1}vi|+S|NP7S{?z{e@|^Fe zkN^Mx32;bRa{vGf6951U69E94oEQKA3^7SWK~#9!?VNdh6y+JmefJoWWiye8c?kqG zIuICBtdp97(c&>s$18Qv03!B9O0DBDxEvF75u~i3)gX9ATLg>6gDNOkF&@;S)E2ot zh&4t*TxlR0V@k5wq}`d>Yj$TtHrd&o^wakbn7s4Ov-{oW{k`w=9`l}r{g0%R{tsee z5Q5Vwfb+VUP$!pS^@{2lr4X)DlF>6tbIF5nF1-?h-nV1*K9fT_nY>#MMAQL+Zc6Xt z@gzZTlEcV|(a3ieBbQMgA;OoDT!PYhUf(E#$3Kr#gw98in4VD#GGqb}h!7H)P~sS! zOO6d+vf)cszi9U}Phd3qp>el9dh0m(Y8=l9F}3@oh(IJrn_SR&Yxe$Bxv(-E;=5?I z7;|%2mmd3rQ@H};x^8|=4pM$_`)Heb$tDJY3~O?bk$b)6AoP<{ERm?y3TT8gGsnQq ztqZK7KM*0Z2|!3zf@b!J{o&TNSrHK+p2z#7M!y5>fB(UBKDH6+rEwyJLg8G6MIq3@#S{C8wg5LpdT#xyya^G61Ya}9Ky}!k-Rl+ zPv`31VJRf{9wncD|GC5p0yMWqoJ*VDD$u_b(#U7ueO4&MfuXdNvJgp7m zaT9^$J^aI_0<0?#RqO$f!dS6WF7x#4_NCsfBfBcVL1j8<)Vp83TNoGpdMLAq-8%o^ zzVWuMO7Ns4Dj*-dTZq#nu8FlMvka`P6}5E<8{TlNMFc^vMQ)cl#SSX!8Y`_`mkEje z&5zzZTV*mI2q@d-TVTPu3G(+h|_K8ZdkeAm}N4@gbR|;`l6aC`I z&6+{%MH`!6lT~XIZM5}%0TzZG9)dxxu@Ru z$bFZH%H9FdwX{|G$65J=Oi+NTR1Fp8oeh9 zu%dr*T9mg9Ib;wD1&6x9{W&Z`nG?Hp_OZq}-RF>J;}KLrejS?o4a6q$_N0t1hT1E= z-Z_>e9$-jDo+?#5!YG@j0v=(jhzx7QKEKXenG8orBaRt&%?N7*m#PUh{LK`IrLwMW zzCEc&7!1N#5R8=L$bi^6p3RWX4|*3R$AKY|mvC90BbGVG zybCQ!KE%=X5KvW5+nsjh(tB1h`lQ9L*0T^t+f@_o;=Ai9=RGhrp}z|U|hV~ zA*!ub1~f8wo&VFGafCGDoO;t#XILXd6`2VTaN35}{pA4b707irT^9i%m8vE07D^`w z7`?G=dsz=TFa}qeTIZDOrZ`|g?YQC*kIaWND4p|KpzQ6on$n(fU_9jI?%X+L%9IO9 zBrjFV9&syT7eqRJ9w(<3__-RsGGCU+x|oW)+-QI>{tEbs<7At11q)pP1icRZP3cb#${Q(vcak| z4$jL1Adn;pS?o{>zFs5pX#oL6tB==JX7|nr#|c4@%P-{IZV^V$q98UMAl5N&`*!vy zEYY-Dw6Y`9dFeHm0?0BXp7t#qmPxx>w_OZ+Ylc;4Ok@ye%ydwC#GW&+u6^C`-rEU@ zeZn;p;z4l3Jz~pSeyr)qf)rQ^d1S&B6Pz@1A&o}dMvEPcezxWC!rWAt;zU*K7hQ4D z4TOLM4Twk^8=}~!Z)w}!Yncbd&T=ZqWfuX0p`ljn#%d(*o&&xu<3VbSF~O=OgQQvP zL)JF8JU%Q%9AUAaciDLWBUr6RjC@-GjNQ~)KiiTrdkjshAQzl_11Cr>jYc@bR;+CH zJNNi^mRnP25vlVF&T}s~7m$*m?b!``eGe2p)X=)26r|83L*rqPv}wdXy~bC2Z&4~a zLK*>Qr4gjy{<^leZnUS?Xc*+2vj9oclt%1^tdD@Pn_HWnJ`JSUECY!k$cP)DRISyB z#{jYC&i=5YJ~f@WR_rdN)dC~V83AZSXro_|N%b0{9FsJ^QDI5FqZyu8LCzduyhgyF zMens8cr@kJDq157h%z-~9EfGihQn=Jrso*a5=KDs$5Fh*LF0P%p^NwV>z5A$hHwP> z5oN{%VQ17PUg|Mb@{ z8*E$%%1}X&{CwlY4)SJgJAQO)xz#w1utrYKKN;W<;2|C9RzT5@ZLy46Il#SVr)u;1UZcCr%~%Ms|= zm32?huYW(eYH0^nRBt_E8#sH1-@j*et_?FfvAEj&_UqR#Q{^enDHs3 zkpcY%#CxPyAYjm}XB%1%JX2=Durz{X4afqN%dPDYxt{mzplH!XudjBEK>>-5*wyVO zAUi929EoT~10wYF%}_98!PcYg^{a2p18L&G5TlCSl5J7<328jivnf+BeDR)U|Bn2*Tbf!?<0RY$_gXrFg9e}*akMHqy99&nP zg<%;1u>tJow9BIvJDJ>mEs%HRqKyZA&D$RxlWq)I?2(h(2%gn?L?Dw8yQO&UOCL1( z>NYMq!;Ymt@o{?sdNi;C1(R0oKk9GUyZpw}0hWox(ZL}H@>B_~nAa}4xy}v-ls&NH zSf~HU%d>}o%wQ<%?5Z3j_j7`Xl5MqY0OU?w_Re?y&ZZqJ%CfM`rEtY!1O{VbJVN7a zmk`d=&!4|~+xPAMqr3h%X^0ieWa4llu|_-zUjw&U^Uk>PH*2=k9&h&@sQLZe;%pn1 z*~BwKVh~!lXSe1SjhXx4OMg3XwAI(}kM&EhJi`vKj3)+?i9upDV$B*_I%)B$H}-pv zc679Vzh~2u$v-*;n1BL1;n8hB1J>-Ufx}KK9#b)I@e?oq<&z`F{hgg1z9TzcURFND z?!Ziwx&R@00WSH|w)fxPvFDS2eb>_F@96C8Y;J7$aPt%M$_87M*(38LmPcHIQvqpF zbo}Y%n33XohwS;l5Lncupe>j862< z+l^`gqK?UpI?68UnB2$&AJh|GBs1#x*QjH5Nj;;q-Z8s@Y~>~P1RCLy?ifb59Vc`$ zX}zLI(#fP;dIuM~^o;Uk_f!)NqPr6t*ZU$6>3yc|`igFwPVjn1N$dYQSn?o!IvENg zk}xo!h78W(eH%m~t2|X0;TEJcfDm|e^FiP+g`Y`7L2zM^r_ y^BC|ccp5a~aigl&B~P`7@KjY{lKfAfO#cOOp@>34)Wbsn0000 -#include "examples-common.h" - -const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */ - 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. */ - float * out = malloc(sizeof(*out) * olen); /* Allocate output buffer. */ - size_t odone; - - soxr_error_t error = soxr_oneshot(irate, orate, 1, /* Rates and # of chans. */ - in, AL(in), NULL, /* Input. */ - out, olen, &odone, /* Output. */ - NULL, NULL, NULL); /* Default configuration.*/ - - unsigned i = 0; /* Print out the resampled data... */ - while (i++ < odone) - printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == odone]); - puts(soxr_strerror(error)); /* ...and the reported result. */ - - free(out); /* Tidy up. */ - return !!error; - (void)argc, (void)arg; /* Not used in this example. */ -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Example 1: `One-shot' resample a single block of data in memory. + * + * N.B. See example 2 for how to resample a stream (of blocks). + * + * Optional arguments are: INPUT-RATE OUTPUT-RATE + * + * With the default arguments, the output should produce lines similar to the + * following: + * + * 0.00 0.71 1.00 0.71 -0.00 -0.71 -1.00 -0.71 + * + * Gibbs effect may be seen at the ends of the resampled signal; this is because + * unlike a `real-world' signal, the synthetic input signal is not band-limited. + */ + +#include +#include "examples-common.h" + +const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ + 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, + 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; + +int main(int argc, char const * arg[]) +{ + double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */ + 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. */ + float * out = malloc(sizeof(*out) * olen); /* Allocate output buffer. */ + size_t odone; + + soxr_error_t error = soxr_oneshot(irate, orate, 1, /* Rates and # of chans. */ + in, AL(in), NULL, /* Input. */ + out, olen, &odone, /* Output. */ + NULL, NULL, NULL); /* Default configuration.*/ + + unsigned i = 0; /* Print out the resampled data, */ + while (i++ < odone) + printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == odone]); + printf("%-26s %s\n", arg[0], soxr_strerror(error)); /* and reported result. */ + + if (argc > 3) /* Library version check: */ + printf("runtime=%s API="SOXR_THIS_VERSION_STR"\n", soxr_version()); + + free(out); /* Tidy up. */ + return !!error; +} diff --git a/lib-src/libsoxr/examples/1a-lsr.c b/lib-src/libsoxr/examples/1a-lsr.c new file mode 100644 index 000000000..e42e5308e --- /dev/null +++ b/lib-src/libsoxr/examples/1a-lsr.c @@ -0,0 +1,40 @@ +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Example 1a: Variant of example 1 using libsamplerate-like bindings. */ + +#include +#include "examples-common.h" + +float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ + 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, + 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; + +int main(int argc, char const * arg[]) +{ + double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */ + 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. */ + float * out = (float *)malloc(sizeof(*out) * olen); /* Allocate output buf. */ + + int error, i = 0; + SRC_DATA data; + + data.data_in = in; + data.data_out = out; + data.input_frames = AL(in); + data.output_frames = (int)olen; + data.src_ratio = orate / irate; + error = src_simple(&data, SRC_SINC_FASTEST, 1); + + while (i++ < data.output_frames_gen) /* Print out the resampled data, */ + printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == data.output_frames_gen]); + printf("%-26s %s\n", arg[0], src_strerror(error)); /* and reported result. */ + + if (argc > 3) /* Library version check: */ + printf("runtime=%s\n", src_get_version()); + + free(out); /* Tidy up. */ + return !!error; +} diff --git a/lib-src/libsoxr/examples/2-stream.c b/lib-src/libsoxr/examples/2-stream.C similarity index 95% rename from lib-src/libsoxr/examples/2-stream.c rename to lib-src/libsoxr/examples/2-stream.C index 37a774859..9d703f660 100644 --- a/lib-src/libsoxr/examples/2-stream.c +++ b/lib-src/libsoxr/examples/2-stream.C @@ -1,78 +1,78 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 2: resample a raw, single-channel, floating-point data stream from - * stdin to stdout. - * - * The application uses the single function `soxr_process' for both input and - * output to/from the resampler; compared to the `input function' approach - * (illustrated in example 3) this requires that the application implements - * more logic, but one less function. - * - * Arguments are: INPUT-RATE OUTPUT-RATE - */ - -#include -#include "examples-common.h" - -int main(int argc, char const * arg[]) -{ - double const irate = argc > 1? atof(arg[1]) : 96000.; - double const orate = argc > 2? atof(arg[2]) : 44100.; - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples. */ - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - size_t const osize = sizeof(float), isize = osize; - void * obuf = malloc(osize * olen); - void * ibuf = malloc(isize * ilen); - - size_t odone, written, need_input = 1; - soxr_error_t error; - - /* Create a stream resampler: */ - soxr_t soxr = soxr_create( - irate, orate, 1, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - NULL, NULL, NULL); /* Use configuration defaults.*/ - - if (!error) { /* If all is well, run the resampler: */ - USE_STD_STDIO; - /* Resample in blocks: */ - do { - size_t ilen1 = 0; - - if (need_input) { - - /* Read one block into the buffer, ready to be resampled: */ - ilen1 = fread(ibuf, isize, ilen, stdin); - - if (!ilen1) { /* If the is no (more) input data available, */ - free(ibuf); /* set ibuf to NULL, to indicate end-of-input */ - ibuf = NULL; /* to the resampler. */ - } - } - - /* Copy data from the input buffer into the resampler, and resample - * to produce as much output as is possible to the given output buffer: */ - error = soxr_process(soxr, ibuf, ilen1, NULL, obuf, olen, &odone); - - written = fwrite(obuf, osize, odone, stdout); /* Consume output.*/ - - /* If the actual amount of data output is less than that requested, and - * we have not already reached the end of the input data, then supply some - * more input next time round the loop: */ - need_input = odone < olen && ibuf; - - } while (!error && (need_input || written)); - } - /* Tidy up: */ - 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; -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Example 2: resample a raw, single-channel, floating-point data stream from + * stdin to stdout. + * + * The application uses the single function `soxr_process' for both input and + * output to/from the resampler; compared to the `input function' approach + * (illustrated in example 3) this requires that the application implements + * more logic, but one less function. + * + * Arguments are: INPUT-RATE OUTPUT-RATE + */ + +#include +#include "examples-common.h" + +int main(int argc, char const * arg[]) +{ + double const irate = argc > 1? atof(arg[1]) : 96000.; + double const orate = argc > 2? atof(arg[2]) : 44100.; + + /* Allocate resampling input and output buffers in proportion to the input + * and output rates: */ + #define buf_total_len 15000 /* In samples. */ + size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); + size_t const ilen = buf_total_len - olen; + size_t const osize = sizeof(float), isize = osize; + void * obuf = malloc(osize * olen); + void * ibuf = malloc(isize * ilen); + + size_t odone, written, need_input = 1; + soxr_error_t error; + + /* Create a stream resampler: */ + soxr_t soxr = soxr_create( + irate, orate, 1, /* Input rate, output rate, # of channels. */ + &error, /* To report any error during creation. */ + NULL, NULL, NULL); /* Use configuration defaults.*/ + + if (!error) { /* If all is well, run the resampler: */ + USE_STD_STDIO; + /* Resample in blocks: */ + do { + size_t ilen1 = 0; + + if (need_input) { + + /* Read one block into the buffer, ready to be resampled: */ + ilen1 = fread(ibuf, isize, ilen, stdin); + + if (!ilen1) { /* If the is no (more) input data available, */ + free(ibuf); /* set ibuf to NULL, to indicate end-of-input */ + ibuf = NULL; /* to the resampler. */ + } + } + + /* Copy data from the input buffer into the resampler, and resample + * to produce as much output as is possible to the given output buffer: */ + error = soxr_process(soxr, ibuf, ilen1, NULL, obuf, olen, &odone); + + written = fwrite(obuf, osize, odone, stdout); /* Consume output.*/ + + /* If the actual amount of data output is less than that requested, and + * we have not already reached the end of the input data, then supply some + * more input next time round the loop: */ + need_input = odone < olen && ibuf; + + } while (!error && (need_input || written)); + } + /* Tidy up: */ + 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; +} diff --git a/lib-src/libsoxr/examples/2a-stream.c b/lib-src/libsoxr/examples/2a-stream.c deleted file mode 100644 index e074e09a7..000000000 --- a/lib-src/libsoxr/examples/2a-stream.c +++ /dev/null @@ -1,64 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 2a: resample a raw, single-channel, floating-point data stream from - * stdin to stdout. The application uses the single function `soxr_process' - * for both input and output to/from the resampler. - * - * Arguments are: INPUT-RATE OUTPUT-RATE - */ - -#include -#include "examples-common.h" - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 44100.; - double orate = argc > 2? atof(arg[2]) : 96000.; - - soxr_error_t error; - - soxr_t resampler = soxr_create( - irate, orate, 1, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - NULL, NULL, NULL); /* Use configuration defaults.*/ - - if (!error) { - #define buf_total_len 12000 /* In samples. */ - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - size_t ibuflen = (size_t)(irate * buf_total_len / (irate + orate) + .5); - size_t obuflen = buf_total_len - ibuflen; - char * ibuf = malloc(sizeof(float) * ibuflen), * iptr = 0; - void * obuf = malloc(sizeof(float) * obuflen); - - size_t iavailable = 0; - size_t idone, odone, written; - - USE_STD_STDIO; - do { /* Resample in blocks: */ - if (!iavailable && ibuf) { /* If ibuf is empty, try to fill it: */ - iavailable = fread(ibuf, sizeof(float), ibuflen, stdin); - if (!iavailable) /* If none available, don't retry. Pass NULL */ - free(ibuf), ibuf = 0;/* ibuf to resampler to indicate end-of-input. */ - iptr = ibuf; /* Reset input to the start of the buffer. */ - } - - error = soxr_process(resampler, - iptr, iavailable, &idone, obuf, obuflen, &odone); - - iptr += idone * sizeof(float); /* Update input buffer according to how */ - iavailable -= idone; /* much the resampler has consumed. */ - - written = fwrite(obuf, sizeof(float), odone, stdout); /* Consume output.*/ - } while (!error && (ibuf || written)); - /* Tidy up: */ - free(obuf), free(ibuf); - soxr_delete(resampler); - } - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], - soxr_strerror(error), errno? strerror(errno) : "no error"); - return error || errno; -} diff --git a/lib-src/libsoxr/examples/2b-stream-with-input-fn.c b/lib-src/libsoxr/examples/2b-stream-with-input-fn.c deleted file mode 100644 index 3d3ba3846..000000000 --- a/lib-src/libsoxr/examples/2b-stream-with-input-fn.c +++ /dev/null @@ -1,67 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 2b: resample a raw, single-channel, floating-point data stream from - * stdin to stdout. The application provides an input function, called on - * demand by libsoxr, in response to calls to soxr_output(). - * - * Arguments are: INPUT-RATE OUTPUT-RATE - */ - -#include -#include "examples-common.h" - -#define iolen 10000 - -static size_t input_fn( - void * p, /* Generic pointer to any state variables neded here. */ - soxr_cbuf_t * buf, /* To tell the resampler where the data is. */ - size_t requested_len) /* In samples per channel. */ -{ - static float * ibuf; /* Static context; this could be changed using `p'. */ - size_t actual; - size_t len = min(requested_len, iolen); - - /* Allocate the input buffer memory; check for errors: */ - *buf = ibuf = (float *)realloc(ibuf, sizeof(float) * len); - if (!ibuf) - return 0; /* Indicate failure (*buf is also 0). */ - - /* Read samples from the input stream; check for errors: */ - actual = fread(ibuf, sizeof(float), len, stdin); - if (!actual) { - if (ferror(stdin)) - *buf = 0; /* Indicate failure (actual is also 0). */ - free(ibuf), ibuf = 0; - } - - return actual; - (void)p; /* Not used in this example. */ -} - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 44100.; - double orate = argc > 2? atof(arg[2]) : 96000.; - - soxr_error_t error; - soxr_t resampler = soxr_create(irate, orate, 1, &error, 0, 0, 0); - if (!error) /* Register input_fn with the resampler: */ - error = soxr_set_input_fn(resampler, input_fn, 0); - - if (!error) { /* If all is good, run the resampler: */ - float resampled[iolen]; - size_t actual; - /* Resample in blocks: */ - USE_STD_STDIO; - do actual = soxr_output(resampler, resampled, iolen); - while (fwrite(resampled, sizeof(float), actual, stdout)); - - error = soxr_error(resampler); /* Note: before deleting the resampler! */ - soxr_delete(resampler); - } - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], - soxr_strerror(error), errno? strerror(errno) : "no error"); - return error || errno; -} diff --git a/lib-src/libsoxr/examples/3-options-input-fn.c b/lib-src/libsoxr/examples/3-options-input-fn.c index 11f2c9f0c..bb0bf2db1 100644 --- a/lib-src/libsoxr/examples/3-options-input-fn.c +++ b/lib-src/libsoxr/examples/3-options-input-fn.c @@ -1,97 +1,110 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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, - * and other options. - * - * The application provides an input function, called on demand by libsoxr, in - * response to calls to soxr_output(); compared to the `process' approach - * (illustrated in example 2) this requires that the application implements - * less logic, but one more function. - * - * The eight arguments (which are optional, from last to first) are: - * INPUT-RATE As example 2 - * OUTPUT-RATE Ditto - * NUM-CHANNELS Number of interleaved channels - * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 - * OUT-DATATYPE# Ditto - * Q-RECIPE Quality recipe (in hex) See soxr.h - * Q-FLAGS Quality flags (in hex) See soxr.h - * USE-THREADS 1 to use multi-threading (where available) - */ - -#include -#include "examples-common.h" - -typedef struct {void * ibuf; size_t isize;} input_context_t; - -static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len) -{ - /* Read one block into the buffer, ready to be input to the resampler: */ - len = fread(p->ibuf, p->isize, len, stdin); /* Actual len read may be less. */ - - /* Inform the resampler of the data's whereabouts (which could be anywhere, in - * a freshly malloc'd buffer, for example): */ - *buf = (!len && ferror(stdin))? NULL : p->ibuf; /* NULL if error occurred. */ - - return len; /* # of samples per channel to input. */ -} - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : ""; - 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 long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - int const use_threads = n? --n, atoi(*arg++) : 1; - - 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, otype); - soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - void * const obuf = malloc(osize * olen); - void * const ibuf = malloc(isize * ilen); - - input_context_t icontext; - size_t odone, clips = 0; - soxr_error_t error; - - /* Create a stream resampler: */ - soxr_t soxr = soxr_create( - irate, orate, chans, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - &io_spec, &q_spec, &runtime_spec); - - if (!error) { /* Register input_fn with the resampler: */ - icontext.ibuf = ibuf, icontext.isize = isize; - error = soxr_set_input_fn(soxr, (soxr_input_fn_t)input_fn, &icontext, ilen); - } - - if (!error) { /* If all is well, run the resampler: */ - USE_STD_STDIO; - /* Resample in blocks: */ - do odone = soxr_output(soxr, obuf, olen); - while (fwrite(obuf, osize, odone, stdout)); /* Consume output. */ - - error = soxr_error(soxr); /* Check if any soxr error occurred. */ - clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ - } - /* Tidy up: */ - 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; -} +/* SoX Resampler Library Copyright (c) 2007-13 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, + * and other options. + * + * The application provides an input function, called on demand by libsoxr, in + * response to calls to soxr_output(); compared to the `process' approach + * (illustrated in example 2) this requires that the application implements + * less logic, but one more function. + * + * The 11 arguments (which are optional, from last to first) are: + * INPUT-RATE As example 2 + * OUTPUT-RATE Ditto + * NUM-CHANNELS Number of interleaved channels + * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 + * OUT-DATATYPE# Ditto + * Q-RECIPE Quality recipe (in hex) See soxr.h + * Q-FLAGS Quality flags (in hex) See soxr.h + * PASSBAND-END % + * STOPBAND-BEGIN % + * PHASE-RESPONSE [0,100] + * USE-THREADS 1 to use multi-threading (where available) + */ + +#include +#include "examples-common.h" + +typedef struct {void * ibuf; size_t isize;} input_context_t; + +static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len) +{ + /* Read one block into the buffer, ready to be input to the resampler: */ + len = fread(p->ibuf, p->isize, len, stdin); /* Actual len read may be less. */ + + /* Inform the resampler of the data's whereabouts (which could be anywhere, in + * a freshly malloc'd buffer, for example): */ + *buf = (!len && ferror(stdin))? NULL : p->ibuf; /* NULL if error occurred. */ + + return len; /* # of samples per channel to input. */ +} + +int main(int n, char const * arg[]) +{ + char const * const arg0 = n? --n, *arg++ : ""; + 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 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_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_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); + + /* Allocate resampling input and output buffers in proportion to the input + * and output rates: */ + #define buf_total_len 15000 /* In samples per channel. */ + size_t const osize = soxr_datatype_size(otype) * chans; + size_t const isize = soxr_datatype_size(itype) * chans; + size_t const olen0= (size_t)(orate * buf_total_len / (irate + orate) + .5); + size_t const olen = min(max(olen0, 1), buf_total_len - 1); + size_t const ilen = buf_total_len - olen; + void * const obuf = malloc(osize * olen); + void * const ibuf = malloc(isize * ilen); + + input_context_t icontext; + size_t odone, clips = 0; + soxr_error_t error; + soxr_t soxr; + + /* 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; + + /* Create a stream resampler: */ + soxr = soxr_create( + irate, orate, chans, /* Input rate, output rate, # of channels. */ + &error, /* To report any error during creation. */ + &io_spec, &q_spec, &runtime_spec); + + if (!error) { /* Register input_fn with the resampler: */ + icontext.ibuf = ibuf, icontext.isize = isize; + error = soxr_set_input_fn(soxr, (soxr_input_fn_t)input_fn, &icontext, ilen); + } + + if (!error) { /* If all is well, run the resampler: */ + USE_STD_STDIO; + /* Resample in blocks: */ + do odone = soxr_output(soxr, obuf, olen); + while (fwrite(obuf, osize, odone, stdout)); /* Consume output. */ + + error = soxr_error(soxr); /* Check if any soxr error occurred. */ + clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ + } + /* Tidy up: */ + 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; +} diff --git a/lib-src/libsoxr/examples/3a-options.c b/lib-src/libsoxr/examples/3a-options.c deleted file mode 100644 index 3396f2fa2..000000000 --- a/lib-src/libsoxr/examples/3a-options.c +++ /dev/null @@ -1,83 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 3a: extends example 2a with multiple channels, multiple datatypes, - * and other options. - * - * The eight arguments are: - * INPUT-RATE As example 2a - * OUTPUT-RATE Ditto - * NUM-CHANNELS Number of interleaved channels - * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 - * OUT-DATATYPE# Ditto - * Q-RECIPE Quality recipe (in hex) See soxr.h - * Q-FLAGS Quality flags (in hex) See soxr.h - * USE-THREADS 1 to use multi-threading - */ - -#include -#include "examples-common.h" - -int main(int n, char const * arg[]) -{ - char const * arg0 = n? --n, *arg++ : ""; - double irate = n? --n, atof(*arg++) : 96000.; - double orate = n? --n, atof(*arg++) : 44100.; - unsigned chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t itype = n? --n, (soxr_datatype_t)atoi(*arg++) :SOXR_FLOAT32_I; - soxr_datatype_t otype = n? --n, (soxr_datatype_t)atoi(*arg++) :SOXR_FLOAT32_I; - unsigned long q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - int use_threads = n? --n, atoi(*arg++) : 1; - - size_t isize = soxr_datatype_size(itype) * chans; - size_t osize = soxr_datatype_size(otype) * chans; - size_t clips = 0; - soxr_error_t error; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec = soxr_io_spec(itype, otype); - soxr_runtime_spec_t runtime_spec = soxr_runtime_spec(!use_threads); - - soxr_t resampler = soxr_create( - irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec); - - if (!error) { - #define buf_total_len 15000 /* In samples. */ - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - size_t ibuflen = (size_t)(irate * buf_total_len / (irate + orate) + .5); - size_t obuflen = buf_total_len - ibuflen; - char * ibuf = malloc(isize * ibuflen), * iptr = 0; - void * obuf = malloc(osize * obuflen); - - size_t iavailable = 0; - size_t idone, odone, written; - - USE_STD_STDIO; - do { /* Resample in blocks: */ - if (!iavailable && ibuf) { /* If ibuf is empty, try to fill it: */ - iavailable = fread(ibuf, isize, ibuflen, stdin); - if (!iavailable) /* If none available, don't retry. Pass NULL */ - free(ibuf), ibuf = 0;/* ibuf to resampler to indicate end-of-input. */ - iptr = ibuf; /* Reset input to the start of the buffer. */ - } - - error = soxr_process(resampler, - iptr, iavailable, &idone, obuf, obuflen, &odone); - - iptr += idone * isize; /* Update input buffer according to how */ - iavailable -= idone; /* much the resampler has consumed. */ - - written = fwrite(obuf, osize, odone, stdout); /* Consume output. */ - } while (!error && (ibuf || written)); - - free(obuf), free(ibuf); - clips = *soxr_num_clips(resampler); /* Can occur only with integer output.*/ - soxr_delete(resampler); - } - 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; -} diff --git a/lib-src/libsoxr/examples/3b-options-with-input-fn.c b/lib-src/libsoxr/examples/3b-options-with-input-fn.c deleted file mode 100644 index ddfcc4da5..000000000 --- a/lib-src/libsoxr/examples/3b-options-with-input-fn.c +++ /dev/null @@ -1,85 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 3b: extends example 2b with multiple channels, multiple datatypes, - * and other options. - * - * The eight arguments are: - * INPUT-RATE As example 2b - * OUTPUT-RATE Ditto - * NUM-CHANNELS Number of interleaved channels - * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 - * OUT-DATATYPE# Ditto - * Q-RECIPE Quality recipe (in hex) See soxr.h - * Q-FLAGS Quality flags (in hex) See soxr.h - * USE-THREADS 1 to use multi-threading - */ - -#include -#include "examples-common.h" - -#define iolen 8000 - - - -static size_t input_fn(void * p, soxr_cbuf_t * buf, size_t len) -{ - static float * ibuf; - size_t isize = *(size_t *)p; - len = min(len, iolen); - *buf = ibuf = realloc(ibuf, isize * len); - if (!ibuf) - return 0; - len = fread(ibuf, isize, len, stdin); - if (!len) { - if (ferror(stdin)) - *buf = 0; - free(ibuf), ibuf = 0; - } - return len; -} - - - -int main(int n, char const * arg[]) -{ - char const * arg0 = n? --n, *arg++ : ""; - double irate = n? --n, atof(*arg++) : 96000.; - double orate = n? --n, atof(*arg++) : 44100.; - unsigned chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t itype = n? --n, (soxr_datatype_t)atoi(*arg++) :SOXR_FLOAT32_I; - soxr_datatype_t otype = n? --n, (soxr_datatype_t)atoi(*arg++) :SOXR_FLOAT32_I; - unsigned long q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - int use_threads = n? --n, atoi(*arg++) : 1; - - size_t isize = soxr_datatype_size(itype) * chans; - size_t osize = soxr_datatype_size(otype) * chans; - size_t clips = 0; - soxr_error_t error; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec = soxr_io_spec(itype, otype); - soxr_runtime_spec_t runtime_spec = soxr_runtime_spec(!use_threads); - - soxr_t resampler = soxr_create( - irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec); - if (!error) error = soxr_set_input_fn(resampler, input_fn, &isize); - - USE_STD_STDIO; - if (!error) { - void * resampled = malloc(osize * iolen); - size_t actual; - - do actual = soxr_output(resampler, resampled, iolen); - while (fwrite(resampled, osize, actual, stdout)); - - free(resampled); - error = soxr_error(resampler); - clips = *soxr_num_clips(resampler); /* Can occur only with integer output.*/ - soxr_delete(resampler); - } - 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; -} diff --git a/lib-src/libsoxr/examples/4-split-channels.c b/lib-src/libsoxr/examples/4-split-channels.c index 8788340e3..a4415986d 100644 --- a/lib-src/libsoxr/examples/4-split-channels.c +++ b/lib-src/libsoxr/examples/4-split-channels.c @@ -1,147 +1,147 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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. - * - * Note that, for convenience of the demonstration, split-channel data is - * made available by deinterleaving data sourced from and sent to - * interleaved file-streams; this adds a lot of code to the example that, - * for purposes of understanding how to use split-channels, may safely be - * ignored. In a real application, the channel-data might never be - * interleaved; for example, the split-channel data output from the - * resampler might be sent directly to digital-to-analogue converters. - * - * Note also (not shown in the examples) that split/interleaved channels may - * be used for input and output independently. - */ - -#include -#include "examples-common.h" - - - -#define DEINTERLEAVE(T) do { \ - unsigned i; \ - size_t j; \ - T * const * dest = (T * const *)dest0; \ - T const * src = src0; \ - if (ch == 1) memcpy(dest[0], src, n * sizeof(dest[0][0])); \ - else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = *src++; \ - return; \ -} while (0) - -static void deinterleave(soxr_datatype_t data_type, - void * const * dest0, - void const * src0, - size_t n, unsigned ch) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE(float); - case SOXR_FLOAT64: DEINTERLEAVE(double); - case SOXR_INT32 : DEINTERLEAVE(int32_t); - case SOXR_INT16 : DEINTERLEAVE(int16_t); - default: break; - } -} - -#define INTERLEAVE(T) do { \ - unsigned i; \ - size_t j; \ - T * dest = dest0; \ - T const * const * src = (T const * const *)src0; \ - if (ch == 1) memcpy(dest, src[0], n * sizeof(dest[0])); \ - else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = src[i][j]; \ - return; \ -} while (0) - -static void interleave(soxr_datatype_t data_type, void * dest0, - void * const * src0, size_t n, unsigned ch) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE(float); - case SOXR_FLOAT64: INTERLEAVE(double); - case SOXR_INT32 : INTERLEAVE(int32_t); - case SOXR_INT16 : INTERLEAVE(int16_t); - default: break; - } -} - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : ""; - 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 long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - int const use_threads = n? --n, atoi(*arg++) : 1; - - 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_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - - /* For split channels: */ - void * * const obuf_ptrs = malloc(sizeof(void *) * chans); - void * * ibuf_ptrs = malloc(sizeof(void *) * chans); - char * const obufs = malloc(osize * olen), * optr = obufs; - char * const ibufs = malloc(isize * ilen), * iptr = ibufs; - - /* For interleaved channels: */ - char * const obuf = malloc(osize * olen); - char * const ibuf = malloc(isize * ilen); - - size_t odone, written, need_input = 1, clips = 0; - soxr_error_t error; - - soxr_t 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; - iptr += ilen * soxr_datatype_size(itype); - optr += olen * soxr_datatype_size(otype); - } - - if (!error) { - USE_STD_STDIO; - - do { - size_t ilen1 = 0; - - if (need_input) { - if (!(ilen1 = fread(ibuf, isize, ilen, stdin))) - free(ibuf_ptrs), ibuf_ptrs = 0; /* If none available, don't retry. */ - else deinterleave(itype, ibuf_ptrs, ibuf, ilen1, chans); - } - - error = soxr_process(soxr, ibuf_ptrs, ilen1, NULL, obuf_ptrs, olen, &odone); - interleave(otype, obuf, obuf_ptrs, odone, chans); /* Consume output... */ - written = fwrite(obuf, osize, odone, stdout); - - need_input = odone < olen && ibuf_ptrs; - - } while (!error && (need_input || written)); - - clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ - } - /* Tidy up: */ - soxr_delete(soxr); - 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; -} +/* SoX Resampler Library Copyright (c) 2007-13 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. + * + * Note that, for convenience of the demonstration, split-channel data is + * made available by deinterleaving data sourced from and sent to + * interleaved file-streams; this adds a lot of code to the example that, + * for purposes of understanding how to use split-channels, may safely be + * ignored. In a real application, the channel-data might never be + * interleaved; for example, the split-channel data output from the + * resampler might be sent directly to digital-to-analogue converters. + * + * Note also (not shown in the examples) that split/interleaved channels may + * be used for input and output independently. + */ + +#include +#include "examples-common.h" + + + +#define DEINTERLEAVE(T) do { \ + unsigned i; \ + size_t j; \ + T * const * dest = (T * const *)dest0; \ + T const * src = src0; \ + if (ch == 1) memcpy(dest[0], src, n * sizeof(dest[0][0])); \ + else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = *src++; \ + return; \ +} while (0) + +static void deinterleave(soxr_datatype_t data_type, + void * const * dest0, + void const * src0, + size_t n, unsigned ch) +{ + switch (data_type & 3) { + case SOXR_FLOAT32: DEINTERLEAVE(float); + case SOXR_FLOAT64: DEINTERLEAVE(double); + case SOXR_INT32 : DEINTERLEAVE(int32_t); + case SOXR_INT16 : DEINTERLEAVE(int16_t); + default: break; + } +} + +#define INTERLEAVE(T) do { \ + unsigned i; \ + size_t j; \ + T * dest = dest0; \ + T const * const * src = (T const * const *)src0; \ + if (ch == 1) memcpy(dest, src[0], n * sizeof(dest[0])); \ + else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = src[i][j]; \ + return; \ +} while (0) + +static void interleave(soxr_datatype_t data_type, void * dest0, + void * const * src0, size_t n, unsigned ch) +{ + switch (data_type & 3) { + case SOXR_FLOAT32: INTERLEAVE(float); + case SOXR_FLOAT64: INTERLEAVE(double); + case SOXR_INT32 : INTERLEAVE(int32_t); + case SOXR_INT16 : INTERLEAVE(int16_t); + default: break; + } +} + +int main(int n, char const * arg[]) +{ + char const * const arg0 = n? --n, *arg++ : ""; + 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 long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; + unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; + int const use_threads = n? --n, atoi(*arg++) : 1; + + 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_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); + + /* Allocate resampling input and output buffers in proportion to the input + * and output rates: */ + #define buf_total_len 15000 /* In samples per channel. */ + size_t const osize = soxr_datatype_size(otype) * chans; + size_t const isize = soxr_datatype_size(itype) * chans; + size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); + size_t const ilen = buf_total_len - olen; + + /* For split channels: */ + void * * const obuf_ptrs = malloc(sizeof(void *) * chans); + void * * ibuf_ptrs = malloc(sizeof(void *) * chans); + char * const obufs = malloc(osize * olen), * optr = obufs; + char * const ibufs = malloc(isize * ilen), * iptr = ibufs; + + /* For interleaved channels: */ + char * const obuf = malloc(osize * olen); + char * const ibuf = malloc(isize * ilen); + + size_t odone, written, need_input = 1, clips = 0; + soxr_error_t error; + + soxr_t 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; + iptr += ilen * soxr_datatype_size(itype); + optr += olen * soxr_datatype_size(otype); + } + + if (!error) { + USE_STD_STDIO; + + do { + size_t ilen1 = 0; + + if (need_input) { + if (!(ilen1 = fread(ibuf, isize, ilen, stdin))) + free(ibuf_ptrs), ibuf_ptrs = 0; /* If none available, don't retry. */ + else deinterleave(itype, ibuf_ptrs, ibuf, ilen1, chans); + } + + error = soxr_process(soxr, ibuf_ptrs, ilen1, NULL, obuf_ptrs, olen, &odone); + interleave(otype, obuf, obuf_ptrs, odone, chans); /* Consume output... */ + written = fwrite(obuf, osize, odone, stdout); + + need_input = odone < olen && ibuf_ptrs; + + } while (!error && (need_input || written)); + + clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ + } + /* Tidy up: */ + soxr_delete(soxr); + 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; +} diff --git a/lib-src/libsoxr/examples/5-variable-rate.c b/lib-src/libsoxr/examples/5-variable-rate.c index c2c51e08f..a2496c9cd 100644 --- a/lib-src/libsoxr/examples/5-variable-rate.c +++ b/lib-src/libsoxr/examples/5-variable-rate.c @@ -1,94 +1,94 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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: - * - * Usage: ./5-variable-rate [0|1|2|3] - */ - -#include -#include "examples-common.h" - -#define OCTAVES 5 /* Resampling range. ± */ -#define OLEN 16 /* Output length in seconds. */ -#define FS 44100 /* Output sampling rate in Hz. */ - -/* For output pos in [0,1], returns an ioratio in the 2^±OCTAVES range: */ -static double ioratio(double pos, int fm) -{ - if (fm) /* fm: non-0 for a fast-changing ioratio, 0 for a slow sweep. */ - pos = .5 - cos(pos * 2 * M_PI) * .4 + sin(pos * OLEN * 20 * M_PI) * .05; - return pow(2, 2 * OCTAVES * pos - OCTAVES); -} - -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 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; - - /* When creating a var-rate resampler, q_spec must be set as follows: */ - soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR); - - /* The ratio of the given input rate and output rates must equate to the - * maximum I/O ratio that will be used: */ - soxr_t soxr = soxr_create(1 << OCTAVES, 1, 1, &error, NULL, &q_spec, NULL); - - if (!error) { - USE_STD_STDIO; - - /* Generate input signal, sine or saw, with wave-length = wl: */ - for (i = 0; i < (int)ilen; ++i) - ibuf[i] = (float)(saw? (i%wl)/(wl-1.)-.5 : .9 * sin(2 * M_PI * i / wl)); - - /* Set the initial resampling ratio (N.B. 3rd parameter = 0): */ - soxr_set_io_ratio(soxr, ioratio(0, fm), 0); - - /* Resample in blocks of size olen1: */ - for (total_odone = 0; !error && total_odone < total_olen;) { - - /* The last block might be shorter: */ - size_t block_len = min(olen1, total_olen - total_odone); - - /* Determine the position in [0,1] of the end of the current block: */ - double pos = (double)(total_odone + block_len) / (double)total_olen; - - /* Calculate an ioratio for this position and instruct the resampler to - * move smoothly to the new value, over the course of outputting the next - * 'block_len' samples (or give 0 for an instant change instead): */ - soxr_set_io_ratio(soxr, ioratio(pos, fm), block_len); - - /* Output the block of samples, supplying input samples as needed: */ - 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); - - /* Update counters for the current block and for the total length: */ - block_len -= odone; - total_odone += odone; - - /* If soxr_process did not provide the complete block, we must call it - * again, supplying more input samples: */ - need_input = block_len != 0; - - } while (need_input && !error); - - /* Now that the block for the current ioratio is complete, go back - * round the main `for' loop in order to process the next block. */ - } - 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; -} +/* 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: + * + * Usage: ./5-variable-rate [0|1|2|3] + */ + +#include +#include "examples-common.h" + +#define OCTAVES 5 /* Resampling range. ± */ +#define OLEN 16 /* Output length in seconds. */ +#define FS 44100 /* Output sampling rate in Hz. */ + +/* For output pos in [0,1], returns an ioratio in the 2^±OCTAVES range: */ +static double ioratio(double pos, int fm) +{ + if (fm) /* fm: non-0 for a fast-changing ioratio, 0 for a slow sweep. */ + pos = .5 - cos(pos * 2 * M_PI) * .4 + sin(pos * OLEN * 20 * M_PI) * .05; + return pow(2, 2 * OCTAVES * pos - OCTAVES); +} + +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 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; + + /* When creating a var-rate resampler, q_spec must be set as follows: */ + soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR); + + /* The ratio of the given input rate and output rates must equate to the + * maximum I/O ratio that will be used: */ + soxr_t soxr = soxr_create(1 << OCTAVES, 1, 1, &error, NULL, &q_spec, NULL); + + if (!error) { + USE_STD_STDIO; + + /* Generate input signal, sine or saw, with wave-length = wl: */ + for (i = 0; i < (int)ilen; ++i) + ibuf[i] = (float)(saw? (i%wl)/(wl-1.)-.5 : .9 * sin(2 * M_PI * i / wl)); + + /* Set the initial resampling ratio (N.B. 3rd parameter = 0): */ + soxr_set_io_ratio(soxr, ioratio(0, fm), 0); + + /* Resample in blocks of size olen1: */ + for (total_odone = 0; !error && total_odone < total_olen;) { + + /* The last block might be shorter: */ + size_t block_len = min(olen1, total_olen - total_odone); + + /* Determine the position in [0,1] of the end of the current block: */ + double pos = (double)(total_odone + block_len) / (double)total_olen; + + /* Calculate an ioratio for this position and instruct the resampler to + * move smoothly to the new value, over the course of outputting the next + * 'block_len' samples (or give 0 for an instant change instead): */ + soxr_set_io_ratio(soxr, ioratio(pos, fm), block_len); + + /* Output the block of samples, supplying input samples as needed: */ + 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); + + /* Update counters for the current block and for the total length: */ + block_len -= odone; + total_odone += odone; + + /* If soxr_process did not provide the complete block, we must call it + * again, supplying more input samples: */ + need_input = block_len != 0; + + } while (need_input && !error); + + /* Now that the block for the current ioratio is complete, go back + * round the main `for' loop in order to process the next block. */ + } + 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; +} diff --git a/lib-src/libsoxr/examples/CMakeLists.txt b/lib-src/libsoxr/examples/CMakeLists.txt index 93229e705..862718aae 100644 --- a/lib-src/libsoxr/examples/CMakeLists.txt +++ b/lib-src/libsoxr/examples/CMakeLists.txt @@ -1,21 +1,37 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -if (${BUILD_EXAMPLES}) - project (soxr) - file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cC]) - if (NOT BUILD_SHARED_LIBS AND OPENMP_FOUND) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_C_FLAGS}") - endif () -else () - 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}) - -foreach (fe ${SOURCES}) - get_filename_component (f ${fe} NAME_WE) - add_executable (${f} ${fe}) -endforeach () +# SoX Resampler Library Copyright (c) 2007-13 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 () + +if (${BUILD_EXAMPLES} OR ${BUILD_TESTS}) + if (${WITH_LSR_BINDINGS}) + set (LSR_SOURCES 1a-lsr.c) + endif () +endif () + +if (NOT BUILD_SHARED_LIBS AND OPENMP_FOUND) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_C_FLAGS}") +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) + add_executable (${f} ${fe}) + if (${f} STREQUAL "1a-lsr") + target_link_libraries (${f} soxr-lsr) + endif () +endforeach () + +if (${BUILD_TESTS} AND ${WITH_LSR_BINDINGS}) + add_test (lsr-bindings ${BIN}1a-lsr) +endif () + +file (GLOB INSTALL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cCh]) +install (FILES ${INSTALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/README DESTINATION ${DOC_INSTALL_DIR}/examples) diff --git a/lib-src/libsoxr/examples/README b/lib-src/libsoxr/examples/README index c3d6c3e00..a58939be5 100644 --- a/lib-src/libsoxr/examples/README +++ b/lib-src/libsoxr/examples/README @@ -1,18 +1,20 @@ -SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - -These simple examples show the different ways that an application may -interface with libsoxr. Note that real-world applications may also have to -deal with file-formats, codecs, (more sophisticated) dithering, etc., which -are not covered here. - -With libsoxr installed, the examples may be built using commands similar to -the following. On unix-like systems: - - cc 1-single-block.c -lsoxr - -or, on MS-Windows: - - cl 1-single-block.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr.lib" - -IDEs may hide such commands behind configuration screens and build menus -- -where applicable, consult your IDE's user-manual. +SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + +These simple examples show the different ways that an application may +interface with soxr. Note that real-world applications may also have to +deal with file-formats, codecs, (more sophisticated) dithering, etc., which +are not covered here. + +With the library installed, the examples may be built using commands similar +to the following. On unix-like systems: + + cc 1-single-block.c -lsoxr + cc 1a-lsr.c -lsoxr-lsr + +or, with MSVC on MS-Windows: + + cl 1-single-block.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr.lib" + cl 1a-lsr.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr-lsr.lib" + +IDEs may hide such commands behind configuration screens and build menus -- +where applicable, consult your IDE's user-manual. diff --git a/lib-src/libsoxr/examples/examples-common.h b/lib-src/libsoxr/examples/examples-common.h index 183ea3718..585fac30c 100644 --- a/lib-src/libsoxr/examples/examples-common.h +++ b/lib-src/libsoxr/examples/examples-common.h @@ -1,45 +1,45 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Common includes etc. for the examples. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 - /* Work-around for broken file-I/O on MS-Windows: */ - #include - #include - #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 -#else - #define USE_STD_STDIO -#endif - -#undef int16_t -#define int16_t short - -#undef int32_t -#if LONG_MAX > 2147483647L - #define int32_t int -#elif LONG_MAX < 2147483647L - #error this programme requires that 'long int' has at least 32-bits -#else - #define int32_t long -#endif - -#undef min -#undef max -#define min(x,y) ((x)<(y)?(x):(y)) -#define max(x,y) ((x)>(y)?(x):(y)) - -#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */ +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Common includes etc. for the examples. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + /* Work-around for broken file-I/O on MS-Windows: */ + #include + #include + #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 +#else + #define USE_STD_STDIO +#endif + +#undef int16_t +#define int16_t short + +#undef int32_t +#if LONG_MAX > 2147483647L + #define int32_t int +#elif LONG_MAX < 2147483647L + #error this programme requires that 'long int' has at least 32-bits +#else + #define int32_t long +#endif + +#undef min +#undef max +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) + +#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */ diff --git a/lib-src/libsoxr/go b/lib-src/libsoxr/go index bbf97084a..30adb94c5 100644 --- a/lib-src/libsoxr/go +++ b/lib-src/libsoxr/go @@ -1,15 +1,17 @@ -#!/bin/sh -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -build=$1 -test x$build = x && build=Release - -rm -f CMakeCache.txt # Prevent interference from any in-tree build - -mkdir -p $build -cd $build - -cmake -DCMAKE_BUILD_TYPE=$build -DBUILD_TESTS=ON .. && - make && - (make test || echo "FAILURE details in $build/Testing/Temporary/LastTest.log") +#!/bin/sh +# SoX Resampler Library Copyright (c) 2007-13 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 + +build=$1 +test x$build = x && build=Release + +rm -f CMakeCache.txt # Prevent interference from any in-tree build + +mkdir -p $build +cd $build + +cmake -DCMAKE_BUILD_TYPE=$build .. && + make $j && + (ctest $j || echo "FAILURE details in $build/Testing/Temporary/LastTest.log") diff --git a/lib-src/libsoxr/go.bat b/lib-src/libsoxr/go.bat index 5874d5300..7d63de3d6 100644 --- a/lib-src/libsoxr/go.bat +++ b/lib-src/libsoxr/go.bat @@ -1,27 +1,27 @@ -@echo off -rem SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -rem Licence for this file: LGPL v2.1 See LICENCE for details. - -set build=%1 -if x%build% == x set build=Release - -rem Prevent interference from any in-tree build -del/f CMakeCache.txt - -mkdir %build% -cd %build% - -cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% -DBUILD_TESTS=ON .. -if errorlevel 1 goto end - -nmake -if errorlevel 1 goto end - -nmake test -if errorlevel 1 goto error -goto end - -:error -echo FAILURE details in Testing\Temporary\LastTest.log - -:end +@echo off +rem SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +rem Licence for this file: LGPL v2.1 See LICENCE for details. + +set build=%1 +if x%build% == x set build=Release + +rem Prevent interference from any in-tree build +del/f CMakeCache.txt + +mkdir %build% +cd %build% + +cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% .. +if errorlevel 1 goto end + +nmake +if errorlevel 1 goto end + +nmake test +if errorlevel 1 goto error +goto end + +:error +echo FAILURE details in Testing\Temporary\LastTest.log + +:end diff --git a/lib-src/libsoxr/inst-check b/lib-src/libsoxr/inst-check new file mode 100755 index 000000000..8cf64b76d --- /dev/null +++ b/lib-src/libsoxr/inst-check @@ -0,0 +1,25 @@ +#!/bin/sh +set -e +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +# Sanity-check of library installed on unix-like system + +# This script checks the installation of the entire library (including lsr). +# +# Distros using three separate packages can do the following (in order): +# +# * Install soxr pkg (i.e. basically, just the shared object) +# * ./inst-check-soxr +# * Install soxr-lsr pkg (i.e. basically, just the shared object) +# * ./inst-check-soxr-lsr +# * Install the -dev pkg (i.e. examples, headers, & pkg-config) +# * ./inst-check PATH-OF-INSTALLED-EXAMPLES-DIR (e.g. /usr/share/doc/libsoxr/examples) + +# Where are the example source files: +src=$1 +test x$src = x && src=/usr/local/share/doc/libsoxr/examples + +dir="$(dirname $(readlink -f $0))" +$dir/inst-check-soxr $src +$dir/inst-check-soxr-lsr $src diff --git a/lib-src/libsoxr/inst-check-soxr b/lib-src/libsoxr/inst-check-soxr new file mode 100755 index 000000000..418f65b27 --- /dev/null +++ b/lib-src/libsoxr/inst-check-soxr @@ -0,0 +1,52 @@ +#!/bin/sh +set -e +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +# Sanity-check of sub-library installed on unix-like system + +arg="$1" # path to installed examples (if dev pkg installed); otherwise omitted +dir="$(dirname $(readlink -f $0))" + +# Find the examples: +src="$arg" +test x"$src" = x && src="$dir/examples" +cd $src + +# Somewhere to put the binaries: +tmp=`mktemp -d` + +build_examples() { + if [ x"$arg" = x ]; then + echo "Examples in `pwd`; using local headers:" # for when dev pkg not installed + libs=-l$1 + cflags=-I$dir/src + else + echo "Examples in `pwd`; using pkg-config:" + libs=$(pkg-config --libs $1) + cflags=$(pkg-config --cflags $1) + fi + for f in ?$2-*.[cC]; do + cc=cc; echo $f | grep -q C$ && cc=c++ + out=$tmp/`echo $f | sed "s/.[cC]$//"` + cmd="$cc $cflags -o $out $f $libs" + echo $cmd; $cmd + done +} + +# Determine library: +if [ `basename $0` = inst-check-soxr ]; then + build_examples soxr + gen="dd if=/dev/urandom count=1000" + $tmp/1-single-block 1 2 . + $gen 2> /dev/null | $tmp/2-stream 2>&1 >$tmp/stdout + $gen 2> /dev/null | $tmp/3-options-input-fn 6 7 2 2 0 2>&1 >$tmp/stdout + $gen 2> /dev/null | $tmp/4-split-channels 7 6 2 2 3 2>&1 >$tmp/stdout # Clipping expected here + $gen 2> /dev/null | $tmp/5-variable-rate 2>&1 >$tmp/stdout +else + build_examples soxr-lsr a # lsr has 'a' suffix on example number. + $tmp/1a-lsr 1 2 . +fi + +# Tidy up: +rm -rf $tmp diff --git a/lib-src/libsoxr/lsr-tests/CMakeLists.txt b/lib-src/libsoxr/lsr-tests/CMakeLists.txt deleted file mode 100644 index 98a285574..000000000 --- a/lib-src/libsoxr/lsr-tests/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) - -find_package (FFTW) -if (FFTW_FOUND) - include_directories (${FFTW_INCLUDE_DIRS}) - link_libraries (${FFTW_LIBRARIES}) - set (HAVE_FFTW3 1) -endif () - -find_package (sndfile) -if (SNDFILE_FOUND) - include_directories (${SNDFILE_INCLUDE_DIRS}) - link_libraries (${SNDFILE_LIBRARIES}) - set (HAVE_SNDFILE 1) -endif () - -check_function_exists (lrintf HAVE_LRINTF) -check_function_exists (alarm HAVE_ALARM) -check_function_exists (signal HAVE_SIGNAL) -check_include_files (sys/times.h HAVE_SYS_TIMES_H) -make_exist (HAVE_LRINTF HAVE_ALARM HAVE_SIGNAL HAVE_SYS_TIMES_H) -make_exist (HAVE_FFTW HAVE_SNDFILE) - -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) -include_directories (${CMAKE_CURRENT_BINARY_DIR}) - -add_library (tests_lib SHARED util calc_snr) - -link_libraries (tests_lib ${PROJECT_NAME}-lsr) - -enable_testing () - -set (tests - callback_hang_test callback_test downsample_test - float_short_test misc_test multi_channel_test - reset_test simple_test snr_bw_test termination_test varispeed_test) - -foreach (test ${tests}) - add_executable (${test} ${test}) - add_test (lsr-${test} ${BIN}${test}) - set_property (TEST lsr-${test} PROPERTY ENVIRONMENT "SOXR_LSR_STRICT=1") -endforeach () - -add_executable (multichan_throughput_test multichan_throughput_test) -add_executable (throughput_test throughput_test ) -add_executable (sndfile-resample sndfile-resample) diff --git a/lib-src/libsoxr/lsr-tests/COPYING b/lib-src/libsoxr/lsr-tests/COPYING deleted file mode 100644 index fbdd65f6f..000000000 --- a/lib-src/libsoxr/lsr-tests/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/lib-src/libsoxr/lsr-tests/README b/lib-src/libsoxr/lsr-tests/README deleted file mode 100644 index e8bc07f0f..000000000 --- a/lib-src/libsoxr/lsr-tests/README +++ /dev/null @@ -1,8 +0,0 @@ -The C source and header files in this directory have been copied from -the `libsamplerate' project and are copyrighted by its authors -- see -the notices within the files and the file `COPYING' for details. - -They are used here to test libsoxr's optional libsamplerate-like -wrapper. The only modifications made are to the file `snr_bw_test.c' to -remove reliance on certain frequency response troughs that are specific -to libsamplerate. diff --git a/lib-src/libsoxr/lsr-tests/calc_snr.c b/lib-src/libsoxr/lsr-tests/calc_snr.c deleted file mode 100644 index f363a974f..000000000 --- a/lib-src/libsoxr/lsr-tests/calc_snr.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "config.h" - -#include "util.h" - -#if (HAVE_FFTW3 == 1) - -#include -#include -#include -#include - -#include - -#define MAX_SPEC_LEN (1<<18) -#define MAX_PEAKS 10 - -static void log_mag_spectrum (double *input, int len, double *magnitude) ; -static void smooth_mag_spectrum (double *magnitude, int len) ; -static double find_snr (const double *magnitude, int len, int expected_peaks) ; - -typedef struct -{ double peak ; - int index ; -} PEAK_DATA ; - -double -calculate_snr (float *data, int len, int expected_peaks) -{ static double magnitude [MAX_SPEC_LEN] ; - static double datacopy [MAX_SPEC_LEN] ; - - double snr = 200.0 ; - int k ; - - if (len > MAX_SPEC_LEN) - { printf ("%s : line %d : data length too large.\n", __FILE__, __LINE__) ; - exit (1) ; - } ; - - for (k = 0 ; k < len ; k++) - datacopy [k] = data [k] ; - - /* Pad the data just a little to speed up the FFT. */ - while ((len & 0x1F) && len < MAX_SPEC_LEN) - { datacopy [len] = 0.0 ; - len ++ ; - } ; - - log_mag_spectrum (datacopy, len, magnitude) ; - smooth_mag_spectrum (magnitude, len / 2) ; - - snr = find_snr (magnitude, len, expected_peaks) ; - - return snr ; -} /* calculate_snr */ - -/*============================================================================== -** There is a slight problem with trying to measure SNR with the method used -** here; the side lobes of the windowed FFT can look like a noise/aliasing peak. -** The solution is to smooth the magnitude spectrum by wiping out troughs -** between adjacent peaks as done here. -** This removes side lobe peaks without affecting noise/aliasing peaks. -*/ - -static void linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller) ; - -static void -smooth_mag_spectrum (double *mag, int len) -{ PEAK_DATA peaks [2] ; - - int k ; - - memset (peaks, 0, sizeof (peaks)) ; - - /* Find first peak. */ - for (k = 1 ; k < len - 1 ; k++) - { if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1]) - { peaks [0].peak = mag [k] ; - peaks [0].index = k ; - break ; - } ; - } ; - - /* Find subsequent peaks ans smooth between peaks. */ - for (k = peaks [0].index + 1 ; k < len - 1 ; k++) - { if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1]) - { peaks [1].peak = mag [k] ; - peaks [1].index = k ; - - if (peaks [1].peak > peaks [0].peak) - linear_smooth (mag, &peaks [1], &peaks [0]) ; - else - linear_smooth (mag, &peaks [0], &peaks [1]) ; - peaks [0] = peaks [1] ; - } ; - } ; - -} /* smooth_mag_spectrum */ - -static void -linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller) -{ int k ; - - if (smaller->index < larger->index) - { for (k = smaller->index + 1 ; k < larger->index ; k++) - mag [k] = (mag [k] < mag [k - 1]) ? 0.999 * mag [k - 1] : mag [k] ; - } - else - { for (k = smaller->index - 1 ; k >= larger->index ; k--) - mag [k] = (mag [k] < mag [k + 1]) ? 0.999 * mag [k + 1] : mag [k] ; - } ; - -} /* linear_smooth */ - -/*============================================================================== -*/ - -static int -peak_compare (const void *vp1, const void *vp2) -{ const PEAK_DATA *peak1, *peak2 ; - - peak1 = (const PEAK_DATA*) vp1 ; - peak2 = (const PEAK_DATA*) vp2 ; - - return (peak1->peak < peak2->peak) ? 1 : -1 ; -} /* peak_compare */ - -static double -find_snr (const double *magnitude, int len, int expected_peaks) -{ PEAK_DATA peaks [MAX_PEAKS] ; - - int k, peak_count = 0 ; - double snr ; - - memset (peaks, 0, sizeof (peaks)) ; - - /* Find the MAX_PEAKS largest peaks. */ - for (k = 1 ; k < len - 1 ; k++) - { if (magnitude [k - 1] < magnitude [k] && magnitude [k] >= magnitude [k + 1]) - { if (peak_count < MAX_PEAKS) - { peaks [peak_count].peak = magnitude [k] ; - peaks [peak_count].index = k ; - peak_count ++ ; - qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ; - } - else if (magnitude [k] > peaks [MAX_PEAKS - 1].peak) - { peaks [MAX_PEAKS - 1].peak = magnitude [k] ; - peaks [MAX_PEAKS - 1].index = k ; - qsort (peaks, MAX_PEAKS, sizeof (PEAK_DATA), peak_compare) ; - } ; - } ; - } ; - - if (peak_count < expected_peaks) - { printf ("\n%s : line %d : bad peak_count (%d), expected %d.\n\n", __FILE__, __LINE__, peak_count, expected_peaks) ; - return -1.0 ; - } ; - - /* Sort the peaks. */ - qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ; - - snr = peaks [0].peak ; - for (k = 1 ; k < peak_count ; k++) - if (fabs (snr - peaks [k].peak) > 10.0) - return fabs (peaks [k].peak) ; - - return snr ; -} /* find_snr */ - -static void -log_mag_spectrum (double *input, int len, double *magnitude) -{ fftw_plan plan = NULL ; - - double maxval ; - int k ; - - if (input == NULL || magnitude == NULL) - return ; - - plan = fftw_plan_r2r_1d (len, input, magnitude, FFTW_R2HC, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT) ; - if (plan == NULL) - { printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ; - exit (1) ; - } ; - - fftw_execute (plan) ; - - fftw_destroy_plan (plan) ; - - /* (k < N/2 rounded up) */ - maxval = 0.0 ; - for (k = 1 ; k < len / 2 ; k++) - { magnitude [k] = sqrt (magnitude [k] * magnitude [k] + magnitude [len - k - 1] * magnitude [len - k - 1]) ; - maxval = (maxval < magnitude [k]) ? magnitude [k] : maxval ; - } ; - - memset (magnitude + len / 2, 0, len / 2 * sizeof (magnitude [0])) ; - - /* Don't care about DC component. Make it zero. */ - magnitude [0] = 0.0 ; - - /* log magnitude. */ - for (k = 0 ; k < len ; k++) - { magnitude [k] = magnitude [k] / maxval ; - magnitude [k] = (magnitude [k] < 1e-15) ? -200.0 : 20.0 * log10 (magnitude [k]) ; - } ; - - return ; -} /* log_mag_spectrum */ - -#else /* ! (HAVE_LIBFFTW && HAVE_LIBRFFTW) */ - -double -calculate_snr (float *data, int len, int expected_peaks) -{ double snr = 200.0 ; - - data = data ; - len = len ; - expected_peaks = expected_peaks ; - - return snr ; -} /* calculate_snr */ - -#endif - diff --git a/lib-src/libsoxr/lsr-tests/callback_hang_test.c b/lib-src/libsoxr/lsr-tests/callback_hang_test.c deleted file mode 100644 index 3a50a8323..000000000 --- a/lib-src/libsoxr/lsr-tests/callback_hang_test.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "config.h" - -#include -#include -#include -#include - -#if HAVE_ALARM && HAVE_SIGNAL && HAVE_SIGALRM - -#include - -#include - -#include "util.h" - -#define SHORT_BUFFER_LEN 512 -#define LONG_BUFFER_LEN (1 << 14) - -typedef struct -{ double ratio ; - int count ; -} SRC_PAIR ; - -static void callback_hang_test (int converter) ; - -static void alarm_handler (int number) ; -static long input_callback (void *cb_data, float **data) ; - - -int -main (void) -{ - /* Set up SIGALRM handler. */ - signal (SIGALRM, alarm_handler) ; - - puts ("") ; - callback_hang_test (SRC_ZERO_ORDER_HOLD) ; - callback_hang_test (SRC_LINEAR) ; - callback_hang_test (SRC_SINC_FASTEST) ; - puts ("") ; - - return 0 ; -} /* main */ - - -static void -callback_hang_test (int converter) -{ static float output [LONG_BUFFER_LEN] ; - static SRC_PAIR pairs [] = - { - { 1.2, 5 }, { 1.1, 1 }, { 1.0, 1 }, { 3.0, 1 }, { 2.0, 1 }, { 0.3, 1 }, - { 1.2, 0 }, { 1.1, 10 }, { 1.0, 1 } - } ; - - - SRC_STATE *src_state ; - - double src_ratio = 1.0 ; - int k, error ; - - printf ("\tcallback_hang_test (%-28s) ....... ", src_get_name (converter)) ; - fflush (stdout) ; - - /* Perform sample rate conversion. */ - src_state = src_callback_new (input_callback, converter, 1, &error, NULL) ; - if (src_state == NULL) - { printf ("\n\nLine %d : src_callback_new () failed : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - for (k = 0 ; k < ARRAY_LEN (pairs) ; k++) - { alarm (1) ; - src_ratio = pairs [k].ratio ; - src_callback_read (src_state, src_ratio, pairs [k].count, output) ; - } ; - - src_state = src_delete (src_state) ; - - alarm (0) ; - puts ("ok") ; - - return ; -} /* callback_hang_test */ - -static void -alarm_handler (int number) -{ - (void) number ; - printf ("\n\n Error : Hang inside src_callback_read() detected. Exiting!\n\n") ; - exit (1) ; -} /* alarm_handler */ - -static long -input_callback (void *cb_data, float **data) -{ - static float buffer [20] ; - - (void) cb_data ; - *data = buffer ; - - return ARRAY_LEN (buffer) ; -} /* input_callback */ - -#else - -int -main (void) -{ - puts ("\tCan't run this test on this platform.") ; - return 0 ; -} /* main */ - -#endif diff --git a/lib-src/libsoxr/lsr-tests/callback_test.c b/lib-src/libsoxr/lsr-tests/callback_test.c deleted file mode 100644 index a8295cc3a..000000000 --- a/lib-src/libsoxr/lsr-tests/callback_test.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -** Copyright (C) 2003-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include - -#include - -#include "util.h" - -#define BUFFER_LEN 10000 -#define CB_READ_LEN 256 - -static void callback_test (int converter, double ratio) ; -static void end_of_stream_test (int converter) ; - -int -main (void) -{ static double src_ratios [] = - { 1.0, 0.099, 0.1, 0.33333333, 0.789, 1.0001, 1.9, 3.1, 9.9 - } ; - - int k ; - - puts ("") ; - - puts (" Zero Order Hold interpolator :") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - callback_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; - - puts (" Linear interpolator :") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - callback_test (SRC_LINEAR, src_ratios [k]) ; - - puts (" Sinc interpolator :") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - callback_test (SRC_SINC_FASTEST, src_ratios [k]) ; - - puts ("") ; - - puts (" End of stream test :") ; - end_of_stream_test (SRC_ZERO_ORDER_HOLD) ; - end_of_stream_test (SRC_LINEAR) ; - end_of_stream_test (SRC_SINC_FASTEST) ; - - puts ("") ; - return 0 ; -} /* main */ - -/*===================================================================================== -*/ - -typedef struct -{ int channels ; - long count, total ; - int end_of_data ; - float data [BUFFER_LEN] ; -} TEST_CB_DATA ; - -static long -test_callback_func (void *cb_data, float **data) -{ TEST_CB_DATA *pcb_data ; - - long frames ; - - if ((pcb_data = cb_data) == NULL) - return 0 ; - - if (data == NULL) - return 0 ; - - if (pcb_data->total - pcb_data->count > CB_READ_LEN) - frames = CB_READ_LEN / pcb_data->channels ; - else - frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ; - - *data = pcb_data->data + pcb_data->count ; - pcb_data->count += frames ; - - return frames ; -} /* test_callback_func */ - - -static void -callback_test (int converter, double src_ratio) -{ static TEST_CB_DATA test_callback_data ; - static float output [BUFFER_LEN] ; - - SRC_STATE *src_state ; - - long read_count, read_total ; - int error ; - - printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ; - fflush (stdout) ; - - test_callback_data.channels = 2 ; - test_callback_data.count = 0 ; - test_callback_data.end_of_data = 0 ; - test_callback_data.total = ARRAY_LEN (test_callback_data.data) ; - - if ((src_state = src_callback_new (test_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - read_total = 0 ; - do - { /* We will be throwing away output data, so just grab as much as possible. */ - read_count = ARRAY_LEN (output) / test_callback_data.channels ; - read_count = src_callback_read (src_state, src_ratio, read_count, output) ; - read_total += read_count ; - } - while (read_count > 0) ; - - if ((error = src_error (src_state)) != 0) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_state = src_delete (src_state) ; - - if (fabs (read_total / src_ratio - ARRAY_LEN (test_callback_data.data)) > 2.0) - { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; - printf (" input len : %d\n", ARRAY_LEN (test_callback_data.data)) ; - printf (" output len : %ld (should be %g +/- 2)\n\n", read_total, - floor (0.5 + src_ratio * ARRAY_LEN (test_callback_data.data))) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* callback_test */ - -/*===================================================================================== -*/ - -static long -eos_callback_func (void *cb_data, float **data) -{ - TEST_CB_DATA *pcb_data ; - long frames ; - - if (data == NULL) - return 0 ; - - if ((pcb_data = cb_data) == NULL) - return 0 ; - - /* - ** Return immediately if there is no more data. - ** In this case, the output pointer 'data' will not be set and - ** valgrind should not warn about it. - */ - if (pcb_data->end_of_data) - return 0 ; - - if (pcb_data->total - pcb_data->count > CB_READ_LEN) - frames = CB_READ_LEN / pcb_data->channels ; - else - frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ; - - *data = pcb_data->data + pcb_data->count ; - pcb_data->count += frames ; - - /* - ** Set end_of_data so that the next call to the callback function will - ** return zero ocunt without setting the 'data' pointer. - */ - if (pcb_data->total < 2 * pcb_data->count) - pcb_data->end_of_data = 1 ; - - return frames ; -} /* eos_callback_data */ - - -static void -end_of_stream_test (int converter) -{ static TEST_CB_DATA test_callback_data ; - static float output [BUFFER_LEN] ; - - SRC_STATE *src_state ; - - double src_ratio = 0.3 ; - long read_count, read_total ; - int error ; - - printf ("\t%-30s ........... ", src_get_name (converter)) ; - fflush (stdout) ; - - test_callback_data.channels = 2 ; - test_callback_data.count = 0 ; - test_callback_data.end_of_data = 0 ; - test_callback_data.total = ARRAY_LEN (test_callback_data.data) ; - - if ((src_state = src_callback_new (eos_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - read_total = 0 ; - do - { /* We will be throwing away output data, so just grab as much as possible. */ - read_count = ARRAY_LEN (output) / test_callback_data.channels ; - read_count = src_callback_read (src_state, src_ratio, read_count, output) ; - read_total += read_count ; - } - while (read_count > 0) ; - - if ((error = src_error (src_state)) != 0) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_state = src_delete (src_state) ; - - if (test_callback_data.end_of_data == 0) - { printf ("\n\nLine %d : test_callback_data.end_of_data should not be 0." - " This is a bug in the test.\n\n", __LINE__) ; - exit (1) ; - } ; - - puts ("ok") ; - return ; -} /* end_of_stream_test */ diff --git a/lib-src/libsoxr/lsr-tests/cmake/Modules/FindFFTW.cmake b/lib-src/libsoxr/lsr-tests/cmake/Modules/FindFFTW.cmake deleted file mode 100644 index 9c6012d3e..000000000 --- a/lib-src/libsoxr/lsr-tests/cmake/Modules/FindFFTW.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Find FFTW -# Find the native installation of this package: includes and libraries. -# -# FFTW_INCLUDES - where to find headers for this package. -# FFTW_LIBRARIES - List of libraries when using this package. -# FFTW_FOUND - True if this package can be found. - -if (FFTW_INCLUDES) - set (FFTW_FIND_QUIETLY TRUE) -endif (FFTW_INCLUDES) - -find_path (FFTW_INCLUDES fftw3.h) - -find_library (FFTW_LIBRARIES NAMES fftw3) - -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args ( - FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES) - -mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES) diff --git a/lib-src/libsoxr/lsr-tests/cmake/Modules/Findsndfile.cmake b/lib-src/libsoxr/lsr-tests/cmake/Modules/Findsndfile.cmake deleted file mode 100644 index 018861d9c..000000000 --- a/lib-src/libsoxr/lsr-tests/cmake/Modules/Findsndfile.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Find SNDFILE -# Find the native installation of this package: includes and libraries. -# -# SNDFILE_INCLUDES - where to find headers for this package. -# SNDFILE_LIBRARIES - List of libraries when using this package. -# SNDFILE_FOUND - True if this package can be found. - -if (SNDFILE_INCLUDES) - set (SNDFILE_FIND_QUIETLY TRUE) -endif (SNDFILE_INCLUDES) - -find_path (SNDFILE_INCLUDES sndfile.h) - -find_library (SNDFILE_LIBRARIES NAMES sndfile) - -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args ( - SNDFILE DEFAULT_MSG SNDFILE_LIBRARIES SNDFILE_INCLUDES) - -mark_as_advanced (SNDFILE_LIBRARIES SNDFILE_INCLUDES) diff --git a/lib-src/libsoxr/lsr-tests/config.h.in b/lib-src/libsoxr/lsr-tests/config.h.in deleted file mode 100644 index d62479d5b..000000000 --- a/lib-src/libsoxr/lsr-tests/config.h.in +++ /dev/null @@ -1,24 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxsrc_lsr_tests_config_included -#define soxsrc_lsr_tests_config_included - -#define HAVE_ALARM @HAVE_ALARM@ -#define HAVE_FFTW3 @HAVE_FFTW3@ -#define HAVE_LRINTF @HAVE_LRINTF@ -#define HAVE_LRINT @HAVE_LRINT@ -#define HAVE_SIGNAL @HAVE_SIGNAL@ -#define HAVE_SNDFILE @HAVE_SNDFILE@ -#define HAVE_SYS_TIMES_H @HAVE_SYS_TIMES_H@ - -#if HAVE_SIGNAL - #include - #if defined SIGALRM - #define HAVE_SIGALRM 1 - #else - #define HAVE_SIGALRM 0 - #endif -#endif - -#endif diff --git a/lib-src/libsoxr/lsr-tests/downsample_test.c b/lib-src/libsoxr/lsr-tests/downsample_test.c deleted file mode 100644 index b2b1812a4..000000000 --- a/lib-src/libsoxr/lsr-tests/downsample_test.c +++ /dev/null @@ -1,61 +0,0 @@ -/* -** Copyright (C) 2008-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include - -#include "util.h" - -static void -downsample_test (int converter) -{ static float in [1000], out [10] ; - SRC_DATA data ; - - printf (" downsample_test (%-28s) ....... ", src_get_name (converter)) ; - fflush (stdout) ; - - data.src_ratio = 1.0 / 255.0 ; - data.input_frames = ARRAY_LEN (in) ; - data.output_frames = ARRAY_LEN (out) ; - data.data_in = in ; - data.data_out = out ; - - if (src_simple (&data, converter, 1)) - { puts ("src_simple failed.") ; - exit (1) ; - } ; - - puts ("ok") ; -} /* downsample_test */ - -int -main (void) -{ - puts ("") ; - - downsample_test (SRC_ZERO_ORDER_HOLD) ; - downsample_test (SRC_LINEAR) ; - downsample_test (SRC_SINC_FASTEST) ; - downsample_test (SRC_SINC_MEDIUM_QUALITY) ; - downsample_test (SRC_SINC_BEST_QUALITY) ; - - puts ("") ; - - return 0 ; -} /* main */ diff --git a/lib-src/libsoxr/lsr-tests/float_cast.h b/lib-src/libsoxr/lsr-tests/float_cast.h deleted file mode 100644 index f305d212b..000000000 --- a/lib-src/libsoxr/lsr-tests/float_cast.h +++ /dev/null @@ -1,281 +0,0 @@ -/* -** Copyright (C) 2001-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* Version 1.5 */ - -#ifndef FLOAT_CAST_HEADER -#define FLOAT_CAST_HEADER - -/*============================================================================ -** On Intel Pentium processors (especially PIII and probably P4), converting -** from float to int is very slow. To meet the C specs, the code produced by -** most C compilers targeting Pentium needs to change the FPU rounding mode -** before the float to int conversion is performed. -** -** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It -** is this flushing of the pipeline which is so slow. -** -** Fortunately the ISO C99 specifications define the functions lrint, lrintf, -** llrint and llrintf which fix this problem as a side effect. -** -** On Unix-like systems, the configure process should have detected the -** presence of these functions. If they weren't found we have to replace them -** here with a standard C cast. -*/ - -/* -** The C99 prototypes for lrint and lrintf are as follows: -** -** long int lrintf (float x) ; -** long int lrint (double x) ; -*/ - -#include "config.h" - -/* -** The presence of the required functions are detected during the configure -** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in -** the config.h file. -*/ - -#define HAVE_LRINT_REPLACEMENT 0 - -#if (HAVE_LRINT && HAVE_LRINTF) - - /* - ** These defines enable functionality introduced with the 1999 ISO C - ** standard. They must be defined before the inclusion of math.h to - ** engage them. If optimisation is enabled, these functions will be - ** inlined. With optimisation switched off, you have to link in the - ** maths library using -lm. - */ - - #define _ISOC9X_SOURCE 1 - #define _ISOC99_SOURCE 1 - - #define __USE_ISOC9X 1 - #define __USE_ISOC99 1 - - #include - -#elif (defined (__CYGWIN__)) - - #include - - #undef HAVE_LRINT_REPLACEMENT - #define HAVE_LRINT_REPLACEMENT 1 - - #undef lrint - #undef lrintf - - #define lrint double2int - #define lrintf float2int - - /* - ** The native CYGWIN lrint and lrintf functions are buggy: - ** http://sourceware.org/ml/cygwin/2005-06/msg00153.html - ** http://sourceware.org/ml/cygwin/2005-09/msg00047.html - ** and slow. - ** These functions (pulled from the Public Domain MinGW math.h header) - ** replace the native versions. - */ - - static inline long double2int (double in) - { long retval ; - - __asm__ __volatile__ - ( "fistpl %0" - : "=m" (retval) - : "t" (in) - : "st" - ) ; - - return retval ; - } /* double2int */ - - static inline long float2int (float in) - { long retval ; - - __asm__ __volatile__ - ( "fistpl %0" - : "=m" (retval) - : "t" (in) - : "st" - ) ; - - return retval ; - } /* float2int */ - -#elif (defined (WIN64) || defined(_WIN64)) - - /* Win64 section should be places before Win32 one, because - ** most likely both WIN32 and WIN64 will be defined in 64-bit case. - */ - - #include - - /* Win64 doesn't seem to have these functions, nor inline assembly. - ** Therefore implement inline versions of these functions here. - */ - #include - #include - - __inline long int - lrint(double flt) - { - return _mm_cvtsd_si32(_mm_load_sd(&flt)); - } - - __inline long int - lrintf(float flt) - { - return _mm_cvtss_si32(_mm_load_ss(&flt)); - } - -#elif (defined (WIN32) || defined (_WIN32)) - - #undef HAVE_LRINT_REPLACEMENT - #define HAVE_LRINT_REPLACEMENT 1 - - #include - - /* - ** Win32 doesn't seem to have these functions. - ** Therefore implement inline versions of these functions here. - */ - - __inline long int - lrint (double flt) - { int intgr ; - - _asm - { fld flt - fistp intgr - } ; - - return intgr ; - } - - __inline long int - lrintf (float flt) - { int intgr ; - - _asm - { fld flt - fistp intgr - } ; - - return intgr ; - } - -#elif (defined (__MWERKS__) && defined (macintosh)) - - /* This MacOS 9 solution was provided by Stephane Letz */ - - #undef HAVE_LRINT_REPLACEMENT - #define HAVE_LRINT_REPLACEMENT 1 - #include - - #undef lrint - #undef lrintf - - #define lrint double2int - #define lrintf float2int - - inline int - float2int (register float in) - { long res [2] ; - - asm - { fctiw in, in - stfd in, res - } - return res [1] ; - } /* float2int */ - - inline int - double2int (register double in) - { long res [2] ; - - asm - { fctiw in, in - stfd in, res - } - return res [1] ; - } /* double2int */ - -#elif (defined (__MACH__) && defined (__APPLE__)) - - /* For Apple MacOSX. */ - - #undef HAVE_LRINT_REPLACEMENT - #define HAVE_LRINT_REPLACEMENT 1 - #include - - #undef lrint - #undef lrintf - - #define lrint double2int - #define lrintf float2int - - inline static long - float2int (register float in) - { int res [2] ; - - __asm__ __volatile__ - ( "fctiw %1, %1\n\t" - "stfd %1, %0" - : "=m" (res) /* Output */ - : "f" (in) /* Input */ - : "memory" - ) ; - - return res [1] ; - } /* lrintf */ - - inline static long - double2int (register double in) - { int res [2] ; - - __asm__ __volatile__ - ( "fctiw %1, %1\n\t" - "stfd %1, %0" - : "=m" (res) /* Output */ - : "f" (in) /* Input */ - : "memory" - ) ; - - return res [1] ; - } /* lrint */ - -#else - #ifndef __sgi - #warning "Don't have the functions lrint() and lrintf()." - #warning "Replacing these functions with a standard C cast." - #endif - - #include - - #define lrint(dbl) ((long) (dbl)) - #define lrintf(flt) ((long) (flt)) - -#endif - - -#endif /* FLOAT_CAST_HEADER */ - diff --git a/lib-src/libsoxr/lsr-tests/float_short_test.c b/lib-src/libsoxr/lsr-tests/float_short_test.c deleted file mode 100644 index c6a1f76f8..000000000 --- a/lib-src/libsoxr/lsr-tests/float_short_test.c +++ /dev/null @@ -1,192 +0,0 @@ -/* -** Copyright (C) 2003-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include - -#include - -#include "util.h" - -#define BUFFER_LEN 10000 - -static void float_to_short_test (void) ; -static void short_to_float_test (void) ; - -static void float_to_int_test (void) ; -static void int_to_float_test (void) ; - -int -main (void) -{ - puts ("") ; - - float_to_short_test () ; - short_to_float_test () ; - - float_to_int_test () ; - int_to_float_test () ; - - puts ("") ; - - return 0 ; -} /* main */ - -/*===================================================================================== -*/ - -static void -float_to_short_test (void) -{ - static float fpos [] = - { 0.95, 0.99, 1.0, 1.01, 1.1, 2.0, 11.1, 111.1, 2222.2, 33333.3 - } ; - static float fneg [] = - { -0.95, -0.99, -1.0, -1.01, -1.1, -2.0, -11.1, -111.1, -2222.2, -33333.3 - } ; - - static short out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ; - - int k ; - - printf ("\tfloat_to_short_test ............................. ") ; - - src_float_to_short_array (fpos, out, ARRAY_LEN (fpos)) ; - - for (k = 0 ; k < ARRAY_LEN (fpos) ; k++) - if (out [k] < 30000) - { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; - exit (1) ; - } ; - - src_float_to_short_array (fneg, out, ARRAY_LEN (fneg)) ; - - for (k = 0 ; k < ARRAY_LEN (fneg) ; k++) - if (out [k] > -30000) - { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* float_to_short_test */ - -/*------------------------------------------------------------------------------------- -*/ - -static void -short_to_float_test (void) -{ - static short input [BUFFER_LEN] ; - static short output [BUFFER_LEN] ; - static float temp [BUFFER_LEN] ; - - int k ; - - printf ("\tshort_to_float_test ............................. ") ; - - for (k = 0 ; k < ARRAY_LEN (input) ; k++) - input [k] = (k * 0x8000) / ARRAY_LEN (input) ; - - src_short_to_float_array (input, temp, ARRAY_LEN (temp)) ; - src_float_to_short_array (temp, output, ARRAY_LEN (output)) ; - - for (k = 0 ; k < ARRAY_LEN (input) ; k++) - if (ABS (input [k] - output [k]) > 0) - { printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* short_to_float_test */ - -/*===================================================================================== -*/ - -static void -float_to_int_test (void) -{ - static float fpos [] = - { 0.95, 0.99, 1.0, 1.01, 1.1, 2.0, 11.1, 111.1, 2222.2, 33333.3 - } ; - static float fneg [] = - { -0.95, -0.99, -1.0, -1.01, -1.1, -2.0, -11.1, -111.1, -2222.2, -33333.3 - } ; - - static int out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ; - - int k ; - - printf ("\tfloat_to_int_test ............................... ") ; - - src_float_to_int_array (fpos, out, ARRAY_LEN (fpos)) ; - - for (k = 0 ; k < ARRAY_LEN (fpos) ; k++) - if (out [k] < 30000 * 0x10000) - { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; - exit (1) ; - } ; - - src_float_to_int_array (fneg, out, ARRAY_LEN (fneg)) ; - - for (k = 0 ; k < ARRAY_LEN (fneg) ; k++) - if (out [k] > -30000 * 0x1000) - { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* float_to_int_test */ - -/*------------------------------------------------------------------------------------- -*/ - -static void -int_to_float_test (void) -{ - static int input [BUFFER_LEN] ; - static int output [BUFFER_LEN] ; - static float temp [BUFFER_LEN] ; - - int k ; - - printf ("\tint_to_float_test ............................... ") ; - - for (k = 0 ; k < ARRAY_LEN (input) ; k++) - input [k] = (k * 0x80000000) / ARRAY_LEN (input) ; - - src_int_to_float_array (input, temp, ARRAY_LEN (temp)) ; - src_float_to_int_array (temp, output, ARRAY_LEN (output)) ; - - for (k = 0 ; k < ARRAY_LEN (input) ; k++) - if (ABS (input [k] - output [k]) > 0) - { printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* int_to_float_test */ - diff --git a/lib-src/libsoxr/lsr-tests/misc_test.c b/lib-src/libsoxr/lsr-tests/misc_test.c deleted file mode 100644 index bdc9c8221..000000000 --- a/lib-src/libsoxr/lsr-tests/misc_test.c +++ /dev/null @@ -1,175 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include - -#include - -#include "util.h" - -static void name_test (void) ; -static void error_test (void) ; -static void src_ratio_test (void) ; -static void zero_input_test (int converter) ; - -int -main (void) -{ - puts ("") ; - - printf (" version : %s\n\n", src_get_version ()) ; - - /* Current max converter is SRC_LINEAR. */ - name_test () ; - - error_test () ; - - src_ratio_test () ; - - zero_input_test (SRC_ZERO_ORDER_HOLD) ; - zero_input_test (SRC_LINEAR) ; - zero_input_test (SRC_SINC_FASTEST) ; - - puts ("") ; - return 0 ; -} /* main */ - -static void -name_test (void) -{ const char *name ; - int k = 0 ; - - puts (" name_test :") ; - - while (1) - { name = src_get_name (k) ; - if (name == NULL) - break ; - printf ("\tName %d : %s\n", k, name) ; - printf ("\tDesc %d : %s\n", k, src_get_description (k)) ; - k ++ ; - } ; - - puts ("") ; - - return ; -} /* name_test */ - -/*------------------------------------------------------------------------------ -*/ - -typedef struct -{ double ratio ; - int should_pass ; -} RATIO_TEST ; - -static RATIO_TEST ratio_test [] = -{ { 1.0 / 256.1, 0 }, - { 1.0 / 256.0, 1 }, - { 1.0, 1 }, - { 256.0, 1 }, - { 256.1, 0 }, - { -1.0, 0 } -} ; - -static void -src_ratio_test (void) -{ int k ; - - puts (" src_ratio_test (SRC ratio must be in range [1/256, 256]):" ) ; - - - for (k = 0 ; k < ARRAY_LEN (ratio_test) ; k++) - { if (ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) == 0) - { printf ("\n\nLine %d : SRC ratio %f should have passed.\n\n", __LINE__, ratio_test [k].ratio) ; - exit (1) ; - } ; - if (! ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) != 0) - { printf ("\n\nLine %d : SRC ratio %f should not have passed.\n\n", __LINE__, ratio_test [k].ratio) ; - exit (1) ; - } ; - printf ("\t SRC ratio (%9.5f) : %s ................... ok\n", ratio_test [k].ratio, - (ratio_test [k].should_pass ? "pass" : "fail")) ; - } ; - - puts ("") ; - - return ; -} /* src_ratio_test */ - -static void -error_test (void) -{ const char *errorstr ; - int k, errors = 0 ; - - puts (" error_test :") ; - - for (k = 0 ; 1 ; k++) - { errorstr = src_strerror (k) ; - printf ("\t%-2d : %s\n", k, errorstr) ; - if (errorstr == NULL) - { errors ++ ; - continue ; - } ; - if (strstr (errorstr, "Placeholder.") == errorstr) - break ; - } ; - - if (errors != 0) - { printf ("\n\nLine %d : Missing error numbers above.\n\n", __LINE__) ; - exit (1) ; - } ; - - puts ("") ; - - return ; -} /* error_test */ - -static void -zero_input_test (int converter) -{ SRC_DATA data ; - SRC_STATE *state ; - float out [100] ; - int error ; - - printf (" %s (%-26s) ........ ", __func__, src_get_name (converter)) ; - fflush (stdout) ; - - if ((state = src_new (converter, 1, &error)) == NULL) - { printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - data.data_in = (float *) 0xdeadbeef ; - data.input_frames = 0 ; - data.data_out = out ; - data.output_frames = ARRAY_LEN (out) ; - data.end_of_input = 0 ; - data.src_ratio = 1.0 ; - - if ((error = src_process (state, &data))) - { printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - state = src_delete (state) ; - - puts ("ok") ; -} /* zero_input_test */ diff --git a/lib-src/libsoxr/lsr-tests/multi_channel_test.c b/lib-src/libsoxr/lsr-tests/multi_channel_test.c deleted file mode 100644 index 4668a7c77..000000000 --- a/lib-src/libsoxr/lsr-tests/multi_channel_test.c +++ /dev/null @@ -1,364 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include - -#include "util.h" -#define BUFFER_LEN 50000 -#define BLOCK_LEN (12) - -#define MAX_CHANNELS 10 - -static void simple_test (int converter, int channel_count, double target_snr) ; -static void process_test (int converter, int channel_count, double target_snr) ; -static void callback_test (int converter, int channel_count, double target_snr) ; - -int -main (void) -{ double target ; - int k ; - - puts ("\n Zero Order Hold interpolator :") ; - target = 38.0 ; - for (k = 1 ; k <= 3 ; k++) - { simple_test (SRC_ZERO_ORDER_HOLD, k, target) ; - process_test (SRC_ZERO_ORDER_HOLD, k, target) ; - callback_test (SRC_ZERO_ORDER_HOLD, k, target) ; - } ; - - puts ("\n Linear interpolator :") ; - target = 79.0 ; - for (k = 1 ; k <= 3 ; k++) - { simple_test (SRC_LINEAR, k, target) ; - process_test (SRC_LINEAR, k, target) ; - callback_test (SRC_LINEAR, k, target) ; - } ; - - puts ("\n Sinc interpolator :") ; - target = 100.0 ; - for (k = 1 ; k <= MAX_CHANNELS ; k++) - { simple_test (SRC_SINC_FASTEST, k, target) ; - process_test (SRC_SINC_FASTEST, k, target) ; - callback_test (SRC_SINC_FASTEST, k, target) ; - } ; - - puts ("") ; - - return 0 ; -} /* main */ - -/*============================================================================== -*/ - -static float input_serial [BUFFER_LEN * MAX_CHANNELS] ; -static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ; -static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ; -static float output_serial [BUFFER_LEN * MAX_CHANNELS] ; - -static void -simple_test (int converter, int channel_count, double target_snr) -{ SRC_DATA src_data ; - - double freq, snr ; - int ch, error, frames ; - - printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ; - fflush (stdout) ; - - assert (channel_count <= MAX_CHANNELS) ; - - memset (input_serial, 0, sizeof (input_serial)) ; - memset (input_interleaved, 0, sizeof (input_interleaved)) ; - memset (output_interleaved, 0, sizeof (output_interleaved)) ; - memset (output_serial, 0, sizeof (output_serial)) ; - - frames = BUFFER_LEN ; - - /* Calculate channel_count separate windowed sine waves. */ - for (ch = 0 ; ch < channel_count ; ch++) - { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; - gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; - } ; - - /* Interleave the data in preparation for SRC. */ - interleave_data (input_serial, input_interleaved, frames, channel_count) ; - - /* Choose a converstion ratio <= 1.0. */ - src_data.src_ratio = 0.95 ; - - src_data.data_in = input_interleaved ; - src_data.input_frames = frames ; - - src_data.data_out = output_interleaved ; - src_data.output_frames = frames ; - - if ((error = src_simple (&src_data, converter, channel_count))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2) - { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, - src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ; - printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; - printf ("\tinput_len : %ld\n", src_data.input_frames) ; - printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ; - exit (1) ; - } ; - - /* De-interleave data so SNR can be calculated for each channel. */ - deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; - - for (ch = 0 ; ch < channel_count ; ch++) - { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; - if (snr < target_snr) - { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; - save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; - exit (1) ; - } ; - } ; - - puts ("ok") ; - - return ; -} /* simple_test */ - -/*============================================================================== -*/ - -static void -process_test (int converter, int channel_count, double target_snr) -{ SRC_STATE *src_state ; - SRC_DATA src_data ; - - double freq, snr ; - int ch, error, frames, current_in, current_out ; - - printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ; - fflush (stdout) ; - - assert (channel_count <= MAX_CHANNELS) ; - - memset (input_serial, 0, sizeof (input_serial)) ; - memset (input_interleaved, 0, sizeof (input_interleaved)) ; - memset (output_interleaved, 0, sizeof (output_interleaved)) ; - memset (output_serial, 0, sizeof (output_serial)) ; - - frames = BUFFER_LEN ; - - /* Calculate channel_count separate windowed sine waves. */ - for (ch = 0 ; ch < channel_count ; ch++) - { freq = (400.0 + 11.333333333 * ch) / 44100.0 ; - gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; - } ; - - /* Interleave the data in preparation for SRC. */ - interleave_data (input_serial, input_interleaved, frames, channel_count) ; - - /* Perform sample rate conversion. */ - if ((src_state = src_new (converter, channel_count, &error)) == NULL) - { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_data.end_of_input = 0 ; /* Set this later. */ - - /* Choose a converstion ratio < 1.0. */ - src_data.src_ratio = 0.95 ; - - src_data.data_in = input_interleaved ; - src_data.data_out = output_interleaved ; - - current_in = current_out = 0 ; - - while (1) - { src_data.input_frames = MAX (MIN (BLOCK_LEN, frames - current_in), 0) ; - src_data.output_frames = MAX (MIN (BLOCK_LEN, frames - current_out), 0) ; - - if ((error = src_process (src_state, &src_data))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - if (src_data.end_of_input && src_data.output_frames_gen == 0) - break ; - - current_in += src_data.input_frames_used ; - current_out += src_data.output_frames_gen ; - - src_data.data_in += src_data.input_frames_used * channel_count ; - src_data.data_out += src_data.output_frames_gen * channel_count ; - - src_data.end_of_input = (current_in >= frames) ? 1 : 0 ; - } ; - - src_state = src_delete (src_state) ; - - if (fabs (current_out - src_data.src_ratio * current_in) > 2) - { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, - current_out, (int) floor (src_data.src_ratio * current_in)) ; - printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; - printf ("\tinput_len : %d\n", frames) ; - printf ("\toutput_len : %d\n\n", current_out) ; - exit (1) ; - } ; - - /* De-interleave data so SNR can be calculated for each channel. */ - deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; - - for (ch = 0 ; ch < channel_count ; ch++) - { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; - if (snr < target_snr) - { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; - save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; - exit (1) ; - } ; - } ; - - puts ("ok") ; - - return ; -} /* process_test */ - -/*============================================================================== -*/ - -typedef struct -{ int channels ; - long total_frames ; - long current_frame ; - float *data ; -} TEST_CB_DATA ; - -static long -test_callback_func (void *cb_data, float **data) -{ TEST_CB_DATA *pcb_data ; - - long frames ; - - if ((pcb_data = cb_data) == NULL) - return 0 ; - - if (data == NULL) - return 0 ; - - *data = pcb_data->data + (pcb_data->current_frame * pcb_data->channels) ; - - if (pcb_data->total_frames - pcb_data->current_frame < BLOCK_LEN) - frames = pcb_data->total_frames - pcb_data->current_frame ; - else - frames = BLOCK_LEN ; - - pcb_data->current_frame += frames ; - - return frames ; -} /* test_callback_func */ - -static void -callback_test (int converter, int channel_count, double target_snr) -{ TEST_CB_DATA test_callback_data ; - SRC_STATE *src_state = NULL ; - - double freq, snr, src_ratio ; - int ch, error, frames, read_total, read_count ; - - printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ; - fflush (stdout) ; - - assert (channel_count <= MAX_CHANNELS) ; - - memset (input_serial, 0, sizeof (input_serial)) ; - memset (input_interleaved, 0, sizeof (input_interleaved)) ; - memset (output_interleaved, 0, sizeof (output_interleaved)) ; - memset (output_serial, 0, sizeof (output_serial)) ; - memset (&test_callback_data, 0, sizeof (test_callback_data)) ; - - frames = BUFFER_LEN ; - - /* Calculate channel_count separate windowed sine waves. */ - for (ch = 0 ; ch < channel_count ; ch++) - { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; - gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; - } ; - - /* Interleave the data in preparation for SRC. */ - interleave_data (input_serial, input_interleaved, frames, channel_count) ; - - /* Perform sample rate conversion. */ - src_ratio = 0.95 ; - test_callback_data.channels = channel_count ; - test_callback_data.total_frames = frames ; - test_callback_data.current_frame = 0 ; - test_callback_data.data = input_interleaved ; - - if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - read_total = 0 ; - while (read_total < frames) - { read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ; - - if (read_count <= 0) - break ; - - read_total += read_count ; - } ; - - if ((error = src_error (src_state)) != 0) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_state = src_delete (src_state) ; - - if (fabs (read_total - src_ratio * frames) > 2) - { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, - read_total, (int) floor (src_ratio * frames)) ; - printf ("\tsrc_ratio : %.4f\n", src_ratio) ; - printf ("\tinput_len : %d\n", frames) ; - printf ("\toutput_len : %d\n\n", read_total) ; - exit (1) ; - } ; - - /* De-interleave data so SNR can be calculated for each channel. */ - deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; - - for (ch = 0 ; ch < channel_count ; ch++) - { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; - if (snr < target_snr) - { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; - save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; - exit (1) ; - } ; - } ; - - puts ("ok") ; - - return ; -} /* callback_test */ - diff --git a/lib-src/libsoxr/lsr-tests/multichan_throughput_test.c b/lib-src/libsoxr/lsr-tests/multichan_throughput_test.c deleted file mode 100644 index 72b786af6..000000000 --- a/lib-src/libsoxr/lsr-tests/multichan_throughput_test.c +++ /dev/null @@ -1,216 +0,0 @@ -/* -** Copyright (C) 2008-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include - -#include - -#include "config.h" - -#include "util.h" -#include "float_cast.h" - -#define BUFFER_LEN (1<<17) - -static float input [BUFFER_LEN] ; -static float output [BUFFER_LEN] ; - -static long -throughput_test (int converter, int channels, long best_throughput) -{ SRC_DATA src_data ; - clock_t start_time, clock_time ; - double duration ; - long total_frames = 0, throughput ; - int error ; - - printf (" %-30s %2d ", src_get_name (converter), channels) ; - fflush (stdout) ; - - src_data.data_in = input ; - src_data.input_frames = ARRAY_LEN (input) / channels ; - - src_data.data_out = output ; - src_data.output_frames = ARRAY_LEN (output) / channels ; - - src_data.src_ratio = 0.99 ; - - sleep (2) ; - - start_time = clock () ; - - do - { - if ((error = src_simple (&src_data, converter, channels)) != 0) - { puts (src_strerror (error)) ; - exit (1) ; - } ; - - total_frames += src_data.output_frames_gen ; - - clock_time = clock () - start_time ; - duration = (1.0 * clock_time) / CLOCKS_PER_SEC ; - } - while (duration < 5.0) ; - - if (src_data.input_frames_used != src_data.input_frames) - { printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ; - exit (1) ; - } ; - - if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2) - { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; - printf (" input len : %d\n", ARRAY_LEN (input) / channels) ; - printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen, - floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ; - exit (1) ; - } ; - - throughput = lrint (floor (total_frames / duration)) ; - - if (best_throughput == 0) - { best_throughput = MAX (throughput, best_throughput) ; - printf ("%5.2f %10ld\n", duration, throughput) ; - } - else - { best_throughput = MAX (throughput, best_throughput) ; - printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ; - } - - return best_throughput ; -} /* throughput_test */ - -static void -single_run (void) -{ const int max_channels = 10 ; - int k ; - - printf ("\n CPU name : %s\n", get_cpu_name ()) ; - - puts ( - "\n" - " Converter Channels Duration Throughput\n" - " ---------------------------------------------------------------------" - ) ; - - for (k = 1 ; k <= max_channels / 2 ; k++) - throughput_test (SRC_SINC_FASTEST, k, 0) ; - - puts ("") ; - for (k = 1 ; k <= max_channels / 2 ; k++) - throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ; - - puts ("") ; - for (k = 1 ; k <= max_channels ; k++) - throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ; - - puts ("") ; - return ; -} /* single_run */ - -static void -multi_run (int run_count) -{ int k, ch ; - - printf ("\n CPU name : %s\n", get_cpu_name ()) ; - - puts ( - "\n" - " Converter Channels Duration Throughput Best Throughput\n" - " ----------------------------------------------------------------------------------------" - ) ; - - for (ch = 1 ; ch <= 5 ; ch++) - { long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ; - - for (k = 0 ; k < run_count ; k++) - { sinc_fastest = throughput_test (SRC_SINC_FASTEST, ch, sinc_fastest) ; - sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, sinc_medium) ; - sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, ch, sinc_best) ; - - puts ("") ; - - /* Let the CPU cool down. We might be running on a laptop. */ - sleep (10) ; - } ; - - puts ( - "\n" - " Converter Best Throughput\n" - " ------------------------------------------------" - ) ; - - printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ; - printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ; - printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ; - } ; - - puts ("") ; -} /* multi_run */ - -static void -usage_exit (const char * argv0) -{ const char * cptr ; - - if ((cptr = strrchr (argv0, '/')) != NULL) - argv0 = cptr ; - - printf ( - "Usage :\n" - " %s - Single run of the throughput test.\n" - " %s --best-of N - Do N runs of test a print bext result.\n" - "\n", - argv0, argv0) ; - - exit (0) ; -} /* usage_exit */ - -int -main (int argc, char ** argv) -{ double freq ; - - memset (input, 0, sizeof (input)) ; - freq = 0.01 ; - gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ; - - if (argc == 1) - single_run () ; - else if (argc == 3 && strcmp (argv [1], "--best-of") == 0) - { int run_count = atoi (argv [2]) ; - - if (run_count < 1 || run_count > 20) - { printf ("Please be sensible. Run count should be in range (1, 10].\n") ; - exit (1) ; - } ; - - multi_run (run_count) ; - } - else - usage_exit (argv [0]) ; - - puts ( - " Duration is in seconds.\n" - " Throughput is in frames/sec (more is better).\n" - ) ; - - return 0 ; -} /* main */ - diff --git a/lib-src/libsoxr/lsr-tests/reset_test.c b/lib-src/libsoxr/lsr-tests/reset_test.c deleted file mode 100644 index e0d6d7831..000000000 --- a/lib-src/libsoxr/lsr-tests/reset_test.c +++ /dev/null @@ -1,238 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include - -#include - -#include "util.h" - -#define BUFFER_LEN 2048 -#define CB_READ_LEN 256 - -static void process_reset_test (int converter) ; -static void callback_reset_test (int converter) ; - -static float data_one [BUFFER_LEN] ; -static float data_zero [BUFFER_LEN] ; - -int -main (void) -{ - puts ("") ; - - process_reset_test (SRC_ZERO_ORDER_HOLD) ; - process_reset_test (SRC_LINEAR) ; - process_reset_test (SRC_SINC_FASTEST) ; - - callback_reset_test (SRC_ZERO_ORDER_HOLD) ; - callback_reset_test (SRC_LINEAR) ; - callback_reset_test (SRC_SINC_FASTEST) ; - - puts ("") ; - - return 0 ; -} /* main */ - -static void -process_reset_test (int converter) -{ static float output [BUFFER_LEN] ; - - SRC_STATE *src_state ; - SRC_DATA src_data ; - int k, error ; - - printf ("\tprocess_reset_test (%-28s) ....... ", src_get_name (converter)) ; - fflush (stdout) ; - - for (k = 0 ; k < BUFFER_LEN ; k++) - { data_one [k] = 1.0 ; - data_zero [k] = 0.0 ; - } ; - - /* Get a converter. */ - if ((src_state = src_new (converter, 1, &error)) == NULL) - { printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - /* Process a bunch of 1.0 valued samples. */ - src_data.data_in = data_one ; - src_data.data_out = output ; - src_data.input_frames = BUFFER_LEN ; - src_data.output_frames = BUFFER_LEN ; - src_data.src_ratio = 0.9 ; - src_data.end_of_input = 1 ; - - if ((error = src_process (src_state, &src_data)) != 0) - { printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - /* Reset the state of the converter.*/ - src_reset (src_state) ; - - /* Now process some zero data. */ - src_data.data_in = data_zero ; - src_data.data_out = output ; - src_data.input_frames = BUFFER_LEN ; - src_data.output_frames = BUFFER_LEN ; - src_data.src_ratio = 0.9 ; - src_data.end_of_input = 1 ; - - if ((error = src_process (src_state, &src_data)) != 0) - { printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - /* Finally make sure that the output data is zero ie reset was sucessful. */ - for (k = 0 ; k < BUFFER_LEN / 2 ; k++) - if (output [k] != 0.0) - { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n", __LINE__, k, output [k]) ; - exit (1) ; - } ; - - /* Make sure that this function has been exported. */ - src_set_ratio (src_state, 1.0) ; - - /* Delete converter. */ - src_state = src_delete (src_state) ; - - puts ("ok") ; -} /* process_reset_test */ - -/*============================================================================== -*/ - -typedef struct -{ int channels ; - long count, total ; - float *data ; -} TEST_CB_DATA ; - -static long -test_callback_func (void *cb_data, float **data) -{ TEST_CB_DATA *pcb_data ; - - long frames ; - - if ((pcb_data = cb_data) == NULL) - return 0 ; - - if (data == NULL) - return 0 ; - - if (pcb_data->total - pcb_data->count > 0) - frames = pcb_data->total - pcb_data->count ; - else - frames = 0 ; - - *data = pcb_data->data + pcb_data->count ; - pcb_data->count += frames ; - - return frames ; -} /* test_callback_func */ - -static void -callback_reset_test (int converter) -{ static TEST_CB_DATA test_callback_data ; - - static float output [BUFFER_LEN] ; - - SRC_STATE *src_state ; - - double src_ratio = 1.1 ; - long read_count, read_total ; - int k, error ; - - printf ("\tcallback_reset_test (%-28s) ....... ", src_get_name (converter)) ; - fflush (stdout) ; - - for (k = 0 ; k < ARRAY_LEN (data_one) ; k++) - { data_one [k] = 1.0 ; - data_zero [k] = 0.0 ; - } ; - - if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - /* Process a bunch of 1.0 valued samples. */ - test_callback_data.channels = 1 ; - test_callback_data.count = 0 ; - test_callback_data.total = ARRAY_LEN (data_one) ; - test_callback_data.data = data_one ; - - read_total = 0 ; - do - { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; - read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; - read_total += read_count ; - } - while (read_count > 0) ; - - /* Check for errors. */ - if ((error = src_error (src_state)) != 0) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - /* Reset the state of the converter.*/ - src_reset (src_state) ; - - /* Process a bunch of 0.0 valued samples. */ - test_callback_data.channels = 1 ; - test_callback_data.count = 0 ; - test_callback_data.total = ARRAY_LEN (data_zero) ; - test_callback_data.data = data_zero ; - - /* Now process some zero data. */ - read_total = 0 ; - do - { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; - read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; - read_total += read_count ; - } - while (read_count > 0) ; - - /* Check for errors. */ - if ((error = src_error (src_state)) != 0) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - /* Finally make sure that the output data is zero ie reset was sucessful. */ - for (k = 0 ; k < BUFFER_LEN / 2 ; k++) - if (output [k] != 0.0) - { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n\n", __LINE__, k, output [k]) ; - save_oct_float ("output.dat", data_one, ARRAY_LEN (data_one), output, ARRAY_LEN (output)) ; - exit (1) ; - } ; - - /* Make sure that this function has been exported. */ - src_set_ratio (src_state, 1.0) ; - - /* Delete converter. */ - src_state = src_delete (src_state) ; - - puts ("ok") ; -} /* callback_reset_test */ - - diff --git a/lib-src/libsoxr/lsr-tests/simple_test.c b/lib-src/libsoxr/lsr-tests/simple_test.c deleted file mode 100644 index 82ed84c38..000000000 --- a/lib-src/libsoxr/lsr-tests/simple_test.c +++ /dev/null @@ -1,117 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include - -#include - -#include "util.h" - -#define BUFFER_LEN 2048 - -static void simple_test (int converter, double ratio) ; - -int -main (void) -{ static double src_ratios [] = - { 1.0001, 0.099, 0.1, 0.33333333, 0.789, 1.9, 3.1, 9.9 - } ; - - int k ; - - puts ("") ; - - puts (" Zero Order Hold interpolator :") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - simple_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; - - puts (" Linear interpolator :") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - simple_test (SRC_LINEAR, src_ratios [k]) ; - - puts (" Sinc interpolator :") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - simple_test (SRC_SINC_FASTEST, src_ratios [k]) ; - - puts ("") ; - - return 0 ; -} /* main */ - -static void -simple_test (int converter, double src_ratio) -{ static float input [BUFFER_LEN], output [BUFFER_LEN] ; - - SRC_DATA src_data ; - - int input_len, output_len, error, terminate ; - - printf ("\tsimple_test (SRC ratio = %6.4f) ........... ", src_ratio) ; - fflush (stdout) ; - - /* Calculate maximun input and output lengths. */ - if (src_ratio >= 1.0) - { output_len = BUFFER_LEN ; - input_len = (int) floor (BUFFER_LEN / src_ratio) ; - } - else - { input_len = BUFFER_LEN ; - output_len = (int) floor (BUFFER_LEN * src_ratio) ; - } ; - - /* Reduce input_len by 10 so output is longer than necessary. */ - input_len -= 10 ; - - if (output_len > BUFFER_LEN) - { printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ; - exit (1) ; - } ; - - memset (&src_data, 0, sizeof (src_data)) ; - - src_data.data_in = input ; - src_data.input_frames = input_len ; - - src_data.src_ratio = src_ratio ; - - src_data.data_out = output ; - src_data.output_frames = BUFFER_LEN ; - - if ((error = src_simple (&src_data, converter, 1))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; - - if (fabs (src_data.output_frames_gen - src_ratio * input_len) > 2 * terminate) - { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, - src_data.output_frames_gen, (int) floor (src_ratio * input_len)) ; - printf ("\tsrc_ratio : %.4f\n", src_ratio) ; - printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* simple_test */ - diff --git a/lib-src/libsoxr/lsr-tests/sndfile-resample.c b/lib-src/libsoxr/lsr-tests/sndfile-resample.c deleted file mode 100644 index 3fc198209..000000000 --- a/lib-src/libsoxr/lsr-tests/sndfile-resample.c +++ /dev/null @@ -1,332 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "config.h" - -#include -#include -#include -#include -#include - -#if (HAVE_SNDFILE) - -#include -#include - -#define DEFAULT_CONVERTER SRC_SINC_MEDIUM_QUALITY - -#define BUFFER_LEN 4096 /*-(1<<16)-*/ - -static void usage_exit (const char *progname) ; -static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain) ; -static double apply_gain (float * data, long frames, int channels, double max, double gain) ; - -int -main (int argc, char *argv []) -{ SNDFILE *infile, *outfile = NULL ; - SF_INFO sfinfo ; - - sf_count_t count ; - double src_ratio = -1.0, gain = 1.0 ; - int new_sample_rate = -1, k, converter, max_speed = SF_FALSE ; - - if (argc == 2 && strcmp (argv [1], "--version") == 0) - { char buffer [64], *cptr ; - - if ((cptr = strrchr (argv [0], '/')) != NULL) - argv [0] = cptr + 1 ; - if ((cptr = strrchr (argv [0], '\\')) != NULL) - argv [0] = cptr + 1 ; - - sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ; - - printf ("%s (%s,%s)\n", argv [0], src_get_version (), buffer) ; - exit (0) ; - } ; - - if (argc != 5 && argc != 7 && argc != 8) - usage_exit (argv [0]) ; - - /* Set default converter. */ - converter = DEFAULT_CONVERTER ; - - for (k = 1 ; k < argc - 2 ; k++) - { if (strcmp (argv [k], "--max-speed") == 0) - max_speed = SF_TRUE ; - else if (strcmp (argv [k], "-to") == 0) - { k ++ ; - new_sample_rate = atoi (argv [k]) ; - } - else if (strcmp (argv [k], "-by") == 0) - { k ++ ; - src_ratio = atof (argv [k]) ; - } - else if (strcmp (argv [k], "-c") == 0) - { k ++ ; - converter = atoi (argv [k]) ; - } - else - usage_exit (argv [0]) ; - } ; - - if (new_sample_rate <= 0 && src_ratio <= 0.0) - usage_exit (argv [0]) ; - - if (src_get_name (converter) == NULL) - { printf ("Error : bad converter number.\n") ; - usage_exit (argv [0]) ; - } ; - - if (strcmp (argv [argc - 2], argv [argc - 1]) == 0) - { printf ("Error : input and output file names are the same.\n") ; - exit (1) ; - } ; - - if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL) - { printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ; - exit (1) ; - } ; - - printf ("Input File : %s\n", argv [argc - 2]) ; - printf ("Sample Rate : %d\n", sfinfo.samplerate) ; - printf ("Input Frames : %ld\n\n", (long) sfinfo.frames) ; - - if (new_sample_rate > 0) - { src_ratio = (1.0 * new_sample_rate) / sfinfo.samplerate ; - sfinfo.samplerate = new_sample_rate ; - } - else if (src_is_valid_ratio (src_ratio)) - sfinfo.samplerate = (int) floor (sfinfo.samplerate * src_ratio) ; - else - { printf ("Not able to determine new sample rate. Exiting.\n") ; - sf_close (infile) ; - exit (1) ; - } ; - - if (fabs (src_ratio - 1.0) < 1e-20) - { printf ("Target samplerate and input samplerate are the same. Exiting.\n") ; - sf_close (infile) ; - exit (0) ; - } ; - - printf ("SRC Ratio : %f\n", src_ratio) ; - printf ("Converter : %s\n\n", src_get_name (converter)) ; - - if (src_is_valid_ratio (src_ratio) == 0) - { printf ("Error : Sample rate change out of valid range.\n") ; - sf_close (infile) ; - exit (1) ; - } ; - - /* Delete the output file length to zero if already exists. */ - remove (argv [argc - 1]) ; - - printf ("Output file : %s\n", argv [argc - 1]) ; - printf ("Sample Rate : %d\n", sfinfo.samplerate) ; - - do - { sf_close (outfile) ; - - if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) - { printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ; - sf_close (infile) ; - exit (1) ; - } ; - - if (max_speed) - { /* This is mainly for the comparison program tests/src-evaluate.c */ - sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; - } - else - { /* Update the file header after every write. */ - sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ; - } ; - - sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ; - - count = sample_rate_convert (infile, outfile, converter, src_ratio, sfinfo.channels, &gain) ; - } - while (count < 0) ; - - printf ("Output Frames : %ld\n\n", (long) count) ; - - sf_close (infile) ; - sf_close (outfile) ; - - return 0 ; -} /* main */ - -/*============================================================================== -*/ - -static sf_count_t -sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain) -{ static float input [BUFFER_LEN] ; - static float output [BUFFER_LEN] ; - - SRC_STATE *src_state ; - SRC_DATA src_data ; - int error ; - double max = 0.0 ; - sf_count_t output_count = 0 ; - - sf_seek (infile, 0, SEEK_SET) ; - sf_seek (outfile, 0, SEEK_SET) ; - - /* Initialize the sample rate converter. */ - if ((src_state = src_new (converter, channels, &error)) == NULL) - { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ; - exit (1) ; - } ; - - src_data.end_of_input = 0 ; /* Set this later. */ - - /* Start with zero to force load in while loop. */ - src_data.input_frames = 0 ; - src_data.data_in = input ; - - src_data.src_ratio = src_ratio ; - - src_data.data_out = output ; - src_data.output_frames = BUFFER_LEN /channels ; - - while (1) - { - /* If the input buffer is empty, refill it. */ - if (src_data.input_frames == 0) - { src_data.input_frames = sf_readf_float (infile, input, BUFFER_LEN / channels) ; - src_data.data_in = input ; - - /* The last read will not be a full buffer, so snd_of_input. */ - if (src_data.input_frames < BUFFER_LEN / channels) - src_data.end_of_input = SF_TRUE ; - } ; - - if ((error = src_process (src_state, &src_data))) - { printf ("\nError : %s\n", src_strerror (error)) ; - exit (1) ; - } ; - - /* Terminate if done. */ - if (src_data.end_of_input && src_data.output_frames_gen == 0) - break ; - - max = apply_gain (src_data.data_out, src_data.output_frames_gen, channels, max, *gain) ; - - /* Write output. */ - sf_writef_float (outfile, output, src_data.output_frames_gen) ; - output_count += src_data.output_frames_gen ; - - src_data.data_in += src_data.input_frames_used * channels ; - src_data.input_frames -= src_data.input_frames_used ; - } ; - - src_state = src_delete (src_state) ; - - if (max > 1.0) - { *gain = 1.0 / max ; - printf ("\nOutput has clipped. Restarting conversion to prevent clipping.\n\n") ; - return -1 ; - } ; - - return output_count ; -} /* sample_rate_convert */ - -static double -apply_gain (float * data, long frames, int channels, double max, double gain) -{ - long k ; - - for (k = 0 ; k < frames * channels ; k++) - { data [k] *= gain ; - - if (fabs (data [k]) > max) - max = fabs (data [k]) ; - } ; - - return max ; -} /* apply_gain */ - -static void -usage_exit (const char *progname) -{ char lsf_ver [128] ; - const char *cptr ; - int k ; - - if ((cptr = strrchr (progname, '/')) != NULL) - progname = cptr + 1 ; - - if ((cptr = strrchr (progname, '\\')) != NULL) - progname = cptr + 1 ; - - - sf_command (NULL, SFC_GET_LIB_VERSION, lsf_ver, sizeof (lsf_ver)) ; - - printf ("\n" - " A Sample Rate Converter using libsndfile for file I/O and Secret \n" - " Rabbit Code (aka libsamplerate) for performing the conversion.\n" - " It works on any file format supported by libsndfile with any \n" - " number of channels (limited only by host memory).\n" - "\n" - " %s\n" - " %s\n" - "\n" - " Usage : \n" - " %s -to [-c ] \n" - " %s -by [-c ] \n" - "\n", src_get_version (), lsf_ver, progname, progname) ; - - puts ( - " The optional -c argument allows the converter type to be chosen from\n" - " the following list :" - "\n" - ) ; - - for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++) - printf (" %d : %s%s\n", k, cptr, k == DEFAULT_CONVERTER ? " (default)" : "") ; - - puts ("") ; - - exit (1) ; -} /* usage_exit */ - -/*============================================================================== -*/ - -#else /* (HAVE_SNFILE == 0) */ - -/* Alternative main function when libsndfile is not available. */ - -int -main (void) -{ puts ( - "\n" - "****************************************************************\n" - " This example program was compiled without libsndfile \n" - " (http://www.mega-nerd.com/libsndfile/).\n" - " It is therefore completely broken and non-functional.\n" - "****************************************************************\n" - "\n" - ) ; - - return 0 ; -} /* main */ - -#endif - diff --git a/lib-src/libsoxr/lsr-tests/snr_bw_test.c b/lib-src/libsoxr/lsr-tests/snr_bw_test.c deleted file mode 100644 index 9ecd213df..000000000 --- a/lib-src/libsoxr/lsr-tests/snr_bw_test.c +++ /dev/null @@ -1,401 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "config.h" - -#include -#include -#include -#include -#include - -#if (HAVE_FFTW3) - -#include - -#include "util.h" - -#define BUFFER_LEN 50000 -#define MAX_FREQS 4 -#define MAX_RATIOS 6 -#define MAX_SPEC_LEN (1<<15) - -#ifndef M_PI -#define M_PI 3.14159265358979323846264338 -#endif - -enum -{ BOOLEAN_FALSE = 0, - BOOLEAN_TRUE = 1 -} ; - -typedef struct -{ int freq_count ; - double freqs [MAX_FREQS] ; - - double src_ratio ; - int pass_band_peaks ; - - double snr ; - double peak_value ; -} SINGLE_TEST ; - -typedef struct -{ int converter ; - int tests ; - int do_bandwidth_test ; - SINGLE_TEST test_data [10] ; -} CONVERTER_TEST ; - -static double snr_test (SINGLE_TEST *snr_test_data, int number, int converter, int verbose) ; -static double find_peak (float *output, int output_len) ; -static double bandwidth_test (int converter, int verbose) ; - -int -main (int argc, char *argv []) -{ CONVERTER_TEST snr_test_data [] = - { - { SRC_ZERO_ORDER_HOLD, - 8, - BOOLEAN_FALSE, - { { 1, { 0.01111111111 }, 3.0, 1, 28.0, 1.0 }, - { 1, { 0.01111111111 }, 0.6, 1, 36.0, 1.0 }, - { 1, { 0.01111111111 }, 0.3, 1, 36.0, 1.0 }, - { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 }, - { 1, { 0.01111111111 }, 1.001, 1, 38.0, 1.0 }, - { 2, { 0.011111, 0.324 }, 1.9999, 2, 14.0, .96 }, - { 2, { 0.012345, 0.457 }, 0.456789, 1, 12.0, .96 }, - { 1, { 0.3511111111 }, 1.33, 1, 10.0, 1.0 } - } - }, - - { SRC_LINEAR, - 8, - BOOLEAN_FALSE, - { { 1, { 0.01111111111 }, 3.0, 1, 73.0, 1.0 }, - { 1, { 0.01111111111 }, 0.6, 1, 73.0, 1.0 }, - { 1, { 0.01111111111 }, 0.3, 1, 73.0, 1.0 }, - { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 }, - { 1, { 0.01111111111 }, 1.001, 1, 77.0, 1.0 }, - { 2, { 0.011111, 0.324 }, 1.9999, 2, 16.0, 0.96 }, - { 2, { 0.012345, 0.457 }, 0.456789, 1, 26.0, 0.96 }, - { 1, { 0.3511111111 }, 1.33, 1, 14.4, 0.99 } - } - }, - - { SRC_SINC_FASTEST, - 9, - BOOLEAN_TRUE, - { { 1, { 0.01111111111 }, 3.0, 1, 100.0, 1.0 }, - { 1, { 0.01111111111 }, 0.6, 1, 99.0, 1.0 }, - { 1, { 0.01111111111 }, 0.3, 1, 100.0, 1.0 }, - { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 }, - { 1, { 0.01111111111 }, 1.001, 1, 100.0, 1.0 }, - { 2, { 0.011111, 0.324 }, 1.9999, 2, 97.0, 1.0 }, - { 2, { 0.012345, 0.457 }, 0.456789, 1, 100.0, 0.5 }, - { 2, { 0.011111, 0.45 }, 0.6, 1, 97.0, 0.5 }, - { 1, { 0.3511111111 }, 1.33, 1, 97.0, 1.0 } - } - }, - - { SRC_SINC_MEDIUM_QUALITY, - 9, - BOOLEAN_TRUE, - { { 1, { 0.01111111111 }, 3.0, 1, 130.0, 1.0 }, - { 1, { 0.01111111111 }, 0.6, 1, 132.0, 1.0 }, - { 1, { 0.01111111111 }, 0.3, 1, 138.0, 1.0 }, - { 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 }, - { 1, { 0.01111111111 }, 1.001, 1, 134.0, 1.0 }, - { 2, { 0.011111, 0.324 }, 1.9999, 2, 127.0, 1.0 }, - { 2, { 0.012345, 0.457 }, 0.456789, 1, 124.0, 0.5 }, - { 2, { 0.011111, 0.45 }, 0.6, 1, 126.0, 0.5 }, - { 1, { 0.43111111111 }, 1.33, 1, 121.0, 1.0 } - } - }, - - { SRC_SINC_BEST_QUALITY, - 9, - BOOLEAN_TRUE, - { { 1, { 0.01111111111 }, 3.0, 1, 147.0, 1.0 }, - { 1, { 0.01111111111 }, 0.6, 1, 147.0, 1.0 }, - { 1, { 0.01111111111 }, 0.3, 1, 147.0, 1.0 }, - { 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 }, - { 1, { 0.01111111111 }, 1.001, 1, 147.0, 1.0 }, - { 2, { 0.011111, 0.324 }, 1.9999, 2, 147.0, 1.0 }, - { 2, { 0.012345, 0.457 }, 0.456789, 1, 148.0, 0.5 }, - { 2, { 0.011111, 0.45 }, 0.6, 1, 149.0, 0.5 }, - { 1, { 0.43111111111 }, 1.33, 1, 145.0, 1.0 } - } - }, - } ; /* snr_test_data */ - - double best_snr, snr, freq3dB ; - int j, k, converter, verbose = 0 ; - - if (argc == 2 && strcmp (argv [1], "--verbose") == 0) - verbose = 1 ; - - puts ("") ; - - for (j = 0 ; j < ARRAY_LEN (snr_test_data) ; j++) - { best_snr = 5000.0 ; - - converter = snr_test_data [j].converter ; - - printf (" Converter %d : %s\n", converter, src_get_name (converter)) ; - printf (" %s\n", src_get_description (converter)) ; - - for (k = 0 ; k < snr_test_data [j].tests ; k++) - { snr = snr_test (&(snr_test_data [j].test_data [k]), k, converter, verbose) ; - if (best_snr > snr) - best_snr = snr ; - } ; - - printf (" Worst case Signal-to-Noise Ratio : %.2f dB.\n", best_snr) ; - - if (snr_test_data [j].do_bandwidth_test == BOOLEAN_FALSE) - { puts (" Bandwith test not performed on this converter.\n") ; - continue ; - } - - freq3dB = bandwidth_test (converter, verbose) ; - - printf (" Measured -3dB rolloff point : %5.2f %%.\n\n", freq3dB) ; - } ; - - return 0 ; -} /* main */ - -/*============================================================================== -*/ - -static double -snr_test (SINGLE_TEST *test_data, int number, int converter, int verbose) -{ static float data [BUFFER_LEN + 1] ; - static float output [MAX_SPEC_LEN] ; - - SRC_STATE *src_state ; - SRC_DATA src_data ; - - double output_peak, snr ; - int k, output_len, input_len, error ; - - if (verbose != 0) - { printf ("\tSignal-to-Noise Ratio Test %d.\n" - "\t=====================================\n", number) ; - printf ("\tFrequencies : [ ") ; - for (k = 0 ; k < test_data->freq_count ; k++) - printf ("%6.4f ", test_data->freqs [k]) ; - - printf ("]\n\tSRC Ratio : %8.4f\n", test_data->src_ratio) ; - } - else - { printf ("\tSignal-to-Noise Ratio Test %d : ", number) ; - fflush (stdout) ; - } ; - - /* Set up the output array. */ - if (test_data->src_ratio >= 1.0) - { output_len = MAX_SPEC_LEN ; - input_len = (int) ceil (MAX_SPEC_LEN / test_data->src_ratio) ; - if (input_len > BUFFER_LEN) - input_len = BUFFER_LEN ; - } - else - { input_len = BUFFER_LEN ; - output_len = (int) ceil (BUFFER_LEN * test_data->src_ratio) ; - output_len &= ((-1) << 4) ; - if (output_len > MAX_SPEC_LEN) - output_len = MAX_SPEC_LEN ; - input_len = (int) ceil (output_len / test_data->src_ratio) ; - } ; - - memset (output, 0, sizeof (output)) ; - - /* Generate input data array. */ - gen_windowed_sines (test_data->freq_count, test_data->freqs, 1.0, data, input_len) ; - - /* Perform sample rate conversion. */ - if ((src_state = src_new (converter, 1, &error)) == NULL) - { printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_data.end_of_input = 1 ; /* Only one buffer worth of input. */ - - src_data.data_in = data ; - src_data.input_frames = input_len ; - - src_data.src_ratio = test_data->src_ratio ; - - src_data.data_out = output ; - src_data.output_frames = output_len ; - - if ((error = src_process (src_state, &src_data))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_state = src_delete (src_state) ; - - if (verbose != 0) - printf ("\tOutput Len : %ld\n", src_data.output_frames_gen) ; - - if (abs (src_data.output_frames_gen - output_len) > 4) - { printf ("\n\nLine %d : output data length should be %d.\n\n", __LINE__, output_len) ; - exit (1) ; - } ; - - /* Check output peak. */ - output_peak = find_peak (output, src_data.output_frames_gen) ; - - if (verbose != 0) - printf ("\tOutput Peak : %6.4f\n", output_peak) ; - - if (fabs (output_peak - test_data->peak_value) > 0.01) - { printf ("\n\nLine %d : output peak (%6.4f) should be %6.4f\n\n", __LINE__, output_peak, test_data->peak_value) ; - save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, output_len) ; - exit (1) ; - } ; - - /* Calculate signal-to-noise ratio. */ - snr = calculate_snr (output, src_data.output_frames_gen, test_data->pass_band_peaks) ; - - if (snr < 0.0) - { /* An error occurred. */ - save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, src_data.output_frames_gen) ; - exit (1) ; - } ; - - if (verbose != 0) - printf ("\tSNR Ratio : %.2f dB\n", snr) ; - - if (snr < test_data->snr) - { printf ("\n\nLine %d : SNR (%5.2f) should be > %6.2f dB\n\n", __LINE__, snr, test_data->snr) ; - exit (1) ; - } ; - - if (verbose != 0) - puts ("\t-------------------------------------\n\tPass\n") ; - else - puts ("Pass") ; - - return snr ; -} /* snr_test */ - -static double -find_peak (float *data, int len) -{ double peak = 0.0 ; - int k = 0 ; - - for (k = 0 ; k < len ; k++) - if (fabs (data [k]) > peak) - peak = fabs (data [k]) ; - - return peak ; -} /* find_peak */ - - -static double -find_attenuation (double freq, int converter, int verbose) -{ static float input [BUFFER_LEN] ; - static float output [2 * BUFFER_LEN] ; - - SRC_DATA src_data ; - double output_peak ; - int error ; - - gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ; - - src_data.end_of_input = 1 ; /* Only one buffer worth of input. */ - - src_data.data_in = input ; - src_data.input_frames = BUFFER_LEN ; - - src_data.src_ratio = 1.999 ; - - src_data.data_out = output ; - src_data.output_frames = ARRAY_LEN (output) ; - - if ((error = src_simple (&src_data, converter, 1))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - output_peak = find_peak (output, ARRAY_LEN (output)) ; - - if (verbose) - printf ("\tFreq : %6f InPeak : %6f OutPeak : %6f Atten : %6.2f dB\n", - freq, 1.0, output_peak, 20.0 * log10 (1.0 / output_peak)) ; - - return 20.0 * log10 (1.0 / output_peak) ; -} /* find_attenuation */ - -static double -bandwidth_test (int converter, int verbose) -{ double f1, f2, a1, a2 ; - double freq, atten ; - - f1 = 0.35 ; - a1 = find_attenuation (f1, converter, verbose) ; - - f2 = 0.495 ; - a2 = find_attenuation (f2, converter, verbose) ; - - if (a1 > 3.0 || a2 < 3.0) - { printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ; - exit (1) ; - } ; - - while (a2 - a1 > 1.0) - { freq = f1 + 0.5 * (f2 - f1) ; - atten = find_attenuation (freq, converter, verbose) ; - - if (atten < 3.0) - { f1 = freq ; - a1 = atten ; - } - else - { f2 = freq ; - a2 = atten ; - } ; - } ; - - freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ; - - return 200.0 * freq ; -} /* bandwidth_test */ - -#else /* (HAVE_FFTW3) == 0 */ - -/* Alternative main function when librfftw is not available. */ - -int -main (void) -{ puts ("\n" - "****************************************************************\n" - " This test cannot be run without FFTW (http://www.fftw.org/).\n" - " Both the real and the complex versions of the library are\n" - " required.") ; - puts ("****************************************************************\n") ; - - return 0 ; -} /* main */ - -#endif - diff --git a/lib-src/libsoxr/lsr-tests/termination_test.c b/lib-src/libsoxr/lsr-tests/termination_test.c deleted file mode 100644 index 40976784d..000000000 --- a/lib-src/libsoxr/lsr-tests/termination_test.c +++ /dev/null @@ -1,339 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include - -#include - -#include "util.h" - -#define SHORT_BUFFER_LEN 2048 -#define LONG_BUFFER_LEN ((1 << 16) - 20) - -static void simple_test (int converter) ; -static void stream_test (int converter, double ratio) ; -static void init_term_test (int converter, double ratio) ; - -static int next_block_length (int reset) ; - -int -main (void) -{ static double src_ratios [] = - { 0.999900, 1.000100, 0.789012, 1.200000, 0.333333, 3.100000, - 0.125000, 8.000000, 0.099900, 9.990000, 0.100000, 10.00000 - } ; - - int k ; - - puts ("\n Zero Order Hold interpolator:") ; - - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - init_term_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; - puts ("") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; - - - puts ("\n Linear interpolator:") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - init_term_test (SRC_LINEAR, src_ratios [k]) ; - puts ("") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - stream_test (SRC_LINEAR, src_ratios [k]) ; - - - puts ("\n Sinc interpolator:") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - init_term_test (SRC_SINC_FASTEST, src_ratios [k]) ; - puts ("") ; - for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) - stream_test (SRC_SINC_FASTEST, src_ratios [k]) ; - - puts ("") ; - - simple_test (SRC_SINC_FASTEST) ; - - return 0 ; -} /* main */ - -static void -simple_test (int converter) -{ - int ilen = 199030, olen = 1000, error ; - - { - float in [ilen] ; - float out [olen] ; - double ratio = (1.0 * olen) / ilen ; - SRC_DATA src_data = - { in, out, - ilen, olen, - 0, 0, 0, - ratio - } ; - - error = src_simple (&src_data, converter, 1) ; - if (error) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - } ; - - return ; -} /* simple_test */ - -static void -init_term_test (int converter, double src_ratio) -{ static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ; - - SRC_DATA src_data ; - - int k, input_len, output_len, error, terminate ; - - printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ; - fflush (stdout) ; - - /* Calculate maximun input and output lengths. */ - if (src_ratio >= 1.0) - { output_len = SHORT_BUFFER_LEN ; - input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ; - } - else - { input_len = SHORT_BUFFER_LEN ; - output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ; - } ; - - /* Reduce input_len by 10 so output is longer than necessary. */ - input_len -= 10 ; - - for (k = 0 ; k < ARRAY_LEN (input) ; k++) - input [k] = 1.0 ; - - if (output_len > SHORT_BUFFER_LEN) - { printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ; - exit (1) ; - } ; - - src_data.data_in = input ; - src_data.input_frames = input_len ; - - src_data.src_ratio = src_ratio ; - - src_data.data_out = output ; - src_data.output_frames = SHORT_BUFFER_LEN ; - - if ((error = src_simple (&src_data, converter, 1))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ; - - if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate) - { printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ; - printf ("\tterminate : %d\n", terminate) ; - printf ("\tsrc_ratio : %.4f\n", src_ratio) ; - printf ("\tinput_len : %d\n" - "\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ; - printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ; - exit (1) ; - } ; - - if (abs (src_data.input_frames_used - input_len) > 1) - { printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n", - __LINE__, input_len, src_data.input_frames_used) ; - printf ("\tsrc_ratio : %.4f\n", src_ratio) ; - printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ; - exit (1) ; - } ; - - if (fabs (output [0]) < 0.1) - { printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ; - printf ("\toutput [0] == %f\n\n", output [0]) ; - exit (1) ; - } - - puts ("ok") ; - - return ; -} /* init_term_test */ - -static void -stream_test (int converter, double src_ratio) -{ static float input [LONG_BUFFER_LEN], output [LONG_BUFFER_LEN] ; - - SRC_STATE *src_state ; - SRC_DATA src_data ; - - int input_len, output_len, current_in, current_out ; - int k, error, terminate ; - - printf ("\tstream_test (SRC ratio = %7.4f) .......... ", src_ratio) ; - fflush (stdout) ; - -/* Erik */ -for (k = 0 ; k < LONG_BUFFER_LEN ; k++) input [k] = k * 1.0 ; - - /* Calculate maximun input and output lengths. */ - if (src_ratio >= 1.0) - { output_len = LONG_BUFFER_LEN ; - input_len = (int) floor (LONG_BUFFER_LEN / src_ratio) ; - } - else - { input_len = LONG_BUFFER_LEN ; - output_len = (int) floor (LONG_BUFFER_LEN * src_ratio) ; - } ; - - /* Reduce input_len by 10 so output is longer than necessary. */ - input_len -= 20 ; - - if (output_len > LONG_BUFFER_LEN) - { printf ("\n\nLine %d : output_len > LONG_BUFFER_LEN\n\n", __LINE__) ; - exit (1) ; - } ; - - current_in = current_out = 0 ; - - /* Perform sample rate conversion. */ - if ((src_state = src_new (converter, 1, &error)) == NULL) - { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_data.end_of_input = 0 ; /* Set this later. */ - - src_data.data_in = input ; - - src_data.src_ratio = src_ratio ; - - src_data.data_out = output ; - src_data.output_frames = ARRAY_LEN (output) / 10 ; - - terminate = 1 + (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; - - while (1) - { - src_data.input_frames = next_block_length (0) ; - src_data.input_frames = MIN (src_data.input_frames, input_len - current_in) ; - - src_data.output_frames = ARRAY_LEN (output) - current_out ; - /*-Erik MIN (src_data.output_frames, output_len - current_out) ;-*/ - - src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ; - - if ((error = src_process (src_state, &src_data))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; - printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; - exit (1) ; - } ; - - if (src_data.end_of_input && src_data.output_frames_gen == 0) - break ; - - if (src_data.input_frames_used > src_data.input_frames) - { printf ("\n\nLine %d : input_frames_used > input_frames\n\n", __LINE__) ; - printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; - printf (" src_data.input_frames_used : %ld\n", src_data.input_frames_used) ; - printf (" src_data.output_frames : %ld\n", src_data.output_frames) ; - printf (" src_data.output_frames_gen : %ld\n\n", src_data.output_frames_gen) ; - exit (1) ; - } ; - - if (src_data.input_frames_used < 0) - { printf ("\n\nLine %d : input_frames_used (%ld) < 0\n\n", __LINE__, src_data.input_frames_used) ; - exit (1) ; - } ; - - if (src_data.output_frames_gen < 0) - { printf ("\n\nLine %d : output_frames_gen (%ld) < 0\n\n", __LINE__, src_data.output_frames_gen) ; - exit (1) ; - } ; - - current_in += src_data.input_frames_used ; - current_out += src_data.output_frames_gen ; - - if (current_in > input_len + terminate) - { printf ("\n\nLine %d : current_in (%d) > input_len (%d + %d)\n\n", __LINE__, current_in, input_len, terminate) ; - exit (1) ; - } ; - - if (current_out > output_len) - { printf ("\n\nLine %d : current_out (%d) > output_len (%d)\n\n", __LINE__, current_out, output_len) ; - exit (1) ; - } ; - - if (src_data.input_frames_used > input_len) - { printf ("\n\nLine %d : input_frames_used (%ld) > %d\n\n", __LINE__, src_data.input_frames_used, input_len) ; - exit (1) ; - } ; - - if (src_data.output_frames_gen > output_len) - { printf ("\n\nLine %d : output_frames_gen (%ld) > %d\n\n", __LINE__, src_data.output_frames_gen, output_len) ; - exit (1) ; - } ; - - if (src_data.data_in == NULL && src_data.output_frames_gen == 0) - break ; - - - src_data.data_in += src_data.input_frames_used ; - src_data.data_out += src_data.output_frames_gen ; - } ; - - src_state = src_delete (src_state) ; - - if (fabs (current_out - src_ratio * input_len) > terminate) - { printf ("\n\nLine %d : bad output data length %d should be %2.1f +/- %d.\n", __LINE__, - current_out, src_ratio * input_len, terminate) ; - printf ("\tsrc_ratio : %.4f\n", src_ratio) ; - printf ("\tinput_len : %d\n\tinput_used : %d\n", input_len, current_in) ; - printf ("\toutput_len : %d\n\toutput_gen : %d\n\n", output_len, current_out) ; - exit (1) ; - } ; - - if (current_in != input_len) - { printf ("\n\nLine %d : unused input.\n", __LINE__) ; - printf ("\tinput_len : %d\n", input_len) ; - printf ("\tinput_frames_used : %d\n\n", current_in) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* stream_test */ - -static int -next_block_length (int reset) -{ static int block_lengths [] = /* Should be an odd length. */ - { /*-2, 500, 5, 400, 10, 300, 20, 200, 50, 100, 70 -*/ - 5, 400, 10, 300, 20, 200, 50, 100, 70 - } ; - static int block_len_index = 0 ; - - if (reset) - block_len_index = 0 ; - else - block_len_index = (block_len_index + 1) % ARRAY_LEN (block_lengths) ; - - return block_lengths [block_len_index] ; -} /* next_block_length */ - diff --git a/lib-src/libsoxr/lsr-tests/throughput_test.c b/lib-src/libsoxr/lsr-tests/throughput_test.c deleted file mode 100644 index 0c8b7d0b3..000000000 --- a/lib-src/libsoxr/lsr-tests/throughput_test.c +++ /dev/null @@ -1,212 +0,0 @@ -/* -** Copyright (C) 2004-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include - -#include - -#include "config.h" - -#include "util.h" -#include "float_cast.h" - -#define BUFFER_LEN (1<<16) - -static float input [BUFFER_LEN] ; -static float output [BUFFER_LEN] ; - -static long -throughput_test (int converter, long best_throughput) -{ SRC_DATA src_data ; - clock_t start_time, clock_time ; - double duration ; - long total_frames = 0, throughput ; - int error ; - - printf (" %-30s ", src_get_name (converter)) ; - fflush (stdout) ; - - src_data.data_in = input ; - src_data.input_frames = ARRAY_LEN (input) ; - - src_data.data_out = output ; - src_data.output_frames = ARRAY_LEN (output) ; - - src_data.src_ratio = 0.99 ; - - sleep (2) ; - - start_time = clock () ; - - do - { - if ((error = src_simple (&src_data, converter, 1)) != 0) - { puts (src_strerror (error)) ; - exit (1) ; - } ; - - total_frames += src_data.output_frames_gen ; - - clock_time = clock () - start_time ; - duration = (1.0 * clock_time) / CLOCKS_PER_SEC ; - } - while (duration < 3.0) ; - - if (src_data.input_frames_used != ARRAY_LEN (input)) - { printf ("\n\nLine %d : input frames used %ld should be %d\n", __LINE__, src_data.input_frames_used, ARRAY_LEN (input)) ; - exit (1) ; - } ; - - if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2) - { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; - printf (" input len : %d\n", ARRAY_LEN (input)) ; - printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen, - floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ; - exit (1) ; - } ; - - throughput = lrint (floor (total_frames / duration)) ; - - if (best_throughput == 0) - { best_throughput = MAX (throughput, best_throughput) ; - printf ("%5.2f %10ld\n", duration, throughput) ; - } - else - { best_throughput = MAX (throughput, best_throughput) ; - printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ; - } - - - return best_throughput ; -} /* throughput_test */ - -static void -single_run (void) -{ - - printf ("\n CPU name : %s\n", get_cpu_name ()) ; - - puts ( - "\n" - " Converter Duration Throughput\n" - " -----------------------------------------------------------" - ) ; - - throughput_test (SRC_ZERO_ORDER_HOLD, 0) ; - throughput_test (SRC_LINEAR, 0) ; - throughput_test (SRC_SINC_FASTEST, 0) ; - throughput_test (SRC_SINC_MEDIUM_QUALITY, 0) ; - throughput_test (SRC_SINC_BEST_QUALITY, 0) ; - - puts ("") ; - return ; -} /* single_run */ - -static void -multi_run (int run_count) -{ long zero_order_hold = 0, linear = 0 ; - long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ; - int k ; - - puts ( - "\n" - " Converter Duration Throughput Best Throughput\n" - " --------------------------------------------------------------------------------" - ) ; - - for (k = 0 ; k < run_count ; k++) - { zero_order_hold = throughput_test (SRC_ZERO_ORDER_HOLD, zero_order_hold) ; - linear = throughput_test (SRC_LINEAR, linear) ; - sinc_fastest = throughput_test (SRC_SINC_FASTEST, sinc_fastest) ; - sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, sinc_medium) ; - sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, sinc_best) ; - - puts ("") ; - - /* Let the CPU cool down. We might be running on a laptop. */ - sleep (10) ; - } ; - - printf ("\n CPU name : %s\n", get_cpu_name ()) ; - - puts ( - "\n" - " Converter Best Throughput\n" - " ------------------------------------------------" - ) ; - printf (" %-30s %10ld\n", src_get_name (SRC_ZERO_ORDER_HOLD), zero_order_hold) ; - printf (" %-30s %10ld\n", src_get_name (SRC_LINEAR), linear) ; - printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ; - printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ; - printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ; - - puts ("") ; -} /* multi_run */ - -static void -usage_exit (const char * argv0) -{ const char * cptr ; - - if ((cptr = strrchr (argv0, '/')) != NULL) - argv0 = cptr ; - - printf ( - "Usage :\n" - " %s - Single run of the throughput test.\n" - " %s --best-of N - Do N runs of test a print bext result.\n" - "\n", - argv0, argv0) ; - - exit (0) ; -} /* usage_exit */ - -int -main (int argc, char ** argv) -{ double freq ; - - memset (input, 0, sizeof (input)) ; - freq = 0.01 ; - gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ; - - if (argc == 1) - single_run () ; - else if (argc == 3 && strcmp (argv [1], "--best-of") == 0) - { int run_count = atoi (argv [2]) ; - - if (run_count < 1 || run_count > 20) - { printf ("Please be sensible. Run count should be in range (1, 10].\n") ; - exit (1) ; - } ; - - multi_run (run_count) ; - } - else - usage_exit (argv [0]) ; - - puts ( - " Duration is in seconds.\n" - " Throughput is in samples/sec (more is better).\n" - ) ; - - return 0 ; -} /* main */ - diff --git a/lib-src/libsoxr/lsr-tests/util.c b/lib-src/libsoxr/lsr-tests/util.c deleted file mode 100644 index d5ab43905..000000000 --- a/lib-src/libsoxr/lsr-tests/util.c +++ /dev/null @@ -1,230 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include - -#include "util.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846264338 -#endif - -void -gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len) -{ int k, freq ; - double amplitude, phase ; - - amplitude = max / freq_count ; - - for (k = 0 ; k < output_len ; k++) - output [k] = 0.0 ; - - for (freq = 0 ; freq < freq_count ; freq++) - { phase = 0.9 * M_PI / freq_count ; - - if (freqs [freq] <= 0.0 || freqs [freq] >= 0.5) - { printf ("\n%s : Error : freq [%d] == %g is out of range. Should be < 0.5.\n", __FILE__, freq, freqs [freq]) ; - exit (1) ; - } ; - - for (k = 0 ; k < output_len ; k++) - output [k] += amplitude * sin (freqs [freq] * (2 * k) * M_PI + phase) ; - } ; - - /* Apply Hanning Window. */ - for (k = 0 ; k < output_len ; k++) - output [k] *= 0.5 - 0.5 * cos ((2 * k) * M_PI / (output_len - 1)) ; - - /* data [k] *= 0.3635819 - 0.4891775 * cos ((2 * k) * M_PI / (output_len - 1)) - + 0.1365995 * cos ((4 * k) * M_PI / (output_len - 1)) - - 0.0106411 * cos ((6 * k) * M_PI / (output_len - 1)) ; - */ - - return ; -} /* gen_windowed_sines */ - -void -save_oct_float (char *filename, float *input, int in_len, float *output, int out_len) -{ FILE *file ; - int k ; - - printf ("Dumping input and output data to file : %s.\n\n", filename) ; - - if (! (file = fopen (filename, "w"))) - return ; - - fprintf (file, "# Not created by Octave\n") ; - - fprintf (file, "# name: input\n") ; - fprintf (file, "# type: matrix\n") ; - fprintf (file, "# rows: %d\n", in_len) ; - fprintf (file, "# columns: 1\n") ; - - for (k = 0 ; k < in_len ; k++) - fprintf (file, "% g\n", input [k]) ; - - fprintf (file, "# name: output\n") ; - fprintf (file, "# type: matrix\n") ; - fprintf (file, "# rows: %d\n", out_len) ; - fprintf (file, "# columns: 1\n") ; - - for (k = 0 ; k < out_len ; k++) - fprintf (file, "% g\n", output [k]) ; - - fclose (file) ; - return ; -} /* save_oct_float */ - -void -save_oct_double (char *filename, double *input, int in_len, double *output, int out_len) -{ FILE *file ; - int k ; - - printf ("Dumping input and output data to file : %s.\n\n", filename) ; - - if (! (file = fopen (filename, "w"))) - return ; - - fprintf (file, "# Not created by Octave\n") ; - - fprintf (file, "# name: input\n") ; - fprintf (file, "# type: matrix\n") ; - fprintf (file, "# rows: %d\n", in_len) ; - fprintf (file, "# columns: 1\n") ; - - for (k = 0 ; k < in_len ; k++) - fprintf (file, "% g\n", input [k]) ; - - fprintf (file, "# name: output\n") ; - fprintf (file, "# type: matrix\n") ; - fprintf (file, "# rows: %d\n", out_len) ; - fprintf (file, "# columns: 1\n") ; - - for (k = 0 ; k < out_len ; k++) - fprintf (file, "% g\n", output [k]) ; - - fclose (file) ; - return ; -} /* save_oct_double */ - -void -interleave_data (const float *in, float *out, int frames, int channels) -{ int fr, ch ; - - for (fr = 0 ; fr < frames ; fr++) - for (ch = 0 ; ch < channels ; ch++) - out [ch + channels * fr] = in [fr + frames * ch] ; - - return ; -} /* interleave_data */ - -void -deinterleave_data (const float *in, float *out, int frames, int channels) -{ int fr, ch ; - - for (ch = 0 ; ch < channels ; ch++) - for (fr = 0 ; fr < frames ; fr++) - out [fr + frames * ch] = in [ch + channels * fr] ; - - return ; -} /* deinterleave_data */ - -void -reverse_data (float *data, int datalen) -{ int left, right ; - float temp ; - - left = 0 ; - right = datalen - 1 ; - - while (left < right) - { temp = data [left] ; - data [left] = data [right] ; - data [right] = temp ; - left ++ ; - right -- ; - } ; - -} /* reverse_data */ - -const char * -get_cpu_name (void) -{ - const char *name = "Unknown", *search = NULL ; - static char buffer [512] ; - FILE * file = NULL ; - int is_pipe = 0 ; - -#if defined (__linux__) - file = fopen ("/proc/cpuinfo", "r") ; - search = "model name" ; -#elif defined (__APPLE__) - file = popen ("/usr/sbin/system_profiler -detailLevel full SPHardwareDataType", "r") ; - search = "Processor Name" ; - is_pipe = 1 ; -#elif defined (__FreeBSD__) - file = popen ("sysctl -a", "r") ; - search = "hw.model" ; - is_pipe = 1 ; -#else - file = NULL ; -#endif - - if (file == NULL) - return name ; - - if (search == NULL) - { printf ("Error : search is NULL in function %s.\n", __func__) ; - return name ; - } ; - - while (fgets (buffer, sizeof (buffer), file) != NULL) - if (strstr (buffer, search)) - { char *src, *dest ; - - if ((src = strchr (buffer, ':')) != NULL) - { src ++ ; - while (isspace (src [0])) - src ++ ; - name = src ; - - /* Remove consecutive spaces. */ - src ++ ; - for (dest = src ; src [0] ; src ++) - { if (isspace (src [0]) && isspace (dest [-1])) - continue ; - dest [0] = src [0] ; - dest ++ ; - } ; - dest [0] = 0 ; - break ; - } ; - } ; - - if (is_pipe) - pclose (file) ; - else - fclose (file) ; - - return name ; -} /* get_cpu_name */ - diff --git a/lib-src/libsoxr/lsr-tests/util.h b/lib-src/libsoxr/lsr-tests/util.h deleted file mode 100644 index 8a9e60307..000000000 --- a/lib-src/libsoxr/lsr-tests/util.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -** Copyright (C) 2002-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#define ABS(a) (((a) < 0) ? - (a) : (a)) -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) - -void gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len) ; - -void save_oct_float (char *filename, float *input, int in_len, float *output, int out_len) ; -void save_oct_double (char *filename, double *input, int in_len, double *output, int out_len) ; - -void interleave_data (const float *in, float *out, int frames, int channels) ; - -void deinterleave_data (const float *in, float *out, int frames, int channels) ; - -void reverse_data (float *data, int datalen) ; - -double calculate_snr (float *data, int len, int expected_peaks) ; - -const char * get_cpu_name (void) ; - -#if OS_IS_WIN32 -/* -** Extra Win32 hacks. -** -** Despite Microsoft claim of windows being POSIX compatibile it has '_sleep' -** instead of 'sleep'. -*/ - -#define sleep _sleep -#endif - diff --git a/lib-src/libsoxr/lsr-tests/varispeed_test.c b/lib-src/libsoxr/lsr-tests/varispeed_test.c deleted file mode 100644 index 8cf3f790b..000000000 --- a/lib-src/libsoxr/lsr-tests/varispeed_test.c +++ /dev/null @@ -1,152 +0,0 @@ -/* -** Copyright (C) 2006-2011 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include - -#include - -#include "util.h" - -#define BUFFER_LEN (1 << 16) - -static void varispeed_test (int converter, double target_snr) ; - -int -main (void) -{ - puts ("") ; - printf (" Zero Order Hold interpolator : ") ; - varispeed_test (SRC_ZERO_ORDER_HOLD, 10.0) ; - - printf (" Linear interpolator : ") ; - varispeed_test (SRC_LINEAR, 10.0) ; - - printf (" Sinc interpolator : ") ; - varispeed_test (SRC_SINC_FASTEST, 115.0) ; - - puts ("") ; - - return 0 ; -} /* main */ - -static void -varispeed_test (int converter, double target_snr) -{ static float input [BUFFER_LEN], output [BUFFER_LEN] ; - double sine_freq, snr ; - - SRC_STATE *src_state ; - SRC_DATA src_data ; - - int input_len, error ; - - memset (input, 0, sizeof (input)) ; - - input_len = ARRAY_LEN (input) / 2 ; - - sine_freq = 0.0111 ; - gen_windowed_sines (1, &sine_freq, 1.0, input, input_len) ; - - /* Perform sample rate conversion. */ - if ((src_state = src_new (converter, 1, &error)) == NULL) - { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_data.end_of_input = 1 ; - - src_data.data_in = input ; - src_data.input_frames = input_len ; - - src_data.src_ratio = 3.0 ; - - src_data.data_out = output ; - src_data.output_frames = ARRAY_LEN (output) ; - - if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - if ((error = src_process (src_state, &src_data))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; - printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; - exit (1) ; - } ; - - if (src_data.input_frames_used != input_len) - { printf ("\n\nLine %d : unused input.\n", __LINE__) ; - printf ("\tinput_len : %d\n", input_len) ; - printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ; - exit (1) ; - } ; - - /* Copy the last output to the input. */ - memcpy (input, output, sizeof (input)) ; - reverse_data (input, src_data.output_frames_gen) ; - - if ((error = src_reset (src_state))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - src_data.end_of_input = 1 ; - - src_data.data_in = input ; - input_len = src_data.input_frames = src_data.output_frames_gen ; - - src_data.data_out = output ; - src_data.output_frames = ARRAY_LEN (output) ; - - if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - exit (1) ; - } ; - - if ((error = src_process (src_state, &src_data))) - { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; - printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; - printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; - exit (1) ; - } ; - - if (src_data.input_frames_used != input_len) - { printf ("\n\nLine %d : unused input.\n", __LINE__) ; - printf ("\tinput_len : %d\n", input_len) ; - printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ; - exit (1) ; - } ; - - src_state = src_delete (src_state) ; - - snr = calculate_snr (output, src_data.output_frames_gen, 1) ; - - if (target_snr > snr) - { printf ("\n\nLine %d : snr (%3.1f) does not meet target (%3.1f)\n\n", __LINE__, snr, target_snr) ; - save_oct_float ("varispeed.mat", input, src_data.input_frames, output, src_data.output_frames_gen) ; - exit (1) ; - } ; - - puts ("ok") ; - - return ; -} /* varispeed_test */ - diff --git a/lib-src/libsoxr/msvc/README b/lib-src/libsoxr/msvc/README index 285051db3..5a34ebab0 100644 --- a/lib-src/libsoxr/msvc/README +++ b/lib-src/libsoxr/msvc/README @@ -1,9 +1,9 @@ -SoX Resampler Library Copyright (c) 2007-12 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. - - * libsoxr.vcproj Builds a static lib for MSVC ver >= 9 (2008). - * soxr-config.h Pre-configured for a typical Win32 system. +SoX Resampler Library Copyright (c) 2007-13 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. + + * libsoxr.vcproj Builds a static lib for MSVC ver >= 9 (2008). + * soxr-config.h Pre-configured for a typical Win32 system. diff --git a/lib-src/libsoxr/msvc/soxr-config.h b/lib-src/libsoxr/msvc/soxr-config.h index 935beed91..a158de446 100644 --- a/lib-src/libsoxr/msvc/soxr-config.h +++ b/lib-src/libsoxr/msvc/soxr-config.h @@ -1,25 +1,19 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net * Licence for this file: LGPL v2.1 See LICENCE for details. */ -/* N.B. Pre-configured for typical Win32 systems. Normal procedure is to use - * the cmake configuration and build system. See INSTALL. */ +/* N.B. Pre-configured for typical 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 SOXR_VERSION_MAJOR 0 -#define SOXR_VERSION_MINOR 0 -#define SOXR_VERSION_PATCH 1 -#define SOXR_VERSION "0.0.5" - #define HAVE_SINGLE_PRECISION 1 #define HAVE_DOUBLE_PRECISION 1 -#define HAVE_VR 1 -#define HAVE_AVFFT 0 -#define HAVE_SIMD 1 -#define HAVE_FENV_H 0 -#define HAVE_LRINT 0 -#define WORDS_BIGENDIAN 0 +#define HAVE_AVFFT 0 +#define HAVE_SIMD 1 +#define HAVE_FENV_H 0 +#define HAVE_LRINT 0 +#define WORDS_BIGENDIAN 0 #include @@ -39,17 +33,15 @@ #if LONG_MAX > 2147483647L #define int32_t int #define int64_t long - #define DBL (double) #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) + #if defined _MSC_VER #define int64_t __int64 #else #define int64_t long long #endif - #define DBL #endif #define uint32_t unsigned int32_t #define uint64_t unsigned int64_t diff --git a/lib-src/libsoxr/soxr-config.h.in b/lib-src/libsoxr/soxr-config.h.in index 8e2a60367..227bcfd91 100644 --- a/lib-src/libsoxr/soxr-config.h.in +++ b/lib-src/libsoxr/soxr-config.h.in @@ -1,13 +1,11 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net * Licence for this file: LGPL v2.1 See LICENCE for details. */ #if !defined soxr_config_included #define soxr_config_included -#define SOXR_VERSION "@PROJECT_VERSION@" #define HAVE_SINGLE_PRECISION @HAVE_SINGLE_PRECISION@ #define HAVE_DOUBLE_PRECISION @HAVE_DOUBLE_PRECISION@ -#define HAVE_VR @HAVE_VR@ #define HAVE_AVFFT @HAVE_AVFFT@ #define HAVE_SIMD @HAVE_SIMD@ #define HAVE_FENV_H @HAVE_FENV_H@ @@ -32,7 +30,6 @@ #if LONG_MAX > 2147483647L #define int32_t int #define int64_t long - #define DBL (double) #elif LONG_MAX < 2147483647L #error this library requires that 'long int' has at least 32-bits #else @@ -42,7 +39,6 @@ #else #define int64_t long long #endif - #define DBL #endif #define uint32_t unsigned int32_t #define uint64_t unsigned int64_t diff --git a/lib-src/libsoxr/src/CMakeLists.txt b/lib-src/libsoxr/src/CMakeLists.txt index b52a52606..2a21156c0 100644 --- a/lib-src/libsoxr/src/CMakeLists.txt +++ b/lib-src/libsoxr/src/CMakeLists.txt @@ -1,112 +1,110 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB) - - - -# Libsoxr configuration: - -set (RDFT32 fft4g32) -if (WITH_AVFFT AND AVCODEC_FOUND) - set (RDFT32S avfft32s) -elseif (WITH_PFFFT) - set (RDFT32S pffft32s) -elseif (WITH_SIMD) - set (RDFT32S fft4g32s) -endif () - -if (WITH_DOUBLE_PRECISION) - set (DP_SOURCES rate64) -endif () - -if (WITH_SINGLE_PRECISION) - set (SP_SOURCES rate32 ${RDFT32}) -endif () - -if (HAVE_VR) - set (VR_SOURCES vr32) -endif () - -if (HAVE_SIMD) - set (SIMD_SOURCES rate32s ${RDFT32S} simd) - foreach (source ${SIMD_SOURCES}) - set_property (SOURCE ${source} PROPERTY COMPILE_FLAGS ${SIMD_C_FLAGS}) - endforeach () -endif () - - - -# Libsoxr: - -add_library (${PROJECT_NAME} ${LIB_TYPE} ${PROJECT_NAME}.c data-io dbesi0 filter fft4g64 - ${SP_SOURCES} ${VR_SOURCES} ${DP_SOURCES} ${SIMD_SOURCES}) -set_target_properties (${PROJECT_NAME} PROPERTIES - VERSION "${SO_VERSION}" - SOVERSION ${SO_VERSION_MAJOR} - INSTALL_NAME_DIR ${LIB_INSTALL_DIR} - LINK_INTERFACE_LIBRARIES "" - PUBLIC_HEADER "${PROJECT_NAME}.h") -if (BUILD_FRAMEWORK) - set_target_properties (${PROJECT_NAME} PROPERTIES FRAMEWORK TRUE) -elseif (NOT WIN32) - set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.pc) - configure_file (${CMAKE_CURRENT_SOURCE_DIR}/lib${PROJECT_NAME}.pc.in ${TARGET_PCS}) - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -endif () - - - -# LSR bindings: - -if (WITH_LSR_BINDINGS) - set (LSR ${PROJECT_NAME}-lsr) - set (LSR_SO_VERSION 0.1.8) - set (LSR_SO_VERSION_MAJOR 0) - add_library (${LSR} ${LIB_TYPE} lsr) - target_link_libraries (${LSR} ${PROJECT_NAME}) - set_target_properties (${LSR} PROPERTIES - VERSION "${LSR_SO_VERSION}" - SOVERSION ${LSR_SO_VERSION_MAJOR} - INSTALL_NAME_DIR ${LIB_INSTALL_DIR} - LINK_INTERFACE_LIBRARIES "" - PUBLIC_HEADER "${LSR}.h") - if (BUILD_FRAMEWORK) - set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE) - elseif (NOT WIN32) - set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/lib${LSR}.pc") - configure_file (${CMAKE_CURRENT_SOURCE_DIR}/lib${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/lib${LSR}.pc) - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) - endif () -endif () - - - -# Installation (from build from source): - -install (TARGETS ${PROJECT_NAME} ${LSR} - FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - 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) +# 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} -DSOXR_LIB) + + + +# Libsoxr configuration: + +set (RDFT32 fft4g32) +if (WITH_AVFFT AND AVCODEC_FOUND) + set (RDFT32 avfft32) + set (RDFT32S avfft32s) +elseif (WITH_PFFFT) + #set (RDFT32 pffft32) + set (RDFT32S pffft32s) +elseif (WITH_SIMD) + set (RDFT32S fft4g32s) +endif () + +if (WITH_DOUBLE_PRECISION) + set (DP_SOURCES rate64) +endif () + +if (WITH_SINGLE_PRECISION) + set (SP_SOURCES rate32 ${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}) + endforeach () +endif () + + + +# Libsoxr: + +add_library (${PROJECT_NAME} ${LIB_TYPE} ${PROJECT_NAME}.c data-io dbesi0 filter fft4g64 + ${SP_SOURCES} vr32 ${DP_SOURCES} ${SIMD_SOURCES}) +set_target_properties (${PROJECT_NAME} PROPERTIES + VERSION "${SO_VERSION}" + SOVERSION ${SO_VERSION_MAJOR} + INSTALL_NAME_DIR ${LIB_INSTALL_DIR} + LINK_INTERFACE_LIBRARIES "" + PUBLIC_HEADER "${PROJECT_NAME}.h") +if (BUILD_FRAMEWORK) + set_target_properties (${PROJECT_NAME} PROPERTIES FRAMEWORK TRUE) +elseif (NOT WIN32) + set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc) + configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${TARGET_PCS}) + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +endif () + + + +# LSR bindings: + +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) + target_link_libraries (${LSR} ${PROJECT_NAME}) + set_target_properties (${LSR} PROPERTIES + VERSION "${LSR_SO_VERSION}" + SOVERSION ${LSR_SO_VERSION_MAJOR} + INSTALL_NAME_DIR ${LIB_INSTALL_DIR} + LINK_INTERFACE_LIBRARIES "" + PUBLIC_HEADER "${LSR}.h") + if (BUILD_FRAMEWORK) + set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE) + elseif (NOT WIN32) + set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc") + configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc) + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + endif () +endif () + + + +# Installation (from build from source): + +install (TARGETS ${PROJECT_NAME} ${LSR} + FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR} + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + 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) diff --git a/lib-src/libsoxr/src/aliases.h b/lib-src/libsoxr/src/aliases.h index 7e2f7faba..eb42bdc69 100644 --- a/lib-src/libsoxr/src/aliases.h +++ b/lib-src/libsoxr/src/aliases.h @@ -1,37 +1,37 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if defined SOXR_LIB - -#define lsx_bessel_I_0 _soxr_bessel_I_0 -#define lsx_cdft_f _soxr_cdft_f -#define lsx_cdft _soxr_cdft -#define lsx_clear_fft_cache_f _soxr_clear_fft_cache_f -#define lsx_clear_fft_cache _soxr_clear_fft_cache -#define lsx_ddct_f _soxr_ddct_f -#define lsx_ddct _soxr_ddct -#define lsx_ddst_f _soxr_ddst_f -#define lsx_ddst _soxr_ddst -#define lsx_design_lpf _soxr_design_lpf -#define lsx_dfct_f _soxr_dfct_f -#define lsx_dfct _soxr_dfct -#define lsx_dfst_f _soxr_dfst_f -#define lsx_dfst _soxr_dfst -#define lsx_fir_to_phase _soxr_fir_to_phase -#define lsx_init_fft_cache_f _soxr_init_fft_cache_f -#define lsx_init_fft_cache _soxr_init_fft_cache -#define lsx_kaiser_beta _soxr_kaiser_beta -#define lsx_kaiser_params _soxr_kaiser_params -#define lsx_make_lpf _soxr_make_lpf -#define lsx_ordered_convolve_f _soxr_ordered_convolve_f -#define lsx_ordered_convolve _soxr_ordered_convolve -#define lsx_ordered_partial_convolve_f _soxr_ordered_partial_convolve_f -#define lsx_ordered_partial_convolve _soxr_ordered_partial_convolve -#define lsx_rdft_f _soxr_rdft_f -#define lsx_rdft _soxr_rdft -#define lsx_safe_cdft_f _soxr_safe_cdft_f -#define lsx_safe_cdft _soxr_safe_cdft -#define lsx_safe_rdft_f _soxr_safe_rdft_f -#define lsx_safe_rdft _soxr_safe_rdft - -#endif +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#if defined SOXR_LIB + +#define lsx_bessel_I_0 _soxr_bessel_I_0 +#define lsx_cdft_f _soxr_cdft_f +#define lsx_cdft _soxr_cdft +#define lsx_clear_fft_cache_f _soxr_clear_fft_cache_f +#define lsx_clear_fft_cache _soxr_clear_fft_cache +#define lsx_ddct_f _soxr_ddct_f +#define lsx_ddct _soxr_ddct +#define lsx_ddst_f _soxr_ddst_f +#define lsx_ddst _soxr_ddst +#define lsx_design_lpf _soxr_design_lpf +#define lsx_dfct_f _soxr_dfct_f +#define lsx_dfct _soxr_dfct +#define lsx_dfst_f _soxr_dfst_f +#define lsx_dfst _soxr_dfst +#define lsx_fir_to_phase _soxr_fir_to_phase +#define lsx_init_fft_cache_f _soxr_init_fft_cache_f +#define lsx_init_fft_cache _soxr_init_fft_cache +#define lsx_kaiser_beta _soxr_kaiser_beta +#define lsx_kaiser_params _soxr_kaiser_params +#define lsx_make_lpf _soxr_make_lpf +#define lsx_ordered_convolve_f _soxr_ordered_convolve_f +#define lsx_ordered_convolve _soxr_ordered_convolve +#define lsx_ordered_partial_convolve_f _soxr_ordered_partial_convolve_f +#define lsx_ordered_partial_convolve _soxr_ordered_partial_convolve +#define lsx_rdft_f _soxr_rdft_f +#define lsx_rdft _soxr_rdft +#define lsx_safe_cdft_f _soxr_safe_cdft_f +#define lsx_safe_cdft _soxr_safe_cdft +#define lsx_safe_rdft_f _soxr_safe_rdft_f +#define lsx_safe_rdft _soxr_safe_rdft + +#endif diff --git a/lib-src/libsoxr/src/avfft32.c b/lib-src/libsoxr/src/avfft32.c index cc1c93fe8..5be13d2e5 100644 --- a/lib-src/libsoxr/src/avfft32.c +++ b/lib-src/libsoxr/src/avfft32.c @@ -1,27 +1,27 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include "filter.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) {} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft32_cb[] = { - (fn_t)forward_setup, - (fn_t)backward_setup, - (fn_t)av_rdft_end, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)_soxr_ordered_convolve_f, - (fn_t)_soxr_ordered_partial_convolve_f, - (fn_t)multiplier, - (fn_t)nothing, -}; +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include +#include +#include "filter.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) {} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft32_cb[] = { + (fn_t)forward_setup, + (fn_t)backward_setup, + (fn_t)av_rdft_end, + (fn_t)rdft, + (fn_t)rdft, + (fn_t)rdft, + (fn_t)rdft, + (fn_t)_soxr_ordered_convolve_f, + (fn_t)_soxr_ordered_partial_convolve_f, + (fn_t)multiplier, + (fn_t)nothing, +}; diff --git a/lib-src/libsoxr/src/avfft32s.c b/lib-src/libsoxr/src/avfft32s.c index 3c8862ecc..75e485e95 100644 --- a/lib-src/libsoxr/src/avfft32s.c +++ b/lib-src/libsoxr/src/avfft32s.c @@ -1,27 +1,27 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include "simd.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) {} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft32s_cb[] = { - (fn_t)forward_setup, - (fn_t)backward_setup, - (fn_t)av_rdft_end, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)_soxr_ordered_convolve_simd, - (fn_t)_soxr_ordered_partial_convolve_simd, - (fn_t)multiplier, - (fn_t)nothing, -}; +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include +#include +#include "simd.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) {} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft32s_cb[] = { + (fn_t)forward_setup, + (fn_t)backward_setup, + (fn_t)av_rdft_end, + (fn_t)rdft, + (fn_t)rdft, + (fn_t)rdft, + (fn_t)rdft, + (fn_t)_soxr_ordered_convolve_simd, + (fn_t)_soxr_ordered_partial_convolve_simd, + (fn_t)multiplier, + (fn_t)nothing, +}; diff --git a/lib-src/libsoxr/src/ccrw2.h b/lib-src/libsoxr/src/ccrw2.h index cc454dac7..b42185b14 100644 --- a/lib-src/libsoxr/src/ccrw2.h +++ b/lib-src/libsoxr/src/ccrw2.h @@ -1,73 +1,75 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */ - -#if !defined ccrw2_included -#define ccrw2_included - -#include "internal.h" - -#if defined _OPENMP - -#include - -typedef struct { - int readcount, writecount; /* initial value = 0 */ - omp_lock_t mutex_1, mutex_2, mutex_3, w, r; /* initial value = 1 */ -} ccrw2_t; /* Problem #2: `writers-preference' */ - -#define ccrw2_become_reader(p) do {\ - omp_set_lock(&p.mutex_3);\ - omp_set_lock(&p.r);\ - omp_set_lock(&p.mutex_1);\ - if (++p.readcount == 1) omp_set_lock(&p.w);\ - omp_unset_lock(&p.mutex_1);\ - omp_unset_lock(&p.r);\ - omp_unset_lock(&p.mutex_3);\ -} while (0) -#define ccrw2_cease_reading(p) do {\ - omp_set_lock(&p.mutex_1);\ - if (!--p.readcount) omp_unset_lock(&p.w);\ - omp_unset_lock(&p.mutex_1);\ -} while (0) -#define ccrw2_become_writer(p) do {\ - omp_set_lock(&p.mutex_2);\ - if (++p.writecount == 1) omp_set_lock(&p.r);\ - omp_unset_lock(&p.mutex_2);\ - omp_set_lock(&p.w);\ -} while (0) -#define ccrw2_cease_writing(p) do {\ - omp_unset_lock(&p.w);\ - omp_set_lock(&p.mutex_2);\ - if (!--p.writecount) omp_unset_lock(&p.r);\ - omp_unset_lock(&p.mutex_2);\ -} while (0) -#define ccrw2_init(p) do {\ - omp_init_lock(&p.mutex_1);\ - omp_init_lock(&p.mutex_2);\ - omp_init_lock(&p.mutex_3);\ - omp_init_lock(&p.w);\ - omp_init_lock(&p.r);\ -} while (0) -#define ccrw2_clear(p) do {\ - omp_destroy_lock(&p.r);\ - omp_destroy_lock(&p.w);\ - omp_destroy_lock(&p.mutex_3);\ - omp_destroy_lock(&p.mutex_2);\ - omp_destroy_lock(&p.mutex_1);\ -} while (0) - -#else - -typedef int ccrw2_t; -#define ccrw2_become_reader(x) (void)(x) -#define ccrw2_cease_reading(x) (void)(x) -#define ccrw2_become_writer(x) (void)(x) -#define ccrw2_cease_writing(x) (void)(x) -#define ccrw2_init(x) (void)(x) -#define ccrw2_clear(x) (void)(x) - -#endif /* _OPENMP */ - -#endif +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */ + +#if !defined ccrw2_included +#define ccrw2_included + +#if defined SOXR_LIB +#include "internal.h" +#endif + +#if defined _OPENMP + +#include + +typedef struct { + int readcount, writecount; /* initial value = 0 */ + omp_lock_t mutex_1, mutex_2, mutex_3, w, r; /* initial value = 1 */ +} ccrw2_t; /* Problem #2: `writers-preference' */ + +#define ccrw2_become_reader(p) do {\ + omp_set_lock(&p.mutex_3);\ + omp_set_lock(&p.r);\ + omp_set_lock(&p.mutex_1);\ + if (++p.readcount == 1) omp_set_lock(&p.w);\ + omp_unset_lock(&p.mutex_1);\ + omp_unset_lock(&p.r);\ + omp_unset_lock(&p.mutex_3);\ +} while (0) +#define ccrw2_cease_reading(p) do {\ + omp_set_lock(&p.mutex_1);\ + if (!--p.readcount) omp_unset_lock(&p.w);\ + omp_unset_lock(&p.mutex_1);\ +} while (0) +#define ccrw2_become_writer(p) do {\ + omp_set_lock(&p.mutex_2);\ + if (++p.writecount == 1) omp_set_lock(&p.r);\ + omp_unset_lock(&p.mutex_2);\ + omp_set_lock(&p.w);\ +} while (0) +#define ccrw2_cease_writing(p) do {\ + omp_unset_lock(&p.w);\ + omp_set_lock(&p.mutex_2);\ + if (!--p.writecount) omp_unset_lock(&p.r);\ + omp_unset_lock(&p.mutex_2);\ +} while (0) +#define ccrw2_init(p) do {\ + omp_init_lock(&p.mutex_1);\ + omp_init_lock(&p.mutex_2);\ + omp_init_lock(&p.mutex_3);\ + omp_init_lock(&p.w);\ + omp_init_lock(&p.r);\ +} while (0) +#define ccrw2_clear(p) do {\ + omp_destroy_lock(&p.r);\ + omp_destroy_lock(&p.w);\ + omp_destroy_lock(&p.mutex_3);\ + omp_destroy_lock(&p.mutex_2);\ + omp_destroy_lock(&p.mutex_1);\ +} while (0) + +#else + +typedef int ccrw2_t; +#define ccrw2_become_reader(x) (void)(x) +#define ccrw2_cease_reading(x) (void)(x) +#define ccrw2_become_writer(x) (void)(x) +#define ccrw2_cease_writing(x) (void)(x) +#define ccrw2_init(x) (void)(x) +#define ccrw2_clear(x) (void)(x) + +#endif /* _OPENMP */ + +#endif diff --git a/lib-src/libsoxr/src/data-io.c b/lib-src/libsoxr/src/data-io.c index b1b18000e..1cd8e7fec 100644 --- a/lib-src/libsoxr/src/data-io.c +++ b/lib-src/libsoxr/src/data-io.c @@ -1,249 +1,252 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include - -#include "data-io.h" -#include "internal.h" - - - -#define DEINTERLEAVE_FROM(T,flag) do { \ - 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++; \ - 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; \ -} while (0) - - - -#if HAVE_DOUBLE_PRECISION -void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */ - soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) -{ -#define DEINTERLEAVE_TO double - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE_FROM(float, 0); break; - case SOXR_FLOAT64: DEINTERLEAVE_FROM(double, 1); break; - case SOXR_INT32: DEINTERLEAVE_FROM(int32_t, 0); break; - case SOXR_INT16: DEINTERLEAVE_FROM(int16_t, 0); break; - default: break; - } -} -#endif - - - -#if HAVE_SINGLE_PRECISION -void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */ - soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) -{ -#undef DEINTERLEAVE_TO -#define DEINTERLEAVE_TO float - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE_FROM(float, 1); break; - case SOXR_FLOAT64: DEINTERLEAVE_FROM(double, 0); break; - case SOXR_INT32: DEINTERLEAVE_FROM(int32_t, 0); break; - case SOXR_INT16: DEINTERLEAVE_FROM(int16_t, 0); break; - default: break; - } -} -#endif - - - -#include "rint.h" - -#if HAVE_FENV_H - #include -#elif defined _MSC_VER - #define FE_INVALID 1 - #define FE_DIVBYZERO 4 - #define FE_OVERFLOW 8 - #define FE_UNDERFLOW 16 - #define FE_INEXACT 32 - #define FE_ALL_EXCEPT (FE_INEXACT|FE_DIVBYZERO|FE_UNDERFLOW|FE_OVERFLOW|FE_INVALID) - static __inline int fetestexcept(int excepts) - { - short status_word; - __asm fnstsw status_word - return status_word & excepts & FE_ALL_EXCEPT; - } - - static __inline int feclearexcept(int excepts) - { - int16_t status[14]; - __asm fnstenv status - status[2] &= ~(excepts & FE_ALL_EXCEPT); - __asm fldenv status - return 0; - } -#endif - - - -#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ - #if __STDC_VERSION__ >= 199901L - #pragma STDC FENV_ACCESS ON - #endif -#endif - -#if HAVE_DOUBLE_PRECISION -#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 -#if defined FPU_RINT32 - #define FPU_RINT -#endif -#define RINT_T int32_t -#define RINT_MAX 2147483647L -#include "rint-clip.h" - -#define LSX_RINT_CLIP_2 lsx_rint16_clip_2 -#define LSX_RINT_CLIP lsx_rint16_clip -#define RINT_CLIP rint16_clip -#define RINT rint16 -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#include "rint-clip.h" - -#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 -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#define DITHER -#include "rint-clip.h" - -#undef FLOATX -#endif - - - -#if HAVE_SINGLE_PRECISION -#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 -#if defined FPU_RINT32 - #define FPU_RINT -#endif -#define RINT_T int32_t -#define RINT_MAX 2147483647L -#include "rint-clip.h" - -#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 -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#include "rint-clip.h" - -#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 -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#define DITHER -#include "rint-clip.h" - -#undef FLOATX -#endif - -#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ - #if __STDC_VERSION__ >= 199901L - #pragma STDC FENV_ACCESS OFF - #endif -#endif - - - -#define INTERLEAVE_TO(T,flag) do { \ - unsigned i; \ - size_t j; \ - T * dest = *dest0; \ - if (ch > 1) \ - for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = (T)src[i][j]; \ - else if (flag) memcpy(dest, src[0], n * sizeof(T)), dest = &dest[n]; \ - else for (j = 0; j < n; *dest++ = (T)src[0][j++]); \ - *dest0 = dest; \ - return 0; \ -} while (0) - -#if HAVE_DOUBLE_PRECISION -size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0, - double const * const * src, size_t n, unsigned ch, unsigned long * seed) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE_TO(float, 0); - case SOXR_FLOAT64: INTERLEAVE_TO(double, 1); - - case SOXR_INT32: if (ch == 1) - return lsx_rint32_clip(dest0, src[0], n); - return lsx_rint32_clip_2(dest0, src, ch, n); - - case SOXR_INT16: if (seed) { - if (ch == 1) - return lsx_rint16_clip_dither(dest0, src[0], n, seed); - return lsx_rint16_clip_2_dither(dest0, src, ch, n, seed); - } - if (ch == 1) - return lsx_rint16_clip(dest0, src[0], n); - return lsx_rint16_clip_2(dest0, src, ch, n); - default: break; - } - return 0; -} -#endif - -#if HAVE_SINGLE_PRECISION -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) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE_TO(float, 1); - case SOXR_FLOAT64: INTERLEAVE_TO(double, 0); - - case SOXR_INT32: if (ch == 1) - return lsx_rint32_clip_f(dest0, src[0], n); - return lsx_rint32_clip_2_f(dest0, src, ch, n); - - case SOXR_INT16: if (seed) { - if (ch == 1) - return lsx_rint16_clip_dither_f(dest0, src[0], n, seed); - return lsx_rint16_clip_2_dither_f(dest0, src, ch, n, seed); - } - if (ch == 1) - return lsx_rint16_clip_f(dest0, src[0], n); - return lsx_rint16_clip_2_f(dest0, src, ch, n); - default: break; - } - return 0; -} -#endif +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include +#include +#include + +#include "data-io.h" +#include "internal.h" + + + +#define DEINTERLEAVE_FROM(T,flag) do { \ + 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++; \ + 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; \ +} while (0) + + + +#if HAVE_DOUBLE_PRECISION +void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */ + soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) +{ +#define DEINTERLEAVE_TO double + switch (data_type & 3) { + case SOXR_FLOAT32: DEINTERLEAVE_FROM(float, 0); break; + case SOXR_FLOAT64: DEINTERLEAVE_FROM(double, 1); break; + case SOXR_INT32: DEINTERLEAVE_FROM(int32_t, 0); break; + case SOXR_INT16: DEINTERLEAVE_FROM(int16_t, 0); break; + default: break; + } +} +#endif + + + +#if HAVE_SINGLE_PRECISION +void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */ + soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) +{ +#undef DEINTERLEAVE_TO +#define DEINTERLEAVE_TO float + switch (data_type & 3) { + case SOXR_FLOAT32: DEINTERLEAVE_FROM(float, 1); break; + case SOXR_FLOAT64: DEINTERLEAVE_FROM(double, 0); break; + case SOXR_INT32: DEINTERLEAVE_FROM(int32_t, 0); break; + case SOXR_INT16: DEINTERLEAVE_FROM(int16_t, 0); break; + default: break; + } +} +#endif + + + +#include "rint.h" + +#if HAVE_FENV_H + #include + #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 + #define fe_test_invalid() (_statusfp() & _SW_INVALID) + #define fe_clear_invalid _clearfp /* FIXME clears all */ + #else + static __inline int fe_test_invalid() + { + short status_word; + __asm fnstsw status_word + return status_word & FE_INVALID; + } + + static __inline int fe_clear_invalid() + { + int16_t status[14]; + __asm fnstenv status + status[2] &= ~FE_INVALID; + __asm fldenv status + return 0; + } + #endif +#endif + + + +#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #pragma STDC FENV_ACCESS ON + #endif +#endif + +#if HAVE_DOUBLE_PRECISION +#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 +#if defined FPU_RINT32 + #define FPU_RINT +#endif +#define RINT_T int32_t +#define RINT_MAX 2147483647L +#include "rint-clip.h" + +#define LSX_RINT_CLIP_2 lsx_rint16_clip_2 +#define LSX_RINT_CLIP lsx_rint16_clip +#define RINT_CLIP rint16_clip +#define RINT rint16 +#if defined FPU_RINT16 + #define FPU_RINT +#endif +#define RINT_T int16_t +#define RINT_MAX 32767 +#include "rint-clip.h" + +#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 +#if defined FPU_RINT16 + #define FPU_RINT +#endif +#define RINT_T int16_t +#define RINT_MAX 32767 +#define DITHER +#include "rint-clip.h" + +#undef FLOATX +#endif + + + +#if HAVE_SINGLE_PRECISION +#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 +#if defined FPU_RINT32 + #define FPU_RINT +#endif +#define RINT_T int32_t +#define RINT_MAX 2147483647L +#include "rint-clip.h" + +#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 +#if defined FPU_RINT16 + #define FPU_RINT +#endif +#define RINT_T int16_t +#define RINT_MAX 32767 +#include "rint-clip.h" + +#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 +#if defined FPU_RINT16 + #define FPU_RINT +#endif +#define RINT_T int16_t +#define RINT_MAX 32767 +#define DITHER +#include "rint-clip.h" + +#undef FLOATX +#endif + +#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #pragma STDC FENV_ACCESS OFF + #endif +#endif + + + +#define INTERLEAVE_TO(T,flag) do { \ + unsigned i; \ + size_t j; \ + T * dest = *dest0; \ + if (ch > 1) \ + for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = (T)src[i][j]; \ + else if (flag) memcpy(dest, src[0], n * sizeof(T)), dest = &dest[n]; \ + else for (j = 0; j < n; *dest++ = (T)src[0][j++]); \ + *dest0 = dest; \ + return 0; \ +} while (0) + +#if HAVE_DOUBLE_PRECISION +size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0, + double const * const * src, size_t n, unsigned ch, unsigned long * seed) +{ + switch (data_type & 3) { + case SOXR_FLOAT32: INTERLEAVE_TO(float, 0); + case SOXR_FLOAT64: INTERLEAVE_TO(double, 1); + + case SOXR_INT32: if (ch == 1) + return lsx_rint32_clip(dest0, src[0], n); + return lsx_rint32_clip_2(dest0, src, ch, n); + + case SOXR_INT16: if (seed) { + if (ch == 1) + return lsx_rint16_clip_dither(dest0, src[0], n, seed); + return lsx_rint16_clip_2_dither(dest0, src, ch, n, seed); + } + if (ch == 1) + return lsx_rint16_clip(dest0, src[0], n); + return lsx_rint16_clip_2(dest0, src, ch, n); + default: break; + } + return 0; +} +#endif + +#if HAVE_SINGLE_PRECISION +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) +{ + switch (data_type & 3) { + case SOXR_FLOAT32: INTERLEAVE_TO(float, 1); + case SOXR_FLOAT64: INTERLEAVE_TO(double, 0); + + case SOXR_INT32: if (ch == 1) + return lsx_rint32_clip_f(dest0, src[0], n); + return lsx_rint32_clip_2_f(dest0, src, ch, n); + + case SOXR_INT16: if (seed) { + if (ch == 1) + return lsx_rint16_clip_dither_f(dest0, src[0], n, seed); + return lsx_rint16_clip_2_dither_f(dest0, src, ch, n, seed); + } + if (ch == 1) + return lsx_rint16_clip_f(dest0, src[0], n); + return lsx_rint16_clip_2_f(dest0, src, ch, n); + default: break; + } + return 0; +} +#endif diff --git a/lib-src/libsoxr/src/data-io.h b/lib-src/libsoxr/src/data-io.h index 4cf4aaccc..83a0a133d 100644 --- a/lib-src/libsoxr/src/data-io.h +++ b/lib-src/libsoxr/src/data-io.h @@ -1,39 +1,39 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_data_io_included -#define soxr_data_io_included - -#include "soxr.h" - -void _soxr_deinterleave( - double * * dest, - soxr_datatype_t data_type, - void const * * src0, - size_t n, - unsigned ch); - -void _soxr_deinterleave_f( - float * * dest, - soxr_datatype_t data_type, - void const * * src0, - size_t n, - unsigned ch); - -size_t /* clips */ _soxr_interleave( - soxr_datatype_t data_type, - void * * dest, - double const * const * src, - size_t n, - unsigned ch, - unsigned long * seed); - -size_t /* clips */ _soxr_interleave_f( - soxr_datatype_t data_type, - void * * dest, - float const * const * src, - size_t n, - unsigned ch, - unsigned long * seed); - -#endif +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#if !defined soxr_data_io_included +#define soxr_data_io_included + +#include "soxr.h" + +void _soxr_deinterleave( + double * * dest, + soxr_datatype_t data_type, + void const * * src0, + size_t n, + unsigned ch); + +void _soxr_deinterleave_f( + float * * dest, + soxr_datatype_t data_type, + void const * * src0, + size_t n, + unsigned ch); + +size_t /* clips */ _soxr_interleave( + soxr_datatype_t data_type, + void * * dest, + double const * const * src, + size_t n, + unsigned ch, + unsigned long * seed); + +size_t /* clips */ _soxr_interleave_f( + soxr_datatype_t data_type, + void * * dest, + float const * const * src, + size_t n, + unsigned ch, + unsigned long * seed); + +#endif diff --git a/lib-src/libsoxr/src/dbesi0.c b/lib-src/libsoxr/src/dbesi0.c index 8b2d9b59e..654216eb4 100644 --- a/lib-src/libsoxr/src/dbesi0.c +++ b/lib-src/libsoxr/src/dbesi0.c @@ -1,149 +1,149 @@ -/* Copyright(C) 1996 Takuya OOURA - -You may use, copy, modify this code for any purpose and -without fee. - -Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/bessel.html -*/ - -#include "filter.h" -#define dbesi0 lsx_bessel_I_0 - -/* Bessel I_0(x) function in double precision */ - -#include - -double dbesi0(double x) -{ - int k; - double w, t, y; - static double a[65] = { - 8.5246820682016865877e-11, 2.5966600546497407288e-9, - 7.9689994568640180274e-8, 1.9906710409667748239e-6, - 4.0312469446528002532e-5, 6.4499871606224265421e-4, - 0.0079012345761930579108, 0.071111111109207045212, - 0.444444444444724909, 1.7777777777777532045, - 4.0000000000000011182, 3.99999999999999998, - 1.0000000000000000001, - 1.1520919130377195927e-10, 2.2287613013610985225e-9, - 8.1903951930694585113e-8, 1.9821560631611544984e-6, - 4.0335461940910133184e-5, 6.4495330974432203401e-4, - 0.0079013012611467520626, 0.071111038160875566622, - 0.44444450319062699316, 1.7777777439146450067, - 4.0000000132337935071, 3.9999999968569015366, - 1.0000000003426703174, - 1.5476870780515238488e-10, 1.2685004214732975355e-9, - 9.2776861851114223267e-8, 1.9063070109379044378e-6, - 4.0698004389917945832e-5, 6.4370447244298070713e-4, - 0.0079044749458444976958, 0.071105052411749363882, - 0.44445280640924755082, 1.7777694934432109713, - 4.0000055808824003386, 3.9999977081165740932, - 1.0000004333949319118, - 2.0675200625006793075e-10, -6.1689554705125681442e-10, - 1.2436765915401571654e-7, 1.5830429403520613423e-6, - 4.2947227560776583326e-5, 6.3249861665073441312e-4, - 0.0079454472840953930811, 0.070994327785661860575, - 0.44467219586283000332, 1.7774588182255374745, - 4.0003038986252717972, 3.9998233869142057195, - 1.0000472932961288324, - 2.7475684794982708655e-10, -3.8991472076521332023e-9, - 1.9730170483976049388e-7, 5.9651531561967674521e-7, - 5.1992971474748995357e-5, 5.7327338675433770752e-4, - 0.0082293143836530412024, 0.069990934858728039037, - 0.44726764292723985087, 1.7726685170014087784, - 4.0062907863712704432, 3.9952750700487845355, - 1.0016354346654179322 - }; - static double b[70] = { - 6.7852367144945531383e-8, 4.6266061382821826854e-7, - 6.9703135812354071774e-6, 7.6637663462953234134e-5, - 7.9113515222612691636e-4, 0.0073401204731103808981, - 0.060677114958668837046, 0.43994941411651569622, - 2.7420017097661750609, 14.289661921740860534, - 59.820609640320710779, 188.78998681199150629, - 399.8731367825601118, 427.56411572180478514, - 1.8042097874891098754e-7, 1.2277164312044637357e-6, - 1.8484393221474274861e-5, 2.0293995900091309208e-4, - 0.0020918539850246207459, 0.019375315654033949297, - 0.15985869016767185908, 1.1565260527420641724, - 7.1896341224206072113, 37.354773811947484532, - 155.80993164266268457, 489.5211371158540918, - 1030.9147225169564806, 1093.5883545113746958, - 4.8017305613187493564e-7, 3.261317843912380074e-6, - 4.9073137508166159639e-5, 5.3806506676487583755e-4, - 0.0055387918291051866561, 0.051223717488786549025, - 0.42190298621367914765, 3.0463625987357355872, - 18.895299447327733204, 97.915189029455461554, - 407.13940115493494659, 1274.3088990480582632, - 2670.9883037012547506, 2815.7166284662544712, - 1.2789926338424623394e-6, 8.6718263067604918916e-6, - 1.3041508821299929489e-4, 0.001428224737372747892, - 0.014684070635768789378, 0.13561403190404185755, - 1.1152592585977393953, 8.0387088559465389038, - 49.761318895895479206, 257.2684232313529138, - 1066.8543146269566231, 3328.3874581009636362, - 6948.8586598121634874, 7288.4893398212481055, - 3.409350368197032893e-6, 2.3079025203103376076e-5, - 3.4691373283901830239e-4, 0.003794994977222908545, - 0.038974209677945602145, 0.3594948380414878371, - 2.9522878893539528226, 21.246564609514287056, - 131.28727387146173141, 677.38107093296675421, - 2802.3724744545046518, 8718.5731420798254081, - 18141.348781638832286, 18948.925349296308859 - }; - static double c[45] = { - 2.5568678676452702768e-15, 3.0393953792305924324e-14, - 6.3343751991094840009e-13, 1.5041298011833009649e-11, - 4.4569436918556541414e-10, 1.746393051427167951e-8, - 1.0059224011079852317e-6, 1.0729838945088577089e-4, - 0.05150322693642527738, - 5.2527963991711562216e-15, 7.202118481421005641e-15, - 7.2561421229904797156e-13, 1.482312146673104251e-11, - 4.4602670450376245434e-10, 1.7463600061788679671e-8, - 1.005922609132234756e-6, 1.0729838937545111487e-4, - 0.051503226936437300716, - 1.3365917359358069908e-14, -1.2932643065888544835e-13, - 1.7450199447905602915e-12, 1.0419051209056979788e-11, - 4.58047881980598326e-10, 1.7442405450073548966e-8, - 1.0059461453281292278e-6, 1.0729837434500161228e-4, - 0.051503226940658446941, - 5.3771611477352308649e-14, -1.1396193006413731702e-12, - 1.2858641335221653409e-11, -5.9802086004570057703e-11, - 7.3666894305929510222e-10, 1.6731837150730356448e-8, - 1.0070831435812128922e-6, 1.0729733111203704813e-4, - 0.051503227360726294675, - 3.7819492084858931093e-14, -4.8600496888588034879e-13, - 1.6898350504817224909e-12, 4.5884624327524255865e-11, - 1.2521615963377513729e-10, 1.8959658437754727957e-8, - 1.0020716710561353622e-6, 1.073037119856927559e-4, - 0.05150322383300230775 - }; - - w = fabs(x); - if (w < 8.5) { - t = w * w * 0.0625; - k = 13 * ((int) t); - y = (((((((((((a[k] * t + a[k + 1]) * t + - a[k + 2]) * t + a[k + 3]) * t + a[k + 4]) * t + - a[k + 5]) * t + a[k + 6]) * t + a[k + 7]) * t + - a[k + 8]) * t + a[k + 9]) * t + a[k + 10]) * t + - a[k + 11]) * t + a[k + 12]; - } else if (w < 12.5) { - k = (int) w; - t = w - k; - k = 14 * (k - 8); - y = ((((((((((((b[k] * t + b[k + 1]) * t + - b[k + 2]) * t + b[k + 3]) * t + b[k + 4]) * t + - b[k + 5]) * t + b[k + 6]) * t + b[k + 7]) * t + - b[k + 8]) * t + b[k + 9]) * t + b[k + 10]) * t + - b[k + 11]) * t + b[k + 12]) * t + b[k + 13]; - } else { - t = 60 / w; - k = 9 * ((int) t); - y = ((((((((c[k] * t + c[k + 1]) * t + - c[k + 2]) * t + c[k + 3]) * t + c[k + 4]) * t + - c[k + 5]) * t + c[k + 6]) * t + c[k + 7]) * t + - c[k + 8]) * sqrt(t) * exp(w); - } - return y; -} +/* Copyright(C) 1996 Takuya OOURA + +You may use, copy, modify this code for any purpose and +without fee. + +Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/bessel.html +*/ + +#include "filter.h" +#define dbesi0 lsx_bessel_I_0 + +/* Bessel I_0(x) function in double precision */ + +#include + +double dbesi0(double x) +{ + int k; + double w, t, y; + static double a[65] = { + 8.5246820682016865877e-11, 2.5966600546497407288e-9, + 7.9689994568640180274e-8, 1.9906710409667748239e-6, + 4.0312469446528002532e-5, 6.4499871606224265421e-4, + 0.0079012345761930579108, 0.071111111109207045212, + 0.444444444444724909, 1.7777777777777532045, + 4.0000000000000011182, 3.99999999999999998, + 1.0000000000000000001, + 1.1520919130377195927e-10, 2.2287613013610985225e-9, + 8.1903951930694585113e-8, 1.9821560631611544984e-6, + 4.0335461940910133184e-5, 6.4495330974432203401e-4, + 0.0079013012611467520626, 0.071111038160875566622, + 0.44444450319062699316, 1.7777777439146450067, + 4.0000000132337935071, 3.9999999968569015366, + 1.0000000003426703174, + 1.5476870780515238488e-10, 1.2685004214732975355e-9, + 9.2776861851114223267e-8, 1.9063070109379044378e-6, + 4.0698004389917945832e-5, 6.4370447244298070713e-4, + 0.0079044749458444976958, 0.071105052411749363882, + 0.44445280640924755082, 1.7777694934432109713, + 4.0000055808824003386, 3.9999977081165740932, + 1.0000004333949319118, + 2.0675200625006793075e-10, -6.1689554705125681442e-10, + 1.2436765915401571654e-7, 1.5830429403520613423e-6, + 4.2947227560776583326e-5, 6.3249861665073441312e-4, + 0.0079454472840953930811, 0.070994327785661860575, + 0.44467219586283000332, 1.7774588182255374745, + 4.0003038986252717972, 3.9998233869142057195, + 1.0000472932961288324, + 2.7475684794982708655e-10, -3.8991472076521332023e-9, + 1.9730170483976049388e-7, 5.9651531561967674521e-7, + 5.1992971474748995357e-5, 5.7327338675433770752e-4, + 0.0082293143836530412024, 0.069990934858728039037, + 0.44726764292723985087, 1.7726685170014087784, + 4.0062907863712704432, 3.9952750700487845355, + 1.0016354346654179322 + }; + static double b[70] = { + 6.7852367144945531383e-8, 4.6266061382821826854e-7, + 6.9703135812354071774e-6, 7.6637663462953234134e-5, + 7.9113515222612691636e-4, 0.0073401204731103808981, + 0.060677114958668837046, 0.43994941411651569622, + 2.7420017097661750609, 14.289661921740860534, + 59.820609640320710779, 188.78998681199150629, + 399.8731367825601118, 427.56411572180478514, + 1.8042097874891098754e-7, 1.2277164312044637357e-6, + 1.8484393221474274861e-5, 2.0293995900091309208e-4, + 0.0020918539850246207459, 0.019375315654033949297, + 0.15985869016767185908, 1.1565260527420641724, + 7.1896341224206072113, 37.354773811947484532, + 155.80993164266268457, 489.5211371158540918, + 1030.9147225169564806, 1093.5883545113746958, + 4.8017305613187493564e-7, 3.261317843912380074e-6, + 4.9073137508166159639e-5, 5.3806506676487583755e-4, + 0.0055387918291051866561, 0.051223717488786549025, + 0.42190298621367914765, 3.0463625987357355872, + 18.895299447327733204, 97.915189029455461554, + 407.13940115493494659, 1274.3088990480582632, + 2670.9883037012547506, 2815.7166284662544712, + 1.2789926338424623394e-6, 8.6718263067604918916e-6, + 1.3041508821299929489e-4, 0.001428224737372747892, + 0.014684070635768789378, 0.13561403190404185755, + 1.1152592585977393953, 8.0387088559465389038, + 49.761318895895479206, 257.2684232313529138, + 1066.8543146269566231, 3328.3874581009636362, + 6948.8586598121634874, 7288.4893398212481055, + 3.409350368197032893e-6, 2.3079025203103376076e-5, + 3.4691373283901830239e-4, 0.003794994977222908545, + 0.038974209677945602145, 0.3594948380414878371, + 2.9522878893539528226, 21.246564609514287056, + 131.28727387146173141, 677.38107093296675421, + 2802.3724744545046518, 8718.5731420798254081, + 18141.348781638832286, 18948.925349296308859 + }; + static double c[45] = { + 2.5568678676452702768e-15, 3.0393953792305924324e-14, + 6.3343751991094840009e-13, 1.5041298011833009649e-11, + 4.4569436918556541414e-10, 1.746393051427167951e-8, + 1.0059224011079852317e-6, 1.0729838945088577089e-4, + 0.05150322693642527738, + 5.2527963991711562216e-15, 7.202118481421005641e-15, + 7.2561421229904797156e-13, 1.482312146673104251e-11, + 4.4602670450376245434e-10, 1.7463600061788679671e-8, + 1.005922609132234756e-6, 1.0729838937545111487e-4, + 0.051503226936437300716, + 1.3365917359358069908e-14, -1.2932643065888544835e-13, + 1.7450199447905602915e-12, 1.0419051209056979788e-11, + 4.58047881980598326e-10, 1.7442405450073548966e-8, + 1.0059461453281292278e-6, 1.0729837434500161228e-4, + 0.051503226940658446941, + 5.3771611477352308649e-14, -1.1396193006413731702e-12, + 1.2858641335221653409e-11, -5.9802086004570057703e-11, + 7.3666894305929510222e-10, 1.6731837150730356448e-8, + 1.0070831435812128922e-6, 1.0729733111203704813e-4, + 0.051503227360726294675, + 3.7819492084858931093e-14, -4.8600496888588034879e-13, + 1.6898350504817224909e-12, 4.5884624327524255865e-11, + 1.2521615963377513729e-10, 1.8959658437754727957e-8, + 1.0020716710561353622e-6, 1.073037119856927559e-4, + 0.05150322383300230775 + }; + + w = fabs(x); + if (w < 8.5) { + t = w * w * 0.0625; + k = 13 * ((int) t); + y = (((((((((((a[k] * t + a[k + 1]) * t + + a[k + 2]) * t + a[k + 3]) * t + a[k + 4]) * t + + a[k + 5]) * t + a[k + 6]) * t + a[k + 7]) * t + + a[k + 8]) * t + a[k + 9]) * t + a[k + 10]) * t + + a[k + 11]) * t + a[k + 12]; + } else if (w < 12.5) { + k = (int) w; + t = w - k; + k = 14 * (k - 8); + y = ((((((((((((b[k] * t + b[k + 1]) * t + + b[k + 2]) * t + b[k + 3]) * t + b[k + 4]) * t + + b[k + 5]) * t + b[k + 6]) * t + b[k + 7]) * t + + b[k + 8]) * t + b[k + 9]) * t + b[k + 10]) * t + + b[k + 11]) * t + b[k + 12]) * t + b[k + 13]; + } else { + t = 60 / w; + k = 9 * ((int) t); + y = ((((((((c[k] * t + c[k + 1]) * t + + c[k + 2]) * t + c[k + 3]) * t + c[k + 4]) * t + + c[k + 5]) * t + c[k + 6]) * t + c[k + 7]) * t + + c[k + 8]) * sqrt(t) * exp(w); + } + return y; +} diff --git a/lib-src/libsoxr/src/fft4g.c b/lib-src/libsoxr/src/fft4g.c index 27c9d1f3e..5fae8a6e0 100644 --- a/lib-src/libsoxr/src/fft4g.c +++ b/lib-src/libsoxr/src/fft4g.c @@ -1,1352 +1,1352 @@ -/* Copyright Takuya OOURA, 1996-2001. - -You may use, copy, modify and distribute this code for any -purpose (include commercial use) and without fee. Please -refer to this package when you modify this code. - -Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html - -Fast Fourier/Cosine/Sine Transform - dimension :one - data length :power of 2 - decimation :frequency - radix :4, 2 - data :inplace - table :use -functions - cdft: Complex Discrete Fourier Transform - rdft: Real Discrete Fourier Transform - ddct: Discrete Cosine Transform - ddst: Discrete Sine Transform - dfct: Cosine Transform of RDFT (Real Symmetric DFT) - dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) -function prototypes - void cdft(int, int, double *, int *, double *); - void rdft(int, int, double *, int *, double *); - void ddct(int, int, double *, int *, double *); - void ddst(int, int, double *, int *, double *); - void dfct(int, double *, double *, int *, double *); - void dfst(int, double *, double *, int *, double *); - - --------- Complex DFT (Discrete Fourier Transform) -------- - [definition] - - X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k - X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k - ip[0] = 0; // first time only - cdft(2*n, 1, a, ip, w); - - ip[0] = 0; // first time only - cdft(2*n, -1, a, ip, w); - [parameters] - 2*n :data length (int) - n >= 1, n = power of 2 - a[0...2*n-1] :input/output data (double *) - input data - a[2*j] = Re(x[j]), - a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) - strictly, - length of ip >= - 2+(1<<(int)(log(n+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - cdft(2*n, -1, a, ip, w); - is - cdft(2*n, 1, a, ip, w); - for (j = 0; j <= 2 * n - 1; j++) { - a[j] *= 1.0 / n; - } - . - - --------- Real DFT / Inverse of Real DFT -------- - [definition] - RDFT - R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 - I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) - a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + - sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + - sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k - ip[0] = 0; // first time only - rdft(n, 1, a, ip, w); - - ip[0] = 0; // first time only - rdft(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - - output data - a[2*k] = R[k], 0<=k - input data - a[2*j] = R[j], 0<=j= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - rdft(n, 1, a, ip, w); - is - rdft(n, -1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- - [definition] - IDCT (excluding scale) - C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT - C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k - ip[0] = 0; // first time only - ddct(n, 1, a, ip, w); - - ip[0] = 0; // first time only - ddct(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - output data - a[k] = C[k], 0<=k= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/4-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - ddct(n, -1, a, ip, w); - is - a[0] *= 0.5; - ddct(n, 1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- DST (Discrete Sine Transform) / Inverse of DST -------- - [definition] - IDST (excluding scale) - S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST - S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 - ip[0] = 0; // first time only - ddst(n, 1, a, ip, w); - - ip[0] = 0; // first time only - ddst(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - - input data - a[j] = A[j], 0 - output data - a[k] = S[k], 0= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/4-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - ddst(n, -1, a, ip, w); - is - a[0] *= 0.5; - ddst(n, 1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- Cosine Transform of RDFT (Real Symmetric DFT) -------- - [definition] - C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n - [usage] - ip[0] = 0; // first time only - dfct(n, a, t, ip, w); - [parameters] - n :data length - 1 (int) - n >= 2, n = power of 2 - a[0...n] :input/output data (double *) - output data - a[k] = C[k], 0<=k<=n - t[0...n/2] :work area (double *) - ip[0...*] :work area for bit reversal (int *) - length of ip >= 2+sqrt(n/4) - strictly, - length of ip >= - 2+(1<<(int)(log(n/4+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/8-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - a[0] *= 0.5; - a[n] *= 0.5; - dfct(n, a, t, ip, w); - is - a[0] *= 0.5; - a[n] *= 0.5; - dfct(n, a, t, ip, w); - for (j = 0; j <= n; j++) { - a[j] *= 2.0 / n; - } - . - - --------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- - [definition] - S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - output data - a[k] = S[k], 0= 2+sqrt(n/4) - strictly, - length of ip >= - 2+(1<<(int)(log(n/4+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/8-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - dfst(n, a, t, ip, w); - is - dfst(n, a, t, ip, w); - for (j = 1; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - -Appendix : - The cos/sin table is recalculated when the larger table required. - w[] and ip[] are compatible with all routines. -*/ - - -#include -#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 cdft lsx_cdft_f - #define rdft lsx_rdft_f - #define ddct lsx_ddct_f - #define ddst lsx_ddst_f - #define dfct lsx_dfct_f - #define dfst lsx_dfst_f -#else - #define one_half 0.5 - #define cdft lsx_cdft - #define rdft lsx_rdft - #define ddct lsx_ddct - #define ddst lsx_ddst - #define dfct lsx_dfct - #define dfst lsx_dfst -#endif - -static void bitrv2conj(int n, int *ip, double *a); -static void bitrv2(int n, int *ip, double *a); -static void cft1st(int n, double *a, double const *w); -static void cftbsub(int n, double *a, double const *w); -static void cftfsub(int n, double *a, double const *w); -static void cftmdl(int n, int l, double *a, double const *w); -static void dctsub(int n, double *a, int nc, double const *c); -static void dstsub(int n, double *a, int nc, double const *c); -static void makect(int nc, int *ip, double *c); -static void makewt(int nw, int *ip, double *w); -static void rftbsub(int n, double *a, int nc, double const *c); -static void rftfsub(int n, double *a, int nc, double const *c); - - -void cdft(int n, int isgn, double *a, int *ip, double *w) -{ - if (n > (ip[0] << 2)) { - makewt(n >> 2, ip, w); - } - if (n > 4) { - if (isgn >= 0) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - } else { - bitrv2conj(n, ip + 2, a); - cftbsub(n, a, w); - } - } else if (n == 4) { - cftfsub(n, a, w); - } -} - - -void rdft(int n, int isgn, double *a, int *ip, double *w) -{ - int nw, nc; - double xi; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 2)) { - nc = n >> 2; - makect(nc, ip, w + nw); - } - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xi = a[0] - a[1]; - a[0] += a[1]; - a[1] = xi; - } else { - a[1] = one_half * (a[0] - a[1]); - a[0] -= a[1]; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } -} - - -void ddct(int n, int isgn, double *a, int *ip, double *w) -{ - int j, nw, nc; - double xr; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = n; - makect(nc, ip, w + nw); - } - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = a[j] - a[j - 1]; - a[j] += a[j - 1]; - } - a[1] = a[0] - xr; - a[0] += xr; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } - dctsub(n, a, nc, w + nw); - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = a[j] - a[j + 1]; - a[j] += a[j + 1]; - } - a[n - 1] = xr; - } -} - - -void ddst(int n, int isgn, double *a, int *ip, double *w) -{ - int j, nw, nc; - double xr; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = n; - makect(nc, ip, w + nw); - } - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = -a[j] - a[j - 1]; - a[j] -= a[j - 1]; - } - a[1] = a[0] + xr; - a[0] -= xr; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } - dstsub(n, a, nc, w + nw); - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = -a[j] - a[j + 1]; - a[j] -= a[j + 1]; - } - a[n - 1] = -xr; - } -} - - -void dfct(int n, double *a, double *t, int *ip, double *w) -{ - int j, k, l, m, mh, nw, nc; - double xr, xi, yr, yi; - - nw = ip[0]; - if (n > (nw << 3)) { - nw = n >> 3; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 1)) { - nc = n >> 1; - makect(nc, ip, w + nw); - } - m = n >> 1; - yi = a[m]; - xi = a[0] + a[n]; - a[0] -= a[n]; - t[0] = xi - yi; - t[m] = xi + yi; - if (n > 2) { - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - xr = a[j] - a[n - j]; - xi = a[j] + a[n - j]; - yr = a[k] - a[n - k]; - yi = a[k] + a[n - k]; - a[j] = xr; - a[k] = yr; - t[j] = xi - yi; - t[k] = xi + yi; - } - t[mh] = a[mh] + a[n - mh]; - a[mh] -= a[n - mh]; - dctsub(m, a, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, a); - cftfsub(m, a, w); - rftfsub(m, a, nc, w + nw); - } else if (m == 4) { - cftfsub(m, a, w); - } - a[n - 1] = a[0] - a[1]; - a[1] = a[0] + a[1]; - for (j = m - 2; j >= 2; j -= 2) { - a[2 * j + 1] = a[j] + a[j + 1]; - a[2 * j - 1] = a[j] - a[j + 1]; - } - l = 2; - m = mh; - while (m >= 2) { - dctsub(m, t, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, t); - cftfsub(m, t, w); - rftfsub(m, t, nc, w + nw); - } else if (m == 4) { - cftfsub(m, t, w); - } - a[n - l] = t[0] - t[1]; - a[l] = t[0] + t[1]; - k = 0; - for (j = 2; j < m; j += 2) { - k += l << 2; - a[k - l] = t[j] - t[j + 1]; - a[k + l] = t[j] + t[j + 1]; - } - l <<= 1; - mh = m >> 1; - for (j = 0; j < mh; j++) { - k = m - j; - t[j] = t[m + k] - t[m + j]; - t[k] = t[m + k] + t[m + j]; - } - t[mh] = t[m + mh]; - m = mh; - } - a[l] = t[0]; - a[n] = t[2] - t[1]; - a[0] = t[2] + t[1]; - } else { - a[1] = a[0]; - a[2] = t[0]; - a[0] = t[1]; - } -} - - -void dfst(int n, double *a, double *t, int *ip, double *w) -{ - int j, k, l, m, mh, nw, nc; - double xr, xi, yr, yi; - - nw = ip[0]; - if (n > (nw << 3)) { - nw = n >> 3; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 1)) { - nc = n >> 1; - makect(nc, ip, w + nw); - } - if (n > 2) { - m = n >> 1; - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - xr = a[j] + a[n - j]; - xi = a[j] - a[n - j]; - yr = a[k] + a[n - k]; - yi = a[k] - a[n - k]; - a[j] = xr; - a[k] = yr; - t[j] = xi + yi; - t[k] = xi - yi; - } - t[0] = a[mh] - a[n - mh]; - a[mh] += a[n - mh]; - a[0] = a[m]; - dstsub(m, a, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, a); - cftfsub(m, a, w); - rftfsub(m, a, nc, w + nw); - } else if (m == 4) { - cftfsub(m, a, w); - } - a[n - 1] = a[1] - a[0]; - a[1] = a[0] + a[1]; - for (j = m - 2; j >= 2; j -= 2) { - a[2 * j + 1] = a[j] - a[j + 1]; - a[2 * j - 1] = -a[j] - a[j + 1]; - } - l = 2; - m = mh; - while (m >= 2) { - dstsub(m, t, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, t); - cftfsub(m, t, w); - rftfsub(m, t, nc, w + nw); - } else if (m == 4) { - cftfsub(m, t, w); - } - a[n - l] = t[1] - t[0]; - a[l] = t[0] + t[1]; - k = 0; - for (j = 2; j < m; j += 2) { - k += l << 2; - a[k - l] = -t[j] - t[j + 1]; - a[k + l] = t[j] - t[j + 1]; - } - l <<= 1; - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - t[j] = t[m + k] + t[m + j]; - t[k] = t[m + k] - t[m + j]; - } - t[0] = t[m + mh]; - m = mh; - } - a[l] = t[0]; - } - a[0] = 0; -} - - -/* -------- initializing routines -------- */ - - -static void makewt(int nw, int *ip, double *w) -{ - int j, nwh; - double delta, x, y; - - ip[0] = nw; - ip[1] = 1; - if (nw > 2) { - nwh = nw >> 1; - delta = atan(1.0) / (double)nwh; - w[0] = 1; - w[1] = 0; - w[nwh] = cos(delta * (double)nwh); - w[nwh + 1] = w[nwh]; - if (nwh > 2) { - for (j = 2; j < nwh; j += 2) { - x = cos(delta * (double)j); - y = sin(delta * (double)j); - w[j] = x; - w[j + 1] = y; - w[nw - j] = y; - w[nw - j + 1] = x; - } - bitrv2(nw, ip + 2, w); - } - } -} - - -static void makect(int nc, int *ip, double *c) -{ - int j, nch; - double delta; - - ip[1] = nc; - if (nc > 1) { - nch = nc >> 1; - delta = atan(1.0) / (double)nch; - c[0] = cos(delta * (double)nch); - c[nch] = one_half * c[0]; - for (j = 1; j < nch; j++) { - c[j] = one_half * cos(delta * (double)j); - c[nc - j] = one_half * sin(delta * (double)j); - } - } -} - - -/* -------- child routines -------- */ - - -static void bitrv2(int n, int *ip0, double *a) -{ - int j, j1, k, k1, l, m, m2, ip[1024]; - double xr, xi, yr, yi; - - (void)ip0; - ip[0] = 0; - l = n; - m = 1; - while ((m << 3) < l) { - l >>= 1; - for (j = 0; j < m; j++) { - ip[m + j] = ip[j] + l; - } - m <<= 1; - } - m2 = 2 * m; - if ((m << 3) == l) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - j1 = 2 * k + m2 + ip[k]; - k1 = j1 + m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } else { - for (k = 1; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } - } -} - - -static void bitrv2conj(int n, int *ip0, double *a) -{ - int j, j1, k, k1, l, m, m2, ip[256]; - double xr, xi, yr, yi; - - (void)ip0; - ip[0] = 0; - l = n; - m = 1; - while ((m << 3) < l) { - l >>= 1; - for (j = 0; j < m; j++) { - ip[m + j] = ip[j] + l; - } - m <<= 1; - } - m2 = 2 * m; - if ((m << 3) == l) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 -= m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 2 * k + ip[k]; - a[k1 + 1] = -a[k1 + 1]; - j1 = k1 + m2; - k1 = j1 + m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - k1 += m2; - a[k1 + 1] = -a[k1 + 1]; - } - } else { - a[1] = -a[1]; - a[m2 + 1] = -a[m2 + 1]; - for (k = 1; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 2 * k + ip[k]; - a[k1 + 1] = -a[k1 + 1]; - a[k1 + m2 + 1] = -a[k1 + m2 + 1]; - } - } -} - - -static void cftfsub(int n, double *a, double const *w) -{ - int j, j1, j2, j3, l; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - l = 2; - if (n > 8) { - cft1st(n, a, w); - l = 8; - while ((l << 2) < n) { - cftmdl(n, l, a, w); - l <<= 2; - } - } - if ((l << 2) == n) { - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i - x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - } - } else { - for (j = 0; j < l; j += 2) { - j1 = j + l; - x0r = a[j] - a[j1]; - x0i = a[j + 1] - a[j1 + 1]; - a[j] += a[j1]; - a[j + 1] += a[j1 + 1]; - a[j1] = x0r; - a[j1 + 1] = x0i; - } - } -} - - -static void cftbsub(int n, double *a, double const *w) -{ - int j, j1, j2, j3, l; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - l = 2; - if (n > 8) { - cft1st(n, a, w); - l = 8; - while ((l << 2) < n) { - cftmdl(n, l, a, w); - l <<= 2; - } - } - if ((l << 2) == n) { - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = -a[j + 1] - a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = -a[j + 1] + a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i - x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i + x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i - x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i + x3r; - } - } else { - for (j = 0; j < l; j += 2) { - j1 = j + l; - x0r = a[j] - a[j1]; - x0i = -a[j + 1] + a[j1 + 1]; - a[j] += a[j1]; - a[j + 1] = -a[j + 1] - a[j1 + 1]; - a[j1] = x0r; - a[j1 + 1] = x0i; - } - } -} - - -static void cft1st(int n, double *a, double const *w) -{ - int j, k1, k2; - double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[2]; - x0i = a[1] + a[3]; - x1r = a[0] - a[2]; - x1i = a[1] - a[3]; - x2r = a[4] + a[6]; - x2i = a[5] + a[7]; - x3r = a[4] - a[6]; - x3i = a[5] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[2] = x1r - x3i; - a[3] = x1i + x3r; - a[6] = x1r + x3i; - a[7] = x1i - x3r; - wk1r = w[2]; - x0r = a[8] + a[10]; - x0i = a[9] + a[11]; - x1r = a[8] - a[10]; - x1i = a[9] - a[11]; - x2r = a[12] + a[14]; - x2i = a[13] + a[15]; - x3r = a[12] - a[14]; - x3i = a[13] - a[15]; - a[8] = x0r + x2r; - a[9] = x0i + x2i; - a[12] = x2i - x0i; - a[13] = x0r - x2r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[10] = wk1r * (x0r - x0i); - a[11] = wk1r * (x0r + x0i); - x0r = x3i + x1r; - x0i = x3r - x1i; - a[14] = wk1r * (x0i - x0r); - a[15] = wk1r * (x0i + x0r); - k1 = 0; - for (j = 16; j < n; j += 16) { - k1 += 2; - k2 = 2 * k1; - wk2r = w[k1]; - wk2i = w[k1 + 1]; - wk1r = w[k2]; - wk1i = w[k2 + 1]; - wk3r = wk1r - 2 * wk2i * wk1i; - wk3i = 2 * wk2i * wk1r - wk1i; - x0r = a[j] + a[j + 2]; - x0i = a[j + 1] + a[j + 3]; - x1r = a[j] - a[j + 2]; - x1i = a[j + 1] - a[j + 3]; - x2r = a[j + 4] + a[j + 6]; - x2i = a[j + 5] + a[j + 7]; - x3r = a[j + 4] - a[j + 6]; - x3i = a[j + 5] - a[j + 7]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j + 4] = wk2r * x0r - wk2i * x0i; - a[j + 5] = wk2r * x0i + wk2i * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j + 2] = wk1r * x0r - wk1i * x0i; - a[j + 3] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j + 6] = wk3r * x0r - wk3i * x0i; - a[j + 7] = wk3r * x0i + wk3i * x0r; - wk1r = w[k2 + 2]; - wk1i = w[k2 + 3]; - wk3r = wk1r - 2 * wk2r * wk1i; - wk3i = 2 * wk2r * wk1r - wk1i; - x0r = a[j + 8] + a[j + 10]; - x0i = a[j + 9] + a[j + 11]; - x1r = a[j + 8] - a[j + 10]; - x1i = a[j + 9] - a[j + 11]; - x2r = a[j + 12] + a[j + 14]; - x2i = a[j + 13] + a[j + 15]; - x3r = a[j + 12] - a[j + 14]; - x3i = a[j + 13] - a[j + 15]; - a[j + 8] = x0r + x2r; - a[j + 9] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j + 12] = -wk2i * x0r - wk2r * x0i; - a[j + 13] = -wk2i * x0i + wk2r * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j + 10] = wk1r * x0r - wk1i * x0i; - a[j + 11] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j + 14] = wk3r * x0r - wk3i * x0i; - a[j + 15] = wk3r * x0i + wk3i * x0r; - } -} - - -static void cftmdl(int n, int l, double *a, double const *w) -{ - int j, j1, j2, j3, k, k1, k2, m, m2; - double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - m = l << 2; - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i - x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - } - wk1r = w[2]; - for (j = m; j < l + m; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x2i - x0i; - a[j2 + 1] = x0r - x2r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * (x0r - x0i); - a[j1 + 1] = wk1r * (x0r + x0i); - x0r = x3i + x1r; - x0i = x3r - x1i; - a[j3] = wk1r * (x0i - x0r); - a[j3 + 1] = wk1r * (x0i + x0r); - } - k1 = 0; - m2 = 2 * m; - for (k = m2; k < n; k += m2) { - k1 += 2; - k2 = 2 * k1; - wk2r = w[k1]; - wk2i = w[k1 + 1]; - wk1r = w[k2]; - wk1i = w[k2 + 1]; - wk3r = wk1r - 2 * wk2i * wk1i; - wk3i = 2 * wk2i * wk1r - wk1i; - for (j = k; j < l + k; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j2] = wk2r * x0r - wk2i * x0i; - a[j2 + 1] = wk2r * x0i + wk2i * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * x0r - wk1i * x0i; - a[j1 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r - wk3i * x0i; - a[j3 + 1] = wk3r * x0i + wk3i * x0r; - } - wk1r = w[k2 + 2]; - wk1i = w[k2 + 3]; - wk3r = wk1r - 2 * wk2r * wk1i; - wk3i = 2 * wk2r * wk1r - wk1i; - for (j = k + m; j < l + (k + m); j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j2] = -wk2i * x0r - wk2r * x0i; - a[j2 + 1] = -wk2i * x0i + wk2r * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * x0r - wk1i * x0i; - a[j1 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r - wk3i * x0i; - a[j3 + 1] = wk3r * x0i + wk3i * x0r; - } - } -} - - -static void rftfsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = one_half - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - } -} - - -static void rftbsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - - a[1] = -a[1]; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = one_half - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a[j] -= yr; - a[j + 1] = yi - a[j + 1]; - a[k] += yr; - a[k + 1] = yi - a[k + 1]; - } - a[m + 1] = -a[m + 1]; -} - - -static void dctsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr; - - m = n >> 1; - ks = nc / n; - kk = 0; - for (j = 1; j < m; j++) { - k = n - j; - kk += ks; - wkr = c[kk] - c[nc - kk]; - wki = c[kk] + c[nc - kk]; - xr = wki * a[j] - wkr * a[k]; - a[j] = wkr * a[j] + wki * a[k]; - a[k] = xr; - } - a[m] *= c[0]; -} - - -static void dstsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr; - - m = n >> 1; - ks = nc / n; - kk = 0; - for (j = 1; j < m; j++) { - k = n - j; - kk += ks; - wkr = c[kk] - c[nc - kk]; - wki = c[kk] + c[nc - kk]; - xr = wki * a[k] - wkr * a[j]; - a[k] = wkr * a[k] + wki * a[j]; - a[j] = xr; - } - a[m] *= c[0]; -} +/* Copyright Takuya OOURA, 1996-2001. + +You may use, copy, modify and distribute this code for any +purpose (include commercial use) and without fee. Please +refer to this package when you modify this code. + +Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + +Fast Fourier/Cosine/Sine Transform + dimension :one + data length :power of 2 + decimation :frequency + radix :4, 2 + data :inplace + table :use +functions + cdft: Complex Discrete Fourier Transform + rdft: Real Discrete Fourier Transform + ddct: Discrete Cosine Transform + ddst: Discrete Sine Transform + dfct: Cosine Transform of RDFT (Real Symmetric DFT) + dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) +function prototypes + void cdft(int, int, double *, int *, double *); + void rdft(int, int, double *, int *, double *); + void ddct(int, int, double *, int *, double *); + void ddst(int, int, double *, int *, double *); + void dfct(int, double *, double *, int *, double *); + void dfst(int, double *, double *, int *, double *); + + +-------- Complex DFT (Discrete Fourier Transform) -------- + [definition] + + X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k + X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k + ip[0] = 0; // first time only + cdft(2*n, 1, a, ip, w); + + ip[0] = 0; // first time only + cdft(2*n, -1, a, ip, w); + [parameters] + 2*n :data length (int) + n >= 1, n = power of 2 + a[0...2*n-1] :input/output data (double *) + input data + a[2*j] = Re(x[j]), + a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) + strictly, + length of ip >= + 2+(1<<(int)(log(n+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n/2-1] :cos/sin table (double *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + cdft(2*n, -1, a, ip, w); + is + cdft(2*n, 1, a, ip, w); + for (j = 0; j <= 2 * n - 1; j++) { + a[j] *= 1.0 / n; + } + . + + +-------- Real DFT / Inverse of Real DFT -------- + [definition] + RDFT + R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 + I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) + a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k + ip[0] = 0; // first time only + rdft(n, 1, a, ip, w); + + ip[0] = 0; // first time only + rdft(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (double *) + + output data + a[2*k] = R[k], 0<=k + input data + a[2*j] = R[j], 0<=j= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n/2-1] :cos/sin table (double *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + rdft(n, 1, a, ip, w); + is + rdft(n, -1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- + [definition] + IDCT (excluding scale) + C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT + C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k + ip[0] = 0; // first time only + ddct(n, 1, a, ip, w); + + ip[0] = 0; // first time only + ddct(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (double *) + output data + a[k] = C[k], 0<=k= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/4-1] :cos/sin table (double *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + ddct(n, -1, a, ip, w); + is + a[0] *= 0.5; + ddct(n, 1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- DST (Discrete Sine Transform) / Inverse of DST -------- + [definition] + IDST (excluding scale) + S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST + S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 + ip[0] = 0; // first time only + ddst(n, 1, a, ip, w); + + ip[0] = 0; // first time only + ddst(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (double *) + + input data + a[j] = A[j], 0 + output data + a[k] = S[k], 0= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/4-1] :cos/sin table (double *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + ddst(n, -1, a, ip, w); + is + a[0] *= 0.5; + ddst(n, 1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- Cosine Transform of RDFT (Real Symmetric DFT) -------- + [definition] + C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n + [usage] + ip[0] = 0; // first time only + dfct(n, a, t, ip, w); + [parameters] + n :data length - 1 (int) + n >= 2, n = power of 2 + a[0...n] :input/output data (double *) + output data + a[k] = C[k], 0<=k<=n + t[0...n/2] :work area (double *) + ip[0...*] :work area for bit reversal (int *) + length of ip >= 2+sqrt(n/4) + strictly, + length of ip >= + 2+(1<<(int)(log(n/4+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/8-1] :cos/sin table (double *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + a[0] *= 0.5; + a[n] *= 0.5; + dfct(n, a, t, ip, w); + is + a[0] *= 0.5; + a[n] *= 0.5; + dfct(n, a, t, ip, w); + for (j = 0; j <= n; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- + [definition] + S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 + a[0...n-1] :input/output data (double *) + output data + a[k] = S[k], 0= 2+sqrt(n/4) + strictly, + length of ip >= + 2+(1<<(int)(log(n/4+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/8-1] :cos/sin table (double *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + dfst(n, a, t, ip, w); + is + dfst(n, a, t, ip, w); + for (j = 1; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +Appendix : + The cos/sin table is recalculated when the larger table required. + w[] and ip[] are compatible with all routines. +*/ + + +#include +#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 cdft lsx_cdft_f + #define rdft lsx_rdft_f + #define ddct lsx_ddct_f + #define ddst lsx_ddst_f + #define dfct lsx_dfct_f + #define dfst lsx_dfst_f +#else + #define one_half 0.5 + #define cdft lsx_cdft + #define rdft lsx_rdft + #define ddct lsx_ddct + #define ddst lsx_ddst + #define dfct lsx_dfct + #define dfst lsx_dfst +#endif + +static void bitrv2conj(int n, int *ip, double *a); +static void bitrv2(int n, int *ip, double *a); +static void cft1st(int n, double *a, double const *w); +static void cftbsub(int n, double *a, double const *w); +static void cftfsub(int n, double *a, double const *w); +static void cftmdl(int n, int l, double *a, double const *w); +static void dctsub(int n, double *a, int nc, double const *c); +static void dstsub(int n, double *a, int nc, double const *c); +static void makect(int nc, int *ip, double *c); +static void makewt(int nw, int *ip, double *w); +static void rftbsub(int n, double *a, int nc, double const *c); +static void rftfsub(int n, double *a, int nc, double const *c); + + +void cdft(int n, int isgn, double *a, int *ip, double *w) +{ + if (n > (ip[0] << 2)) { + makewt(n >> 2, ip, w); + } + if (n > 4) { + if (isgn >= 0) { + bitrv2(n, ip + 2, a); + cftfsub(n, a, w); + } else { + bitrv2conj(n, ip + 2, a); + cftbsub(n, a, w); + } + } else if (n == 4) { + cftfsub(n, a, w); + } +} + + +void rdft(int n, int isgn, double *a, int *ip, double *w) +{ + int nw, nc; + double xi; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 2)) { + nc = n >> 2; + makect(nc, ip, w + nw); + } + if (isgn >= 0) { + if (n > 4) { + bitrv2(n, ip + 2, a); + cftfsub(n, a, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, w); + } + xi = a[0] - a[1]; + a[0] += a[1]; + a[1] = xi; + } else { + a[1] = one_half * (a[0] - a[1]); + a[0] -= a[1]; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + bitrv2(n, ip + 2, a); + cftbsub(n, a, w); + } else if (n == 4) { + cftfsub(n, a, w); + } + } +} + + +void ddct(int n, int isgn, double *a, int *ip, double *w) +{ + int j, nw, nc; + double xr; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > nc) { + nc = n; + makect(nc, ip, w + nw); + } + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = a[j] - a[j - 1]; + a[j] += a[j - 1]; + } + a[1] = a[0] - xr; + a[0] += xr; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + bitrv2(n, ip + 2, a); + cftbsub(n, a, w); + } else if (n == 4) { + cftfsub(n, a, w); + } + } + dctsub(n, a, nc, w + nw); + if (isgn >= 0) { + if (n > 4) { + bitrv2(n, ip + 2, a); + cftfsub(n, a, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = a[j] - a[j + 1]; + a[j] += a[j + 1]; + } + a[n - 1] = xr; + } +} + + +void ddst(int n, int isgn, double *a, int *ip, double *w) +{ + int j, nw, nc; + double xr; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > nc) { + nc = n; + makect(nc, ip, w + nw); + } + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = -a[j] - a[j - 1]; + a[j] -= a[j - 1]; + } + a[1] = a[0] + xr; + a[0] -= xr; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + bitrv2(n, ip + 2, a); + cftbsub(n, a, w); + } else if (n == 4) { + cftfsub(n, a, w); + } + } + dstsub(n, a, nc, w + nw); + if (isgn >= 0) { + if (n > 4) { + bitrv2(n, ip + 2, a); + cftfsub(n, a, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = -a[j] - a[j + 1]; + a[j] -= a[j + 1]; + } + a[n - 1] = -xr; + } +} + + +void dfct(int n, double *a, double *t, int *ip, double *w) +{ + int j, k, l, m, mh, nw, nc; + double xr, xi, yr, yi; + + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 1)) { + nc = n >> 1; + makect(nc, ip, w + nw); + } + m = n >> 1; + yi = a[m]; + xi = a[0] + a[n]; + a[0] -= a[n]; + t[0] = xi - yi; + t[m] = xi + yi; + if (n > 2) { + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + xr = a[j] - a[n - j]; + xi = a[j] + a[n - j]; + yr = a[k] - a[n - k]; + yi = a[k] + a[n - k]; + a[j] = xr; + a[k] = yr; + t[j] = xi - yi; + t[k] = xi + yi; + } + t[mh] = a[mh] + a[n - mh]; + a[mh] -= a[n - mh]; + dctsub(m, a, nc, w + nw); + if (m > 4) { + bitrv2(m, ip + 2, a); + cftfsub(m, a, w); + rftfsub(m, a, nc, w + nw); + } else if (m == 4) { + cftfsub(m, a, w); + } + a[n - 1] = a[0] - a[1]; + a[1] = a[0] + a[1]; + for (j = m - 2; j >= 2; j -= 2) { + a[2 * j + 1] = a[j] + a[j + 1]; + a[2 * j - 1] = a[j] - a[j + 1]; + } + l = 2; + m = mh; + while (m >= 2) { + dctsub(m, t, nc, w + nw); + if (m > 4) { + bitrv2(m, ip + 2, t); + cftfsub(m, t, w); + rftfsub(m, t, nc, w + nw); + } else if (m == 4) { + cftfsub(m, t, w); + } + a[n - l] = t[0] - t[1]; + a[l] = t[0] + t[1]; + k = 0; + for (j = 2; j < m; j += 2) { + k += l << 2; + a[k - l] = t[j] - t[j + 1]; + a[k + l] = t[j] + t[j + 1]; + } + l <<= 1; + mh = m >> 1; + for (j = 0; j < mh; j++) { + k = m - j; + t[j] = t[m + k] - t[m + j]; + t[k] = t[m + k] + t[m + j]; + } + t[mh] = t[m + mh]; + m = mh; + } + a[l] = t[0]; + a[n] = t[2] - t[1]; + a[0] = t[2] + t[1]; + } else { + a[1] = a[0]; + a[2] = t[0]; + a[0] = t[1]; + } +} + + +void dfst(int n, double *a, double *t, int *ip, double *w) +{ + int j, k, l, m, mh, nw, nc; + double xr, xi, yr, yi; + + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 1)) { + nc = n >> 1; + makect(nc, ip, w + nw); + } + if (n > 2) { + m = n >> 1; + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + xr = a[j] + a[n - j]; + xi = a[j] - a[n - j]; + yr = a[k] + a[n - k]; + yi = a[k] - a[n - k]; + a[j] = xr; + a[k] = yr; + t[j] = xi + yi; + t[k] = xi - yi; + } + t[0] = a[mh] - a[n - mh]; + a[mh] += a[n - mh]; + a[0] = a[m]; + dstsub(m, a, nc, w + nw); + if (m > 4) { + bitrv2(m, ip + 2, a); + cftfsub(m, a, w); + rftfsub(m, a, nc, w + nw); + } else if (m == 4) { + cftfsub(m, a, w); + } + a[n - 1] = a[1] - a[0]; + a[1] = a[0] + a[1]; + for (j = m - 2; j >= 2; j -= 2) { + a[2 * j + 1] = a[j] - a[j + 1]; + a[2 * j - 1] = -a[j] - a[j + 1]; + } + l = 2; + m = mh; + while (m >= 2) { + dstsub(m, t, nc, w + nw); + if (m > 4) { + bitrv2(m, ip + 2, t); + cftfsub(m, t, w); + rftfsub(m, t, nc, w + nw); + } else if (m == 4) { + cftfsub(m, t, w); + } + a[n - l] = t[1] - t[0]; + a[l] = t[0] + t[1]; + k = 0; + for (j = 2; j < m; j += 2) { + k += l << 2; + a[k - l] = -t[j] - t[j + 1]; + a[k + l] = t[j] - t[j + 1]; + } + l <<= 1; + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + t[j] = t[m + k] + t[m + j]; + t[k] = t[m + k] - t[m + j]; + } + t[0] = t[m + mh]; + m = mh; + } + a[l] = t[0]; + } + a[0] = 0; +} + + +/* -------- initializing routines -------- */ + + +static void makewt(int nw, int *ip, double *w) +{ + int j, nwh; + double delta, x, y; + + ip[0] = nw; + ip[1] = 1; + if (nw > 2) { + nwh = nw >> 1; + delta = atan(1.0) / (double)nwh; + w[0] = 1; + w[1] = 0; + w[nwh] = cos(delta * (double)nwh); + w[nwh + 1] = w[nwh]; + if (nwh > 2) { + for (j = 2; j < nwh; j += 2) { + x = cos(delta * (double)j); + y = sin(delta * (double)j); + w[j] = x; + w[j + 1] = y; + w[nw - j] = y; + w[nw - j + 1] = x; + } + bitrv2(nw, ip + 2, w); + } + } +} + + +static void makect(int nc, int *ip, double *c) +{ + int j, nch; + double delta; + + ip[1] = nc; + if (nc > 1) { + nch = nc >> 1; + delta = atan(1.0) / (double)nch; + c[0] = cos(delta * (double)nch); + c[nch] = one_half * c[0]; + for (j = 1; j < nch; j++) { + c[j] = one_half * cos(delta * (double)j); + c[nc - j] = one_half * sin(delta * (double)j); + } + } +} + + +/* -------- child routines -------- */ + + +static void bitrv2(int n, int *ip0, double *a) +{ + int j, j1, k, k1, l, m, m2, ip[1024]; + double xr, xi, yr, yi; + + (void)ip0; + ip[0] = 0; + l = n; + m = 1; + while ((m << 3) < l) { + l >>= 1; + for (j = 0; j < m; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + m2 = 2 * m; + if ((m << 3) == l) { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + j1 = 2 * k + m2 + ip[k]; + k1 = j1 + m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } else { + for (k = 1; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } +} + + +static void bitrv2conj(int n, int *ip0, double *a) +{ + int j, j1, k, k1, l, m, m2, ip[256]; + double xr, xi, yr, yi; + + (void)ip0; + ip[0] = 0; + l = n; + m = 1; + while ((m << 3) < l) { + l >>= 1; + for (j = 0; j < m; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + m2 = 2 * m; + if ((m << 3) == l) { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 -= m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 2 * k + ip[k]; + a[k1 + 1] = -a[k1 + 1]; + j1 = k1 + m2; + k1 = j1 + m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + k1 += m2; + a[k1 + 1] = -a[k1 + 1]; + } + } else { + a[1] = -a[1]; + a[m2 + 1] = -a[m2 + 1]; + for (k = 1; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 2 * k + ip[k]; + a[k1 + 1] = -a[k1 + 1]; + a[k1 + m2 + 1] = -a[k1 + m2 + 1]; + } + } +} + + +static void cftfsub(int n, double *a, double const *w) +{ + int j, j1, j2, j3, l; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + if (n > 8) { + cft1st(n, a, w); + l = 8; + while ((l << 2) < n) { + cftmdl(n, l, a, w); + l <<= 2; + } + } + if ((l << 2) == n) { + for (j = 0; j < l; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i - x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + } + } else { + for (j = 0; j < l; j += 2) { + j1 = j + l; + x0r = a[j] - a[j1]; + x0i = a[j + 1] - a[j1 + 1]; + a[j] += a[j1]; + a[j + 1] += a[j1 + 1]; + a[j1] = x0r; + a[j1 + 1] = x0i; + } + } +} + + +static void cftbsub(int n, double *a, double const *w) +{ + int j, j1, j2, j3, l; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + if (n > 8) { + cft1st(n, a, w); + l = 8; + while ((l << 2) < n) { + cftmdl(n, l, a, w); + l <<= 2; + } + } + if ((l << 2) == n) { + for (j = 0; j < l; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = -a[j + 1] - a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = -a[j + 1] + a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i - x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i + x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i - x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i + x3r; + } + } else { + for (j = 0; j < l; j += 2) { + j1 = j + l; + x0r = a[j] - a[j1]; + x0i = -a[j + 1] + a[j1 + 1]; + a[j] += a[j1]; + a[j + 1] = -a[j + 1] - a[j1 + 1]; + a[j1] = x0r; + a[j1 + 1] = x0i; + } + } +} + + +static void cft1st(int n, double *a, double const *w) +{ + int j, k1, k2; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[2]; + x0i = a[1] + a[3]; + x1r = a[0] - a[2]; + x1i = a[1] - a[3]; + x2r = a[4] + a[6]; + x2i = a[5] + a[7]; + x3r = a[4] - a[6]; + x3i = a[5] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[2] = x1r - x3i; + a[3] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; + wk1r = w[2]; + x0r = a[8] + a[10]; + x0i = a[9] + a[11]; + x1r = a[8] - a[10]; + x1i = a[9] - a[11]; + x2r = a[12] + a[14]; + x2i = a[13] + a[15]; + x3r = a[12] - a[14]; + x3i = a[13] - a[15]; + a[8] = x0r + x2r; + a[9] = x0i + x2i; + a[12] = x2i - x0i; + a[13] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[10] = wk1r * (x0r - x0i); + a[11] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[14] = wk1r * (x0i - x0r); + a[15] = wk1r * (x0i + x0r); + k1 = 0; + for (j = 16; j < n; j += 16) { + k1 += 2; + k2 = 2 * k1; + wk2r = w[k1]; + wk2i = w[k1 + 1]; + wk1r = w[k2]; + wk1i = w[k2 + 1]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + x0r = a[j] + a[j + 2]; + x0i = a[j + 1] + a[j + 3]; + x1r = a[j] - a[j + 2]; + x1i = a[j + 1] - a[j + 3]; + x2r = a[j + 4] + a[j + 6]; + x2i = a[j + 5] + a[j + 7]; + x3r = a[j + 4] - a[j + 6]; + x3i = a[j + 5] - a[j + 7]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j + 4] = wk2r * x0r - wk2i * x0i; + a[j + 5] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j + 2] = wk1r * x0r - wk1i * x0i; + a[j + 3] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j + 6] = wk3r * x0r - wk3i * x0i; + a[j + 7] = wk3r * x0i + wk3i * x0r; + wk1r = w[k2 + 2]; + wk1i = w[k2 + 3]; + wk3r = wk1r - 2 * wk2r * wk1i; + wk3i = 2 * wk2r * wk1r - wk1i; + x0r = a[j + 8] + a[j + 10]; + x0i = a[j + 9] + a[j + 11]; + x1r = a[j + 8] - a[j + 10]; + x1i = a[j + 9] - a[j + 11]; + x2r = a[j + 12] + a[j + 14]; + x2i = a[j + 13] + a[j + 15]; + x3r = a[j + 12] - a[j + 14]; + x3i = a[j + 13] - a[j + 15]; + a[j + 8] = x0r + x2r; + a[j + 9] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j + 12] = -wk2i * x0r - wk2r * x0i; + a[j + 13] = -wk2i * x0i + wk2r * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j + 10] = wk1r * x0r - wk1i * x0i; + a[j + 11] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j + 14] = wk3r * x0r - wk3i * x0i; + a[j + 15] = wk3r * x0i + wk3i * x0r; + } +} + + +static void cftmdl(int n, int l, double *a, double const *w) +{ + int j, j1, j2, j3, k, k1, k2, m, m2; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + m = l << 2; + for (j = 0; j < l; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i - x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + } + wk1r = w[2]; + for (j = m; j < l + m; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x2i - x0i; + a[j2 + 1] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * (x0r - x0i); + a[j1 + 1] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[j3] = wk1r * (x0i - x0r); + a[j3 + 1] = wk1r * (x0i + x0r); + } + k1 = 0; + m2 = 2 * m; + for (k = m2; k < n; k += m2) { + k1 += 2; + k2 = 2 * k1; + wk2r = w[k1]; + wk2i = w[k1 + 1]; + wk1r = w[k2]; + wk1i = w[k2 + 1]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for (j = k; j < l + k; j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2] = wk2r * x0r - wk2i * x0i; + a[j2 + 1] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * x0r - wk1i * x0i; + a[j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r - wk3i * x0i; + a[j3 + 1] = wk3r * x0i + wk3i * x0r; + } + wk1r = w[k2 + 2]; + wk1i = w[k2 + 3]; + wk3r = wk1r - 2 * wk2r * wk1i; + wk3i = 2 * wk2r * wk1r - wk1i; + for (j = k + m; j < l + (k + m); j += 2) { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2] = -wk2i * x0r - wk2r * x0i; + a[j2 + 1] = -wk2i * x0i + wk2r * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * x0r - wk1i * x0i; + a[j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r - wk3i * x0i; + a[j3 + 1] = wk3r * x0i + wk3i * x0r; + } + } +} + + +static void rftfsub(int n, double *a, int nc, double const *c) +{ + int j, k, kk, ks, m; + double wkr, wki, xr, xi, yr, yi; + + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) { + k = n - j; + kk += ks; + wkr = one_half - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr - wki * xi; + yi = wkr * xi + wki * xr; + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + } +} + + +static void rftbsub(int n, double *a, int nc, double const *c) +{ + int j, k, kk, ks, m; + double wkr, wki, xr, xi, yr, yi; + + a[1] = -a[1]; + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) { + k = n - j; + kk += ks; + wkr = one_half - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr + wki * xi; + yi = wkr * xi - wki * xr; + a[j] -= yr; + a[j + 1] = yi - a[j + 1]; + a[k] += yr; + a[k + 1] = yi - a[k + 1]; + } + a[m + 1] = -a[m + 1]; +} + + +static void dctsub(int n, double *a, int nc, double const *c) +{ + int j, k, kk, ks, m; + double wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[j] - wkr * a[k]; + a[j] = wkr * a[j] + wki * a[k]; + a[k] = xr; + } + a[m] *= c[0]; +} + + +static void dstsub(int n, double *a, int nc, double const *c) +{ + int j, k, kk, ks, m; + double wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[k] - wkr * a[j]; + a[k] = wkr * a[k] + wki * a[j]; + a[j] = xr; + } + a[m] *= c[0]; +} diff --git a/lib-src/libsoxr/src/fft4g.h b/lib-src/libsoxr/src/fft4g.h index 6b4982397..0f906abcf 100644 --- a/lib-src/libsoxr/src/fft4g.h +++ b/lib-src/libsoxr/src/fft4g.h @@ -1,23 +1,23 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -void lsx_cdft(int, int, double *, int *, double *); -void lsx_rdft(int, int, double *, int *, double *); -void lsx_ddct(int, int, double *, int *, double *); -void lsx_ddst(int, int, double *, int *, double *); -void lsx_dfct(int, double *, double *, int *, double *); -void lsx_dfst(int, double *, double *, int *, double *); - -void lsx_cdft_f(int, int, float *, int *, float *); -void lsx_rdft_f(int, int, float *, int *, float *); -void lsx_ddct_f(int, int, float *, int *, float *); -void lsx_ddst_f(int, int, float *, int *, float *); -void lsx_dfct_f(int, float *, float *, int *, float *); -void lsx_dfst_f(int, float *, float *, int *, float *); - -#define dft_br_len(l) (2ul + (1ul << (int)(log(l / 2 + .5) / log(2.)) / 2)) -#define dft_sc_len(l) ((unsigned long)l / 2) - -/* Over-allocate h by 2 to use these macros */ -#define LSX_PACK(h, n) h[1] = h[n] -#define LSX_UNPACK(h, n) h[n] = h[1], h[n + 1] = h[1] = 0; +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +void lsx_cdft(int, int, double *, int *, double *); +void lsx_rdft(int, int, double *, int *, double *); +void lsx_ddct(int, int, double *, int *, double *); +void lsx_ddst(int, int, double *, int *, double *); +void lsx_dfct(int, double *, double *, int *, double *); +void lsx_dfst(int, double *, double *, int *, double *); + +void lsx_cdft_f(int, int, float *, int *, float *); +void lsx_rdft_f(int, int, float *, int *, float *); +void lsx_ddct_f(int, int, float *, int *, float *); +void lsx_ddst_f(int, int, float *, int *, float *); +void lsx_dfct_f(int, float *, float *, int *, float *); +void lsx_dfst_f(int, float *, float *, int *, float *); + +#define dft_br_len(l) (2ul + (1ul << (int)(log(l / 2 + .5) / log(2.)) / 2)) +#define dft_sc_len(l) ((unsigned long)l / 2) + +/* Over-allocate h by 2 to use these macros */ +#define LSX_PACK(h, n) h[1] = h[n] +#define LSX_UNPACK(h, n) h[n] = h[1], h[n + 1] = h[1] = 0; diff --git a/lib-src/libsoxr/src/fft4g32.c b/lib-src/libsoxr/src/fft4g32.c index 4a428bac5..8741394ed 100644 --- a/lib-src/libsoxr/src/fft4g32.c +++ b/lib-src/libsoxr/src/fft4g32.c @@ -1,27 +1,27 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "filter.h" -#define FFT4G_FLOAT -#include "fft4g.c" - -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) {} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft32_cb[] = { - (fn_t)null, - (fn_t)null, - (fn_t)nothing, - (fn_t)forward, - (fn_t)forward, - (fn_t)backward, - (fn_t)backward, - (fn_t)_soxr_ordered_convolve_f, - (fn_t)_soxr_ordered_partial_convolve_f, - (fn_t)multiplier, - (fn_t)nothing, -}; +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include "filter.h" +#define FFT4G_FLOAT +#include "fft4g.c" + +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) {} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft32_cb[] = { + (fn_t)null, + (fn_t)null, + (fn_t)nothing, + (fn_t)forward, + (fn_t)forward, + (fn_t)backward, + (fn_t)backward, + (fn_t)_soxr_ordered_convolve_f, + (fn_t)_soxr_ordered_partial_convolve_f, + (fn_t)multiplier, + (fn_t)nothing, +}; diff --git a/lib-src/libsoxr/src/fft4g32s.c b/lib-src/libsoxr/src/fft4g32s.c index c95f6fb8f..4a95a7d1d 100644 --- a/lib-src/libsoxr/src/fft4g32s.c +++ b/lib-src/libsoxr/src/fft4g32s.c @@ -1,26 +1,26 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "filter.h" -#include "simd.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;} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft32s_cb[] = { - (fn_t)null, - (fn_t)null, - (fn_t)nothing, - (fn_t)forward, - (fn_t)forward, - (fn_t)backward, - (fn_t)backward, - (fn_t)_soxr_ordered_convolve_simd, - (fn_t)_soxr_ordered_partial_convolve_simd, - (fn_t)multiplier, - (fn_t)nothing, -}; +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include "filter.h" +#include "simd.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;} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft32s_cb[] = { + (fn_t)null, + (fn_t)null, + (fn_t)nothing, + (fn_t)forward, + (fn_t)forward, + (fn_t)backward, + (fn_t)backward, + (fn_t)_soxr_ordered_convolve_simd, + (fn_t)_soxr_ordered_partial_convolve_simd, + (fn_t)multiplier, + (fn_t)nothing, +}; diff --git a/lib-src/libsoxr/src/fft4g64.c b/lib-src/libsoxr/src/fft4g64.c index d85e255bb..48eadddea 100644 --- a/lib-src/libsoxr/src/fft4g64.c +++ b/lib-src/libsoxr/src/fft4g64.c @@ -1,29 +1,29 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "filter.h" -#include "fft4g.c" -#include "soxr-config.h" - -#if HAVE_DOUBLE_PRECISION -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;} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft64_cb[] = { - (fn_t)null, - (fn_t)null, - (fn_t)nothing, - (fn_t)forward, - (fn_t)forward, - (fn_t)backward, - (fn_t)backward, - (fn_t)_soxr_ordered_convolve, - (fn_t)_soxr_ordered_partial_convolve, - (fn_t)multiplier, - (fn_t)nothing, -}; -#endif +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include "filter.h" +#include "fft4g.c" +#include "soxr-config.h" + +#if HAVE_DOUBLE_PRECISION +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;} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft64_cb[] = { + (fn_t)null, + (fn_t)null, + (fn_t)nothing, + (fn_t)forward, + (fn_t)forward, + (fn_t)backward, + (fn_t)backward, + (fn_t)_soxr_ordered_convolve, + (fn_t)_soxr_ordered_partial_convolve, + (fn_t)multiplier, + (fn_t)nothing, +}; +#endif diff --git a/lib-src/libsoxr/src/fft4g_cache.h b/lib-src/libsoxr/src/fft4g_cache.h index 7f62ab28f..d776c16c4 100644 --- a/lib-src/libsoxr/src/fft4g_cache.h +++ b/lib-src/libsoxr/src/fft4g_cache.h @@ -1,92 +1,92 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -static int * LSX_FFT_BR; -static DFT_FLOAT * LSX_FFT_SC; -static int FFT_LEN = -1; -static ccrw2_t FFT_CACHE_CCRW; - -void LSX_INIT_FFT_CACHE(void) -{ - if (FFT_LEN >= 0) - return; - assert(LSX_FFT_BR == NULL); - assert(LSX_FFT_SC == NULL); - assert(FFT_LEN == -1); - ccrw2_init(FFT_CACHE_CCRW); - FFT_LEN = 0; -} - -void LSX_CLEAR_FFT_CACHE(void) -{ - assert(FFT_LEN >= 0); - ccrw2_clear(FFT_CACHE_CCRW); - free(LSX_FFT_BR); - free(LSX_FFT_SC); - LSX_FFT_SC = NULL; - LSX_FFT_BR = NULL; - FFT_LEN = -1; -} - -static bool UPDATE_FFT_CACHE(int len) -{ - LSX_INIT_FFT_CACHE(); - assert(lsx_is_power_of_2(len)); - assert(FFT_LEN >= 0); - ccrw2_become_reader(FFT_CACHE_CCRW); - if (len > FFT_LEN) { - ccrw2_cease_reading(FFT_CACHE_CCRW); - ccrw2_become_writer(FFT_CACHE_CCRW); - if (len > FFT_LEN) { - int old_n = FFT_LEN; - FFT_LEN = len; - LSX_FFT_BR = realloc(LSX_FFT_BR, dft_br_len(FFT_LEN) * sizeof(*LSX_FFT_BR)); - LSX_FFT_SC = realloc(LSX_FFT_SC, dft_sc_len(FFT_LEN) * sizeof(*LSX_FFT_SC)); - if (!old_n) { - LSX_FFT_BR[0] = 0; -#if SOXR_LIB - atexit(LSX_CLEAR_FFT_CACHE); -#endif - } - return true; - } - ccrw2_cease_writing(FFT_CACHE_CCRW); - ccrw2_become_reader(FFT_CACHE_CCRW); - } - return false; -} - -static void DONE_WITH_FFT_CACHE(bool is_writer) -{ - if (is_writer) - ccrw2_cease_writing(FFT_CACHE_CCRW); - else ccrw2_cease_reading(FFT_CACHE_CCRW); -} - -void LSX_SAFE_RDFT(int len, int type, DFT_FLOAT * d) -{ - bool is_writer = UPDATE_FFT_CACHE(len); - LSX_RDFT(len, type, d, LSX_FFT_BR, LSX_FFT_SC); - DONE_WITH_FFT_CACHE(is_writer); -} - -void LSX_SAFE_CDFT(int len, int type, DFT_FLOAT * d) -{ - bool is_writer = UPDATE_FFT_CACHE(len); - LSX_CDFT(len, type, d, LSX_FFT_BR, LSX_FFT_SC); - DONE_WITH_FFT_CACHE(is_writer); -} - -#undef UPDATE_FFT_CACHE -#undef LSX_SAFE_RDFT -#undef LSX_SAFE_CDFT -#undef LSX_RDFT -#undef LSX_INIT_FFT_CACHE -#undef LSX_FFT_SC -#undef LSX_FFT_BR -#undef LSX_CLEAR_FFT_CACHE -#undef LSX_CDFT -#undef FFT_LEN -#undef FFT_CACHE_CCRW -#undef DONE_WITH_FFT_CACHE -#undef DFT_FLOAT +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +static int * LSX_FFT_BR; +static DFT_FLOAT * LSX_FFT_SC; +static int FFT_LEN = -1; +static ccrw2_t FFT_CACHE_CCRW; + +void LSX_INIT_FFT_CACHE(void) +{ + if (FFT_LEN >= 0) + return; + assert(LSX_FFT_BR == NULL); + assert(LSX_FFT_SC == NULL); + assert(FFT_LEN == -1); + ccrw2_init(FFT_CACHE_CCRW); + FFT_LEN = 0; +} + +void LSX_CLEAR_FFT_CACHE(void) +{ + assert(FFT_LEN >= 0); + ccrw2_clear(FFT_CACHE_CCRW); + free(LSX_FFT_BR); + free(LSX_FFT_SC); + LSX_FFT_SC = NULL; + LSX_FFT_BR = NULL; + FFT_LEN = -1; +} + +static bool UPDATE_FFT_CACHE(int len) +{ + LSX_INIT_FFT_CACHE(); + assert(lsx_is_power_of_2(len)); + assert(FFT_LEN >= 0); + ccrw2_become_reader(FFT_CACHE_CCRW); + if (len > FFT_LEN) { + ccrw2_cease_reading(FFT_CACHE_CCRW); + ccrw2_become_writer(FFT_CACHE_CCRW); + if (len > FFT_LEN) { + int old_n = FFT_LEN; + FFT_LEN = len; + LSX_FFT_BR = realloc(LSX_FFT_BR, dft_br_len(FFT_LEN) * sizeof(*LSX_FFT_BR)); + LSX_FFT_SC = realloc(LSX_FFT_SC, dft_sc_len(FFT_LEN) * sizeof(*LSX_FFT_SC)); + if (!old_n) { + LSX_FFT_BR[0] = 0; +#if SOXR_LIB + atexit(LSX_CLEAR_FFT_CACHE); +#endif + } + return true; + } + ccrw2_cease_writing(FFT_CACHE_CCRW); + ccrw2_become_reader(FFT_CACHE_CCRW); + } + return false; +} + +static void DONE_WITH_FFT_CACHE(bool is_writer) +{ + if (is_writer) + ccrw2_cease_writing(FFT_CACHE_CCRW); + else ccrw2_cease_reading(FFT_CACHE_CCRW); +} + +void LSX_SAFE_RDFT(int len, int type, DFT_FLOAT * d) +{ + bool is_writer = UPDATE_FFT_CACHE(len); + LSX_RDFT(len, type, d, LSX_FFT_BR, LSX_FFT_SC); + DONE_WITH_FFT_CACHE(is_writer); +} + +void LSX_SAFE_CDFT(int len, int type, DFT_FLOAT * d) +{ + bool is_writer = UPDATE_FFT_CACHE(len); + LSX_CDFT(len, type, d, LSX_FFT_BR, LSX_FFT_SC); + DONE_WITH_FFT_CACHE(is_writer); +} + +#undef UPDATE_FFT_CACHE +#undef LSX_SAFE_RDFT +#undef LSX_SAFE_CDFT +#undef LSX_RDFT +#undef LSX_INIT_FFT_CACHE +#undef LSX_FFT_SC +#undef LSX_FFT_BR +#undef LSX_CLEAR_FFT_CACHE +#undef LSX_CDFT +#undef FFT_LEN +#undef FFT_CACHE_CCRW +#undef DONE_WITH_FFT_CACHE +#undef DFT_FLOAT diff --git a/lib-src/libsoxr/src/fifo.h b/lib-src/libsoxr/src/fifo.h index e4760c450..b2bda43e7 100644 --- a/lib-src/libsoxr/src/fifo.h +++ b/lib-src/libsoxr/src/fifo.h @@ -1,124 +1,124 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#ifndef fifo_included -#define fifo_included - -#if !defined FIFO_SIZE_T -#define FIFO_SIZE_T size_t -#endif - -#if !defined FIFO_REALLOC - #define FIFO_REALLOC(a,b,c) realloc(a,b) - #undef FIFO_FREE - #define FIFO_FREE free - #undef FIFO_MALLOC - #define FIFO_MALLOC malloc -#endif - -typedef struct { - char * data; - size_t allocation; /* Number of bytes allocated for data. */ - size_t item_size; /* Size of each item in data */ - size_t begin; /* Offset of the first byte to read. */ - size_t end; /* 1 + Offset of the last byte byte to read. */ -} fifo_t; - -#if !defined FIFO_MIN - #define FIFO_MIN 0x4000 -#endif - -#if !defined UNUSED - #define UNUSED -#endif - -UNUSED static void fifo_clear(fifo_t * f) -{ - f->end = f->begin = 0; -} - -UNUSED static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n0) -{ - size_t n = (size_t)n0; - n *= f->item_size; - - if (f->begin == f->end) - fifo_clear(f); - - while (1) { - if (f->end + n <= f->allocation) { - void *p = f->data + f->end; - - f->end += n; - return p; - } - if (f->begin > FIFO_MIN) { - memmove(f->data, f->data + f->begin, f->end - f->begin); - f->end -= f->begin; - f->begin = 0; - continue; - } - f->data = FIFO_REALLOC(f->data, f->allocation + n, f->allocation); - f->allocation += n; - if (!f->data) - return 0; - } -} - -UNUSED static void * fifo_write(fifo_t * f, FIFO_SIZE_T n0, void const * data) -{ - size_t n = (size_t)n0; - void * s = fifo_reserve(f, n0); - if (data) - memcpy(s, data, n * f->item_size); - return s; -} - -UNUSED static void fifo_trim_to(fifo_t * f, FIFO_SIZE_T n0) -{ - size_t n = (size_t)n0; - n *= f->item_size; - f->end = f->begin + n; -} - -UNUSED static void fifo_trim_by(fifo_t * f, FIFO_SIZE_T n0) -{ - size_t n = (size_t)n0; - n *= f->item_size; - f->end -= n; -} - -UNUSED static FIFO_SIZE_T fifo_occupancy(fifo_t * f) -{ - return (FIFO_SIZE_T)((f->end - f->begin) / f->item_size); -} - -UNUSED static void * fifo_read(fifo_t * f, FIFO_SIZE_T n0, void * data) -{ - size_t n = (size_t)n0; - char * ret = f->data + f->begin; - n *= f->item_size; - if (n > (f->end - f->begin)) - return NULL; - if (data) - memcpy(data, ret, (size_t)n); - f->begin += n; - return ret; -} - -#define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL) - -UNUSED static void fifo_delete(fifo_t * f) -{ - FIFO_FREE(f->data); -} - -UNUSED static int fifo_create(fifo_t * f, FIFO_SIZE_T item_size) -{ - f->item_size = (size_t)item_size; - f->allocation = FIFO_MIN; - fifo_clear(f); - return !(f->data = FIFO_MALLOC(f->allocation)); -} - -#endif +/* 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 + +#if !defined FIFO_SIZE_T +#define FIFO_SIZE_T size_t +#endif + +#if !defined FIFO_REALLOC + #define FIFO_REALLOC(a,b,c) realloc(a,b) + #undef FIFO_FREE + #define FIFO_FREE free + #undef FIFO_MALLOC + #define FIFO_MALLOC malloc +#endif + +typedef struct { + char * data; + size_t allocation; /* Number of bytes allocated for data. */ + size_t item_size; /* Size of each item in data */ + size_t begin; /* Offset of the first byte to read. */ + size_t end; /* 1 + Offset of the last byte byte to read. */ +} fifo_t; + +#if !defined FIFO_MIN + #define FIFO_MIN 0x4000 +#endif + +#if !defined UNUSED + #define UNUSED +#endif + +UNUSED static void fifo_clear(fifo_t * f) +{ + f->end = f->begin = 0; +} + +UNUSED static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n0) +{ + size_t n = (size_t)n0; + n *= f->item_size; + + if (f->begin == f->end) + fifo_clear(f); + + while (1) { + if (f->end + n <= f->allocation) { + void *p = f->data + f->end; + + f->end += n; + return p; + } + if (f->begin > FIFO_MIN) { + memmove(f->data, f->data + f->begin, f->end - f->begin); + f->end -= f->begin; + f->begin = 0; + continue; + } + f->data = FIFO_REALLOC(f->data, f->allocation + n, f->allocation); + f->allocation += n; + if (!f->data) + return 0; + } +} + +UNUSED static void * fifo_write(fifo_t * f, FIFO_SIZE_T n0, void const * data) +{ + size_t n = (size_t)n0; + void * s = fifo_reserve(f, n0); + if (data) + memcpy(s, data, n * f->item_size); + return s; +} + +UNUSED static void fifo_trim_to(fifo_t * f, FIFO_SIZE_T n0) +{ + size_t n = (size_t)n0; + n *= f->item_size; + f->end = f->begin + n; +} + +UNUSED static void fifo_trim_by(fifo_t * f, FIFO_SIZE_T n0) +{ + size_t n = (size_t)n0; + n *= f->item_size; + f->end -= n; +} + +UNUSED static FIFO_SIZE_T fifo_occupancy(fifo_t * f) +{ + return (FIFO_SIZE_T)((f->end - f->begin) / f->item_size); +} + +UNUSED static void * fifo_read(fifo_t * f, FIFO_SIZE_T n0, void * data) +{ + size_t n = (size_t)n0; + char * ret = f->data + f->begin; + n *= f->item_size; + if (n > (f->end - f->begin)) + return NULL; + if (data) + memcpy(data, ret, (size_t)n); + f->begin += n; + return ret; +} + +#define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL) + +UNUSED static void fifo_delete(fifo_t * f) +{ + FIFO_FREE(f->data); +} + +UNUSED static int fifo_create(fifo_t * f, FIFO_SIZE_T item_size) +{ + f->item_size = (size_t)item_size; + f->allocation = FIFO_MIN; + fifo_clear(f); + return !(f->data = FIFO_MALLOC(f->allocation)); +} + +#endif diff --git a/lib-src/libsoxr/src/filter.c b/lib-src/libsoxr/src/filter.c index e6aa8b098..ca146d2c6 100644 --- a/lib-src/libsoxr/src/filter.c +++ b/lib-src/libsoxr/src/filter.c @@ -1,245 +1,245 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "filter.h" - -#include -#if !defined M_PI -#define M_PI 3.14159265358979323846 -#endif -#include -#include -#include - -#include "fft4g.h" -#include "ccrw2.h" - -#if 1 || HAVE_DOUBLE_PRECISION /* 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 -#define FFT_LEN fft_len -#define LSX_CDFT lsx_cdft -#define LSX_CLEAR_FFT_CACHE lsx_clear_fft_cache -#define LSX_FFT_BR lsx_fft_br -#define LSX_FFT_SC lsx_fft_sc -#define LSX_INIT_FFT_CACHE lsx_init_fft_cache -#define LSX_RDFT lsx_rdft -#define LSX_SAFE_CDFT lsx_safe_cdft -#define LSX_SAFE_RDFT lsx_safe_rdft -#define UPDATE_FFT_CACHE update_fft_cache -#include "fft4g_cache.h" -#endif - -#if HAVE_SINGLE_PRECISION && !HAVE_AVFFT -#define DFT_FLOAT float -#define DONE_WITH_FFT_CACHE done_with_fft_cache_f -#define FFT_CACHE_CCRW fft_cache_ccrw_f -#define FFT_LEN fft_len_f -#define LSX_CDFT lsx_cdft_f -#define LSX_CLEAR_FFT_CACHE lsx_clear_fft_cache_f -#define LSX_FFT_BR lsx_fft_br_f -#define LSX_FFT_SC lsx_fft_sc_f -#define LSX_INIT_FFT_CACHE lsx_init_fft_cache_f -#define LSX_RDFT lsx_rdft_f -#define LSX_SAFE_CDFT lsx_safe_cdft_f -#define LSX_SAFE_RDFT lsx_safe_rdft_f -#define UPDATE_FFT_CACHE update_fft_cache_f -#include "fft4g_cache.h" -#endif - -#if HAVE_DOUBLE_PRECISION || !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 -#define DFT_FLOAT float -#define ORDERED_CONVOLVE lsx_ordered_convolve_f -#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f -#include "rdft.h" -#endif - -double lsx_kaiser_beta(double att, double tr_bw) -{ - if (att >= 60) { - static const double coefs[][4] = { - {-6.784957e-10,1.02856e-05,0.1087556,-0.8988365+.001}, - {-6.897885e-10,1.027433e-05,0.10876,-0.8994658+.002}, - {-1.000683e-09,1.030092e-05,0.1087677,-0.9007898+.003}, - {-3.654474e-10,1.040631e-05,0.1087085,-0.8977766+.006}, - {8.106988e-09,6.983091e-06,0.1091387,-0.9172048+.015}, - {9.519571e-09,7.272678e-06,0.1090068,-0.9140768+.025}, - {-5.626821e-09,1.342186e-05,0.1083999,-0.9065452+.05}, - {-9.965946e-08,5.073548e-05,0.1040967,-0.7672778+.085}, - {1.604808e-07,-5.856462e-05,0.1185998,-1.34824+.1}, - {-1.511964e-07,6.363034e-05,0.1064627,-0.9876665+.18}, - }; - double realm = log(tr_bw/.0005)/log(2.); - double const * c0 = coefs[range_limit( (int)realm, 0, (int)array_length(coefs)-1)]; - double const * c1 = coefs[range_limit(1+(int)realm, 0, (int)array_length(coefs)-1)]; - double b0 = ((c0[0]*att + c0[1])*att + c0[2])*att + c0[3]; - double b1 = ((c1[0]*att + c1[1])*att + c1[2])*att + c1[3]; - return b0 + (b1 - b0) * (realm - (int)realm); - } - if (att > 50 ) return .1102 * (att - 8.7); - if (att > 20.96) return .58417 * pow(att -20.96, .4) + .07886 * (att - 20.96); - return 0; -} - -double * lsx_make_lpf( - int num_taps, double Fc, double beta, double rho, double scale) -{ - int i, m = num_taps - 1; - 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)", - 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] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult; - if (m - i != i) - h[m - i] = h[i]; - } - return h; -} - -void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps) -{ - *beta = *beta < 0? lsx_kaiser_beta(att, tr_bw * .5 / Fc): *beta; - att = att < 60? (att - 7.95) / (2.285 * M_PI * 2) : - ((.0007528358-1.577737e-05**beta)**beta+.6248022)**beta+.06186902; - *num_taps = !*num_taps? (int)ceil(att/tr_bw + 1) : *num_taps; -} - -double * lsx_design_lpf( - double Fp, /* End of pass-band */ - double Fs, /* Start of stop-band */ - 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) */ - 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; - - 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; - tr_bw = min(tr_bw, .5 * Fs); - Fc = Fs - tr_bw; - assert(Fc - tr_bw >= 0); - lsx_kaiser_params(att, Fc, tr_bw, &beta, num_taps); - if (!n) - *num_taps = phases > 1? *num_taps / phases * phases + phases - 1 : - (*num_taps + modulo - 2) / modulo * modulo + 1; - return Fn < 0? 0 : lsx_make_lpf(*num_taps, Fc, beta, rho, (double)phases); -} - -static double safe_log(double x) -{ - assert(x >= 0); - if (x) - return log(x); - lsx_debug("log(0)"); - return -26; -} - -void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase) -{ - double * pi_wraps, * work, phase1 = (phase > 50 ? 100 - phase : phase) / 50; - int i, work_len, begin, end, imp_peak = 0, peak = 0; - double imp_sum = 0, peak_imp_sum = 0; - double prev_angle2 = 0, cum_2pi = 0, prev_angle1 = 0, cum_1pi = 0; - - for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1); - - work = calloc((size_t)work_len + 2, sizeof(*work)); /* +2: (UN)PACK */ - pi_wraps = malloc((((size_t)work_len + 2) / 2) * sizeof(*pi_wraps)); - - memcpy(work, *h, (size_t)*len * sizeof(*work)); - lsx_safe_rdft(work_len, 1, work); /* Cepstral: */ - LSX_UNPACK(work, work_len); - - for (i = 0; i <= work_len; i += 2) { - double angle = atan2(work[i + 1], work[i]); - double detect = 2 * M_PI; - double delta = angle - prev_angle2; - double adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); - prev_angle2 = angle; - cum_2pi += adjust; - angle += cum_2pi; - detect = M_PI; - delta = angle - prev_angle1; - adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); - prev_angle1 = angle; - cum_1pi += fabs(adjust); /* fabs for when 2pi and 1pi have combined */ - pi_wraps[i >> 1] = cum_1pi; - - work[i] = safe_log(sqrt(sqr(work[i]) + sqr(work[i + 1]))); - work[i + 1] = 0; - } - LSX_PACK(work, work_len); - lsx_safe_rdft(work_len, -1, work); - for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; - - for (i = 1; i < work_len / 2; ++i) { /* Window to reject acausal components */ - work[i] *= 2; - work[i + work_len / 2] = 0; - } - lsx_safe_rdft(work_len, 1, work); - - for (i = 2; i < work_len; i += 2) /* Interpolate between linear & min phase */ - work[i + 1] = phase1 * i / work_len * pi_wraps[work_len >> 1] + - (1 - phase1) * (work[i + 1] + pi_wraps[i >> 1]) - pi_wraps[i >> 1]; - - work[0] = exp(work[0]), work[1] = exp(work[1]); - for (i = 2; i < work_len; i += 2) { - double x = exp(work[i]); - work[i ] = x * cos(work[i + 1]); - work[i + 1] = x * sin(work[i + 1]); - } - - lsx_safe_rdft(work_len, -1, work); - for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; - - /* Find peak pos. */ - for (i = 0; i <= (int)(pi_wraps[work_len >> 1] / M_PI + .5); ++i) { - imp_sum += work[i]; - if (fabs(imp_sum) > fabs(peak_imp_sum)) { - peak_imp_sum = imp_sum; - peak = i; - } - if (work[i] > work[imp_peak]) /* For debug check only */ - imp_peak = i; - } - while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0) - --peak; - - if (!phase1) - begin = 0; - else if (phase1 == 1) - begin = peak - *len / 2; - else { - begin = (int)((.997 - (2 - phase1) * .22) * *len + .5); - end = (int)((.997 + (0 - phase1) * .22) * *len + .5); - begin = peak - (begin & ~3); - end = peak + 1 + ((end + 3) & ~3); - *len = end - begin; - *h = realloc(*h, (size_t)*len * sizeof(**h)); - } - for (i = 0; i < *len; ++i) (*h)[i] = - work[(begin + (phase > 50 ? *len - 1 - i : i) + work_len) & (work_len - 1)]; - *post_len = phase > 50 ? peak - begin : begin + *len - (peak + 1); - - lsx_debug("nPI=%g peak-sum@%i=%g (val@%i=%g); len=%i post=%i (%g%%)", - pi_wraps[work_len >> 1] / M_PI, peak, peak_imp_sum, imp_peak, - work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1)); - free(pi_wraps), free(work); -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include "filter.h" + +#include +#if !defined M_PI +#define M_PI 3.14159265358979323846 +#endif +#include +#include +#include + +#include "fft4g.h" +#include "ccrw2.h" + +#if 1 || HAVE_DOUBLE_PRECISION /* 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 +#define FFT_LEN fft_len +#define LSX_CDFT lsx_cdft +#define LSX_CLEAR_FFT_CACHE lsx_clear_fft_cache +#define LSX_FFT_BR lsx_fft_br +#define LSX_FFT_SC lsx_fft_sc +#define LSX_INIT_FFT_CACHE lsx_init_fft_cache +#define LSX_RDFT lsx_rdft +#define LSX_SAFE_CDFT lsx_safe_cdft +#define LSX_SAFE_RDFT lsx_safe_rdft +#define UPDATE_FFT_CACHE update_fft_cache +#include "fft4g_cache.h" +#endif + +#if HAVE_SINGLE_PRECISION && !HAVE_AVFFT +#define DFT_FLOAT float +#define DONE_WITH_FFT_CACHE done_with_fft_cache_f +#define FFT_CACHE_CCRW fft_cache_ccrw_f +#define FFT_LEN fft_len_f +#define LSX_CDFT lsx_cdft_f +#define LSX_CLEAR_FFT_CACHE lsx_clear_fft_cache_f +#define LSX_FFT_BR lsx_fft_br_f +#define LSX_FFT_SC lsx_fft_sc_f +#define LSX_INIT_FFT_CACHE lsx_init_fft_cache_f +#define LSX_RDFT lsx_rdft_f +#define LSX_SAFE_CDFT lsx_safe_cdft_f +#define LSX_SAFE_RDFT lsx_safe_rdft_f +#define UPDATE_FFT_CACHE update_fft_cache_f +#include "fft4g_cache.h" +#endif + +#if HAVE_DOUBLE_PRECISION || !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 +#define DFT_FLOAT float +#define ORDERED_CONVOLVE lsx_ordered_convolve_f +#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f +#include "rdft.h" +#endif + +double lsx_kaiser_beta(double att, double tr_bw) +{ + if (att >= 60) { + static const double coefs[][4] = { + {-6.784957e-10,1.02856e-05,0.1087556,-0.8988365+.001}, + {-6.897885e-10,1.027433e-05,0.10876,-0.8994658+.002}, + {-1.000683e-09,1.030092e-05,0.1087677,-0.9007898+.003}, + {-3.654474e-10,1.040631e-05,0.1087085,-0.8977766+.006}, + {8.106988e-09,6.983091e-06,0.1091387,-0.9172048+.015}, + {9.519571e-09,7.272678e-06,0.1090068,-0.9140768+.025}, + {-5.626821e-09,1.342186e-05,0.1083999,-0.9065452+.05}, + {-9.965946e-08,5.073548e-05,0.1040967,-0.7672778+.085}, + {1.604808e-07,-5.856462e-05,0.1185998,-1.34824+.1}, + {-1.511964e-07,6.363034e-05,0.1064627,-0.9876665+.18}, + }; + double realm = log(tr_bw/.0005)/log(2.); + double const * c0 = coefs[range_limit( (int)realm, 0, (int)array_length(coefs)-1)]; + double const * c1 = coefs[range_limit(1+(int)realm, 0, (int)array_length(coefs)-1)]; + double b0 = ((c0[0]*att + c0[1])*att + c0[2])*att + c0[3]; + double b1 = ((c1[0]*att + c1[1])*att + c1[2])*att + c1[3]; + return b0 + (b1 - b0) * (realm - (int)realm); + } + if (att > 50 ) return .1102 * (att - 8.7); + if (att > 20.96) return .58417 * pow(att -20.96, .4) + .07886 * (att - 20.96); + return 0; +} + +double * lsx_make_lpf( + int num_taps, double Fc, double beta, double rho, double scale) +{ + int i, m = num_taps - 1; + 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)", + 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] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult; + if (m - i != i) + h[m - i] = h[i]; + } + return h; +} + +void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps) +{ + *beta = *beta < 0? lsx_kaiser_beta(att, tr_bw * .5 / Fc): *beta; + att = att < 60? (att - 7.95) / (2.285 * M_PI * 2) : + ((.0007528358-1.577737e-05**beta)**beta+.6248022)**beta+.06186902; + *num_taps = !*num_taps? (int)ceil(att/tr_bw + 1) : *num_taps; +} + +double * lsx_design_lpf( + double Fp, /* End of pass-band */ + double Fs, /* Start of stop-band */ + 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) */ + 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; + + 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; + tr_bw = min(tr_bw, .5 * Fs); + Fc = Fs - tr_bw; + assert(Fc - tr_bw >= 0); + lsx_kaiser_params(att, Fc, tr_bw, &beta, num_taps); + if (!n) + *num_taps = phases > 1? *num_taps / phases * phases + phases - 1 : + (*num_taps + modulo - 2) / modulo * modulo + 1; + return Fn < 0? 0 : lsx_make_lpf(*num_taps, Fc, beta, rho, (double)phases); +} + +static double safe_log(double x) +{ + assert(x >= 0); + if (x) + return log(x); + lsx_debug("log(0)"); + return -26; +} + +void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase) +{ + double * pi_wraps, * work, phase1 = (phase > 50 ? 100 - phase : phase) / 50; + int i, work_len, begin, end, imp_peak = 0, peak = 0; + double imp_sum = 0, peak_imp_sum = 0; + double prev_angle2 = 0, cum_2pi = 0, prev_angle1 = 0, cum_1pi = 0; + + for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1); + + work = calloc((size_t)work_len + 2, sizeof(*work)); /* +2: (UN)PACK */ + pi_wraps = malloc((((size_t)work_len + 2) / 2) * sizeof(*pi_wraps)); + + memcpy(work, *h, (size_t)*len * sizeof(*work)); + lsx_safe_rdft(work_len, 1, work); /* Cepstral: */ + LSX_UNPACK(work, work_len); + + for (i = 0; i <= work_len; i += 2) { + double angle = atan2(work[i + 1], work[i]); + double detect = 2 * M_PI; + double delta = angle - prev_angle2; + double adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); + prev_angle2 = angle; + cum_2pi += adjust; + angle += cum_2pi; + detect = M_PI; + delta = angle - prev_angle1; + adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); + prev_angle1 = angle; + cum_1pi += fabs(adjust); /* fabs for when 2pi and 1pi have combined */ + pi_wraps[i >> 1] = cum_1pi; + + work[i] = safe_log(sqrt(sqr(work[i]) + sqr(work[i + 1]))); + work[i + 1] = 0; + } + LSX_PACK(work, work_len); + lsx_safe_rdft(work_len, -1, work); + for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; + + for (i = 1; i < work_len / 2; ++i) { /* Window to reject acausal components */ + work[i] *= 2; + work[i + work_len / 2] = 0; + } + lsx_safe_rdft(work_len, 1, work); + + for (i = 2; i < work_len; i += 2) /* Interpolate between linear & min phase */ + work[i + 1] = phase1 * i / work_len * pi_wraps[work_len >> 1] + + (1 - phase1) * (work[i + 1] + pi_wraps[i >> 1]) - pi_wraps[i >> 1]; + + work[0] = exp(work[0]), work[1] = exp(work[1]); + for (i = 2; i < work_len; i += 2) { + double x = exp(work[i]); + work[i ] = x * cos(work[i + 1]); + work[i + 1] = x * sin(work[i + 1]); + } + + lsx_safe_rdft(work_len, -1, work); + for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; + + /* Find peak pos. */ + for (i = 0; i <= (int)(pi_wraps[work_len >> 1] / M_PI + .5); ++i) { + imp_sum += work[i]; + if (fabs(imp_sum) > fabs(peak_imp_sum)) { + peak_imp_sum = imp_sum; + peak = i; + } + if (work[i] > work[imp_peak]) /* For debug check only */ + imp_peak = i; + } + while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0) + --peak; + + if (!phase1) + begin = 0; + else if (phase1 == 1) + begin = peak - *len / 2; + else { + begin = (int)((.997 - (2 - phase1) * .22) * *len + .5); + end = (int)((.997 + (0 - phase1) * .22) * *len + .5); + begin = peak - (begin & ~3); + end = peak + 1 + ((end + 3) & ~3); + *len = end - begin; + *h = realloc(*h, (size_t)*len * sizeof(**h)); + } + for (i = 0; i < *len; ++i) (*h)[i] = + work[(begin + (phase > 50 ? *len - 1 - i : i) + work_len) & (work_len - 1)]; + *post_len = phase > 50 ? peak - begin : begin + *len - (peak + 1); + + lsx_debug("nPI=%g peak-sum@%i=%g (val@%i=%g); len=%i post=%i (%g%%)", + pi_wraps[work_len >> 1] / M_PI, peak, peak_imp_sum, imp_peak, + work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1)); + free(pi_wraps), free(work); +} diff --git a/lib-src/libsoxr/src/filter.h b/lib-src/libsoxr/src/filter.h index f56428557..435303b40 100644 --- a/lib-src/libsoxr/src/filter.h +++ b/lib-src/libsoxr/src/filter.h @@ -1,39 +1,39 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_filter_included -#define soxr_filter_included - -#include "aliases.h" - -double lsx_bessel_I_0(double x); -void lsx_init_fft_cache(void); -void lsx_clear_fft_cache(void); -void lsx_init_fft_cache_f(void); -void lsx_clear_fft_cache_f(void); -#define lsx_is_power_of_2(x) !(x < 2 || (x & (x - 1))) -void lsx_safe_rdft(int len, int type, double * d); -void lsx_safe_cdft(int len, int type, double * d); -void lsx_safe_rdft_f(int len, int type, float * d); -void lsx_safe_cdft_f(int len, int type, float * d); -void lsx_ordered_convolve(int n, void * not_used, double * a, const double * b); -void lsx_ordered_convolve_f(int n, void * not_used, float * a, const float * b); -void lsx_ordered_partial_convolve(int n, double * a, const double * b); -void lsx_ordered_partial_convolve_f(int n, float * a, const float * b); - -double lsx_kaiser_beta(double att, double tr_bw); -double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, - double scale); -void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps); -double * lsx_design_lpf( - double Fp, /* End of pass-band */ - double Fs, /* Start of stop-band */ - 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) */ - double beta); /* <0: value will be estimated */ -void lsx_fir_to_phase(double * * h, int * len, - int * post_len, double phase0); - -#endif +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#if !defined soxr_filter_included +#define soxr_filter_included + +#include "aliases.h" + +double lsx_bessel_I_0(double x); +void lsx_init_fft_cache(void); +void lsx_clear_fft_cache(void); +void lsx_init_fft_cache_f(void); +void lsx_clear_fft_cache_f(void); +#define lsx_is_power_of_2(x) !(x < 2 || (x & (x - 1))) +void lsx_safe_rdft(int len, int type, double * d); +void lsx_safe_cdft(int len, int type, double * d); +void lsx_safe_rdft_f(int len, int type, float * d); +void lsx_safe_cdft_f(int len, int type, float * d); +void lsx_ordered_convolve(int n, void * not_used, double * a, const double * b); +void lsx_ordered_convolve_f(int n, void * not_used, float * a, const float * b); +void lsx_ordered_partial_convolve(int n, double * a, const double * b); +void lsx_ordered_partial_convolve_f(int n, float * a, const float * b); + +double lsx_kaiser_beta(double att, double tr_bw); +double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, + double scale); +void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps); +double * lsx_design_lpf( + double Fp, /* End of pass-band */ + double Fs, /* Start of stop-band */ + 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) */ + double beta); /* <0: value will be estimated */ +void lsx_fir_to_phase(double * * h, int * len, + int * post_len, double phase0); + +#endif diff --git a/lib-src/libsoxr/src/filters.h b/lib-src/libsoxr/src/filters.h index c3fe8f7ab..e9a80119e 100644 --- a/lib-src/libsoxr/src/filters.h +++ b/lib-src/libsoxr/src/filters.h @@ -1,151 +1,151 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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}}}, -}; +/* 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}}}, +}; diff --git a/lib-src/libsoxr/src/half-fir.h b/lib-src/libsoxr/src/half-fir.h index d1eae0687..0a8ee97bb 100644 --- a/lib-src/libsoxr/src/half-fir.h +++ b/lib-src/libsoxr/src/half-fir.h @@ -1,25 +1,25 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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).*/ -/* 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) -{ - 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); - - for (i = 0; i < num_out; ++i, input += 2) { - int j = 0; - sample_t sum = input[0] * .5f; - CONVOLVE - output[i] = sum; - } - fifo_read(&p->fifo, 2 * num_out, NULL); -} -#undef _ -#undef COEFS -#undef CONVOLVE -#undef FUNCTION +/* SoX Resampler Library Copyright (c) 2007-13 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).*/ +/* 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) +{ + 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); + + for (i = 0; i < num_out; ++i, input += 2) { + int j = 0; + sample_t sum = input[0] * .5f; + CONVOLVE + output[i] = sum; + } + fifo_read(&p->fifo, 2 * num_out, NULL); +} +#undef _ +#undef COEFS +#undef CONVOLVE +#undef FUNCTION diff --git a/lib-src/libsoxr/src/half_coefs.h b/lib-src/libsoxr/src/half_coefs.h index 94c74bfea..aac77697c 100644 --- a/lib-src/libsoxr/src/half_coefs.h +++ b/lib-src/libsoxr/src/half_coefs.h @@ -1,57 +1,57 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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 +/* 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 diff --git a/lib-src/libsoxr/src/internal.h b/lib-src/libsoxr/src/internal.h index 80f400034..f29e29f6d 100644 --- a/lib-src/libsoxr/src/internal.h +++ b/lib-src/libsoxr/src/internal.h @@ -1,46 +1,46 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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" - -#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])) -#define AL(a) array_length(a) -#define iAL(a) (int)AL(a) -#define sqr(a) ((a) * (a)) - -#ifdef __GNUC__ - #define UNUSED __attribute__ ((unused)) -#else - #define UNUSED -#endif - -#if defined NDEBUG - #ifdef __GNUC__ - void lsx_dummy(char const *, ...); - #else - static __inline void lsx_dummy(char const * x, ...) {} - #endif - #define lsx_debug if(0) lsx_dummy -#else - #include - #include - 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); - } -#endif -#endif +/* SoX Resampler Library Copyright (c) 2007-13 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" + +#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])) +#define AL(a) array_length(a) +#define iAL(a) (int)AL(a) +#define sqr(a) ((a) * (a)) + +#ifdef __GNUC__ + #define UNUSED __attribute__ ((unused)) +#else + #define UNUSED +#endif + +#if defined NDEBUG + #ifdef __GNUC__ + void lsx_dummy(char const *, ...); + #else + static __inline void lsx_dummy(char const * x, ...) {} + #endif + #define lsx_debug if(0) lsx_dummy +#else + #include + #include + 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); + } +#endif +#endif diff --git a/lib-src/libsoxr/src/libsoxr-dev.src.in b/lib-src/libsoxr/src/libsoxr-dev.src.in index d080c5e77..ce879f95b 100644 --- a/lib-src/libsoxr/src/libsoxr-dev.src.in +++ b/lib-src/libsoxr/src/libsoxr-dev.src.in @@ -1,2 +1,2 @@ -set(TARGET_HEADERS "@TARGET_HEADERS@") -set(TARGET_PCS "@TARGET_PCS@") +set(TARGET_HEADERS "@TARGET_HEADERS@") +set(TARGET_PCS "@TARGET_PCS@") diff --git a/lib-src/libsoxr/src/libsoxr-lsr.pc.in b/lib-src/libsoxr/src/libsoxr-lsr.pc.in deleted file mode 100644 index 98417122e..000000000 --- a/lib-src/libsoxr/src/libsoxr-lsr.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=${CMAKE_INSTALL_PREFIX} -exec_prefix=${CMAKE_INSTALL_PREFIX} -libdir=${LIB_INSTALL_DIR} -includedir=${INCLUDE_INSTALL_DIR} - -Name: lib${LSR} -Description: ${DESCRIPTION_SUMMARY} (with libsamplerate-like bindings) -Requires: libsoxr -Version: ${PROJECT_VERSION} -Libs: -L${LIB_INSTALL_DIR} -l${LSR} -Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/lib-src/libsoxr/src/libsoxr.pc.in b/lib-src/libsoxr/src/libsoxr.pc.in deleted file mode 100644 index 2e8587ed9..000000000 --- a/lib-src/libsoxr/src/libsoxr.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=${CMAKE_INSTALL_PREFIX} -exec_prefix=${CMAKE_INSTALL_PREFIX} -libdir=${LIB_INSTALL_DIR} -includedir=${INCLUDE_INSTALL_DIR} - -Name: lib${PROJECT_NAME} -Description: ${DESCRIPTION_SUMMARY} -Requires: -Version: ${PROJECT_VERSION} -Libs: -L${LIB_INSTALL_DIR} -l${PROJECT_NAME} -Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/lib-src/libsoxr/src/libsoxr.src.in b/lib-src/libsoxr/src/libsoxr.src.in index d66955513..1c926ff3e 100644 --- a/lib-src/libsoxr/src/libsoxr.src.in +++ b/lib-src/libsoxr/src/libsoxr.src.in @@ -1 +1 @@ -set(TARGET_LIBS "@TARGET_LIBS@") +set(TARGET_LIBS "@TARGET_LIBS@") diff --git a/lib-src/libsoxr/src/lsr.c b/lib-src/libsoxr/src/lsr.c index 8fe74e1d4..64b57987b 100644 --- a/lib-src/libsoxr/src/lsr.c +++ b/lib-src/libsoxr/src/lsr.c @@ -1,114 +1,114 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Wrapper mostly compatible with `libsamplerate'. */ - -#include -#include -#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); - *(int *)error0 = (int)(long)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." : soxr_strerror(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);} +/* 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 +#include +#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);} diff --git a/lib-src/libsoxr/src/pffft.c b/lib-src/libsoxr/src/pffft.c index 2eb928668..9b4f59d93 100644 --- a/lib-src/libsoxr/src/pffft.c +++ b/lib-src/libsoxr/src/pffft.c @@ -1,1729 +1,1729 @@ -/* Copyright (c) 2011 Julien Pommier ( pommier@modartt.com ) - - Based on original fortran 77 code from FFTPACKv4 from NETLIB - (http://www.netlib.org/fftpack), authored by Dr Paul Swarztrauber - of NCAR, in 1985. - - As confirmed by the NCAR fftpack software curators, the following - FFTPACKv5 license applies to FFTPACKv4 sources. My changes are - released under the same terms. - - FFTPACK license: - - http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html - - Copyright (c) 2004 the University Corporation for Atmospheric - Research ("UCAR"). All rights reserved. Developed by NCAR's - Computational and Information Systems Laboratory, UCAR, - www.cisl.ucar.edu. - - Redistribution and use of the Software in source and binary forms, - with or without modification, is permitted provided that the - following conditions are met: - - - Neither the names of NCAR's Computational and Information Systems - Laboratory, the University Corporation for Atmospheric Research, - nor the names of its sponsors or contributors may be used to - endorse or promote products derived from this Software without - specific prior written permission. - - - Redistributions of source code must retain the above copyright - notices, this list of conditions, and the disclaimer below. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the disclaimer below in the - documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE - SOFTWARE. - - - PFFFT : a Pretty Fast FFT. - - This file is largerly based on the original FFTPACK implementation, modified in - order to take advantage of SIMD instructions of modern CPUs. -*/ - -/* - ChangeLog: - - 2011/10/02, version 1: This is the very first release of this file. -*/ - -#if !defined PFFT_MACROS_ONLY -#include "pffft.h" -#include "simd.h" -#include -#include -#include -#include - -#define pffft_aligned_free _soxr_simd_aligned_free -#define pffft_aligned_malloc _soxr_simd_aligned_malloc -#define pffft_aligned_calloc _soxr_simd_aligned_calloc -#endif - -/* - vector support macros: the rest of the code is independant of - SSE/Altivec/NEON -- adding support for other platforms with 4-element - vectors should be limited to these macros -*/ - - -/* define PFFFT_SIMD_DISABLE if you want to use scalar code instead of simd code */ -/*#define PFFFT_SIMD_DISABLE */ - -/* detect compiler flavour */ -#if defined(_MSC_VER) -# define COMPILER_MSVC -#elif defined(__GNUC__) -# define COMPILER_GCC -#endif - -#if defined(COMPILER_GCC) -# define ALWAYS_INLINE(return_type) return_type __attribute__ ((always_inline)) -# define NEVER_INLINE(return_type) return_type __attribute__ ((noinline)) -# define RESTRICT __restrict -/*# define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ varname__[size__]; */ -#elif defined(COMPILER_MSVC) -# define ALWAYS_INLINE(return_type) __forceinline return_type -# define NEVER_INLINE(return_type) __declspec(noinline) return_type -# define RESTRICT __restrict -/*# define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ *varname__ = (v4sf*)_alloca(size__ * sizeof(type__)) */ -#endif - -/* - Altivec support macros -*/ -#if !defined(PFFFT_SIMD_DISABLE) && (defined(__ppc__) || defined(__ppc64__)) -typedef vector float v4sf; -# define SIMD_SZ 4 -# define VZERO() ((vector float) vec_splat_u8(0)) -# define VMUL(a,b) vec_madd(a,b, VZERO()) -# define VADD(a,b) vec_add(a,b) -# define VMADD(a,b,c) vec_madd(a,b,c) -# define VSUB(a,b) vec_sub(a,b) -inline v4sf ld_ps1(const float *p) { v4sf v=vec_lde(0,p); return vec_splat(vec_perm(v, v, vec_lvsl(0, p)), 0); } -# define LD_PS1(p) ld_ps1(&p) -# define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = vec_mergeh(in1, in2); out2 = vec_mergel(in1, in2); out1 = tmp__; } -# define UNINTERLEAVE2(in1, in2, out1, out2) { \ - vector unsigned char vperm1 = (vector unsigned char)(0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27); \ - vector unsigned char vperm2 = (vector unsigned char)(4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31); \ - v4sf tmp__ = vec_perm(in1, in2, vperm1); out2 = vec_perm(in1, in2, vperm2); out1 = tmp__; \ - } -# define VTRANSPOSE4(x0,x1,x2,x3) { \ - v4sf y0 = vec_mergeh(x0, x2); \ - v4sf y1 = vec_mergel(x0, x2); \ - v4sf y2 = vec_mergeh(x1, x3); \ - v4sf y3 = vec_mergel(x1, x3); \ - x0 = vec_mergeh(y0, y2); \ - x1 = vec_mergel(y0, y2); \ - x2 = vec_mergeh(y1, y3); \ - x3 = vec_mergel(y1, y3); \ - } -# define VSWAPHL(a,b) vec_perm(a,b, (vector unsigned char)(16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15)) -# define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) - -/* - SSE1 support macros -*/ -#elif !defined(PFFFT_SIMD_DISABLE) && (defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)) - -#include -typedef __m128 v4sf; -# define SIMD_SZ 4 /* 4 floats by simd vector -- this is pretty much hardcoded in the preprocess/finalize functions anyway so you will have to work if you want to enable AVX with its 256-bit vectors. */ -# define VZERO() _mm_setzero_ps() -# define VMUL(a,b) _mm_mul_ps(a,b) -# define VADD(a,b) _mm_add_ps(a,b) -# define VMADD(a,b,c) _mm_add_ps(_mm_mul_ps(a,b), c) -# define VSUB(a,b) _mm_sub_ps(a,b) -# define LD_PS1(p) _mm_set1_ps(p) -# define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_unpacklo_ps(in1, in2); out2 = _mm_unpackhi_ps(in1, in2); out1 = tmp__; } -# define UNINTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(2,0,2,0)); out2 = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(3,1,3,1)); out1 = tmp__; } -# define VTRANSPOSE4(x0,x1,x2,x3) _MM_TRANSPOSE4_PS(x0,x1,x2,x3) -# define VSWAPHL(a,b) _mm_shuffle_ps(b, a, _MM_SHUFFLE(3,2,1,0)) -# define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) - -/* - ARM NEON support macros -*/ -#elif !defined(PFFFT_SIMD_DISABLE) && defined(__arm__) -# include -typedef float32x4_t v4sf; -# define SIMD_SZ 4 -# define VZERO() vdupq_n_f32(0) -# define VMUL(a,b) vmulq_f32(a,b) -# define VADD(a,b) vaddq_f32(a,b) -# define VMADD(a,b,c) vmlaq_f32(c,a,b) -# define VSUB(a,b) vsubq_f32(a,b) -# define LD_PS1(p) vld1q_dup_f32(&(p)) -# define INTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vzipq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } -# define UNINTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vuzpq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } -# define VTRANSPOSE4_(x0,x1,x2,x3) { \ - float32x4x2_t t0_ = vzipq_f32(x0, x2); \ - float32x4x2_t t1_ = vzipq_f32(x1, x3); \ - float32x4x2_t u0_ = vzipq_f32(t0_.val[0], t1_.val[0]); \ - float32x4x2_t u1_ = vzipq_f32(t0_.val[1], t1_.val[1]); \ - x0 = u0_.val[0]; x1 = u0_.val[1]; x2 = u1_.val[0]; x3 = u1_.val[1]; \ - } -/* marginally faster version */ -# define VTRANSPOSE4(x0,x1,x2,x3) { asm("vtrn.32 %q0, %q1;\n vtrn.32 %q2,%q3\n vswp %f0,%e2\n vswp %f1,%e3" : "+w"(x0), "+w"(x1), "+w"(x2), "+w"(x3)::); } -# define VSWAPHL(a,b) vcombine_f32(vget_low_f32(b), vget_high_f32(a)) -# define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) -#else -# if !defined(PFFFT_SIMD_DISABLE) -# warning "building with simd disabled !\n"; -# define PFFFT_SIMD_DISABLE /* fallback to scalar code */ -# endif -#endif - -/* fallback mode for situations where SSE/Altivec are not available, use scalar mode instead */ -#ifdef PFFFT_SIMD_DISABLE -typedef float v4sf; -# define SIMD_SZ 1 -# define VZERO() 0.f -# define VMUL(a,b) ((a)*(b)) -# define VADD(a,b) ((a)+(b)) -# define VMADD(a,b,c) ((a)*(b)+(c)) -# define VSUB(a,b) ((a)-(b)) -# define LD_PS1(p) (p) -# define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) -#endif - -/* shortcuts for complex multiplcations */ -#define VCPLXMUL(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VSUB(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VADD(ai,tmp); } -#define VCPLXMULCONJ(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VADD(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VSUB(ai,tmp); } - -#if !defined(PFFFT_SIMD_DISABLE) -typedef union v4sf_union { - v4sf v; - float f[4]; -} v4sf_union; - -#if 0 -#include - -#define assertv4(v,f0,f1,f2,f3) assert(v.f[0] == (f0) && v.f[1] == (f1) && v.f[2] == (f2) && v.f[3] == (f3)) - -/* detect bugs with the vector support macros */ -void validate_pffft_simd() { - float f[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; - v4sf_union a0, a1, a2, a3, t, u; - memcpy(a0.f, f, 4*sizeof(float)); - memcpy(a1.f, f+4, 4*sizeof(float)); - memcpy(a2.f, f+8, 4*sizeof(float)); - memcpy(a3.f, f+12, 4*sizeof(float)); - - t = a0; u = a1; t.v = VZERO(); - printf("VZERO=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 0, 0, 0, 0); - t.v = VADD(a1.v, a2.v); - printf("VADD(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 12, 14, 16, 18); - t.v = VMUL(a1.v, a2.v); - printf("VMUL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 45, 60, 77); - t.v = VMADD(a1.v, a2.v,a0.v); - printf("VMADD(4:7,8:11,0:3)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 46, 62, 80); - - INTERLEAVE2(a1.v,a2.v,t.v,u.v); - printf("INTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); - assertv4(t, 4, 8, 5, 9); assertv4(u, 6, 10, 7, 11); - UNINTERLEAVE2(a1.v,a2.v,t.v,u.v); - printf("UNINTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); - assertv4(t, 4, 6, 8, 10); assertv4(u, 5, 7, 9, 11); - - t.v=LD_PS1(f[15]); - printf("LD_PS1(15)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); - assertv4(t, 15, 15, 15, 15); - t.v = VSWAPHL(a1.v, a2.v); - printf("VSWAPHL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); - assertv4(t, 8, 9, 6, 7); - VTRANSPOSE4(a0.v, a1.v, a2.v, a3.v); - printf("VTRANSPOSE4(0:3,4:7,8:11,12:15)=[%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", - a0.f[0], a0.f[1], a0.f[2], a0.f[3], a1.f[0], a1.f[1], a1.f[2], a1.f[3], - a2.f[0], a2.f[1], a2.f[2], a2.f[3], a3.f[0], a3.f[1], a3.f[2], a3.f[3]); - assertv4(a0, 0, 4, 8, 12); assertv4(a1, 1, 5, 9, 13); assertv4(a2, 2, 6, 10, 14); assertv4(a3, 3, 7, 11, 15); -} -#endif -#endif /*!PFFFT_SIMD_DISABLE */ - -#if !defined PFFT_MACROS_ONLY - - -#if defined (COMPILER_MSVC) - #define sin (float)sin - #define cos (float)cos -#else - #define sin sinf - #define cos cosf -#endif - -/* -int pffft_simd_size() { return SIMD_SZ; } -*/ - -/* - passf2 and passb2 has been merged here, fsign = -1 for passf2, +1 for passb2 -*/ -static NEVER_INLINE(void) passf2_ps(int ido, int l1, const v4sf *cc, v4sf *ch, const float *wa1, float fsign) { - int k, i; - int l1ido = l1*ido; - if (ido <= 2) { - for (k=0; k < l1ido; k += ido, ch += ido, cc+= 2*ido) { - ch[0] = VADD(cc[0], cc[ido+0]); - ch[l1ido] = VSUB(cc[0], cc[ido+0]); - ch[1] = VADD(cc[1], cc[ido+1]); - ch[l1ido + 1] = VSUB(cc[1], cc[ido+1]); - } - } else { - for (k=0; k < l1ido; k += ido, ch += ido, cc += 2*ido) { - for (i=0; i 2); - for (k=0; k< l1ido; k += ido, cc+= 3*ido, ch +=ido) { - for (i=0; i 5) { - wa[i1-1] = wa[i-1]; - wa[i1] = wa[i]; - } - } - l1 = l2; - } -} /* cffti1 */ - - -static v4sf *cfftf1_ps(int n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, const float *wa, const int *ifac, int isign) { - v4sf *in = (v4sf*)input_readonly; - v4sf *out = (in == work2 ? work1 : work2); - int nf = ifac[1], k1; - int l1 = 1; - int iw = 0; - assert(in != out && work1 != work2); - for (k1=2; k1<=nf+1; k1++) { - int ip = ifac[k1]; - int l2 = ip*l1; - int ido = n / l2; - int idot = ido + ido; - switch (ip) { - case 4: { - int ix2 = iw + idot; - int ix3 = ix2 + idot; - passf4_ps(idot, l1, in, out, &wa[iw], &wa[ix2], &wa[ix3], (float)isign); - } break; - case 2: { - passf2_ps(idot, l1, in, out, &wa[iw], (float)isign); - } break; - case 3: { - int ix2 = iw + idot; - passf3_ps(idot, l1, in, out, &wa[iw], &wa[ix2], (float)isign); - } break; - default: - assert(0); - } - l1 = l2; - iw += (ip - 1)*idot; - if (out == work2) { - out = work1; in = work2; - } else { - out = work2; in = work1; - } - } - - return in; /* this is in fact the output .. */ -} - - -struct PFFFT_Setup { - int N; - int Ncvec; /* nb of complex simd vectors (N/4 if PFFFT_COMPLEX, N/8 if PFFFT_REAL) */ - int ifac[15]; - pffft_transform_t transform; - v4sf *data; /* allocated room for twiddle coefs */ - float *e; /* points into 'data' , N/4*3 elements */ - float *twiddle; /* points into 'data', N/4 elements */ -}; - -PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform) { - int k, m; - PFFFT_Setup *s = (PFFFT_Setup*)malloc(sizeof(PFFFT_Setup)); - if (!s) - return s; - if (transform == PFFFT_REAL) { assert(N >= 32); } - if (transform == PFFFT_COMPLEX) { assert(N >= 16); } - /*assert((N % 32) == 0); */ - s->N = N; - s->transform = transform; - /* nb of complex simd vectors */ - s->Ncvec = (transform == PFFFT_REAL ? N/2 : N)/SIMD_SZ; - s->data = (v4sf*)pffft_aligned_malloc(2*(size_t)s->Ncvec * sizeof(v4sf)); - if (!s->data) { - free(s); - return 0; - } - s->e = (float*)s->data; - s->twiddle = (float*)(s->data + (2*s->Ncvec*(SIMD_SZ-1))/SIMD_SZ); - - if (transform == PFFFT_REAL) { - for (k=0; k < s->Ncvec; ++k) { - int i = k/SIMD_SZ; - int j = k%SIMD_SZ; - for (m=0; m < SIMD_SZ-1; ++m) { - float A = (float)(-2*M_PI*(m+1)*k / N); - s->e[(2*(i*3 + m) + 0) * SIMD_SZ + j] = cos(A); - s->e[(2*(i*3 + m) + 1) * SIMD_SZ + j] = sin(A); - } - } - rffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); - } else { - for (k=0; k < s->Ncvec; ++k) { - int i = k/SIMD_SZ; - int j = k%SIMD_SZ; - for (m=0; m < SIMD_SZ-1; ++m) { - float A = (float)(-2*M_PI*(m+1)*k / N); - s->e[(2*(i*3 + m) + 0)*SIMD_SZ + j] = cos(A); - s->e[(2*(i*3 + m) + 1)*SIMD_SZ + j] = sin(A); - } - } - cffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); - } - return s; -} - - -static void pffft_destroy_setup(PFFFT_Setup *s) { - if(s){ - pffft_aligned_free(s->data); - free(s); - } -} - -#if !defined(PFFFT_SIMD_DISABLE) - -/* [0 0 1 2 3 4 5 6 7 8] -> [0 8 7 6 5 4 3 2 1] */ -static void reversed_copy(int N, const v4sf *in, int in_stride, v4sf *out) { - v4sf g0, g1; - int k; - INTERLEAVE2(in[0], in[1], g0, g1); in += in_stride; - - *--out = VSWAPHL(g0, g1); /* [g0l, g0h], [g1l g1h] -> [g1l, g0h] */ - for (k=1; k < N; ++k) { - v4sf h0, h1; - INTERLEAVE2(in[0], in[1], h0, h1); in += in_stride; - *--out = VSWAPHL(g1, h0); - *--out = VSWAPHL(h0, h1); - g1 = h1; - } - *--out = VSWAPHL(g1, g0); -} - -static void unreversed_copy(int N, const v4sf *in, v4sf *out, int out_stride) { - v4sf g0, g1, h0, h1; - int k; - g0 = g1 = in[0]; ++in; - for (k=1; k < N; ++k) { - h0 = *in++; h1 = *in++; - g1 = VSWAPHL(g1, h0); - h0 = VSWAPHL(h0, h1); - UNINTERLEAVE2(h0, g1, out[0], out[1]); out += out_stride; - g1 = h1; - } - h0 = *in++; h1 = g0; - g1 = VSWAPHL(g1, h0); - h0 = VSWAPHL(h0, h1); - UNINTERLEAVE2(h0, g1, out[0], out[1]); -} - -static void pffft_zreorder(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { - int k, N = setup->N, Ncvec = setup->Ncvec; - const v4sf *vin = (const v4sf*)in; - v4sf *vout = (v4sf*)out; - assert(in != out); - if (setup->transform == PFFFT_REAL) { - int k, dk = N/32; - if (direction == PFFFT_FORWARD) { - for (k=0; k < dk; ++k) { - INTERLEAVE2(vin[k*8 + 0], vin[k*8 + 1], vout[2*(0*dk + k) + 0], vout[2*(0*dk + k) + 1]); - INTERLEAVE2(vin[k*8 + 4], vin[k*8 + 5], vout[2*(2*dk + k) + 0], vout[2*(2*dk + k) + 1]); - } - reversed_copy(dk, vin+2, 8, (v4sf*)(out + N/2)); - reversed_copy(dk, vin+6, 8, (v4sf*)(out + N)); - } else { - for (k=0; k < dk; ++k) { - UNINTERLEAVE2(vin[2*(0*dk + k) + 0], vin[2*(0*dk + k) + 1], vout[k*8 + 0], vout[k*8 + 1]); - UNINTERLEAVE2(vin[2*(2*dk + k) + 0], vin[2*(2*dk + k) + 1], vout[k*8 + 4], vout[k*8 + 5]); - } - unreversed_copy(dk, (v4sf*)(in + N/4), (v4sf*)(out + N - 6*SIMD_SZ), -8); - unreversed_copy(dk, (v4sf*)(in + 3*N/4), (v4sf*)(out + N - 2*SIMD_SZ), -8); - } - } else { - if (direction == PFFFT_FORWARD) { - for (k=0; k < Ncvec; ++k) { - int kk = (k/4) + (k%4)*(Ncvec/4); - INTERLEAVE2(vin[k*2], vin[k*2+1], vout[kk*2], vout[kk*2+1]); - } - } else { - for (k=0; k < Ncvec; ++k) { - int kk = (k/4) + (k%4)*(Ncvec/4); - UNINTERLEAVE2(vin[kk*2], vin[kk*2+1], vout[k*2], vout[k*2+1]); - } - } - } -} - -static void pffft_cplx_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - v4sf r0, i0, r1, i1, r2, i2, r3, i3; - v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; - assert(in != out); - for (k=0; k < dk; ++k) { - r0 = in[8*k+0]; i0 = in[8*k+1]; - r1 = in[8*k+2]; i1 = in[8*k+3]; - r2 = in[8*k+4]; i2 = in[8*k+5]; - r3 = in[8*k+6]; i3 = in[8*k+7]; - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - VCPLXMUL(r1,i1,e[k*6+0],e[k*6+1]); - VCPLXMUL(r2,i2,e[k*6+2],e[k*6+3]); - VCPLXMUL(r3,i3,e[k*6+4],e[k*6+5]); - - sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); - sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); - si0 = VADD(i0,i2); di0 = VSUB(i0, i2); - si1 = VADD(i1,i3); di1 = VSUB(i1, i3); - - /* - transformation for each column is: - - [1 1 1 1 0 0 0 0] [r0] - [1 0 -1 0 0 -1 0 1] [r1] - [1 -1 1 -1 0 0 0 0] [r2] - [1 0 -1 0 0 1 0 -1] [r3] - [0 0 0 0 1 1 1 1] * [i0] - [0 1 0 -1 1 0 -1 0] [i1] - [0 0 0 0 1 -1 1 -1] [i2] - [0 -1 0 1 1 0 -1 0] [i3] - */ - - r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); - r1 = VADD(dr0, di1); i1 = VSUB(di0, dr1); - r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); - r3 = VSUB(dr0, di1); i3 = VADD(di0, dr1); - - *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; - *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; - } -} - -static void pffft_cplx_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - v4sf r0, i0, r1, i1, r2, i2, r3, i3; - v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; - assert(in != out); - for (k=0; k < dk; ++k) { - r0 = in[8*k+0]; i0 = in[8*k+1]; - r1 = in[8*k+2]; i1 = in[8*k+3]; - r2 = in[8*k+4]; i2 = in[8*k+5]; - r3 = in[8*k+6]; i3 = in[8*k+7]; - - sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); - sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); - si0 = VADD(i0,i2); di0 = VSUB(i0, i2); - si1 = VADD(i1,i3); di1 = VSUB(i1, i3); - - r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); - r1 = VSUB(dr0, di1); i1 = VADD(di0, dr1); - r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); - r3 = VADD(dr0, di1); i3 = VSUB(di0, dr1); - - VCPLXMULCONJ(r1,i1,e[k*6+0],e[k*6+1]); - VCPLXMULCONJ(r2,i2,e[k*6+2],e[k*6+3]); - VCPLXMULCONJ(r3,i3,e[k*6+4],e[k*6+5]); - - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - - *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; - *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; - } -} - - -static ALWAYS_INLINE(void) pffft_real_finalize_4x4(const v4sf *in0, const v4sf *in1, const v4sf *in, - const v4sf *e, v4sf *out) { - v4sf r0, i0, r1, i1, r2, i2, r3, i3; - v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; - r0 = *in0; i0 = *in1; - r1 = *in++; i1 = *in++; r2 = *in++; i2 = *in++; r3 = *in++; i3 = *in++; - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - - /* - transformation for each column is: - - [1 1 1 1 0 0 0 0] [r0] - [1 0 -1 0 0 -1 0 1] [r1] - [1 0 -1 0 0 1 0 -1] [r2] - [1 -1 1 -1 0 0 0 0] [r3] - [0 0 0 0 1 1 1 1] * [i0] - [0 -1 0 1 -1 0 1 0] [i1] - [0 -1 0 1 1 0 -1 0] [i2] - [0 0 0 0 -1 1 -1 1] [i3] - */ - - /*cerr << "matrix initial, before e , REAL:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; */ - /*cerr << "matrix initial, before e, IMAG :\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; */ - - VCPLXMUL(r1,i1,e[0],e[1]); - VCPLXMUL(r2,i2,e[2],e[3]); - VCPLXMUL(r3,i3,e[4],e[5]); - - /*cerr << "matrix initial, real part:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; */ - /*cerr << "matrix initial, imag part:\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; */ - - sr0 = VADD(r0,r2); dr0 = VSUB(r0,r2); - sr1 = VADD(r1,r3); dr1 = VSUB(r3,r1); - si0 = VADD(i0,i2); di0 = VSUB(i0,i2); - si1 = VADD(i1,i3); di1 = VSUB(i3,i1); - - r0 = VADD(sr0, sr1); - r3 = VSUB(sr0, sr1); - i0 = VADD(si0, si1); - i3 = VSUB(si1, si0); - r1 = VADD(dr0, di1); - r2 = VSUB(dr0, di1); - i1 = VSUB(dr1, di0); - i2 = VADD(dr1, di0); - - *out++ = r0; - *out++ = i0; - *out++ = r1; - *out++ = i1; - *out++ = r2; - *out++ = i2; - *out++ = r3; - *out++ = i3; - -} - -static NEVER_INLINE(void) pffft_real_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ - - v4sf_union cr, ci, *uout = (v4sf_union*)out; - v4sf save = in[7], zero=VZERO(); - float xr0, xi0, xr1, xi1, xr2, xi2, xr3, xi3; - static const float s = (float)(M_SQRT2/2); - - cr.v = in[0]; ci.v = in[Ncvec*2-1]; - assert(in != out); - pffft_real_finalize_4x4(&zero, &zero, in+1, e, out); - - /* - [cr0 cr1 cr2 cr3 ci0 ci1 ci2 ci3] - - [Xr(1)] ] [1 1 1 1 0 0 0 0] - [Xr(N/4) ] [0 0 0 0 1 s 0 -s] - [Xr(N/2) ] [1 0 -1 0 0 0 0 0] - [Xr(3N/4)] [0 0 0 0 1 -s 0 s] - [Xi(1) ] [1 -1 1 -1 0 0 0 0] - [Xi(N/4) ] [0 0 0 0 0 -s -1 -s] - [Xi(N/2) ] [0 -1 0 1 0 0 0 0] - [Xi(3N/4)] [0 0 0 0 0 -s 1 -s] - */ - - xr0=(cr.f[0]+cr.f[2]) + (cr.f[1]+cr.f[3]); uout[0].f[0] = xr0; - xi0=(cr.f[0]+cr.f[2]) - (cr.f[1]+cr.f[3]); uout[1].f[0] = xi0; - xr2=(cr.f[0]-cr.f[2]); uout[4].f[0] = xr2; - xi2=(cr.f[3]-cr.f[1]); uout[5].f[0] = xi2; - xr1= ci.f[0] + s*(ci.f[1]-ci.f[3]); uout[2].f[0] = xr1; - xi1=-ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[3].f[0] = xi1; - xr3= ci.f[0] - s*(ci.f[1]-ci.f[3]); uout[6].f[0] = xr3; - xi3= ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[7].f[0] = xi3; - - for (k=1; k < dk; ++k) { - v4sf save_next = in[8*k+7]; - pffft_real_finalize_4x4(&save, &in[8*k+0], in + 8*k+1, - e + k*6, out + k*8); - save = save_next; - } - -} - -static ALWAYS_INLINE(void) pffft_real_preprocess_4x4(const v4sf *in, - const v4sf *e, v4sf *out, int first) { - v4sf r0=in[0], i0=in[1], r1=in[2], i1=in[3], r2=in[4], i2=in[5], r3=in[6], i3=in[7]; - /* - transformation for each column is: - - [1 1 1 1 0 0 0 0] [r0] - [1 0 0 -1 0 -1 -1 0] [r1] - [1 -1 -1 1 0 0 0 0] [r2] - [1 0 0 -1 0 1 1 0] [r3] - [0 0 0 0 1 -1 1 -1] * [i0] - [0 -1 1 0 1 0 0 1] [i1] - [0 0 0 0 1 1 -1 -1] [i2] - [0 1 -1 0 1 0 0 1] [i3] - */ - - v4sf sr0 = VADD(r0,r3), dr0 = VSUB(r0,r3); - v4sf sr1 = VADD(r1,r2), dr1 = VSUB(r1,r2); - v4sf si0 = VADD(i0,i3), di0 = VSUB(i0,i3); - v4sf si1 = VADD(i1,i2), di1 = VSUB(i1,i2); - - r0 = VADD(sr0, sr1); - r2 = VSUB(sr0, sr1); - r1 = VSUB(dr0, si1); - r3 = VADD(dr0, si1); - i0 = VSUB(di0, di1); - i2 = VADD(di0, di1); - i1 = VSUB(si0, dr1); - i3 = VADD(si0, dr1); - - VCPLXMULCONJ(r1,i1,e[0],e[1]); - VCPLXMULCONJ(r2,i2,e[2],e[3]); - VCPLXMULCONJ(r3,i3,e[4],e[5]); - - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - - if (!first) { - *out++ = r0; - *out++ = i0; - } - *out++ = r1; - *out++ = i1; - *out++ = r2; - *out++ = i2; - *out++ = r3; - *out++ = i3; -} - -static NEVER_INLINE(void) pffft_real_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ - - v4sf_union Xr, Xi, *uout = (v4sf_union*)out; - float cr0, ci0, cr1, ci1, cr2, ci2, cr3, ci3; - static const float s = (float)M_SQRT2; - assert(in != out); - for (k=0; k < 4; ++k) { - Xr.f[k] = ((float*)in)[8*k]; - Xi.f[k] = ((float*)in)[8*k+4]; - } - - pffft_real_preprocess_4x4(in, e, out+1, 1); /* will write only 6 values */ - - /* - [Xr0 Xr1 Xr2 Xr3 Xi0 Xi1 Xi2 Xi3] - - [cr0] [1 0 2 0 1 0 0 0] - [cr1] [1 0 0 0 -1 0 -2 0] - [cr2] [1 0 -2 0 1 0 0 0] - [cr3] [1 0 0 0 -1 0 2 0] - [ci0] [0 2 0 2 0 0 0 0] - [ci1] [0 s 0 -s 0 -s 0 -s] - [ci2] [0 0 0 0 0 -2 0 2] - [ci3] [0 -s 0 s 0 -s 0 -s] - */ - for (k=1; k < dk; ++k) { - pffft_real_preprocess_4x4(in+8*k, e + k*6, out-1+k*8, 0); - } - - cr0=(Xr.f[0]+Xi.f[0]) + 2*Xr.f[2]; uout[0].f[0] = cr0; - cr1=(Xr.f[0]-Xi.f[0]) - 2*Xi.f[2]; uout[0].f[1] = cr1; - cr2=(Xr.f[0]+Xi.f[0]) - 2*Xr.f[2]; uout[0].f[2] = cr2; - cr3=(Xr.f[0]-Xi.f[0]) + 2*Xi.f[2]; uout[0].f[3] = cr3; - ci0= 2*(Xr.f[1]+Xr.f[3]); uout[2*Ncvec-1].f[0] = ci0; - ci1= s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[1] = ci1; - ci2= 2*(Xi.f[3]-Xi.f[1]); uout[2*Ncvec-1].f[2] = ci2; - ci3=-s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[3] = ci3; -} - - -static void pffft_transform_internal(PFFFT_Setup *setup, const float *finput, float *foutput, v4sf *scratch, - pffft_direction_t direction, int ordered) { - int k, Ncvec = setup->Ncvec; - int nf_odd = (setup->ifac[1] & 1); - - /* temporary buffer is allocated on the stack if the scratch pointer is NULL */ - /*int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); */ - /*VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); */ - - int ib = (nf_odd ^ ordered ? 1 : 0); - const v4sf *vinput = (const v4sf*)finput; - v4sf *voutput = (v4sf*)foutput; - v4sf *buff[2]; - buff[0] = voutput, buff[1] = scratch /*? scratch : scratch_on_stack*/; - - /*if (scratch == 0) scratch = scratch_on_stack; */ - - assert(VALIGNED(finput) && VALIGNED(foutput)); - - /*assert(finput != foutput); */ - if (direction == PFFFT_FORWARD) { - ib = !ib; - if (setup->transform == PFFFT_REAL) { - ib = (rfftf1_ps(Ncvec*2, vinput, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - pffft_real_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); - } else { - v4sf *tmp = buff[ib]; - for (k=0; k < Ncvec; ++k) { - UNINTERLEAVE2(vinput[k*2], vinput[k*2+1], tmp[k*2], tmp[k*2+1]); - } - ib = (cfftf1_ps(Ncvec, buff[ib], buff[!ib], buff[ib], - setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); - pffft_cplx_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); - } - if (ordered) { - pffft_zreorder(setup, (float*)buff[!ib], (float*)buff[ib], PFFFT_FORWARD); - } else ib = !ib; - } else { - if (vinput == buff[ib]) { - ib = !ib; /* may happen when finput == foutput */ - } - if (ordered) { - pffft_zreorder(setup, (float*)vinput, (float*)buff[ib], PFFFT_BACKWARD); - vinput = buff[ib]; ib = !ib; - } - if (setup->transform == PFFFT_REAL) { - pffft_real_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); - ib = (rfftb1_ps(Ncvec*2, buff[ib], buff[0], buff[1], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - } else { - pffft_cplx_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); - ib = (cfftf1_ps(Ncvec, buff[ib], buff[0], buff[1], - setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); - for (k=0; k < Ncvec; ++k) { - INTERLEAVE2(buff[ib][k*2], buff[ib][k*2+1], buff[ib][k*2], buff[ib][k*2+1]); - } - } - } - - if (buff[ib] != voutput) { - /* extra copy required -- this situation should only happen when finput == foutput */ - assert(finput==foutput); - for (k=0; k < Ncvec; ++k) { - v4sf a = buff[ib][2*k], b = buff[ib][2*k+1]; - voutput[2*k] = a; voutput[2*k+1] = b; - } - ib = !ib; - } - assert(buff[ib] == voutput); -} - -#if 0 -static void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { - int i, Ncvec = s->Ncvec; - const v4sf * RESTRICT va = (const v4sf*)a; - const v4sf * RESTRICT vb = (const v4sf*)b; - v4sf * RESTRICT vab = (v4sf*)ab; - -#ifdef __arm__ - __builtin_prefetch(va); - __builtin_prefetch(vb); - __builtin_prefetch(vab); - __builtin_prefetch(va+2); - __builtin_prefetch(vb+2); - __builtin_prefetch(vab+2); - __builtin_prefetch(va+4); - __builtin_prefetch(vb+4); - __builtin_prefetch(vab+4); - __builtin_prefetch(va+6); - __builtin_prefetch(vb+6); - __builtin_prefetch(vab+6); -#endif - - float ar, ai, br, bi, abr, abi; - v4sf vscal = LD_PS1(scaling); - - 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]; - abr = ((v4sf_union*)vab)[0].f[0]; - abi = ((v4sf_union*)vab)[1].f[0]; - -#ifdef __arm__ -# if 1 /* inline asm version */ - const float *a_ = a, *b_ = b; float *ab_ = ab; - int N = Ncvec; - asm volatile("mov r8, %2 \n" - "vdup.f32 q15, %4 \n" - "1: \n" - "pld [%0,#64] \n" - "pld [%1,#64] \n" - "pld [%2,#64] \n" - "pld [%0,#96] \n" - "pld [%1,#96] \n" - "pld [%2,#96] \n" - "vld1.f32 {q0,q1}, [%0,:128]! \n" - "vld1.f32 {q4,q5}, [%1,:128]! \n" - "vld1.f32 {q2,q3}, [%0,:128]! \n" - "vld1.f32 {q6,q7}, [%1,:128]! \n" - "vld1.f32 {q8,q9}, [r8,:128]! \n" - - "vmul.f32 q10, q0, q4 \n" - "vmul.f32 q11, q0, q5 \n" - "vmul.f32 q12, q2, q6 \n" - "vmul.f32 q13, q2, q7 \n" - "vmls.f32 q10, q1, q5 \n" - "vmla.f32 q11, q1, q4 \n" - "vld1.f32 {q0,q1}, [r8,:128]! \n" - "vmls.f32 q12, q3, q7 \n" - "vmla.f32 q13, q3, q6 \n" - "vmla.f32 q8, q10, q15 \n" - "vmla.f32 q9, q11, q15 \n" - "vmla.f32 q0, q12, q15 \n" - "vmla.f32 q1, q13, q15 \n" - "vst1.f32 {q8,q9},[%2,:128]! \n" - "vst1.f32 {q0,q1},[%2,:128]! \n" - "subs %3, #2 \n" - "bne 1b \n" - : "+r"(a_), "+r"(b_), "+r"(ab_), "+r"(N) : "r"(scaling) : "r8", "q0","q1","q2","q3","q4","q5","q6","q7","q8","q9", "q10","q11","q12","q13","q15","memory"); - -# else /* neon instrinsics version, 30% slower that the asm one with gcc 4.6 */ - v4sf a1r, a1i, b1r, b1i; - v4sf a2r, a2i, b2r, b2i; - v4sf ab1r, ab1i, ab2r, ab2i; - for (i=0; i < Ncvec; i += 2) { - __builtin_prefetch(va+8); - __builtin_prefetch(va+10); - - a1r = *va++; a1i = *va++; - a2r = *va++; a2i = *va++; - b1r = *vb++; b1i = *vb++; - b2r = *vb++; b2i = *vb++; - ab1r = vab[0]; ab1i = vab[1]; - ab2r = vab[2]; ab2i = vab[3]; - - v4sf z1r = VMUL(a1r, b1r); - v4sf z2r = VMUL(a2r, b2r); - v4sf z1i = VMUL(a1r, b1i); - v4sf z2i = VMUL(a2r, b2i); - - __builtin_prefetch(vb+4); - __builtin_prefetch(vb+6); - - z1r = vmlsq_f32(z1r, a1i, b1i); - z2r = vmlsq_f32(z2r, a2i, b2i); - z1i = vmlaq_f32(z1i, a1i, b1r); - z2i = vmlaq_f32(z2i, a2i, b2r); - - __builtin_prefetch(vab+4); - __builtin_prefetch(vab+6); - - ab1r = vmlaq_f32(ab1r, z1r, vscal); - ab2r = vmlaq_f32(ab2r, z2r, vscal); - ab1i = vmlaq_f32(ab1i, z1i, vscal); - ab2i = vmlaq_f32(ab2i, z2i, vscal); - - *vab++ = ab1r; *vab++ = ab1i; - *vab++ = ab2r; *vab++ = ab2i; - } -# endif - -#else /* not ARM, no need to use a special routine */ - 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] = VMADD(ar, vscal, vab[2*i+0]); - vab[2*i+1] = VMADD(ai, vscal, vab[2*i+1]); - 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] = VMADD(ar, vscal, vab[2*i+2]); - vab[2*i+3] = VMADD(ai, vscal, vab[2*i+3]); - } -#endif - if (s->transform == PFFFT_REAL) { - ((v4sf_union*)vab)[0].f[0] = abr + ar*br*scaling; - ((v4sf_union*)vab)[1].f[0] = abi + ai*bi*scaling; - } -} -#endif - -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__ -#error -#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 /* defined(PFFFT_SIMD_DISABLE) */ - -/* standard routine using scalar floats, without SIMD stuff. */ - -#define pffft_zreorder_nosimd pffft_zreorder -static void pffft_zreorder_nosimd(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { - int k, N = setup->N; - if (setup->transform == PFFFT_COMPLEX) { - for (k=0; k < 2*N; ++k) out[k] = in[k]; - return; - } - else if (direction == PFFFT_FORWARD) { - float x_N = in[N-1]; - for (k=N-1; k > 1; --k) out[k] = in[k-1]; - out[0] = in[0]; - out[1] = x_N; - } else { - float x_N = in[1]; - for (k=1; k < N-1; ++k) out[k] = in[k+1]; - out[0] = in[0]; - out[N-1] = x_N; - } -} - -#define pffft_transform_internal_nosimd pffft_transform_internal -static void pffft_transform_internal_nosimd(PFFFT_Setup *setup, const float *input, float *output, float *scratch, - pffft_direction_t direction, int ordered) { - int Ncvec = setup->Ncvec; - int nf_odd = (setup->ifac[1] & 1); - - /* temporary buffer is allocated on the stack if the scratch pointer is NULL */ - /*int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); */ - /*VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); */ - /*if (scratch == 0) scratch = scratch_on_stack; */ - - int ib; - float *buff[2]; - buff[0] = output, buff[1] = scratch; - if (setup->transform == PFFFT_COMPLEX) ordered = 0; /* it is always ordered. */ - ib = (nf_odd ^ ordered ? 1 : 0); - - if (direction == PFFFT_FORWARD) { - if (setup->transform == PFFFT_REAL) { - ib = (rfftf1_ps(Ncvec*2, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - } else { - ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); - } - if (ordered) { - pffft_zreorder(setup, buff[ib], buff[!ib], PFFFT_FORWARD); ib = !ib; - } - } else { - if (input == buff[ib]) { - ib = !ib; /* may happen when finput == foutput */ - } - if (ordered) { - pffft_zreorder(setup, input, buff[!ib], PFFFT_BACKWARD); - input = buff[!ib]; - } - if (setup->transform == PFFFT_REAL) { - ib = (rfftb1_ps(Ncvec*2, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - } else { - ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); - } - } - if (buff[ib] != output) { - int k; - /* extra copy required -- this situation should happens only when finput == foutput */ - assert(input==output); - for (k=0; k < Ncvec; ++k) { - float a = buff[ib][2*k], b = buff[ib][2*k+1]; - output[2*k] = a; output[2*k+1] = b; - } - ib = !ib; - } - assert(buff[ib] == output); -} - -#if 0 -#define pffft_zconvolve_accumulate_nosimd pffft_zconvolve_accumulate -static void pffft_zconvolve_accumulate_nosimd(PFFFT_Setup *s, const float *a, const float *b, - float *ab, float scaling) { - int i, Ncvec = s->Ncvec; - - if (s->transform == PFFFT_REAL) { - /* take care of the fftpack ordering */ - ab[0] += a[0]*b[0]*scaling; - ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]*scaling; - ++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*scaling; - ab[2*i+1] += ai*scaling; - } -} -#endif - -#define pffft_zconvolve_nosimd pffft_zconvolve -static void pffft_zconvolve_nosimd(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 /* defined(PFFFT_SIMD_DISABLE) */ - -static void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { - pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 0); -} - -static void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { - pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 1); -} - - -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 +/* Copyright (c) 2011 Julien Pommier ( pommier@modartt.com ) + + Based on original fortran 77 code from FFTPACKv4 from NETLIB + (http://www.netlib.org/fftpack), authored by Dr Paul Swarztrauber + of NCAR, in 1985. + + As confirmed by the NCAR fftpack software curators, the following + FFTPACKv5 license applies to FFTPACKv4 sources. My changes are + released under the same terms. + + FFTPACK license: + + http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html + + Copyright (c) 2004 the University Corporation for Atmospheric + Research ("UCAR"). All rights reserved. Developed by NCAR's + Computational and Information Systems Laboratory, UCAR, + www.cisl.ucar.edu. + + Redistribution and use of the Software in source and binary forms, + with or without modification, is permitted provided that the + following conditions are met: + + - Neither the names of NCAR's Computational and Information Systems + Laboratory, the University Corporation for Atmospheric Research, + nor the names of its sponsors or contributors may be used to + endorse or promote products derived from this Software without + specific prior written permission. + + - Redistributions of source code must retain the above copyright + notices, this list of conditions, and the disclaimer below. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the disclaimer below in the + documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. + + + PFFFT : a Pretty Fast FFT. + + This file is largerly based on the original FFTPACK implementation, modified in + order to take advantage of SIMD instructions of modern CPUs. +*/ + +/* + ChangeLog: + - 2011/10/02, version 1: This is the very first release of this file. +*/ + +#if !defined PFFT_MACROS_ONLY +#include "pffft.h" +#include "simd.h" +#include +#include +#include +#include + +#define pffft_aligned_free _soxr_simd_aligned_free +#define pffft_aligned_malloc _soxr_simd_aligned_malloc +#define pffft_aligned_calloc _soxr_simd_aligned_calloc +#endif + +/* + vector support macros: the rest of the code is independant of + SSE/Altivec/NEON -- adding support for other platforms with 4-element + vectors should be limited to these macros +*/ + + +/* define PFFFT_SIMD_DISABLE if you want to use scalar code instead of simd code */ +/*#define PFFFT_SIMD_DISABLE */ + +/* detect compiler flavour */ +#if defined(_MSC_VER) +# define COMPILER_MSVC +#elif defined(__GNUC__) +# define COMPILER_GCC +#endif + +#if defined(COMPILER_GCC) +# define ALWAYS_INLINE(return_type) inline return_type __attribute__ ((always_inline)) +# define NEVER_INLINE(return_type) return_type __attribute__ ((noinline)) +# define RESTRICT __restrict +/*# define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ varname__[size__]; */ +#elif defined(COMPILER_MSVC) +# define ALWAYS_INLINE(return_type) __forceinline return_type +# define NEVER_INLINE(return_type) __declspec(noinline) return_type +# define RESTRICT __restrict +/*# define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ *varname__ = (v4sf*)_alloca(size__ * sizeof(type__)) */ +#endif + +/* + Altivec support macros +*/ +#if !defined(PFFFT_SIMD_DISABLE) && (defined(__ppc__) || defined(__ppc64__)) +typedef vector float v4sf; +# define SIMD_SZ 4 +# define VZERO() ((vector float) vec_splat_u8(0)) +# define VMUL(a,b) vec_madd(a,b, VZERO()) +# define VADD(a,b) vec_add(a,b) +# define VMADD(a,b,c) vec_madd(a,b,c) +# define VSUB(a,b) vec_sub(a,b) +inline v4sf ld_ps1(const float *p) { v4sf v=vec_lde(0,p); return vec_splat(vec_perm(v, v, vec_lvsl(0, p)), 0); } +# define LD_PS1(p) ld_ps1(&p) +# define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = vec_mergeh(in1, in2); out2 = vec_mergel(in1, in2); out1 = tmp__; } +# define UNINTERLEAVE2(in1, in2, out1, out2) { \ + vector unsigned char vperm1 = (vector unsigned char)(0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27); \ + vector unsigned char vperm2 = (vector unsigned char)(4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31); \ + v4sf tmp__ = vec_perm(in1, in2, vperm1); out2 = vec_perm(in1, in2, vperm2); out1 = tmp__; \ + } +# define VTRANSPOSE4(x0,x1,x2,x3) { \ + v4sf y0 = vec_mergeh(x0, x2); \ + v4sf y1 = vec_mergel(x0, x2); \ + v4sf y2 = vec_mergeh(x1, x3); \ + v4sf y3 = vec_mergel(x1, x3); \ + x0 = vec_mergeh(y0, y2); \ + x1 = vec_mergel(y0, y2); \ + x2 = vec_mergeh(y1, y3); \ + x3 = vec_mergel(y1, y3); \ + } +# define VSWAPHL(a,b) vec_perm(a,b, (vector unsigned char)(16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15)) +# define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) + +/* + SSE1 support macros +*/ +#elif !defined(PFFFT_SIMD_DISABLE) && (defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)) + +#include +typedef __m128 v4sf; +# define SIMD_SZ 4 /* 4 floats by simd vector -- this is pretty much hardcoded in the preprocess/finalize functions anyway so you will have to work if you want to enable AVX with its 256-bit vectors. */ +# define VZERO() _mm_setzero_ps() +# define VMUL(a,b) _mm_mul_ps(a,b) +# define VADD(a,b) _mm_add_ps(a,b) +# define VMADD(a,b,c) _mm_add_ps(_mm_mul_ps(a,b), c) +# define VSUB(a,b) _mm_sub_ps(a,b) +# define LD_PS1(p) _mm_set1_ps(p) +# define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_unpacklo_ps(in1, in2); out2 = _mm_unpackhi_ps(in1, in2); out1 = tmp__; } +# define UNINTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(2,0,2,0)); out2 = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(3,1,3,1)); out1 = tmp__; } +# define VTRANSPOSE4(x0,x1,x2,x3) _MM_TRANSPOSE4_PS(x0,x1,x2,x3) +# define VSWAPHL(a,b) _mm_shuffle_ps(b, a, _MM_SHUFFLE(3,2,1,0)) +# define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) + +/* + ARM NEON support macros +*/ +#elif !defined(PFFFT_SIMD_DISABLE) && defined(__arm__) +# include +typedef float32x4_t v4sf; +# define SIMD_SZ 4 +# define VZERO() vdupq_n_f32(0) +# define VMUL(a,b) vmulq_f32(a,b) +# define VADD(a,b) vaddq_f32(a,b) +# define VMADD(a,b,c) vmlaq_f32(c,a,b) +# define VSUB(a,b) vsubq_f32(a,b) +# define LD_PS1(p) vld1q_dup_f32(&(p)) +# define INTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vzipq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } +# define UNINTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vuzpq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } +# define VTRANSPOSE4_(x0,x1,x2,x3) { \ + float32x4x2_t t0_ = vzipq_f32(x0, x2); \ + float32x4x2_t t1_ = vzipq_f32(x1, x3); \ + float32x4x2_t u0_ = vzipq_f32(t0_.val[0], t1_.val[0]); \ + float32x4x2_t u1_ = vzipq_f32(t0_.val[1], t1_.val[1]); \ + x0 = u0_.val[0]; x1 = u0_.val[1]; x2 = u1_.val[0]; x3 = u1_.val[1]; \ + } +/* marginally faster version */ +# define VTRANSPOSE4(x0,x1,x2,x3) { asm("vtrn.32 %q0, %q1;\n vtrn.32 %q2,%q3\n vswp %f0,%e2\n vswp %f1,%e3" : "+w"(x0), "+w"(x1), "+w"(x2), "+w"(x3)::); } +# define VSWAPHL(a,b) vcombine_f32(vget_low_f32(b), vget_high_f32(a)) +# define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) +#else +# if !defined(PFFFT_SIMD_DISABLE) +# warning "building with simd disabled !\n"; +# define PFFFT_SIMD_DISABLE /* fallback to scalar code */ +# endif +#endif + +/* fallback mode for situations where SSE/Altivec are not available, use scalar mode instead */ +#ifdef PFFFT_SIMD_DISABLE +typedef float v4sf; +# define SIMD_SZ 1 +# define VZERO() 0.f +# define VMUL(a,b) ((a)*(b)) +# define VADD(a,b) ((a)+(b)) +# define VMADD(a,b,c) ((a)*(b)+(c)) +# define VSUB(a,b) ((a)-(b)) +# define LD_PS1(p) (p) +# define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) +#endif + +/* shortcuts for complex multiplcations */ +#define VCPLXMUL(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VSUB(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VADD(ai,tmp); } +#define VCPLXMULCONJ(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VADD(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VSUB(ai,tmp); } + +#if !defined(PFFFT_SIMD_DISABLE) +typedef union v4sf_union { + v4sf v; + float f[4]; +} v4sf_union; + +#if 0 +#include + +#define assertv4(v,f0,f1,f2,f3) assert(v.f[0] == (f0) && v.f[1] == (f1) && v.f[2] == (f2) && v.f[3] == (f3)) + +/* detect bugs with the vector support macros */ +void validate_pffft_simd() { + float f[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; + v4sf_union a0, a1, a2, a3, t, u; + memcpy(a0.f, f, 4*sizeof(float)); + memcpy(a1.f, f+4, 4*sizeof(float)); + memcpy(a2.f, f+8, 4*sizeof(float)); + memcpy(a3.f, f+12, 4*sizeof(float)); + + t = a0; u = a1; t.v = VZERO(); + printf("VZERO=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 0, 0, 0, 0); + t.v = VADD(a1.v, a2.v); + printf("VADD(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 12, 14, 16, 18); + t.v = VMUL(a1.v, a2.v); + printf("VMUL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 45, 60, 77); + t.v = VMADD(a1.v, a2.v,a0.v); + printf("VMADD(4:7,8:11,0:3)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 46, 62, 80); + + INTERLEAVE2(a1.v,a2.v,t.v,u.v); + printf("INTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); + assertv4(t, 4, 8, 5, 9); assertv4(u, 6, 10, 7, 11); + UNINTERLEAVE2(a1.v,a2.v,t.v,u.v); + printf("UNINTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); + assertv4(t, 4, 6, 8, 10); assertv4(u, 5, 7, 9, 11); + + t.v=LD_PS1(f[15]); + printf("LD_PS1(15)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); + assertv4(t, 15, 15, 15, 15); + t.v = VSWAPHL(a1.v, a2.v); + printf("VSWAPHL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); + assertv4(t, 8, 9, 6, 7); + VTRANSPOSE4(a0.v, a1.v, a2.v, a3.v); + printf("VTRANSPOSE4(0:3,4:7,8:11,12:15)=[%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", + a0.f[0], a0.f[1], a0.f[2], a0.f[3], a1.f[0], a1.f[1], a1.f[2], a1.f[3], + a2.f[0], a2.f[1], a2.f[2], a2.f[3], a3.f[0], a3.f[1], a3.f[2], a3.f[3]); + assertv4(a0, 0, 4, 8, 12); assertv4(a1, 1, 5, 9, 13); assertv4(a2, 2, 6, 10, 14); assertv4(a3, 3, 7, 11, 15); +} +#endif +#endif /*!PFFFT_SIMD_DISABLE */ + +#if !defined PFFT_MACROS_ONLY + + +#if defined (COMPILER_MSVC) + #define sin (float)sin + #define cos (float)cos +#else + #define sin sinf + #define cos cosf +#endif + +/* +int pffft_simd_size() { return SIMD_SZ; } +*/ + +/* + passf2 and passb2 has been merged here, fsign = -1 for passf2, +1 for passb2 +*/ +static NEVER_INLINE(void) passf2_ps(int ido, int l1, const v4sf *cc, v4sf *ch, const float *wa1, float fsign) { + int k, i; + int l1ido = l1*ido; + if (ido <= 2) { + for (k=0; k < l1ido; k += ido, ch += ido, cc+= 2*ido) { + ch[0] = VADD(cc[0], cc[ido+0]); + ch[l1ido] = VSUB(cc[0], cc[ido+0]); + ch[1] = VADD(cc[1], cc[ido+1]); + ch[l1ido + 1] = VSUB(cc[1], cc[ido+1]); + } + } else { + for (k=0; k < l1ido; k += ido, ch += ido, cc += 2*ido) { + for (i=0; i 2); + for (k=0; k< l1ido; k += ido, cc+= 3*ido, ch +=ido) { + for (i=0; i 5) { + wa[i1-1] = wa[i-1]; + wa[i1] = wa[i]; + } + } + l1 = l2; + } +} /* cffti1 */ + + +static v4sf *cfftf1_ps(int n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, const float *wa, const int *ifac, int isign) { + v4sf *in = (v4sf*)input_readonly; + v4sf *out = (in == work2 ? work1 : work2); + int nf = ifac[1], k1; + int l1 = 1; + int iw = 0; + assert(in != out && work1 != work2); + for (k1=2; k1<=nf+1; k1++) { + int ip = ifac[k1]; + int l2 = ip*l1; + int ido = n / l2; + int idot = ido + ido; + switch (ip) { + case 4: { + int ix2 = iw + idot; + int ix3 = ix2 + idot; + passf4_ps(idot, l1, in, out, &wa[iw], &wa[ix2], &wa[ix3], (float)isign); + } break; + case 2: { + passf2_ps(idot, l1, in, out, &wa[iw], (float)isign); + } break; + case 3: { + int ix2 = iw + idot; + passf3_ps(idot, l1, in, out, &wa[iw], &wa[ix2], (float)isign); + } break; + default: + assert(0); + } + l1 = l2; + iw += (ip - 1)*idot; + if (out == work2) { + out = work1; in = work2; + } else { + out = work2; in = work1; + } + } + + return in; /* this is in fact the output .. */ +} + + +struct PFFFT_Setup { + int N; + int Ncvec; /* nb of complex simd vectors (N/4 if PFFFT_COMPLEX, N/8 if PFFFT_REAL) */ + int ifac[15]; + pffft_transform_t transform; + v4sf *data; /* allocated room for twiddle coefs */ + float *e; /* points into 'data' , N/4*3 elements */ + float *twiddle; /* points into 'data', N/4 elements */ +}; + +PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform) { + int k, m; + PFFFT_Setup *s = (PFFFT_Setup*)malloc(sizeof(PFFFT_Setup)); + if (!s) + return s; + if (transform == PFFFT_REAL) { assert(N >= 32); } + if (transform == PFFFT_COMPLEX) { assert(N >= 16); } + /*assert((N % 32) == 0); */ + s->N = N; + s->transform = transform; + /* nb of complex simd vectors */ + s->Ncvec = (transform == PFFFT_REAL ? N/2 : N)/SIMD_SZ; + s->data = (v4sf*)pffft_aligned_malloc(2*(size_t)s->Ncvec * sizeof(v4sf)); + if (!s->data) { + free(s); + return 0; + } + s->e = (float*)s->data; + s->twiddle = (float*)(s->data + (2*s->Ncvec*(SIMD_SZ-1))/SIMD_SZ); + + if (transform == PFFFT_REAL) { + for (k=0; k < s->Ncvec; ++k) { + int i = k/SIMD_SZ; + int j = k%SIMD_SZ; + for (m=0; m < SIMD_SZ-1; ++m) { + float A = (float)(-2*M_PI*(m+1)*k / N); + s->e[(2*(i*3 + m) + 0) * SIMD_SZ + j] = cos(A); + s->e[(2*(i*3 + m) + 1) * SIMD_SZ + j] = sin(A); + } + } + rffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); + } else { + for (k=0; k < s->Ncvec; ++k) { + int i = k/SIMD_SZ; + int j = k%SIMD_SZ; + for (m=0; m < SIMD_SZ-1; ++m) { + float A = (float)(-2*M_PI*(m+1)*k / N); + s->e[(2*(i*3 + m) + 0)*SIMD_SZ + j] = cos(A); + s->e[(2*(i*3 + m) + 1)*SIMD_SZ + j] = sin(A); + } + } + cffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); + } + return s; +} + + +static void pffft_destroy_setup(PFFFT_Setup *s) { + if(s){ + pffft_aligned_free(s->data); + free(s); + } +} + +#if !defined(PFFFT_SIMD_DISABLE) + +/* [0 0 1 2 3 4 5 6 7 8] -> [0 8 7 6 5 4 3 2 1] */ +static void reversed_copy(int N, const v4sf *in, int in_stride, v4sf *out) { + v4sf g0, g1; + int k; + INTERLEAVE2(in[0], in[1], g0, g1); in += in_stride; + + *--out = VSWAPHL(g0, g1); /* [g0l, g0h], [g1l g1h] -> [g1l, g0h] */ + for (k=1; k < N; ++k) { + v4sf h0, h1; + INTERLEAVE2(in[0], in[1], h0, h1); in += in_stride; + *--out = VSWAPHL(g1, h0); + *--out = VSWAPHL(h0, h1); + g1 = h1; + } + *--out = VSWAPHL(g1, g0); +} + +static void unreversed_copy(int N, const v4sf *in, v4sf *out, int out_stride) { + v4sf g0, g1, h0, h1; + int k; + g0 = g1 = in[0]; ++in; + for (k=1; k < N; ++k) { + h0 = *in++; h1 = *in++; + g1 = VSWAPHL(g1, h0); + h0 = VSWAPHL(h0, h1); + UNINTERLEAVE2(h0, g1, out[0], out[1]); out += out_stride; + g1 = h1; + } + h0 = *in++; h1 = g0; + g1 = VSWAPHL(g1, h0); + h0 = VSWAPHL(h0, h1); + UNINTERLEAVE2(h0, g1, out[0], out[1]); +} + +static void pffft_zreorder(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { + int k, N = setup->N, Ncvec = setup->Ncvec; + const v4sf *vin = (const v4sf*)in; + v4sf *vout = (v4sf*)out; + assert(in != out); + if (setup->transform == PFFFT_REAL) { + int k, dk = N/32; + if (direction == PFFFT_FORWARD) { + for (k=0; k < dk; ++k) { + INTERLEAVE2(vin[k*8 + 0], vin[k*8 + 1], vout[2*(0*dk + k) + 0], vout[2*(0*dk + k) + 1]); + INTERLEAVE2(vin[k*8 + 4], vin[k*8 + 5], vout[2*(2*dk + k) + 0], vout[2*(2*dk + k) + 1]); + } + reversed_copy(dk, vin+2, 8, (v4sf*)(out + N/2)); + reversed_copy(dk, vin+6, 8, (v4sf*)(out + N)); + } else { + for (k=0; k < dk; ++k) { + UNINTERLEAVE2(vin[2*(0*dk + k) + 0], vin[2*(0*dk + k) + 1], vout[k*8 + 0], vout[k*8 + 1]); + UNINTERLEAVE2(vin[2*(2*dk + k) + 0], vin[2*(2*dk + k) + 1], vout[k*8 + 4], vout[k*8 + 5]); + } + unreversed_copy(dk, (v4sf*)(in + N/4), (v4sf*)(out + N - 6*SIMD_SZ), -8); + unreversed_copy(dk, (v4sf*)(in + 3*N/4), (v4sf*)(out + N - 2*SIMD_SZ), -8); + } + } else { + if (direction == PFFFT_FORWARD) { + for (k=0; k < Ncvec; ++k) { + int kk = (k/4) + (k%4)*(Ncvec/4); + INTERLEAVE2(vin[k*2], vin[k*2+1], vout[kk*2], vout[kk*2+1]); + } + } else { + for (k=0; k < Ncvec; ++k) { + int kk = (k/4) + (k%4)*(Ncvec/4); + UNINTERLEAVE2(vin[kk*2], vin[kk*2+1], vout[k*2], vout[k*2+1]); + } + } + } +} + +static void pffft_cplx_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { + int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ + v4sf r0, i0, r1, i1, r2, i2, r3, i3; + v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; + assert(in != out); + for (k=0; k < dk; ++k) { + r0 = in[8*k+0]; i0 = in[8*k+1]; + r1 = in[8*k+2]; i1 = in[8*k+3]; + r2 = in[8*k+4]; i2 = in[8*k+5]; + r3 = in[8*k+6]; i3 = in[8*k+7]; + VTRANSPOSE4(r0,r1,r2,r3); + VTRANSPOSE4(i0,i1,i2,i3); + VCPLXMUL(r1,i1,e[k*6+0],e[k*6+1]); + VCPLXMUL(r2,i2,e[k*6+2],e[k*6+3]); + VCPLXMUL(r3,i3,e[k*6+4],e[k*6+5]); + + sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); + sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); + si0 = VADD(i0,i2); di0 = VSUB(i0, i2); + si1 = VADD(i1,i3); di1 = VSUB(i1, i3); + + /* + transformation for each column is: + + [1 1 1 1 0 0 0 0] [r0] + [1 0 -1 0 0 -1 0 1] [r1] + [1 -1 1 -1 0 0 0 0] [r2] + [1 0 -1 0 0 1 0 -1] [r3] + [0 0 0 0 1 1 1 1] * [i0] + [0 1 0 -1 1 0 -1 0] [i1] + [0 0 0 0 1 -1 1 -1] [i2] + [0 -1 0 1 1 0 -1 0] [i3] + */ + + r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); + r1 = VADD(dr0, di1); i1 = VSUB(di0, dr1); + r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); + r3 = VSUB(dr0, di1); i3 = VADD(di0, dr1); + + *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; + *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; + } +} + +static void pffft_cplx_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { + int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ + v4sf r0, i0, r1, i1, r2, i2, r3, i3; + v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; + assert(in != out); + for (k=0; k < dk; ++k) { + r0 = in[8*k+0]; i0 = in[8*k+1]; + r1 = in[8*k+2]; i1 = in[8*k+3]; + r2 = in[8*k+4]; i2 = in[8*k+5]; + r3 = in[8*k+6]; i3 = in[8*k+7]; + + sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); + sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); + si0 = VADD(i0,i2); di0 = VSUB(i0, i2); + si1 = VADD(i1,i3); di1 = VSUB(i1, i3); + + r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); + r1 = VSUB(dr0, di1); i1 = VADD(di0, dr1); + r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); + r3 = VADD(dr0, di1); i3 = VSUB(di0, dr1); + + VCPLXMULCONJ(r1,i1,e[k*6+0],e[k*6+1]); + VCPLXMULCONJ(r2,i2,e[k*6+2],e[k*6+3]); + VCPLXMULCONJ(r3,i3,e[k*6+4],e[k*6+5]); + + VTRANSPOSE4(r0,r1,r2,r3); + VTRANSPOSE4(i0,i1,i2,i3); + + *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; + *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; + } +} + + +static ALWAYS_INLINE(void) pffft_real_finalize_4x4(const v4sf *in0, const v4sf *in1, const v4sf *in, + const v4sf *e, v4sf *out) { + v4sf r0, i0, r1, i1, r2, i2, r3, i3; + v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; + r0 = *in0; i0 = *in1; + r1 = *in++; i1 = *in++; r2 = *in++; i2 = *in++; r3 = *in++; i3 = *in++; + VTRANSPOSE4(r0,r1,r2,r3); + VTRANSPOSE4(i0,i1,i2,i3); + + /* + transformation for each column is: + + [1 1 1 1 0 0 0 0] [r0] + [1 0 -1 0 0 -1 0 1] [r1] + [1 0 -1 0 0 1 0 -1] [r2] + [1 -1 1 -1 0 0 0 0] [r3] + [0 0 0 0 1 1 1 1] * [i0] + [0 -1 0 1 -1 0 1 0] [i1] + [0 -1 0 1 1 0 -1 0] [i2] + [0 0 0 0 -1 1 -1 1] [i3] + */ + + /*cerr << "matrix initial, before e , REAL:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; */ + /*cerr << "matrix initial, before e, IMAG :\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; */ + + VCPLXMUL(r1,i1,e[0],e[1]); + VCPLXMUL(r2,i2,e[2],e[3]); + VCPLXMUL(r3,i3,e[4],e[5]); + + /*cerr << "matrix initial, real part:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; */ + /*cerr << "matrix initial, imag part:\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; */ + + sr0 = VADD(r0,r2); dr0 = VSUB(r0,r2); + sr1 = VADD(r1,r3); dr1 = VSUB(r3,r1); + si0 = VADD(i0,i2); di0 = VSUB(i0,i2); + si1 = VADD(i1,i3); di1 = VSUB(i3,i1); + + r0 = VADD(sr0, sr1); + r3 = VSUB(sr0, sr1); + i0 = VADD(si0, si1); + i3 = VSUB(si1, si0); + r1 = VADD(dr0, di1); + r2 = VSUB(dr0, di1); + i1 = VSUB(dr1, di0); + i2 = VADD(dr1, di0); + + *out++ = r0; + *out++ = i0; + *out++ = r1; + *out++ = i1; + *out++ = r2; + *out++ = i2; + *out++ = r3; + *out++ = i3; + +} + +static NEVER_INLINE(void) pffft_real_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { + int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ + /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ + + v4sf_union cr, ci, *uout = (v4sf_union*)out; + v4sf save = in[7], zero=VZERO(); + float xr0, xi0, xr1, xi1, xr2, xi2, xr3, xi3; + static const float s = (float)(M_SQRT2/2); + + cr.v = in[0]; ci.v = in[Ncvec*2-1]; + assert(in != out); + pffft_real_finalize_4x4(&zero, &zero, in+1, e, out); + + /* + [cr0 cr1 cr2 cr3 ci0 ci1 ci2 ci3] + + [Xr(1)] ] [1 1 1 1 0 0 0 0] + [Xr(N/4) ] [0 0 0 0 1 s 0 -s] + [Xr(N/2) ] [1 0 -1 0 0 0 0 0] + [Xr(3N/4)] [0 0 0 0 1 -s 0 s] + [Xi(1) ] [1 -1 1 -1 0 0 0 0] + [Xi(N/4) ] [0 0 0 0 0 -s -1 -s] + [Xi(N/2) ] [0 -1 0 1 0 0 0 0] + [Xi(3N/4)] [0 0 0 0 0 -s 1 -s] + */ + + xr0=(cr.f[0]+cr.f[2]) + (cr.f[1]+cr.f[3]); uout[0].f[0] = xr0; + xi0=(cr.f[0]+cr.f[2]) - (cr.f[1]+cr.f[3]); uout[1].f[0] = xi0; + xr2=(cr.f[0]-cr.f[2]); uout[4].f[0] = xr2; + xi2=(cr.f[3]-cr.f[1]); uout[5].f[0] = xi2; + xr1= ci.f[0] + s*(ci.f[1]-ci.f[3]); uout[2].f[0] = xr1; + xi1=-ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[3].f[0] = xi1; + xr3= ci.f[0] - s*(ci.f[1]-ci.f[3]); uout[6].f[0] = xr3; + xi3= ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[7].f[0] = xi3; + + for (k=1; k < dk; ++k) { + v4sf save_next = in[8*k+7]; + pffft_real_finalize_4x4(&save, &in[8*k+0], in + 8*k+1, + e + k*6, out + k*8); + save = save_next; + } + +} + +static ALWAYS_INLINE(void) pffft_real_preprocess_4x4(const v4sf *in, + const v4sf *e, v4sf *out, int first) { + v4sf r0=in[0], i0=in[1], r1=in[2], i1=in[3], r2=in[4], i2=in[5], r3=in[6], i3=in[7]; + /* + transformation for each column is: + + [1 1 1 1 0 0 0 0] [r0] + [1 0 0 -1 0 -1 -1 0] [r1] + [1 -1 -1 1 0 0 0 0] [r2] + [1 0 0 -1 0 1 1 0] [r3] + [0 0 0 0 1 -1 1 -1] * [i0] + [0 -1 1 0 1 0 0 1] [i1] + [0 0 0 0 1 1 -1 -1] [i2] + [0 1 -1 0 1 0 0 1] [i3] + */ + + v4sf sr0 = VADD(r0,r3), dr0 = VSUB(r0,r3); + v4sf sr1 = VADD(r1,r2), dr1 = VSUB(r1,r2); + v4sf si0 = VADD(i0,i3), di0 = VSUB(i0,i3); + v4sf si1 = VADD(i1,i2), di1 = VSUB(i1,i2); + + r0 = VADD(sr0, sr1); + r2 = VSUB(sr0, sr1); + r1 = VSUB(dr0, si1); + r3 = VADD(dr0, si1); + i0 = VSUB(di0, di1); + i2 = VADD(di0, di1); + i1 = VSUB(si0, dr1); + i3 = VADD(si0, dr1); + + VCPLXMULCONJ(r1,i1,e[0],e[1]); + VCPLXMULCONJ(r2,i2,e[2],e[3]); + VCPLXMULCONJ(r3,i3,e[4],e[5]); + + VTRANSPOSE4(r0,r1,r2,r3); + VTRANSPOSE4(i0,i1,i2,i3); + + if (!first) { + *out++ = r0; + *out++ = i0; + } + *out++ = r1; + *out++ = i1; + *out++ = r2; + *out++ = i2; + *out++ = r3; + *out++ = i3; +} + +static NEVER_INLINE(void) pffft_real_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { + int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ + /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ + + v4sf_union Xr, Xi, *uout = (v4sf_union*)out; + float cr0, ci0, cr1, ci1, cr2, ci2, cr3, ci3; + static const float s = (float)M_SQRT2; + assert(in != out); + for (k=0; k < 4; ++k) { + Xr.f[k] = ((float*)in)[8*k]; + Xi.f[k] = ((float*)in)[8*k+4]; + } + + pffft_real_preprocess_4x4(in, e, out+1, 1); /* will write only 6 values */ + + /* + [Xr0 Xr1 Xr2 Xr3 Xi0 Xi1 Xi2 Xi3] + + [cr0] [1 0 2 0 1 0 0 0] + [cr1] [1 0 0 0 -1 0 -2 0] + [cr2] [1 0 -2 0 1 0 0 0] + [cr3] [1 0 0 0 -1 0 2 0] + [ci0] [0 2 0 2 0 0 0 0] + [ci1] [0 s 0 -s 0 -s 0 -s] + [ci2] [0 0 0 0 0 -2 0 2] + [ci3] [0 -s 0 s 0 -s 0 -s] + */ + for (k=1; k < dk; ++k) { + pffft_real_preprocess_4x4(in+8*k, e + k*6, out-1+k*8, 0); + } + + cr0=(Xr.f[0]+Xi.f[0]) + 2*Xr.f[2]; uout[0].f[0] = cr0; + cr1=(Xr.f[0]-Xi.f[0]) - 2*Xi.f[2]; uout[0].f[1] = cr1; + cr2=(Xr.f[0]+Xi.f[0]) - 2*Xr.f[2]; uout[0].f[2] = cr2; + cr3=(Xr.f[0]-Xi.f[0]) + 2*Xi.f[2]; uout[0].f[3] = cr3; + ci0= 2*(Xr.f[1]+Xr.f[3]); uout[2*Ncvec-1].f[0] = ci0; + ci1= s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[1] = ci1; + ci2= 2*(Xi.f[3]-Xi.f[1]); uout[2*Ncvec-1].f[2] = ci2; + ci3=-s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[3] = ci3; +} + + +static void pffft_transform_internal(PFFFT_Setup *setup, const float *finput, float *foutput, v4sf *scratch, + pffft_direction_t direction, int ordered) { + int k, Ncvec = setup->Ncvec; + int nf_odd = (setup->ifac[1] & 1); + + /* temporary buffer is allocated on the stack if the scratch pointer is NULL */ + /*int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); */ + /*VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); */ + + int ib = (nf_odd ^ ordered ? 1 : 0); + const v4sf *vinput = (const v4sf*)finput; + v4sf *voutput = (v4sf*)foutput; + v4sf *buff[2]; + buff[0] = voutput, buff[1] = scratch /*? scratch : scratch_on_stack*/; + + /*if (scratch == 0) scratch = scratch_on_stack; */ + + assert(VALIGNED(finput) && VALIGNED(foutput)); + + /*assert(finput != foutput); */ + if (direction == PFFFT_FORWARD) { + ib = !ib; + if (setup->transform == PFFFT_REAL) { + ib = (rfftf1_ps(Ncvec*2, vinput, buff[ib], buff[!ib], + setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); + pffft_real_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); + } else { + v4sf *tmp = buff[ib]; + for (k=0; k < Ncvec; ++k) { + UNINTERLEAVE2(vinput[k*2], vinput[k*2+1], tmp[k*2], tmp[k*2+1]); + } + ib = (cfftf1_ps(Ncvec, buff[ib], buff[!ib], buff[ib], + setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); + pffft_cplx_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); + } + if (ordered) { + pffft_zreorder(setup, (float*)buff[!ib], (float*)buff[ib], PFFFT_FORWARD); + } else ib = !ib; + } else { + if (vinput == buff[ib]) { + ib = !ib; /* may happen when finput == foutput */ + } + if (ordered) { + pffft_zreorder(setup, (float*)vinput, (float*)buff[ib], PFFFT_BACKWARD); + vinput = buff[ib]; ib = !ib; + } + if (setup->transform == PFFFT_REAL) { + pffft_real_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); + ib = (rfftb1_ps(Ncvec*2, buff[ib], buff[0], buff[1], + setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); + } else { + pffft_cplx_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); + ib = (cfftf1_ps(Ncvec, buff[ib], buff[0], buff[1], + setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); + for (k=0; k < Ncvec; ++k) { + INTERLEAVE2(buff[ib][k*2], buff[ib][k*2+1], buff[ib][k*2], buff[ib][k*2+1]); + } + } + } + + if (buff[ib] != voutput) { + /* extra copy required -- this situation should only happen when finput == foutput */ + assert(finput==foutput); + for (k=0; k < Ncvec; ++k) { + v4sf a = buff[ib][2*k], b = buff[ib][2*k+1]; + voutput[2*k] = a; voutput[2*k+1] = b; + } + ib = !ib; + } + assert(buff[ib] == voutput); +} + +#if 0 +static void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { + int i, Ncvec = s->Ncvec; + const v4sf * RESTRICT va = (const v4sf*)a; + const v4sf * RESTRICT vb = (const v4sf*)b; + v4sf * RESTRICT vab = (v4sf*)ab; + +#ifdef __arm__ + __builtin_prefetch(va); + __builtin_prefetch(vb); + __builtin_prefetch(vab); + __builtin_prefetch(va+2); + __builtin_prefetch(vb+2); + __builtin_prefetch(vab+2); + __builtin_prefetch(va+4); + __builtin_prefetch(vb+4); + __builtin_prefetch(vab+4); + __builtin_prefetch(va+6); + __builtin_prefetch(vb+6); + __builtin_prefetch(vab+6); +#endif + + float ar, ai, br, bi, abr, abi; + v4sf vscal = LD_PS1(scaling); + + 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]; + abr = ((v4sf_union*)vab)[0].f[0]; + abi = ((v4sf_union*)vab)[1].f[0]; + +#ifdef __arm__ +# if 1 /* inline asm version */ + const float *a_ = a, *b_ = b; float *ab_ = ab; + int N = Ncvec; + asm volatile("mov r8, %2 \n" + "vdup.f32 q15, %4 \n" + "1: \n" + "pld [%0,#64] \n" + "pld [%1,#64] \n" + "pld [%2,#64] \n" + "pld [%0,#96] \n" + "pld [%1,#96] \n" + "pld [%2,#96] \n" + "vld1.f32 {q0,q1}, [%0,:128]! \n" + "vld1.f32 {q4,q5}, [%1,:128]! \n" + "vld1.f32 {q2,q3}, [%0,:128]! \n" + "vld1.f32 {q6,q7}, [%1,:128]! \n" + "vld1.f32 {q8,q9}, [r8,:128]! \n" + + "vmul.f32 q10, q0, q4 \n" + "vmul.f32 q11, q0, q5 \n" + "vmul.f32 q12, q2, q6 \n" + "vmul.f32 q13, q2, q7 \n" + "vmls.f32 q10, q1, q5 \n" + "vmla.f32 q11, q1, q4 \n" + "vld1.f32 {q0,q1}, [r8,:128]! \n" + "vmls.f32 q12, q3, q7 \n" + "vmla.f32 q13, q3, q6 \n" + "vmla.f32 q8, q10, q15 \n" + "vmla.f32 q9, q11, q15 \n" + "vmla.f32 q0, q12, q15 \n" + "vmla.f32 q1, q13, q15 \n" + "vst1.f32 {q8,q9},[%2,:128]! \n" + "vst1.f32 {q0,q1},[%2,:128]! \n" + "subs %3, #2 \n" + "bne 1b \n" + : "+r"(a_), "+r"(b_), "+r"(ab_), "+r"(N) : "r"(scaling) : "r8", "q0","q1","q2","q3","q4","q5","q6","q7","q8","q9", "q10","q11","q12","q13","q15","memory"); + +# else /* neon instrinsics version, 30% slower that the asm one with gcc 4.6 */ + v4sf a1r, a1i, b1r, b1i; + v4sf a2r, a2i, b2r, b2i; + v4sf ab1r, ab1i, ab2r, ab2i; + for (i=0; i < Ncvec; i += 2) { + __builtin_prefetch(va+8); + __builtin_prefetch(va+10); + + a1r = *va++; a1i = *va++; + a2r = *va++; a2i = *va++; + b1r = *vb++; b1i = *vb++; + b2r = *vb++; b2i = *vb++; + ab1r = vab[0]; ab1i = vab[1]; + ab2r = vab[2]; ab2i = vab[3]; + + v4sf z1r = VMUL(a1r, b1r); + v4sf z2r = VMUL(a2r, b2r); + v4sf z1i = VMUL(a1r, b1i); + v4sf z2i = VMUL(a2r, b2i); + + __builtin_prefetch(vb+4); + __builtin_prefetch(vb+6); + + z1r = vmlsq_f32(z1r, a1i, b1i); + z2r = vmlsq_f32(z2r, a2i, b2i); + z1i = vmlaq_f32(z1i, a1i, b1r); + z2i = vmlaq_f32(z2i, a2i, b2r); + + __builtin_prefetch(vab+4); + __builtin_prefetch(vab+6); + + ab1r = vmlaq_f32(ab1r, z1r, vscal); + ab2r = vmlaq_f32(ab2r, z2r, vscal); + ab1i = vmlaq_f32(ab1i, z1i, vscal); + ab2i = vmlaq_f32(ab2i, z2i, vscal); + + *vab++ = ab1r; *vab++ = ab1i; + *vab++ = ab2r; *vab++ = ab2i; + } +# endif + +#else /* not ARM, no need to use a special routine */ + 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] = VMADD(ar, vscal, vab[2*i+0]); + vab[2*i+1] = VMADD(ai, vscal, vab[2*i+1]); + 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] = VMADD(ar, vscal, vab[2*i+2]); + vab[2*i+3] = VMADD(ai, vscal, vab[2*i+3]); + } +#endif + if (s->transform == PFFFT_REAL) { + ((v4sf_union*)vab)[0].f[0] = abr + ar*br*scaling; + ((v4sf_union*)vab)[1].f[0] = abi + ai*bi*scaling; + } +} +#endif + +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__ +#error +#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 /* defined(PFFFT_SIMD_DISABLE) */ + +/* standard routine using scalar floats, without SIMD stuff. */ + +#define pffft_zreorder_nosimd pffft_zreorder +static void pffft_zreorder_nosimd(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { + int k, N = setup->N; + if (setup->transform == PFFFT_COMPLEX) { + for (k=0; k < 2*N; ++k) out[k] = in[k]; + return; + } + else if (direction == PFFFT_FORWARD) { + float x_N = in[N-1]; + for (k=N-1; k > 1; --k) out[k] = in[k-1]; + out[0] = in[0]; + out[1] = x_N; + } else { + float x_N = in[1]; + for (k=1; k < N-1; ++k) out[k] = in[k+1]; + out[0] = in[0]; + out[N-1] = x_N; + } +} + +#define pffft_transform_internal_nosimd pffft_transform_internal +static void pffft_transform_internal_nosimd(PFFFT_Setup *setup, const float *input, float *output, float *scratch, + pffft_direction_t direction, int ordered) { + int Ncvec = setup->Ncvec; + int nf_odd = (setup->ifac[1] & 1); + + /* temporary buffer is allocated on the stack if the scratch pointer is NULL */ + /*int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); */ + /*VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); */ + /*if (scratch == 0) scratch = scratch_on_stack; */ + + int ib; + float *buff[2]; + buff[0] = output, buff[1] = scratch; + if (setup->transform == PFFFT_COMPLEX) ordered = 0; /* it is always ordered. */ + ib = (nf_odd ^ ordered ? 1 : 0); + + if (direction == PFFFT_FORWARD) { + if (setup->transform == PFFFT_REAL) { + ib = (rfftf1_ps(Ncvec*2, input, buff[ib], buff[!ib], + setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); + } else { + ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], + setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); + } + if (ordered) { + pffft_zreorder(setup, buff[ib], buff[!ib], PFFFT_FORWARD); ib = !ib; + } + } else { + if (input == buff[ib]) { + ib = !ib; /* may happen when finput == foutput */ + } + if (ordered) { + pffft_zreorder(setup, input, buff[!ib], PFFFT_BACKWARD); + input = buff[!ib]; + } + if (setup->transform == PFFFT_REAL) { + ib = (rfftb1_ps(Ncvec*2, input, buff[ib], buff[!ib], + setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); + } else { + ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], + setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); + } + } + if (buff[ib] != output) { + int k; + /* extra copy required -- this situation should happens only when finput == foutput */ + assert(input==output); + for (k=0; k < Ncvec; ++k) { + float a = buff[ib][2*k], b = buff[ib][2*k+1]; + output[2*k] = a; output[2*k+1] = b; + } + ib = !ib; + } + assert(buff[ib] == output); +} + +#if 0 +#define pffft_zconvolve_accumulate_nosimd pffft_zconvolve_accumulate +static void pffft_zconvolve_accumulate_nosimd(PFFFT_Setup *s, const float *a, const float *b, + float *ab, float scaling) { + int i, Ncvec = s->Ncvec; + + if (s->transform == PFFFT_REAL) { + /* take care of the fftpack ordering */ + ab[0] += a[0]*b[0]*scaling; + ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]*scaling; + ++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*scaling; + ab[2*i+1] += ai*scaling; + } +} +#endif + +#define pffft_zconvolve_nosimd pffft_zconvolve +static void pffft_zconvolve_nosimd(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 /* defined(PFFFT_SIMD_DISABLE) */ + +static void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { + pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 0); +} + +static void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { + pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 1); +} + + +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 diff --git a/lib-src/libsoxr/src/pffft.h b/lib-src/libsoxr/src/pffft.h index 21947ac86..78d936be2 100644 --- a/lib-src/libsoxr/src/pffft.h +++ b/lib-src/libsoxr/src/pffft.h @@ -1,177 +1,177 @@ -/* Copyright (c) 2011 Julien Pommier ( pommier@modartt.com ) - - Based on original fortran 77 code from FFTPACKv4 from NETLIB, - authored by Dr Paul Swarztrauber of NCAR, in 1985. - - As confirmed by the NCAR fftpack software curators, the following - FFTPACKv5 license applies to FFTPACKv4 sources. My changes are - released under the same terms. - - FFTPACK license: - - http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html - - Copyright (c) 2004 the University Corporation for Atmospheric - Research ("UCAR"). All rights reserved. Developed by NCAR's - Computational and Information Systems Laboratory, UCAR, - www.cisl.ucar.edu. - - Redistribution and use of the Software in source and binary forms, - with or without modification, is permitted provided that the - following conditions are met: - - - Neither the names of NCAR's Computational and Information Systems - Laboratory, the University Corporation for Atmospheric Research, - nor the names of its sponsors or contributors may be used to - endorse or promote products derived from this Software without - specific prior written permission. - - - Redistributions of source code must retain the above copyright - notices, this list of conditions, and the disclaimer below. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the disclaimer below in the - documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE - SOFTWARE. -*/ - -/* - PFFFT : a Pretty Fast FFT. - - This is basically an adaptation of the single precision fftpack - (v4) as found on netlib taking advantage of SIMD instruction found - on cpus such as intel x86 (SSE1), powerpc (Altivec), and arm (NEON). - - For architectures where no SIMD instruction is available, the code - falls back to a scalar version. - - Restrictions: - - - 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. - - - all (float*) pointers in the functions below are expected to - have an "simd-compatible" alignment, that is 16 bytes on x86 and - powerpc CPUs. - - You can allocate such buffers with the functions - pffft_aligned_malloc / pffft_aligned_free (or with stuff like - posix_memalign..) - -*/ - -#ifndef PFFFT_H -#define PFFFT_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - /* opaque struct holding internal stuff (precomputed twiddle factors) - this struct can be shared by many threads as it contains only - read-only data. - */ - typedef struct PFFFT_Setup PFFFT_Setup; - - /* direction of the transform */ - typedef enum { PFFFT_FORWARD, PFFFT_BACKWARD } pffft_direction_t; - - /* type of transform */ - typedef enum { PFFFT_REAL, PFFFT_COMPLEX } pffft_transform_t; - - /* - prepare for performing transforms of size N -- the returned - 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 *); - /* - Perform a Fourier transform , The z-domain data is stored in the - most efficient order for transforming it back, or using it for - convolution. If you need to have its content sorted in the - "usual" way, that is as an array of interleaved complex numbers, - either use pffft_transform_ordered , or call pffft_zreorder after - the forward fft, and before the backward fft. - - Transforms are not scaled: PFFFT_BACKWARD(PFFFT_FORWARD(x)) = N*x. - 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] - - input and output may alias. - */ - 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 - ordered as expected (interleaved complex numbers). This is - similar to calling pffft_transform and then pffft_zreorder. - - input and output may alias. - */ - 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(..., - PFFFT_FORWARD) if you want to have the frequency components in - the correct "canonical" order, as interleaved complex numbers. - - (for real transforms, both 0-frequency and half frequency - components, which are real, are assembled in the first entry as - F(0)+i*F(n/2+1). Note that the original fftpack did place - F(n/2+1) at the end of the arrays). - - input and output should not alias. - */ - 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 - dft_b and accumulate them into dft_ab. The arrays should have - been obtained with pffft_transform(.., PFFFT_FORWARD) and should - *not* have been reordered with pffft_zreorder (otherwise just - perform the operation yourself as the dft coefs are stored as - interleaved complex numbers). - - 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); - */ - - /* - the operation performed is: dft_ab = (dft_a * fdt_b) - - The dft_a, dft_b and dft_ab pointers may alias. - */ - static void pffft_zconvolve(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab); - - /* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */ - int pffft_simd_size(void); - - static void pffft_reorder_back(int length, void * setup, float * data, float * work); - -#ifdef __cplusplus -} -#endif - -#endif +/* Copyright (c) 2011 Julien Pommier ( pommier@modartt.com ) + + Based on original fortran 77 code from FFTPACKv4 from NETLIB, + authored by Dr Paul Swarztrauber of NCAR, in 1985. + + As confirmed by the NCAR fftpack software curators, the following + FFTPACKv5 license applies to FFTPACKv4 sources. My changes are + released under the same terms. + + FFTPACK license: + + http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html + + Copyright (c) 2004 the University Corporation for Atmospheric + Research ("UCAR"). All rights reserved. Developed by NCAR's + Computational and Information Systems Laboratory, UCAR, + www.cisl.ucar.edu. + + Redistribution and use of the Software in source and binary forms, + with or without modification, is permitted provided that the + following conditions are met: + + - Neither the names of NCAR's Computational and Information Systems + Laboratory, the University Corporation for Atmospheric Research, + nor the names of its sponsors or contributors may be used to + endorse or promote products derived from this Software without + specific prior written permission. + + - Redistributions of source code must retain the above copyright + notices, this list of conditions, and the disclaimer below. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the disclaimer below in the + documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +*/ + +/* + PFFFT : a Pretty Fast FFT. + + This is basically an adaptation of the single precision fftpack + (v4) as found on netlib taking advantage of SIMD instruction found + on cpus such as intel x86 (SSE1), powerpc (Altivec), and arm (NEON). + + For architectures where no SIMD instruction is available, the code + falls back to a scalar version. + + Restrictions: + + - 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. + + - all (float*) pointers in the functions below are expected to + have an "simd-compatible" alignment, that is 16 bytes on x86 and + powerpc CPUs. + + You can allocate such buffers with the functions + pffft_aligned_malloc / pffft_aligned_free (or with stuff like + posix_memalign..) + +*/ + +#ifndef PFFFT_H +#define PFFFT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /* opaque struct holding internal stuff (precomputed twiddle factors) + this struct can be shared by many threads as it contains only + read-only data. + */ + typedef struct PFFFT_Setup PFFFT_Setup; + + /* direction of the transform */ + typedef enum { PFFFT_FORWARD, PFFFT_BACKWARD } pffft_direction_t; + + /* type of transform */ + typedef enum { PFFFT_REAL, PFFFT_COMPLEX } pffft_transform_t; + + /* + prepare for performing transforms of size N -- the returned + 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 *); + /* + Perform a Fourier transform , The z-domain data is stored in the + most efficient order for transforming it back, or using it for + convolution. If you need to have its content sorted in the + "usual" way, that is as an array of interleaved complex numbers, + either use pffft_transform_ordered , or call pffft_zreorder after + the forward fft, and before the backward fft. + + Transforms are not scaled: PFFFT_BACKWARD(PFFFT_FORWARD(x)) = N*x. + 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] + + input and output may alias. + */ + 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 + ordered as expected (interleaved complex numbers). This is + similar to calling pffft_transform and then pffft_zreorder. + + input and output may alias. + */ + 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(..., + PFFFT_FORWARD) if you want to have the frequency components in + the correct "canonical" order, as interleaved complex numbers. + + (for real transforms, both 0-frequency and half frequency + components, which are real, are assembled in the first entry as + F(0)+i*F(n/2+1). Note that the original fftpack did place + F(n/2+1) at the end of the arrays). + + input and output should not alias. + */ + 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 + dft_b and accumulate them into dft_ab. The arrays should have + been obtained with pffft_transform(.., PFFFT_FORWARD) and should + *not* have been reordered with pffft_zreorder (otherwise just + perform the operation yourself as the dft coefs are stored as + interleaved complex numbers). + + 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); + */ + + /* + the operation performed is: dft_ab = (dft_a * fdt_b) + + The dft_a, dft_b and dft_ab pointers may alias. + */ + static void pffft_zconvolve(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab); + + /* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */ + int pffft_simd_size(void); + + static void pffft_reorder_back(int length, void * setup, float * data, float * work); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib-src/libsoxr/src/pffft32.c b/lib-src/libsoxr/src/pffft32.c index 7a7ff63a5..21bd845a8 100644 --- a/lib-src/libsoxr/src/pffft32.c +++ b/lib-src/libsoxr/src/pffft32.c @@ -1,30 +1,32 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define PFFFT_SIMD_DISABLE -#include "pffft.c" -#include "filter.h" - -static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} -static void delete_setup(void * setup) {pffft_destroy_setup(setup);} -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 int multiplier(void) {return 1;} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft32_cb[] = { - (fn_t)setup, - (fn_t)setup, - (fn_t)delete_setup, - (fn_t)forward, - (fn_t)oforward, - (fn_t)backward, - (fn_t)obackward, - (fn_t)convolve, - (fn_t)_soxr_ordered_partial_convolve_f, - (fn_t)multiplier, - (fn_t)pffft_reorder_back, -}; +/* 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 PFFFT_SIMD_DISABLE +#include "pffft.c" +#include "filter.h" + +static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} +static void delete_setup(void * setup) {pffft_destroy_setup(setup);} +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 int multiplier(void) {return 1;} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft32_cb[] = { + (fn_t)setup, + (fn_t)setup, + (fn_t)delete_setup, + (fn_t)forward, + (fn_t)oforward, + (fn_t)backward, + (fn_t)obackward, + (fn_t)convolve, + (fn_t)_soxr_ordered_partial_convolve_f, + (fn_t)multiplier, + (fn_t)pffft_reorder_back, +}; diff --git a/lib-src/libsoxr/src/pffft32s.c b/lib-src/libsoxr/src/pffft32s.c index 14e622c9a..d04999066 100644 --- a/lib-src/libsoxr/src/pffft32s.c +++ b/lib-src/libsoxr/src/pffft32s.c @@ -1,27 +1,27 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "pffft.c" - -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 int multiplier(void) {return 1;} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft32s_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)_soxr_ordered_partial_convolve_simd, - (fn_t)multiplier, - (fn_t)pffft_reorder_back, -}; +/* 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" + +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 int multiplier(void) {return 1;} + +typedef void (* fn_t)(void); +fn_t _soxr_rdft32s_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)_soxr_ordered_partial_convolve_simd, + (fn_t)multiplier, + (fn_t)pffft_reorder_back, +}; diff --git a/lib-src/libsoxr/src/poly-fir.h b/lib-src/libsoxr/src/poly-fir.h index 67af303a1..f7b4261a3 100644 --- a/lib-src/libsoxr/src/poly-fir.h +++ b/lib-src/libsoxr/src/poly-fir.h @@ -1,98 +1,98 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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. */ - -#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 - #error COEF_INTERP -#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); - -#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; - } - 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 COEF_INTERP -#undef CONVOLVE -#undef FIR_LENGTH -#undef FUNCTION -#undef PHASE_BITS +/* SoX Resampler Library Copyright (c) 2007-13 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. */ + +#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 + #error COEF_INTERP +#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); + +#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; + } + 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 COEF_INTERP +#undef CONVOLVE +#undef FIR_LENGTH +#undef FUNCTION +#undef PHASE_BITS diff --git a/lib-src/libsoxr/src/poly-fir0.h b/lib-src/libsoxr/src/poly-fir0.h index 72a9bfd75..52d85b39a 100644 --- a/lib-src/libsoxr/src/poly-fir0.h +++ b/lib-src/libsoxr/src/poly-fir0.h @@ -1,32 +1,32 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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. */ - -#define _ sum += (coef(p->shared->poly_fir_coefs, 0, FIR_LENGTH, rem, 0, j)) *at[j], ++j; - -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); - - 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; - } - 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 CONVOLVE -#undef FIR_LENGTH -#undef FUNCTION +/* SoX Resampler Library Copyright (c) 2007-13 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. */ + +#define _ sum += (coef(p->shared->poly_fir_coefs, 0, FIR_LENGTH, rem, 0, j)) *at[j], ++j; + +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); + + 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; + } + 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 CONVOLVE +#undef FIR_LENGTH +#undef FUNCTION diff --git a/lib-src/libsoxr/src/rate.h b/lib-src/libsoxr/src/rate.h index 307b69ff6..81cabff3e 100644 --- a/lib-src/libsoxr/src/rate.h +++ b/lib-src/libsoxr/src/rate.h @@ -1,734 +1,724 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include -#include - -#include "filter.h" -#include "internal.h" - -#if defined SOXR_LIB - -extern struct { - void * (* forward_setup)(int); - void * (* backward_setup)(int); - void (* delete_setup)(void *); - void (* forward)(int, void *, sample_t *, sample_t *); - void (* oforward)(int, void *, sample_t *, sample_t *); - void (* backward)(int, void *, sample_t *, sample_t *); - void (* obackward)(int, void *, sample_t *, sample_t *); - void (* convolve)(int, void *, sample_t *, sample_t const *); - void (* convolve_portion)(int, sample_t *, sample_t const *); - int (* multiplier)(void); - void (* reorder_back)(int, void *, sample_t *, sample_t *); -} RDFT_CB; - -#define rdft_forward_setup (*RDFT_CB.forward_setup) -#define rdft_backward_setup (*RDFT_CB.backward_setup) -#define rdft_delete_setup (*RDFT_CB.delete_setup) -#define rdft_forward (*RDFT_CB.forward) -#define rdft_oforward (*RDFT_CB.oforward) -#define rdft_backward (*RDFT_CB.backward) -#define rdft_obackward (*RDFT_CB.obackward) -#define rdft_convolve (*RDFT_CB.convolve) -#define rdft_convolve_portion (*RDFT_CB.convolve_portion) -#define rdft_multiplier (*RDFT_CB.multiplier) -#define rdft_reorder_back (*RDFT_CB.reorder_back) - -#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; - - 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 = lsx_is_power_of_2(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 = abs(3-M) == 1 && Fs == 1 && 1? -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_PC (67 + 5 / 8.) - -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 bw_pc, /* Pass-band % (0dB pt.) to preserve. 91.3|98.4*/ - double anti_aliasing_pc, /* % bandwidth without aliasing 100 */ - 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 - bw_pc / 100, Fs_a = 2 - anti_aliasing_pc / 100; - 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 || bw_pc > LOW_Q_BW0_PC: - (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 <= bw_pc && bw_pc <= 100); - assert(85 <= anti_aliasing_pc && anti_aliasing_pc <= 100); - - p->factor = factor; - if (bits) while (!n++) { /* Determine stages: */ - int try, L, M, x, maxL = interpolator > 0? 1 : mode? 2048 : - (int)ceil(DBL 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, DBL 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->bits, - q_spec->phase, - q_spec->bw_pc, - q_spec->anti_aliasing_pc, - "\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; -} - -typedef void (* fn_t)(void); -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 +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include +#include +#include +#include + +#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 diff --git a/lib-src/libsoxr/src/rate32.c b/lib-src/libsoxr/src/rate32.c index ab6272c20..d6dd3b9ad 100644 --- a/lib-src/libsoxr/src/rate32.c +++ b/lib-src/libsoxr/src/rate32.c @@ -1,9 +1,9 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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" +/* 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" diff --git a/lib-src/libsoxr/src/rate32s.c b/lib-src/libsoxr/src/rate32s.c index 3133bb5be..26a371a24 100644 --- a/lib-src/libsoxr/src/rate32s.c +++ b/lib-src/libsoxr/src/rate32s.c @@ -1,9 +1,9 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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" +/* 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" diff --git a/lib-src/libsoxr/src/rate64.c b/lib-src/libsoxr/src/rate64.c index 2e62e13c6..6289911e5 100644 --- a/lib-src/libsoxr/src/rate64.c +++ b/lib-src/libsoxr/src/rate64.c @@ -1,9 +1,9 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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" +/* 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" diff --git a/lib-src/libsoxr/src/rdft.h b/lib-src/libsoxr/src/rdft.h index 81415966d..59ba17417 100644 --- a/lib-src/libsoxr/src/rdft.h +++ b/lib-src/libsoxr/src/rdft.h @@ -1,31 +1,31 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -void ORDERED_CONVOLVE(int n, void * not_used, DFT_FLOAT * a, const DFT_FLOAT * b) -{ - int i; - a[0] *= b[0]; - a[1] *= b[1]; - for (i = 2; i < n; i += 2) { - DFT_FLOAT tmp = a[i]; - a[i ] = b[i ] * tmp - b[i+1] * a[i+1]; - a[i+1] = b[i+1] * tmp + b[i ] * a[i+1]; - } - (void)not_used; -} - -void ORDERED_PARTIAL_CONVOLVE(int n, DFT_FLOAT * a, const DFT_FLOAT * b) -{ - int i; - a[0] *= b[0]; - for (i = 2; i < n; i += 2) { - DFT_FLOAT tmp = a[i]; - a[i ] = b[i ] * tmp - b[i+1] * a[i+1]; - a[i+1] = b[i+1] * tmp + b[i ] * a[i+1]; - } - a[1] = b[i] * a[i] - b[i+1] * a[i+1]; -} - -#undef ORDERED_CONVOLVE -#undef ORDERED_PARTIAL_CONVOLVE -#undef DFT_FLOAT +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +void ORDERED_CONVOLVE(int n, void * not_used, DFT_FLOAT * a, const DFT_FLOAT * b) +{ + int i; + a[0] *= b[0]; + a[1] *= b[1]; + for (i = 2; i < n; i += 2) { + DFT_FLOAT tmp = a[i]; + a[i ] = b[i ] * tmp - b[i+1] * a[i+1]; + a[i+1] = b[i+1] * tmp + b[i ] * a[i+1]; + } + (void)not_used; +} + +void ORDERED_PARTIAL_CONVOLVE(int n, DFT_FLOAT * a, const DFT_FLOAT * b) +{ + int i; + a[0] *= b[0]; + for (i = 2; i < n; i += 2) { + DFT_FLOAT tmp = a[i]; + a[i ] = b[i ] * tmp - b[i+1] * a[i+1]; + a[i+1] = b[i+1] * tmp + b[i ] * a[i+1]; + } + a[1] = b[i] * a[i] - b[i+1] * a[i+1]; +} + +#undef ORDERED_CONVOLVE +#undef ORDERED_PARTIAL_CONVOLVE +#undef DFT_FLOAT diff --git a/lib-src/libsoxr/src/rint-clip.h b/lib-src/libsoxr/src/rint-clip.h index 164f6eb39..a501cec4a 100644 --- a/lib-src/libsoxr/src/rint-clip.h +++ b/lib-src/libsoxr/src/rint-clip.h @@ -1,153 +1,153 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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 DITHER_RAND (seed = 1664525UL * seed + 1013904223UL) >> 3 -#define DITHER_VARS unsigned long ran1 = DITHER_RAND, ran2 = DITHER_RAND -#define SEED_ARG , unsigned long * seed0 -#define SAVE_SEED *seed0 = seed -#define COPY_SEED unsigned long seed = *seed0; -#define COPY_SEED1 unsigned long seed1 = seed -#define PASS_SEED1 , &seed1 -#define PASS_SEED0 , seed0 - -#else - -#define DITHERING 0 -#define DITHER_VARS -#define SEED_ARG -#define SAVE_SEED -#define COPY_SEED -#define COPY_SEED1 -#define PASS_SEED1 -#define PASS_SEED0 - -#endif - - - -#if defined FE_INVALID && defined FPU_RINT -static void RINT_CLIP(RINT_T * const dest, FLOATX const * const src, - unsigned stride, size_t i, size_t const n, size_t * const clips SEED_ARG) -{ - COPY_SEED - DITHER_VARS; - for (; i < n; ++i) { - double d = src[i] + DITHERING; - dest[stride * i] = RINT(d); - if (fetestexcept(FE_INVALID)) { - feclearexcept(FE_INVALID); - dest[stride * i] = d > 0? RINT_MAX : -RINT_MAX - 1; - ++*clips; - } - } - SAVE_SEED; -} -#endif - - - -static size_t LSX_RINT_CLIP(void * * const dest0, FLOATX const * const src, - size_t const n SEED_ARG) -{ - size_t i, clips = 0; - RINT_T * dest = *dest0; - COPY_SEED -#if defined FE_INVALID && defined FPU_RINT -#define _ dest[i] = RINT(src[i] + DITHERING), ++i, - feclearexcept(FE_INVALID); - for (i = 0; i < (n & ~7u);) { - COPY_SEED1; - DITHER_VARS; - _ _ _ _ _ _ _ _ 0; - if (fetestexcept(FE_INVALID)) { - feclearexcept(FE_INVALID); - RINT_CLIP(dest, src, 1, i - 8, i, &clips PASS_SEED1); - } - } - RINT_CLIP(dest, src, 1, i, n, &clips PASS_SEED0); -#else -#define _ d = src[i] + DITHERING, dest[i++] = (RINT_T)(d > N - 1? ++clips, (RINT_T)(N - 1) : d < -N? ++clips, (RINT_T)(-N) : RINT(d)), - const double N = 1. + RINT_MAX; - double d; - for (i = 0; i < (n & ~7u);) { - DITHER_VARS; - _ _ _ _ _ _ _ _ 0; - } - { - DITHER_VARS; - for (; i < n; _ 0); - } -#endif - SAVE_SEED; - *dest0 = dest + n; - return clips; -} -#undef _ - - - -static size_t LSX_RINT_CLIP_2(void * * dest0, FLOATX const * const * srcs, - unsigned const stride, size_t const n SEED_ARG) -{ - unsigned j; - size_t i, clips = 0; - RINT_T * dest = *dest0; - COPY_SEED -#if defined FE_INVALID && defined FPU_RINT -#define _ dest[stride * i] = RINT(src[i] + DITHERING), ++i, - feclearexcept(FE_INVALID); - for (j = 0; j < stride; ++j, ++dest) { - FLOATX const * const src = srcs[j]; - for (i = 0; i < (n & ~7u);) { - COPY_SEED1; - DITHER_VARS; - _ _ _ _ _ _ _ _ 0; - if (fetestexcept(FE_INVALID)) { - feclearexcept(FE_INVALID); - RINT_CLIP(dest, src, stride, i - 8, i, &clips PASS_SEED1); - } - } - RINT_CLIP(dest, src, stride, i, n, &clips PASS_SEED0); - } -#else -#define _ d = src[i] + DITHERING, dest[stride * i++] = (RINT_T)(d > N - 1? ++clips, (RINT_T)(N - 1) : d < -N? ++clips, (RINT_T)(-N) : RINT(d)), - 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);) { - DITHER_VARS; - _ _ _ _ _ _ _ _ 0; - } - { - DITHER_VARS; - for (; i < n; _ 0); - } - } -#endif - SAVE_SEED; - *dest0 = dest + stride * (n - 1); - return clips; -} -#undef _ - -#undef PASS_SEED0 -#undef PASS_SEED1 -#undef COPY_SEED1 -#undef COPY_SEED -#undef SAVE_SEED -#undef SEED_ARG -#undef DITHER_VARS -#undef DITHERING -#undef DITHER - -#undef RINT_MAX -#undef RINT_T -#undef FPU_RINT -#undef RINT -#undef RINT_CLIP -#undef LSX_RINT_CLIP -#undef LSX_RINT_CLIP_2 +/* SoX Resampler Library Copyright (c) 2007-13 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 DITHER_RAND (seed = 1664525UL * seed + 1013904223UL) >> 3 +#define DITHER_VARS unsigned long ran1 = DITHER_RAND, ran2 = DITHER_RAND +#define SEED_ARG , unsigned long * seed0 +#define SAVE_SEED *seed0 = seed +#define COPY_SEED unsigned long seed = *seed0; +#define COPY_SEED1 unsigned long seed1 = seed +#define PASS_SEED1 , &seed1 +#define PASS_SEED , &seed + +#else + +#define DITHERING 0 +#define DITHER_VARS +#define SEED_ARG +#define SAVE_SEED +#define COPY_SEED +#define COPY_SEED1 +#define PASS_SEED1 +#define PASS_SEED + +#endif + + + +#if defined FE_INVALID && defined FPU_RINT +static void RINT_CLIP(RINT_T * const dest, FLOATX const * const src, + unsigned stride, size_t i, size_t const n, size_t * const clips SEED_ARG) +{ + COPY_SEED + DITHER_VARS; + for (; i < n; ++i) { + double d = src[i] + DITHERING; + dest[stride * i] = RINT(d); + if (fe_test_invalid()) { + fe_clear_invalid(); + dest[stride * i] = d > 0? RINT_MAX : -RINT_MAX - 1; + ++*clips; + } + } + SAVE_SEED; +} +#endif + + + +static size_t LSX_RINT_CLIP(void * * const dest0, FLOATX const * const src, + size_t const n SEED_ARG) +{ + size_t i, clips = 0; + 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);) { + COPY_SEED1; + DITHER_VARS; + _ _ _ _ _ _ _ _ 0; + if (fe_test_invalid()) { + fe_clear_invalid(); + RINT_CLIP(dest, src, 1, i - 8, 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), + const double N = 1. + RINT_MAX; + double d; + for (i = 0; i < (n & ~7u);) { + DITHER_VARS; + _ _ _ _ _ _ _ _ 0; + } + { + DITHER_VARS; + for (; i < n; _ 0); + } +#endif + SAVE_SEED; + *dest0 = dest + n; + return clips; +} +#undef _ + + + +static size_t LSX_RINT_CLIP_2(void * * dest0, FLOATX const * const * srcs, + unsigned const stride, size_t const n SEED_ARG) +{ + unsigned j; + size_t i, clips = 0; + 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(); + for (j = 0; j < stride; ++j, ++dest) { + FLOATX const * const src = srcs[j]; + for (i = 0; i < (n & ~7u);) { + COPY_SEED1; + DITHER_VARS; + _ _ _ _ _ _ _ _ 0; + if (fe_test_invalid()) { + fe_clear_invalid(); + RINT_CLIP(dest, src, stride, i - 8, 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), + 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);) { + DITHER_VARS; + _ _ _ _ _ _ _ _ 0; + } + { + DITHER_VARS; + for (; i < n; _ 0); + } + } +#endif + SAVE_SEED; + *dest0 = dest + stride * (n - 1); + return clips; +} +#undef _ + +#undef PASS_SEED +#undef PASS_SEED1 +#undef COPY_SEED1 +#undef COPY_SEED +#undef SAVE_SEED +#undef SEED_ARG +#undef DITHER_VARS +#undef DITHERING +#undef DITHER + +#undef RINT_MAX +#undef RINT_T +#undef FPU_RINT +#undef RINT +#undef RINT_CLIP +#undef LSX_RINT_CLIP +#undef LSX_RINT_CLIP_2 diff --git a/lib-src/libsoxr/src/rint.h b/lib-src/libsoxr/src/rint.h index 047455405..529e4bb8b 100644 --- a/lib-src/libsoxr/src/rint.h +++ b/lib-src/libsoxr/src/rint.h @@ -1,68 +1,68 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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 - #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 - #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 - - - -#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) - #define FPU_RINT16 - static __inline int16_t rint16(double input) { - int16_t result; - __asm__ __volatile__("fistps %0": "=m"(result): "t"(input): "st"); - return result; - } -#elif defined _MSC_VER && defined _M_IX86 - #define FPU_RINT16 - static __inline int16_t rint16(double input) { - int16_t result; - _asm { - fld input - fistp result - } - return result; - } -#else - #define rint16(x) (int16_t)floor((x)+.5) /* Is this faster than in rint32? */ -#endif - - - -#endif +/* SoX Resampler Library Copyright (c) 2007-13 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 + #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 + + + +#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) + #define FPU_RINT16 + static __inline int16_t rint16(double input) { + int16_t result; + __asm__ __volatile__("fistps %0": "=m"(result): "t"(input): "st"); + return result; + } +#elif defined _MSC_VER && defined _M_IX86 /* FIXME need solution for MSVC x64 */ + #define FPU_RINT16 + static __inline int16_t rint16(double input) { + int16_t result; + _asm { + fld input + fistp result + } + return result; + } +#else + #define rint16(x) (int16_t)((x) < 0? x - .5 : x + .5) +#endif + + + +#endif diff --git a/lib-src/libsoxr/src/samplerate.h b/lib-src/libsoxr/src/samplerate.h index cc024e55a..911cc5d0c 100644 --- a/lib-src/libsoxr/src/samplerate.h +++ b/lib-src/libsoxr/src/samplerate.h @@ -1 +1 @@ -#include "soxr-lsr.h" +#include "soxr-lsr.h" diff --git a/lib-src/libsoxr/src/simd-dev.h b/lib-src/libsoxr/src/simd-dev.h index 16963969e..019325c40 100644 --- a/lib-src/libsoxr/src/simd-dev.h +++ b/lib-src/libsoxr/src/simd-dev.h @@ -1,5 +1,5 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define PFFT_MACROS_ONLY -#include "pffft.c" +/* 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" diff --git a/lib-src/libsoxr/src/simd.c b/lib-src/libsoxr/src/simd.c index d70c31668..7659ab94c 100644 --- a/lib-src/libsoxr/src/simd.c +++ b/lib-src/libsoxr/src/simd.c @@ -1,84 +1,84 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include -#include "simd.h" -#include "simd-dev.h" - -#define SIMD_ALIGNMENT (sizeof(float) * 4) - -void * _soxr_simd_aligned_malloc(size_t size) -{ - char * p1 = 0, * p = malloc(size + SIMD_ALIGNMENT); - if (p) { - p1 = (char *)((size_t)(p + SIMD_ALIGNMENT) & ~(SIMD_ALIGNMENT - 1)); - *((void * *)p1 - 1) = p; - } - return p1; -} - - - -void * _soxr_simd_aligned_calloc(size_t nmemb, size_t size) -{ - void * p = _soxr_simd_aligned_malloc(nmemb * size); - if (p) - memset(p, 0, nmemb * size); - return p; -} - - - -void _soxr_simd_aligned_free(void * p1) -{ - if (p1) - free(*((void * *)p1 - 1)); -} - - - -void _soxr_ordered_convolve_simd(int n, void * not_used, float * a, const float * b) -{ - int i; - float ab0, ab1; - 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]; - for (i = 0; i < n / 4; i += 2) { - v4sf a1r = va[i+0], a1i = va[i+1]; - v4sf b1r = vb[i+0], b1i = vb[i+1]; - UNINTERLEAVE2(a1r, a1i, a1r, a1i); - UNINTERLEAVE2(b1r, b1i, b1r, b1i); - VCPLXMUL(a1r, a1i, b1r, b1i); - INTERLEAVE2(a1r, a1i, a1r, a1i); - va[i+0] = a1r, va[i+1] = a1i; - } - a[0] = ab0, a[1] = ab1; - (void)not_used; -} - - - -void _soxr_ordered_partial_convolve_simd(int n, float * a, const float * b) -{ - int i; - float ab0; - v4sf * /*RESTRICT*/ va = (v4sf *)a; - v4sf const * RESTRICT vb = (v4sf const *)b; - assert(VALIGNED(a) && VALIGNED(b)); - ab0 = a[0] * b[0]; - for (i = 0; i < n / 4; i += 2) { - v4sf a1r = va[i+0], a1i = va[i+1]; - v4sf b1r = vb[i+0], b1i = vb[i+1]; - UNINTERLEAVE2(a1r, a1i, a1r, a1i); - UNINTERLEAVE2(b1r, b1i, b1r, b1i); - VCPLXMUL(a1r, a1i, b1r, b1i); - INTERLEAVE2(a1r, a1i, a1r, a1i); - va[i+0] = a1r, va[i+1] = a1i; - } - a[0] = ab0; - a[1] = b[n] * a[n] - b[n+1] * a[n+1]; -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include +#include +#include +#include "simd.h" +#include "simd-dev.h" + +#define SIMD_ALIGNMENT (sizeof(float) * 4) + +void * _soxr_simd_aligned_malloc(size_t size) +{ + char * p1 = 0, * p = malloc(size + SIMD_ALIGNMENT); + if (p) { + p1 = (char *)((size_t)(p + SIMD_ALIGNMENT) & ~(SIMD_ALIGNMENT - 1)); + *((void * *)p1 - 1) = p; + } + return p1; +} + + + +void * _soxr_simd_aligned_calloc(size_t nmemb, size_t size) +{ + void * p = _soxr_simd_aligned_malloc(nmemb * size); + if (p) + memset(p, 0, nmemb * size); + return p; +} + + + +void _soxr_simd_aligned_free(void * p1) +{ + if (p1) + free(*((void * *)p1 - 1)); +} + + + +void _soxr_ordered_convolve_simd(int n, void * not_used, float * a, const float * b) +{ + int i; + float ab0, ab1; + 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]; + for (i = 0; i < n / 4; i += 2) { + v4sf a1r = va[i+0], a1i = va[i+1]; + v4sf b1r = vb[i+0], b1i = vb[i+1]; + UNINTERLEAVE2(a1r, a1i, a1r, a1i); + UNINTERLEAVE2(b1r, b1i, b1r, b1i); + VCPLXMUL(a1r, a1i, b1r, b1i); + INTERLEAVE2(a1r, a1i, a1r, a1i); + va[i+0] = a1r, va[i+1] = a1i; + } + a[0] = ab0, a[1] = ab1; + (void)not_used; +} + + + +void _soxr_ordered_partial_convolve_simd(int n, float * a, const float * b) +{ + int i; + float ab0; + v4sf * /*RESTRICT*/ va = (v4sf *)a; + v4sf const * RESTRICT vb = (v4sf const *)b; + assert(VALIGNED(a) && VALIGNED(b)); + ab0 = a[0] * b[0]; + for (i = 0; i < n / 4; i += 2) { + v4sf a1r = va[i+0], a1i = va[i+1]; + v4sf b1r = vb[i+0], b1i = vb[i+1]; + UNINTERLEAVE2(a1r, a1i, a1r, a1i); + UNINTERLEAVE2(b1r, b1i, b1r, b1i); + VCPLXMUL(a1r, a1i, b1r, b1i); + INTERLEAVE2(a1r, a1i, a1r, a1i); + va[i+0] = a1r, va[i+1] = a1i; + } + a[0] = ab0; + a[1] = b[n] * a[n] - b[n+1] * a[n+1]; +} diff --git a/lib-src/libsoxr/src/simd.h b/lib-src/libsoxr/src/simd.h index b20931d02..71eefc6d7 100644 --- a/lib-src/libsoxr/src/simd.h +++ b/lib-src/libsoxr/src/simd.h @@ -1,16 +1,16 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined simd_included -#define simd_included - -#include - -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 +/* 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 + +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 diff --git a/lib-src/libsoxr/src/soxr-lsr.h b/lib-src/libsoxr/src/soxr-lsr.h index f94dca7f1..c0923aa63 100644 --- a/lib-src/libsoxr/src/soxr-lsr.h +++ b/lib-src/libsoxr/src/soxr-lsr.h @@ -1,78 +1,80 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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 - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Wrapper mostly compatible with `libsamplerate'. - * (Libsoxr's native API can be found in soxr.h). */ - -#if !defined SAMPLERATE_H -#define SAMPLERATE_H -#if defined __cplusplus - extern "C" { -#endif - -#if defined SOXR_DLL - #if defined soxr_lsr_EXPORTS - #define SOXR __declspec(dllexport) - #else - #define SOXR __declspec(dllimport) - #endif -#else - #define SOXR -#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 SRC_DATA { - SRC_SAMPLE * data_in, * data_out; - long input_frames, output_frames; - long input_frames_used, output_frames_gen; - 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); -SOXR SRC_ERROR src_reset (SRC_STATE *); -SOXR SRC_ERROR src_error (SRC_STATE *); -SOXR SRC_STATE * src_delete (SRC_STATE *); -SOXR SRC_STATE * src_callback_new( - src_callback_t, SRC_SRCTYPE, int, SRC_ERROR *, void *); -SOXR long src_callback_read( - SRC_STATE *, double src_ratio, long, SRC_SAMPLE *); -SOXR SRC_ERROR src_simple(SRC_DATA *, SRC_SRCTYPE, int); -SOXR char const * src_get_name(SRC_SRCTYPE); -SOXR char const * src_get_description(SRC_SRCTYPE); -SOXR char const * src_get_version(void); -SOXR char const * src_strerror(SRC_ERROR); -SOXR int src_is_valid_ratio(double); -SOXR void src_short_to_float_array(short const *, float *, int); -SOXR void src_float_to_short_array(float const *, short *, int); -SOXR void src_int_to_float_array(int const *, float *, int); -SOXR void src_float_to_int_array(float const *, int *, int); - -#undef SOXR -#if defined __cplusplus - } -#endif -#endif +/* SoX Resampler Library Copyright (c) 2007-13 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 + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Wrapper compatible with `libsamplerate' (constant-rate). + * (Libsoxr's native API can be found in soxr.h). */ + +#if !defined SAMPLERATE_H +#define SAMPLERATE_H +#if defined __cplusplus + extern "C" { +#endif + +#if defined SOXR_DLL + #if defined soxr_lsr_EXPORTS + #define SOXR __declspec(dllexport) + #else + #define SOXR __declspec(dllimport) + #endif +#elif defined SOXR_VISIBILITY && defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) + #define SOXR __attribute__ ((visibility("default"))) +#else + #define SOXR +#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 SRC_DATA { + SRC_SAMPLE * data_in, * data_out; + long input_frames, output_frames; + long input_frames_used, output_frames_gen; + 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); +SOXR SRC_ERROR src_reset (SRC_STATE *); +SOXR SRC_ERROR src_error (SRC_STATE *); +SOXR SRC_STATE * src_delete (SRC_STATE *); +SOXR SRC_STATE * src_callback_new( + src_callback_t, SRC_SRCTYPE, int, SRC_ERROR *, void *); +SOXR long src_callback_read( + SRC_STATE *, double src_ratio, long, SRC_SAMPLE *); +SOXR SRC_ERROR src_simple(SRC_DATA *, SRC_SRCTYPE, int); +SOXR char const * src_get_name(SRC_SRCTYPE); +SOXR char const * src_get_description(SRC_SRCTYPE); +SOXR char const * src_get_version(void); +SOXR char const * src_strerror(SRC_ERROR); +SOXR int src_is_valid_ratio(double); +SOXR void src_short_to_float_array(short const *, float *, int); +SOXR void src_float_to_short_array(float const *, short *, int); +SOXR void src_int_to_float_array(int const *, float *, int); +SOXR void src_float_to_int_array(float const *, int *, int); + +#undef SOXR +#if defined __cplusplus + } +#endif +#endif diff --git a/lib-src/libsoxr/src/soxr-lsr.pc.in b/lib-src/libsoxr/src/soxr-lsr.pc.in new file mode 100644 index 000000000..7b7575769 --- /dev/null +++ b/lib-src/libsoxr/src/soxr-lsr.pc.in @@ -0,0 +1,5 @@ +Name: ${LSR} +Description: ${DESCRIPTION_SUMMARY} (with libsamplerate-like bindings) +Version: ${PROJECT_VERSION} +Libs: -L${LIB_INSTALL_DIR} -l${LSR} +Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/lib-src/libsoxr/src/soxr.c b/lib-src/libsoxr/src/soxr.c index 0ac16bc8e..93dd9c13f 100644 --- a/lib-src/libsoxr/src/soxr.c +++ b/lib-src/libsoxr/src/soxr.c @@ -1,643 +1,634 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include -#include - -#include "soxr.h" -#include "data-io.h" -#include "internal.h" - - - -char const * soxr_version(void) -{ - return "libsoxr-" SOXR_VERSION; -} - - - -typedef void sample_t; /* float or double */ - -typedef struct { - sample_t * (* input)(void *, sample_t * samples, size_t n); - void (* process)(void *, size_t); - sample_t const * (* output)(void *, sample_t * samples, size_t * n); - void (* flush)(void *); - void (* close)(void *); - double (* delay)(void *); - void (* sizes)(size_t * shared, size_t * channel); - char const * (* create)(void * channel, void * shared, double io_ratio, - soxr_quality_spec_t * q_spec, soxr_runtime_spec_t * r_spec, double scale); - void (* set_io_ratio)(void *, double io_ratio, size_t len); - char const * (* id)(void); -} control_block_t; - -#define resampler_input (*p->control_block.input) -#define resampler_process (*p->control_block.process) -#define resampler_output (*p->control_block.output) -#define resampler_flush (*p->control_block.flush) -#define resampler_close (*p->control_block.close) -#define resampler_delay (*p->control_block.delay) -#define resampler_sizes (*p->control_block.sizes) -#define resampler_create (*p->control_block.create) -#define resampler_set_io_ratio (*p->control_block.set_io_ratio) -#define resampler_id (*p->control_block.id) - - - -typedef void * resampler_t; /* For one channel. */ -typedef void * resampler_shared_t; /* Between channels. */ -typedef void (* deinterleave_t)(sample_t * * dest, - soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch); -typedef size_t (* interleave_t)(soxr_datatype_t data_type, void * * dest, - sample_t const * const * src, size_t, unsigned, unsigned long *); - -struct soxr { - unsigned num_channels; - double io_ratio; - soxr_error_t error; - soxr_quality_spec_t q_spec; - soxr_io_spec_t io_spec; - soxr_runtime_spec_t runtime_spec; - - void * input_fn_state; - soxr_input_fn_t input_fn; - size_t max_ilen; - - resampler_shared_t shared; - resampler_t * resamplers; - control_block_t control_block; - deinterleave_t deinterleave; - interleave_t interleave; - - void * * channel_ptrs; - size_t clips; - unsigned long seed; - int flushing; -}; - - - -/* TODO: these should not be here. */ -#define TO_3dB(a) ((1.6e-6*a-7.5e-4)*a+.646) -#define LOW_Q_BW0_PC (67 + 5 / 8.) - -soxr_quality_spec_t soxr_quality_spec(unsigned long recipe, unsigned long flags) -{ - soxr_quality_spec_t spec, * p = &spec; - unsigned quality = recipe & 0xf; - double rej; - memset(p, 0, sizeof(*p)); - if (quality > 13) { - p->e = "invalid quality type"; - return spec; - } - if (quality == 13) - quality = 6; - else if (quality > 10) - quality = 0; - p->phase = "\62\31\144"[(recipe & 0x30)>>8]; - p->anti_aliasing_pc = 100; - p->bits = !quality? 0: quality < 3? 16 : quality < 8? 4 + quality * 4 : 55 - quality * 4; - rej = p->bits * linear_to_dB(2.); - p->flags = flags; - if (quality < 8) { - p->bw_pc = quality == 1? LOW_Q_BW0_PC : 100 - 5 / TO_3dB(rej); - if (quality <= 2) - p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM; - } - else { - static float const bw[] = {93.1f, 83.2f, 66.3f}; - p->bw_pc = bw[quality - 8]; - if (quality - 8 == 2) - p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM; - } - if (recipe & SOXR_STEEP_FILTER) - p->bw_pc = 100 - 1 / TO_3dB(rej); - return spec; -} - - - -char const * soxr_engine(soxr_t p) -{ - return resampler_id(); -} - - - -size_t * soxr_num_clips(soxr_t p) -{ - return &p->clips; -} - - - -soxr_error_t soxr_error(soxr_t p) -{ - return p->error; -} - - - -soxr_runtime_spec_t soxr_runtime_spec(unsigned num_threads) -{ - soxr_runtime_spec_t spec, * p = &spec; - memset(p, 0, sizeof(*p)); - p->log2_min_dft_size = 10; - p->log2_large_dft_size = 17; - p->coef_size_kbytes = 400; - p->num_threads = num_threads; - return spec; -} - - - -soxr_io_spec_t soxr_io_spec( - soxr_datatype_t itype, - soxr_datatype_t otype) -{ - soxr_io_spec_t spec, * p = &spec; - memset(p, 0, sizeof(*p)); - if ((itype | otype) >= SOXR_SPLIT * 2) - p->e = "invalid io datatype(s)"; - else { - p->itype = itype; - p->otype = otype; - p->scale = 1; - } - return 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; -} -#endif - -extern control_block_t _soxr_rate32s_cb, _soxr_rate32_cb, _soxr_rate64_cb, _soxr_vr32_cb; - - - -soxr_t soxr_create( - double input_rate, double output_rate, - unsigned num_channels, - soxr_error_t * error0, - soxr_io_spec_t const * io_spec, - 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; - static const float datatype_full_scale[] = {1, 1, 65536.*32768, 32768}; - soxr_t p = 0; - soxr_error_t error = 0; - - 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)"; - - if (!error && !(p = calloc(sizeof(*p), 1))) error = "malloc failed"; - - if (p) { - p->q_spec = q_spec? *q_spec : soxr_quality_spec(SOXR_HQ, 0); - p->io_ratio = io_ratio; - p->num_channels = num_channels; - if (io_spec) - p->io_spec = *io_spec; - else - p->io_spec.scale = 1; - - p->runtime_spec = runtime_spec? *runtime_spec : soxr_runtime_spec(1); - 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)p; - -#if HAVE_SINGLE_PRECISION - if (!HAVE_DOUBLE_PRECISION || (p->q_spec.bits <= 20 && !(p->q_spec.flags & SOXR_DOUBLE_PRECISION)) -#if HAVE_VR - || (p->q_spec.flags & SOXR_VR) -#endif - ) { - p->deinterleave = (deinterleave_t)_soxr_deinterleave_f; - p->interleave = (interleave_t)_soxr_interleave_f; - memcpy(&p->control_block, -#if HAVE_VR - (p->q_spec.flags & SOXR_VR)? &_soxr_vr32_cb : -#endif -#if HAVE_SIMD - cpu_has_simd()? &_soxr_rate32s_cb : -#endif - &_soxr_rate32_cb, sizeof(p->control_block)); - } -#if HAVE_DOUBLE_PRECISION - else -#endif -#endif -#if HAVE_DOUBLE_PRECISION - { - p->deinterleave = (deinterleave_t)_soxr_deinterleave; - p->interleave = (interleave_t)_soxr_interleave; - memcpy(&p->control_block, &_soxr_rate64_cb, sizeof(p->control_block)); - } -#endif - - if (p->num_channels && io_ratio) - error = soxr_set_io_ratio(p, io_ratio, 0); - } - if (error) - soxr_delete(p), p = 0; - if (error0) - *error0 = error; - return p; -} - - - -soxr_error_t soxr_set_input_fn(soxr_t p, - soxr_input_fn_t input_fn, void * input_fn_state, size_t max_ilen) -{ - p->input_fn_state = input_fn_state; - p->input_fn = input_fn; - p->max_ilen = max_ilen? max_ilen : (size_t)-1; - return 0; -} - - - -static void soxr_delete0(soxr_t p) -{ - unsigned i; - - if (p->resamplers) for (i = 0; i < p->num_channels; ++i) { - if (p->resamplers[i]) - resampler_close(p->resamplers[i]); - free(p->resamplers[i]); - } - free(p->resamplers); - free(p->channel_ptrs); - free(p->shared); - - memset(p, 0, sizeof(*p)); -} - - - -double soxr_delay(soxr_t p) -{ - return (p && !p->error && p->resamplers)? resampler_delay(p->resamplers[0]) : 0; -} - - - -static soxr_error_t fatal_error(soxr_t p, soxr_error_t error) -{ - soxr_delete0(p); - return p->error = error; -} - - - -static soxr_error_t initialise(soxr_t p) -{ - unsigned i; - size_t shared_size, channel_size; - - resampler_sizes(&shared_size, &channel_size); - p->channel_ptrs = calloc(sizeof(*p->channel_ptrs), p->num_channels); - p->shared = calloc(shared_size, 1); - p->resamplers = calloc(sizeof(*p->resamplers), p->num_channels); - if (!p->shared || !p->channel_ptrs || !p->resamplers) - return fatal_error(p, "malloc failed"); - - for (i = 0; i < p->num_channels; ++i) { - soxr_error_t error; - if (!(p->resamplers[i] = calloc(channel_size, 1))) - return fatal_error(p, "malloc failed"); - error = resampler_create( - p->resamplers[i], - p->shared, - p->io_ratio, - &p->q_spec, - &p->runtime_spec, - p->io_spec.scale); - if (error) - return fatal_error(p, error); - } - return 0; -} - - - -soxr_error_t soxr_set_num_channels(soxr_t p, unsigned num_channels) -{ - if (!p) return "invalid soxr_t pointer"; - if (num_channels == p->num_channels) return p->error; - if (!num_channels) return "invalid # of channels"; - if (p->resamplers) return "# of channels can't be changed"; - p->num_channels = num_channels; - return soxr_set_io_ratio(p, p->io_ratio, 0); -} - - - -soxr_error_t soxr_set_io_ratio(soxr_t p, double io_ratio, size_t slew_len) -{ - unsigned i; - soxr_error_t error; - if (!p) return "invalid soxr_t pointer"; - if ((error = p->error)) return error; - if (!p->num_channels) return "must set # channels before O/I ratio"; - if (io_ratio <= 0) return "I/O ratio out-of-range"; - if (!p->channel_ptrs) { - p->io_ratio = io_ratio; - return initialise(p); - } - if (p->control_block.set_io_ratio) { - for (i = 0; !error && i < p->num_channels; ++i) - resampler_set_io_ratio(p->resamplers[i], io_ratio, 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"; -} - - - -void soxr_delete(soxr_t p) -{ - if (p) - soxr_delete0(p), free(p); -} - - - -soxr_error_t soxr_clear(soxr_t p) /* TODO: this, properly. */ -{ - if (p) { - struct soxr tmp = *p; - soxr_delete0(p); - memset(p, 0, sizeof(*p)); - p->input_fn = tmp.input_fn; - p->runtime_spec = tmp.runtime_spec; - p->q_spec = tmp.q_spec; - p->io_spec = tmp.io_spec; - p->num_channels = tmp.num_channels; - p->input_fn_state = tmp.input_fn_state; - p->control_block = tmp.control_block; - p->deinterleave = tmp.deinterleave; - p->interleave = tmp.interleave; - return 0; - } - return "invalid soxr_t pointer"; -} - - - -static void soxr_input_1ch(soxr_t p, unsigned i, soxr_cbuf_t src, size_t len) -{ - sample_t * dest = resampler_input(p->resamplers[i], NULL, len); - (*p->deinterleave)(&dest, p->io_spec.itype, &src, len, 1); -} - - - -static size_t soxr_input(soxr_t p, void const * in, size_t len) -{ - bool separated = !!(p->io_spec.itype & SOXR_SPLIT); - unsigned i; - if (!p || p->error) return 0; - if (!in && len) {p->error = "null input buffer pointer"; return 0;} - if (!len) { - p->flushing = true; - return 0; - } - if (separated) - for (i = 0; i < p->num_channels; ++i) - soxr_input_1ch(p, i, ((soxr_cbufs_t)in)[i], len); - else { - for (i = 0; i < p->num_channels; ++i) - p->channel_ptrs[i] = resampler_input(p->resamplers[i], NULL, len); - (*p->deinterleave)( - (sample_t **)p->channel_ptrs, p->io_spec.itype, &in, len, p->num_channels); - } - return len; -} - - - -static size_t soxr_output_1ch(soxr_t p, unsigned i, soxr_buf_t dest, size_t len, bool separated) -{ - sample_t const * src; - if (p->flushing) - resampler_flush(p->resamplers[i]); - resampler_process(p->resamplers[i], len); - src = resampler_output(p->resamplers[i], NULL, &len); - if (separated) - p->clips += (p->interleave)(p->io_spec.otype, &dest, &src, - len, 1, (p->io_spec.flags & SOXR_NO_DITHER)? 0 : &p->seed); - else p->channel_ptrs[i] = (void /* const */ *)src; - return len; -} - - - -static size_t soxr_output_no_callback(soxr_t p, soxr_buf_t out, size_t len) -{ - unsigned i; - size_t done = 0; - bool separated = !!(p->io_spec.otype & SOXR_SPLIT); -#if defined _OPENMP - if (!p->runtime_spec.num_threads && p->num_channels > 1) -#pragma omp parallel for - for (i = 0; i < p->num_channels; ++i) { - size_t done1; - done1 = soxr_output_1ch(p, i, ((soxr_bufs_t)out)[i], len, separated); - if (!i) - done = done1; - } else -#endif - for (i = 0; i < p->num_channels; ++i) - done = soxr_output_1ch(p, i, ((soxr_bufs_t)out)[i], len, separated); - - if (!separated) - p->clips += (p->interleave)(p->io_spec.otype, &out, (sample_t const * const *)p->channel_ptrs, - done, p->num_channels, (p->io_spec.flags & SOXR_NO_DITHER)? 0 : &p->seed); - return done; -} - - - -size_t soxr_output(soxr_t p, void * out, size_t len0) -{ - size_t odone, odone0 = 0, olen = len0, osize, idone; - size_t ilen = min(p->max_ilen, (size_t)ceil((double)olen *p->io_ratio)); - void const * in = out; /* Set to !=0, so that caller may leave unset. */ - bool was_flushing; - - if (!p || p->error) return 0; - if (!out && len0) {p->error = "null output buffer pointer"; return 0;} - - do { - odone = soxr_output_no_callback(p, out, olen); - odone0 += odone; - if (odone0 == len0 || !p->input_fn || p->flushing) - break; - - osize = soxr_datatype_size(p->io_spec.otype) * p->num_channels; - out = (char *)out + osize * odone; - olen -= odone; - idone = p->input_fn(p->input_fn_state, &in, ilen); - was_flushing = p->flushing; - if (!in) - p->error = "input function reported failure"; - else soxr_input(p, in, idone); - } while (odone || idone || (!was_flushing && p->flushing)); - return odone0; -} - - - -static size_t soxr_i_for_o(soxr_t p, size_t olen, size_t ilen) -{ - size_t result; -#if 0 - if (p->runtime_spec.flags & SOXR_STRICT_BUFFERING) - result = rate_i_for_o(p->resamplers[0], olen); - else -#endif - result = (size_t)ceil((double)olen * p->io_ratio); - return min(result, ilen); -} - - - -#if 0 -static size_t soxr_o_for_i(soxr_t p, size_t ilen, size_t olen) -{ - size_t result = (size_t)ceil((double)ilen / p->io_ratio); - return min(result, olen); -} -#endif - - - -soxr_error_t soxr_process(soxr_t p, - void const * in , size_t ilen0, size_t * idone0, - void * out, size_t olen , size_t * odone0) -{ - size_t ilen, idone, odone = 0; - unsigned i; - bool flush_requested = false; - - if (!p) return "null pointer"; - - if (!in) - flush_requested = true, ilen = ilen0 = 0; - else { - if ((ptrdiff_t)ilen0 < 0) - flush_requested = true, ilen0 = ~ilen0; - if (idone0 && (1 || flush_requested)) - ilen = soxr_i_for_o(p, olen, ilen0); - else - ilen = ilen0/*, olen = soxr_o_for_i(p, ilen, olen)*/; - } - p->flushing |= ilen == ilen0 && flush_requested; - - if (!out && !in) - idone = ilen; - else if (p->io_spec.itype & p->io_spec.otype & SOXR_SPLIT) { /* Both i & o */ -#if defined _OPENMP - if (!p->runtime_spec.num_threads && p->num_channels > 1) -#pragma omp parallel for - for (i = 0; i < p->num_channels; ++i) { - size_t done; - if (in) - soxr_input_1ch(p, i, ((soxr_cbufs_t)in)[i], ilen); - done = soxr_output_1ch(p, i, ((soxr_bufs_t)out)[i], olen, true); - if (!i) - odone = done; - } else -#endif - for (i = 0; i < p->num_channels; ++i) { - if (in) - soxr_input_1ch(p, i, ((soxr_cbufs_t)in)[i], ilen); - odone = soxr_output_1ch(p, i, ((soxr_bufs_t)out)[i], olen, true); - } - idone = ilen; - } - else { - idone = ilen? soxr_input (p, in , ilen) : 0; - odone = soxr_output(p, out, olen); - } - if (idone0) *idone0 = idone; - if (odone0) *odone0 = odone; - return p->error; -} - - - -soxr_error_t soxr_oneshot( - double irate, double orate, - unsigned num_channels, - void const * in , size_t ilen, size_t * idone, - void * out, size_t olen, size_t * odone, - soxr_io_spec_t const * io_spec, - soxr_quality_spec_t const * q_spec, - soxr_runtime_spec_t const * runtime_spec) -{ - soxr_t resampler; - soxr_error_t error = q_spec? q_spec->e : 0; - if (!error) { - soxr_quality_spec_t q_spec1; - if (!q_spec) - q_spec1 = soxr_quality_spec(SOXR_LQ, 0), q_spec = &q_spec1; - resampler = soxr_create(irate, orate, num_channels, - &error, io_spec, q_spec, runtime_spec); - } - if (!error) { - error = soxr_process(resampler, in, ~ilen, idone, out, olen, odone); - soxr_delete(resampler); - } - return error; -} - - - -soxr_error_t soxr_set_error(soxr_t p, soxr_error_t error) -{ - if (!p) return "null pointer"; - if (!p->error && p->error != error) return p->error; - p->error = error; - return 0; -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +#include +#include +#include +#include + +#include "soxr.h" +#include "data-io.h" +#include "internal.h" + + + +char const * soxr_version(void) +{ + return "libsoxr-" SOXR_THIS_VERSION_STR; +} + + + +typedef void sample_t; /* float or double */ +typedef void (* fn_t)(void); +typedef fn_t control_block_t[10]; + +#define resampler_input (*(sample_t * (*)(void *, sample_t * samples, size_t n))p->control_block[0]) +#define resampler_process (*(void (*)(void *, size_t))p->control_block[1]) +#define resampler_output (*(sample_t const * (*)(void *, sample_t * samples, size_t * n))p->control_block[2]) +#define resampler_flush (*(void (*)(void *))p->control_block[3]) +#define resampler_close (*(void (*)(void *))p->control_block[4]) +#define resampler_delay (*(double (*)(void *))p->control_block[5]) +#define resampler_sizes (*(void (*)(size_t * shared, size_t * channel))p->control_block[6]) +#define resampler_create (*(char const * (*)(void * channel, void * shared, double io_ratio, soxr_quality_spec_t * q_spec, soxr_runtime_spec_t * r_spec, double scale))p->control_block[7]) +#define resampler_set_io_ratio (*(void (*)(void *, double io_ratio, size_t len))p->control_block[8]) +#define resampler_id (*(char const * (*)(void))p->control_block[9]) + +typedef void * resampler_t; /* For one channel. */ +typedef void * resampler_shared_t; /* Between channels. */ +typedef void (* deinterleave_t)(sample_t * * dest, + soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch); +typedef size_t (* interleave_t)(soxr_datatype_t data_type, void * * dest, + sample_t const * const * src, size_t, unsigned, unsigned long *); + +struct soxr { + unsigned num_channels; + double io_ratio; + soxr_error_t error; + soxr_quality_spec_t q_spec; + soxr_io_spec_t io_spec; + soxr_runtime_spec_t runtime_spec; + + void * input_fn_state; + soxr_input_fn_t input_fn; + size_t max_ilen; + + resampler_shared_t shared; + resampler_t * resamplers; + control_block_t control_block; + deinterleave_t deinterleave; + interleave_t interleave; + + void * * channel_ptrs; + size_t clips; + unsigned long seed; + int flushing; +}; + + + +/* 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. */ + +soxr_quality_spec_t soxr_quality_spec(unsigned long recipe, unsigned long flags) +{ + soxr_quality_spec_t spec, * p = &spec; + unsigned quality = recipe & 0xf; + double rej; + memset(p, 0, sizeof(*p)); + if (quality > 13) { + 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]; + p->stopband_begin = 1; + p->precision = !quality? 0: quality < 3? 16 : quality < 8? 4 + quality * 4 : 55 - quality * 4; + 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 <= 2) + p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM; + } + else { + 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; + } + if (recipe & SOXR_STEEP_FILTER) + p->passband_end = 1 - .01 / TO_3dB(rej); + return spec; +} + + + +char const * soxr_engine(soxr_t p) +{ + return resampler_id(); +} + + + +size_t * soxr_num_clips(soxr_t p) +{ + return &p->clips; +} + + + +soxr_error_t soxr_error(soxr_t p) +{ + return p->error; +} + + + +soxr_runtime_spec_t soxr_runtime_spec(unsigned num_threads) +{ + soxr_runtime_spec_t spec, * p = &spec; + memset(p, 0, sizeof(*p)); + p->log2_min_dft_size = 10; + p->log2_large_dft_size = 17; + p->coef_size_kbytes = 400; + p->num_threads = num_threads; + return spec; +} + + + +soxr_io_spec_t soxr_io_spec( + soxr_datatype_t itype, + soxr_datatype_t otype) +{ + soxr_io_spec_t spec, * p = &spec; + memset(p, 0, sizeof(*p)); + if ((itype | otype) >= SOXR_SPLIT * 2) + p->e = "invalid io datatype(s)"; + else { + p->itype = itype; + p->otype = otype; + p->scale = 1; + } + return 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; +} +#endif + +extern control_block_t _soxr_rate32s_cb, _soxr_rate32_cb, _soxr_rate64_cb, _soxr_vr32_cb; + + + +soxr_t soxr_create( + double input_rate, double output_rate, + unsigned num_channels, + soxr_error_t * error0, + soxr_io_spec_t const * io_spec, + 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; + static const float datatype_full_scale[] = {1, 1, 65536.*32768, 32768}; + soxr_t p = 0; + soxr_error_t error = 0; + + 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)"; + + if (!error && !(p = calloc(sizeof(*p), 1))) error = "malloc failed"; + + if (p) { + p->q_spec = q_spec? *q_spec : soxr_quality_spec(SOXR_HQ, 0); + + if (q_spec) { /* Backwards compatibility with original API: */ + if (p->q_spec.passband_end > 2) + p->q_spec.passband_end /= 100; + if (p->q_spec.stopband_begin > 2) + p->q_spec.stopband_begin = 2 - p->q_spec.stopband_begin / 100; + } + + p->io_ratio = io_ratio; + p->num_channels = num_channels; + if (io_spec) + p->io_spec = *io_spec; + else + p->io_spec.scale = 1; + + p->runtime_spec = runtime_spec? *runtime_spec : soxr_runtime_spec(1); + 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)) { + 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 : +#endif + &_soxr_rate32_cb, sizeof(p->control_block)); + } +#if HAVE_DOUBLE_PRECISION + else +#endif +#endif +#if HAVE_DOUBLE_PRECISION + { + p->deinterleave = (deinterleave_t)_soxr_deinterleave; + p->interleave = (interleave_t)_soxr_interleave; + memcpy(&p->control_block, &_soxr_rate64_cb, sizeof(p->control_block)); + } +#endif + + if (p->num_channels && io_ratio) + error = soxr_set_io_ratio(p, io_ratio, 0); + } + if (error) + soxr_delete(p), p = 0; + if (error0) + *error0 = error; + return p; +} + + + +soxr_error_t soxr_set_input_fn(soxr_t p, + soxr_input_fn_t input_fn, void * input_fn_state, size_t max_ilen) +{ + p->input_fn_state = input_fn_state; + p->input_fn = input_fn; + p->max_ilen = max_ilen? max_ilen : (size_t)-1; + return 0; +} + + + +static void soxr_delete0(soxr_t p) +{ + unsigned i; + + if (p->resamplers) for (i = 0; i < p->num_channels; ++i) { + if (p->resamplers[i]) + resampler_close(p->resamplers[i]); + free(p->resamplers[i]); + } + free(p->resamplers); + free(p->channel_ptrs); + free(p->shared); + + memset(p, 0, sizeof(*p)); +} + + + +double soxr_delay(soxr_t p) +{ + return (p && !p->error && p->resamplers)? resampler_delay(p->resamplers[0]) : 0; +} + + + +static soxr_error_t fatal_error(soxr_t p, soxr_error_t error) +{ + soxr_delete0(p); + return p->error = error; +} + + + +static soxr_error_t initialise(soxr_t p) +{ + unsigned i; + size_t shared_size, channel_size; + + resampler_sizes(&shared_size, &channel_size); + p->channel_ptrs = calloc(sizeof(*p->channel_ptrs), p->num_channels); + p->shared = calloc(shared_size, 1); + p->resamplers = calloc(sizeof(*p->resamplers), p->num_channels); + if (!p->shared || !p->channel_ptrs || !p->resamplers) + return fatal_error(p, "malloc failed"); + + for (i = 0; i < p->num_channels; ++i) { + soxr_error_t error; + if (!(p->resamplers[i] = calloc(channel_size, 1))) + return fatal_error(p, "malloc failed"); + error = resampler_create( + p->resamplers[i], + p->shared, + p->io_ratio, + &p->q_spec, + &p->runtime_spec, + p->io_spec.scale); + if (error) + return fatal_error(p, error); + } + return 0; +} + + + +soxr_error_t soxr_set_num_channels(soxr_t p, unsigned num_channels) +{ + if (!p) return "invalid soxr_t pointer"; + if (num_channels == p->num_channels) return p->error; + if (!num_channels) return "invalid # of channels"; + if (p->resamplers) return "# of channels can't be changed"; + p->num_channels = num_channels; + return soxr_set_io_ratio(p, p->io_ratio, 0); +} + + + +soxr_error_t soxr_set_io_ratio(soxr_t p, double io_ratio, size_t slew_len) +{ + unsigned i; + soxr_error_t error; + if (!p) return "invalid soxr_t pointer"; + if ((error = p->error)) return error; + if (!p->num_channels) return "must set # channels before O/I ratio"; + if (io_ratio <= 0) return "I/O ratio out-of-range"; + if (!p->channel_ptrs) { + p->io_ratio = io_ratio; + return initialise(p); + } + if (p->control_block[8]) { + for (i = 0; !error && i < p->num_channels; ++i) + resampler_set_io_ratio(p->resamplers[i], io_ratio, 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"; +} + + + +void soxr_delete(soxr_t p) +{ + if (p) + soxr_delete0(p), free(p); +} + + + +soxr_error_t soxr_clear(soxr_t p) /* TODO: this, properly. */ +{ + if (p) { + struct soxr tmp = *p; + soxr_delete0(p); + memset(p, 0, sizeof(*p)); + p->input_fn = tmp.input_fn; + p->runtime_spec = tmp.runtime_spec; + p->q_spec = tmp.q_spec; + p->io_spec = tmp.io_spec; + p->num_channels = tmp.num_channels; + p->input_fn_state = tmp.input_fn_state; + memcpy(p->control_block, tmp.control_block, sizeof(p->control_block)); + p->deinterleave = tmp.deinterleave; + p->interleave = tmp.interleave; + return 0; + } + return "invalid soxr_t pointer"; +} + + + +static void soxr_input_1ch(soxr_t p, unsigned i, soxr_cbuf_t src, size_t len) +{ + sample_t * dest = resampler_input(p->resamplers[i], NULL, len); + (*p->deinterleave)(&dest, p->io_spec.itype, &src, len, 1); +} + + + +static size_t soxr_input(soxr_t p, void const * in, size_t len) +{ + bool separated = !!(p->io_spec.itype & SOXR_SPLIT); + unsigned i; + if (!p || p->error) return 0; + if (!in && len) {p->error = "null input buffer pointer"; return 0;} + if (!len) { + p->flushing = true; + return 0; + } + if (separated) + for (i = 0; i < p->num_channels; ++i) + soxr_input_1ch(p, i, ((soxr_cbufs_t)in)[i], len); + else { + for (i = 0; i < p->num_channels; ++i) + p->channel_ptrs[i] = resampler_input(p->resamplers[i], NULL, len); + (*p->deinterleave)( + (sample_t **)p->channel_ptrs, p->io_spec.itype, &in, len, p->num_channels); + } + return len; +} + + + +static size_t soxr_output_1ch(soxr_t p, unsigned i, soxr_buf_t dest, size_t len, bool separated) +{ + sample_t const * src; + if (p->flushing) + resampler_flush(p->resamplers[i]); + resampler_process(p->resamplers[i], len); + src = resampler_output(p->resamplers[i], NULL, &len); + if (separated) + p->clips += (p->interleave)(p->io_spec.otype, &dest, &src, + len, 1, (p->io_spec.flags & SOXR_NO_DITHER)? 0 : &p->seed); + else p->channel_ptrs[i] = (void /* const */ *)src; + return len; +} + + + +static size_t soxr_output_no_callback(soxr_t p, soxr_buf_t out, size_t len) +{ + unsigned u; + size_t done = 0; + bool separated = !!(p->io_spec.otype & SOXR_SPLIT); +#if defined _OPENMP + int i; + if (!p->runtime_spec.num_threads && p->num_channels > 1) +#pragma omp parallel for + for (i = 0; i < (int)p->num_channels; ++i) { + size_t done1; + done1 = soxr_output_1ch(p, (unsigned)i, ((soxr_bufs_t)out)[i], len, separated); + if (!i) + done = done1; + } else +#endif + for (u = 0; u < p->num_channels; ++u) + done = soxr_output_1ch(p, u, ((soxr_bufs_t)out)[u], len, separated); + + if (!separated) + p->clips += (p->interleave)(p->io_spec.otype, &out, (sample_t const * const *)p->channel_ptrs, + done, p->num_channels, (p->io_spec.flags & SOXR_NO_DITHER)? 0 : &p->seed); + return done; +} + + + +size_t soxr_output(soxr_t p, void * out, size_t len0) +{ + size_t odone, odone0 = 0, olen = len0, osize, idone; + size_t ilen = min(p->max_ilen, (size_t)ceil((double)olen *p->io_ratio)); + void const * in = out; /* Set to !=0, so that caller may leave unset. */ + bool was_flushing; + + if (!p || p->error) return 0; + if (!out && len0) {p->error = "null output buffer pointer"; return 0;} + + do { + odone = soxr_output_no_callback(p, out, olen); + odone0 += odone; + if (odone0 == len0 || !p->input_fn || p->flushing) + break; + + osize = soxr_datatype_size(p->io_spec.otype) * p->num_channels; + out = (char *)out + osize * odone; + olen -= odone; + idone = p->input_fn(p->input_fn_state, &in, ilen); + was_flushing = p->flushing; + if (!in) + p->error = "input function reported failure"; + else soxr_input(p, in, idone); + } while (odone || idone || (!was_flushing && p->flushing)); + return odone0; +} + + + +static size_t soxr_i_for_o(soxr_t p, size_t olen, size_t ilen) +{ + size_t result; +#if 0 + if (p->runtime_spec.flags & SOXR_STRICT_BUFFERING) + result = rate_i_for_o(p->resamplers[0], olen); + else +#endif + result = (size_t)ceil((double)olen * p->io_ratio); + return min(result, ilen); +} + + + +#if 0 +static size_t soxr_o_for_i(soxr_t p, size_t ilen, size_t olen) +{ + size_t result = (size_t)ceil((double)ilen / p->io_ratio); + return min(result, olen); +} +#endif + + + +soxr_error_t soxr_process(soxr_t p, + void const * in , size_t ilen0, size_t * idone0, + void * out, size_t olen , size_t * odone0) +{ + size_t ilen, idone, odone = 0; + unsigned u; + bool flush_requested = false; + + if (!p) return "null pointer"; + + if (!in) + flush_requested = true, ilen = ilen0 = 0; + else { + if ((ptrdiff_t)ilen0 < 0) + flush_requested = true, ilen0 = ~ilen0; + if (idone0 && (1 || flush_requested)) + ilen = soxr_i_for_o(p, olen, ilen0); + else + ilen = ilen0/*, olen = soxr_o_for_i(p, ilen, olen)*/; + } + p->flushing |= ilen == ilen0 && flush_requested; + + if (!out && !in) + idone = ilen; + else if (p->io_spec.itype & p->io_spec.otype & SOXR_SPLIT) { /* Both i & o */ +#if defined _OPENMP + int i; + if (!p->runtime_spec.num_threads && p->num_channels > 1) +#pragma omp parallel for + for (i = 0; i < (int)p->num_channels; ++i) { + size_t done; + if (in) + soxr_input_1ch(p, (unsigned)i, ((soxr_cbufs_t)in)[i], ilen); + done = soxr_output_1ch(p, (unsigned)i, ((soxr_bufs_t)out)[i], olen, true); + if (!i) + odone = done; + } else +#endif + for (u = 0; u < p->num_channels; ++u) { + if (in) + soxr_input_1ch(p, u, ((soxr_cbufs_t)in)[u], ilen); + odone = soxr_output_1ch(p, u, ((soxr_bufs_t)out)[u], olen, true); + } + idone = ilen; + } + else { + idone = ilen? soxr_input (p, in , ilen) : 0; + odone = soxr_output(p, out, olen); + } + if (idone0) *idone0 = idone; + if (odone0) *odone0 = odone; + return p->error; +} + + + +soxr_error_t soxr_oneshot( + double irate, double orate, + unsigned num_channels, + void const * in , size_t ilen, size_t * idone, + void * out, size_t olen, size_t * odone, + soxr_io_spec_t const * io_spec, + soxr_quality_spec_t const * q_spec, + soxr_runtime_spec_t const * runtime_spec) +{ + soxr_t resampler; + soxr_error_t error = q_spec? q_spec->e : 0; + if (!error) { + soxr_quality_spec_t q_spec1; + if (!q_spec) + q_spec1 = soxr_quality_spec(SOXR_LQ, 0), q_spec = &q_spec1; + resampler = soxr_create(irate, orate, num_channels, + &error, io_spec, q_spec, runtime_spec); + } + if (!error) { + error = soxr_process(resampler, in, ~ilen, idone, out, olen, odone); + soxr_delete(resampler); + } + return error; +} + + + +soxr_error_t soxr_set_error(soxr_t p, soxr_error_t error) +{ + if (!p) return "null pointer"; + if (!p->error && p->error != error) return p->error; + p->error = error; + return 0; +} diff --git a/lib-src/libsoxr/src/soxr.h b/lib-src/libsoxr/src/soxr.h index c321f5355..d878bb856 100644 --- a/lib-src/libsoxr/src/soxr.h +++ b/lib-src/libsoxr/src/soxr.h @@ -1,318 +1,329 @@ -/* SoX Resampler Library Copyright (c) 2007-12 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 - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - - -/* -------------------------------- Gubbins --------------------------------- */ - -#if !defined soxr_included -#define soxr_included - - -#if defined __cplusplus - #include - extern "C" { -#else - #include -#endif - -#if defined SOXR_DLL - #if defined soxr_EXPORTS - #define SOXR __declspec(dllexport) - #else - #define SOXR __declspec(dllimport) - #endif -#else - #define SOXR -#endif - -typedef struct soxr_io_spec soxr_io_spec_t; -typedef struct soxr_quality_spec soxr_quality_spec_t; -typedef struct soxr_runtime_spec soxr_runtime_spec_t; - - - -/* ---------------------------- API conventions -------------------------------- - -Buffer lengths (and occupancies) are expressed as the number of contained -samples per channel. - -Parameter names for buffer lengths have the suffix `len'. - -A single-character `i' or 'o' is often used in names to give context as -input or output (e.g. ilen, olen). */ - - - -/* --------------------------- Type declarations ---------------------------- */ - -typedef struct soxr * soxr_t; /* A resampler for 1 or more channels. */ -typedef char const * soxr_error_t; /* 0:no-error; non-0:error. */ - -typedef void * soxr_buf_t; /* 1 buffer of channel-interleaved samples. */ -typedef void const * soxr_cbuf_t; /* Ditto; read-only. */ - -typedef soxr_buf_t const * soxr_bufs_t;/* Or, a separate buffer for each ch. */ -typedef soxr_cbuf_t const * soxr_cbufs_t; /* Ditto; read-only. */ - -typedef void const * soxr_in_t; /* Either a soxr_cbuf_t or soxr_cbufs_t, - depending on itype in soxr_io_spec_t. */ -typedef void * soxr_out_t; /* Either a soxr_buf_t or soxr_bufs_t, - depending on otype in soxr_io_spec_t. */ - - - -/* --------------------------- API main functions --------------------------- */ - -SOXR char const * soxr_version(void); /* Query library version: "x.y.z". */ - -#define soxr_strerror(e) /* Soxr counterpart to strerror. */ \ - ((e)?(e):"no error") - - -/* Create a stream resampler: */ - -SOXR soxr_t soxr_create( - double input_rate, /* Input sample-rate. */ - double output_rate, /* Output sample-rate. */ - unsigned num_channels, /* Number of channels to be used. */ - /* All following arguments are optional (may be set to NULL). */ - 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. */ - - - -/* If not using an app-supplied input function, after creating a stream - * resampler, repeatedly call: */ - -SOXR soxr_error_t soxr_process( - soxr_t resampler, /* As returned by soxr_create. */ - /* Input (to be resampled): */ - soxr_in_t in, /* Input buffer(s); may be NULL (see below). */ - size_t ilen, /* Input buf. length (samples per channel). */ - size_t * idone, /* To return actual # samples used (<= ilen). */ - /* Output (resampled): */ - soxr_out_t out, /* Output buffer(s).*/ - size_t olen, /* Output buf. length (samples per channel). */ - size_t * odone); /* To return actual # samples out (<= olen). - - Note that no special meaning is associated with ilen or olen equal to - zero. End-of-input (i.e. no data is available nor shall be available) - may be indicated by seting `in' to NULL. */ - - - -/* If using an app-supplied input function, it must look and behave like this:*/ - -typedef size_t /* data_len */ - (* soxr_input_fn_t)( /* Supply data to be resampled. */ - void * input_fn_state, /* As given to soxr_set_input_fn (below). */ - soxr_in_t * data, /* Returned data; see below. N.B. ptr to ptr(s)*/ - size_t requested_len); /* Samples per channel, >= returned data_len. - - data_len *data Indicates Meaning - ------- ------- ------------ ------------------------- - !=0 !=0 Success *data contains data to be - input to the resampler. - 0 !=0 (or End-of-input No data is available nor - not set) shall be available. - 0 0 Failure An error occurred whilst trying to - source data to be input to the resampler. */ - -/* and be registered with a previously created stream resampler using: */ - -SOXR soxr_error_t soxr_set_input_fn(/* Set (or reset) an input function.*/ - soxr_t resampler, /* As returned by soxr_create. */ - soxr_input_fn_t, /* Function to supply data to be resampled.*/ - void * input_fn_state, /* If needed by the input function. */ - size_t max_ilen); /* Maximum value for input fn. requested_len.*/ - -/* then repeatedly call: */ - -SOXR size_t /*odone*/ soxr_output(/* Resample and output a block of data.*/ - soxr_t resampler, /* As returned by soxr_create. */ - soxr_out_t data, /* App-supplied buffer(s) for resampled data.*/ - size_t olen); /* Amount of data to output; >= odone. */ - - - -/* Common stream resampler operations: */ - -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 soxr_error_t soxr_clear(soxr_t); /* Ready for fresh signal, same config. */ -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. */ - -SOXR soxr_error_t soxr_oneshot( - double input_rate, - double output_rate, - unsigned num_channels, - soxr_in_t in , size_t ilen, size_t * idone, - soxr_out_t out, size_t olen, size_t * odone, - soxr_io_spec_t const *, - soxr_quality_spec_t const *, - soxr_runtime_spec_t const *); - - - -/* For variable-rate resampling (experimental). 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); - - - -/* -------------------------- API type definitions -------------------------- */ - -typedef enum { /* Datatypes supported for I/O to/from the resampler: */ - /* Internal; do not use: */ - SOXR_FLOAT32, SOXR_FLOAT64, SOXR_INT32, SOXR_INT16, SOXR_SPLIT = 4, - - /* Use for interleaved channels: */ - SOXR_FLOAT32_I = SOXR_FLOAT32, SOXR_FLOAT64_I, SOXR_INT32_I, SOXR_INT16_I, - - /* Use for split channels: */ - SOXR_FLOAT32_S = SOXR_SPLIT , SOXR_FLOAT64_S, SOXR_INT32_S, SOXR_INT16_S - -} soxr_datatype_t; - -#define soxr_datatype_size(x) /* Returns `sizeof' a soxr_datatype_t sample. */\ - ((unsigned char *)"\4\10\4\2")[(x)&3] - - - -struct soxr_io_spec { /* Typically */ - soxr_datatype_t itype; /* Input datatype. SOXR_FLOAT32_I */ - soxr_datatype_t otype; /* Output datatype. SOXR_FLOAT32_I */ - double scale; /* Linear gain to apply during resampling. 1 */ - void * e; /* Reserved for internal use 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - -#define SOXR_TPDF 0 /* Applicable only if otype is INT16. */ -#define SOXR_NO_DITHER 8u /* Disable the above. */ - - - -struct soxr_quality_spec { /* Typically */ - double bits; /* Required bit-accuracy (pass + stop). 20 */ - double phase; /* Linear/minimum etc. phase. [0,100] 50 */ - double bw_pc; /* Pass-band % (0dB pt.) to preserve. 91.3 */ - double anti_aliasing_pc; /* % bandwidth without aliasing. 100 */ - void * e; /* Reserved for internal use. 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - -#define SOXR_ROLLOFF_SMALL 0u /* <= 0.01 dB */ -#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 double prec. even @ bitdepths <= 20.*/ -#define SOXR_VR 32u /* Experimental, 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 */ -}; - /* 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. */ - - - -/* -------------------------- API type constructors ------------------------- */ - -/* These functions allow setting of the most commonly-used structure - * parameters, with other parameters being given default values. The default - * values may then be overridden, directly in the structure, if needed. */ - -SOXR soxr_quality_spec_t soxr_quality_spec( - unsigned long recipe, /* Per the #defines immediately below. */ - unsigned long flags); /* As soxr_quality_spec_t.flags. */ - - /* The 5 standard qualities found in SoX: */ -#define SOXR_QQ 0 /* 'Quick' cubic interpolation. */ -#define SOXR_LQ 1 /* 'Low' 16-bit with larger rolloff. */ -#define SOXR_MQ 2 /* 'Medium' 16-bit with medium rolloff. */ -#define SOXR_HQ SOXR_20_BITQ /* 'High quality'. */ -#define SOXR_VHQ SOXR_28_BITQ /* 'Very high quality'. */ - -#define SOXR_16_BITQ 3 -#define SOXR_20_BITQ 4 -#define SOXR_24_BITQ 5 -#define SOXR_28_BITQ 6 -#define SOXR_32_BITQ 7 - /* Libsamplerate equivalent qualities: */ -#define SOXR_LSR0Q 8 /* 'Best sinc'. */ -#define SOXR_LSR1Q 9 /* 'Medium sinc'. */ -#define SOXR_LSR2Q 10 /* 'Fast sinc'. */ - -#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. */ - - - -SOXR soxr_runtime_spec_t soxr_runtime_spec( - unsigned num_threads); - - - -SOXR soxr_io_spec_t soxr_io_spec( - soxr_datatype_t itype, - soxr_datatype_t otype); - - - -/* --------------------------- Internal use only ---------------------------- */ - -SOXR soxr_error_t soxr_set_error(soxr_t, soxr_error_t); -SOXR soxr_error_t soxr_set_num_channels(soxr_t, unsigned); - - - -#undef SOXR - -#if defined __cplusplus -} -#endif - -#endif +/* SoX Resampler Library Copyright (c) 2007-13 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 + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + + +/* -------------------------------- Gubbins --------------------------------- */ + +#if !defined soxr_included +#define soxr_included + + +#if defined __cplusplus + #include + extern "C" { +#else + #include +#endif + +#if defined SOXR_DLL + #if defined soxr_EXPORTS + #define SOXR __declspec(dllexport) + #else + #define SOXR __declspec(dllimport) + #endif +#elif defined SOXR_VISIBILITY && defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) + #define SOXR __attribute__ ((visibility("default"))) +#else + #define SOXR +#endif + +typedef struct soxr_io_spec soxr_io_spec_t; +typedef struct soxr_quality_spec soxr_quality_spec_t; +typedef struct soxr_runtime_spec soxr_runtime_spec_t; + + + +/* ---------------------------- API conventions -------------------------------- + +Buffer lengths (and occupancies) are expressed as the number of contained +samples per channel. + +Parameter names for buffer lengths have the suffix `len'. + +A single-character `i' or 'o' is often used in names to give context as +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" + + + +/* --------------------------- Type declarations ---------------------------- */ + +typedef struct soxr * soxr_t; /* A resampler for 1 or more channels. */ +typedef char const * soxr_error_t; /* 0:no-error; non-0:error. */ + +typedef void * soxr_buf_t; /* 1 buffer of channel-interleaved samples. */ +typedef void const * soxr_cbuf_t; /* Ditto; read-only. */ + +typedef soxr_buf_t const * soxr_bufs_t;/* Or, a separate buffer for each ch. */ +typedef soxr_cbuf_t const * soxr_cbufs_t; /* Ditto; read-only. */ + +typedef void const * soxr_in_t; /* Either a soxr_cbuf_t or soxr_cbufs_t, + depending on itype in soxr_io_spec_t. */ +typedef void * soxr_out_t; /* Either a soxr_buf_t or soxr_bufs_t, + depending on otype in soxr_io_spec_t. */ + + + +/* --------------------------- API main functions --------------------------- */ + +SOXR char const * soxr_version(void); /* Query library version: "libsoxr-x.y.z" */ + +#define soxr_strerror(e) /* Soxr counterpart to strerror. */ \ + ((e)?(e):"no error") + + +/* Create a stream resampler: */ + +SOXR soxr_t soxr_create( + double input_rate, /* Input sample-rate. */ + double output_rate, /* Output sample-rate. */ + unsigned num_channels, /* Number of channels to be used. */ + /* All following arguments are optional (may be set to NULL). */ + 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. */ + + + +/* If not using an app-supplied input function, after creating a stream + * resampler, repeatedly call: */ + +SOXR soxr_error_t soxr_process( + soxr_t resampler, /* As returned by soxr_create. */ + /* Input (to be resampled): */ + soxr_in_t in, /* Input buffer(s); may be NULL (see below). */ + size_t ilen, /* Input buf. length (samples per channel). */ + size_t * idone, /* To return actual # samples used (<= ilen). */ + /* Output (resampled): */ + soxr_out_t out, /* Output buffer(s).*/ + size_t olen, /* Output buf. length (samples per channel). */ + size_t * odone); /* To return actual # samples out (<= olen). + + Note that no special meaning is associated with ilen or olen equal to + zero. End-of-input (i.e. no data is available nor shall be available) + may be indicated by seting `in' to NULL. */ + + + +/* If using an app-supplied input function, it must look and behave like this:*/ + +typedef size_t /* data_len */ + (* soxr_input_fn_t)( /* Supply data to be resampled. */ + void * input_fn_state, /* As given to soxr_set_input_fn (below). */ + soxr_in_t * data, /* Returned data; see below. N.B. ptr to ptr(s)*/ + size_t requested_len); /* Samples per channel, >= returned data_len. + + data_len *data Indicates Meaning + ------- ------- ------------ ------------------------- + !=0 !=0 Success *data contains data to be + input to the resampler. + 0 !=0 (or End-of-input No data is available nor + not set) shall be available. + 0 0 Failure An error occurred whilst trying to + source data to be input to the resampler. */ + +/* and be registered with a previously created stream resampler using: */ + +SOXR soxr_error_t soxr_set_input_fn(/* Set (or reset) an input function.*/ + soxr_t resampler, /* As returned by soxr_create. */ + soxr_input_fn_t, /* Function to supply data to be resampled.*/ + void * input_fn_state, /* If needed by the input function. */ + size_t max_ilen); /* Maximum value for input fn. requested_len.*/ + +/* then repeatedly call: */ + +SOXR size_t /*odone*/ soxr_output(/* Resample and output a block of data.*/ + soxr_t resampler, /* As returned by soxr_create. */ + soxr_out_t data, /* App-supplied buffer(s) for resampled data.*/ + size_t olen); /* Amount of data to output; >= odone. */ + + + +/* Common stream resampler operations: */ + +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 soxr_error_t soxr_clear(soxr_t); /* Ready for fresh signal, same config. */ +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. */ + +SOXR soxr_error_t soxr_oneshot( + double input_rate, + double output_rate, + unsigned num_channels, + soxr_in_t in , size_t ilen, size_t * idone, + soxr_out_t out, size_t olen, size_t * odone, + soxr_io_spec_t const *, + soxr_quality_spec_t const *, + soxr_runtime_spec_t const *); + + + +/* For variable-rate resampling (experimental). 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); + + + +/* -------------------------- API type definitions -------------------------- */ + +typedef enum { /* Datatypes supported for I/O to/from the resampler: */ + /* Internal; do not use: */ + SOXR_FLOAT32, SOXR_FLOAT64, SOXR_INT32, SOXR_INT16, SOXR_SPLIT = 4, + + /* Use for interleaved channels: */ + SOXR_FLOAT32_I = SOXR_FLOAT32, SOXR_FLOAT64_I, SOXR_INT32_I, SOXR_INT16_I, + + /* Use for split channels: */ + SOXR_FLOAT32_S = SOXR_SPLIT , SOXR_FLOAT64_S, SOXR_INT32_S, SOXR_INT16_S + +} soxr_datatype_t; + +#define soxr_datatype_size(x) /* Returns `sizeof' a soxr_datatype_t sample. */\ + ((unsigned char *)"\4\10\4\2")[(x)&3] + + + +struct soxr_io_spec { /* Typically */ + soxr_datatype_t itype; /* Input datatype. SOXR_FLOAT32_I */ + soxr_datatype_t otype; /* Output datatype. SOXR_FLOAT32_I */ + double scale; /* Linear gain to apply during resampling. 1 */ + void * e; /* Reserved for internal use 0 */ + unsigned long flags; /* Per the following #defines. 0 */ +}; + +#define SOXR_TPDF 0 /* Applicable only if otype is INT16. */ +#define SOXR_NO_DITHER 8u /* Disable the above. */ + + + +struct soxr_quality_spec { /* Typically */ + double precision; /* Conversion precision (in bits). 20 */ + double phase_response; /* 0=minimum, ... 50=linear, ... 100=maximum 50 */ + double passband_end; /* 0dB pt. bandwidth to preserve; nyquist=1 0.913*/ + double stopband_begin; /* Aliasing/imaging control; > passband_end 1 */ + void * e; /* Reserved for internal use. 0 */ + unsigned long flags; /* Per the following #defines. 0 */ +}; + +#define SOXR_ROLLOFF_SMALL 0u /* <= 0.01 dB */ +#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. */ + + + +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 */ +}; + /* 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. */ + + + +/* -------------------------- API type constructors ------------------------- */ + +/* These functions allow setting of the most commonly-used structure + * parameters, with other parameters being given default values. The default + * values may then be overridden, directly in the structure, if needed. */ + +SOXR soxr_quality_spec_t soxr_quality_spec( + unsigned long recipe, /* Per the #defines immediately below. */ + unsigned long flags); /* As soxr_quality_spec_t.flags. */ + + /* The 5 standard qualities found in SoX: */ +#define SOXR_QQ 0 /* 'Quick' cubic interpolation. */ +#define SOXR_LQ 1 /* 'Low' 16-bit with larger rolloff. */ +#define SOXR_MQ 2 /* 'Medium' 16-bit with medium rolloff. */ +#define SOXR_HQ SOXR_20_BITQ /* 'High quality'. */ +#define SOXR_VHQ SOXR_28_BITQ /* 'Very high quality'. */ + +#define SOXR_16_BITQ 3 +#define SOXR_20_BITQ 4 +#define SOXR_24_BITQ 5 +#define SOXR_28_BITQ 6 +#define SOXR_32_BITQ 7 + /* Libsamplerate equivalent qualities: */ +#define SOXR_LSR0Q 8 /* 'Best sinc'. */ +#define SOXR_LSR1Q 9 /* 'Medium sinc'. */ +#define SOXR_LSR2Q 10 /* 'Fast sinc'. */ + +#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. */ + + + +SOXR soxr_runtime_spec_t soxr_runtime_spec( + unsigned num_threads); + + + +SOXR soxr_io_spec_t soxr_io_spec( + soxr_datatype_t itype, + soxr_datatype_t otype); + + + +/* --------------------------- Internal use only ---------------------------- */ + +SOXR soxr_error_t soxr_set_error(soxr_t, soxr_error_t); +SOXR soxr_error_t soxr_set_num_channels(soxr_t, unsigned); + + + +#undef SOXR + +#if defined __cplusplus +} +#endif + +#endif diff --git a/lib-src/libsoxr/src/soxr.pc.in b/lib-src/libsoxr/src/soxr.pc.in new file mode 100644 index 000000000..69d225b22 --- /dev/null +++ b/lib-src/libsoxr/src/soxr.pc.in @@ -0,0 +1,5 @@ +Name: ${PROJECT_NAME} +Description: ${DESCRIPTION_SUMMARY} +Version: ${PROJECT_VERSION} +Libs: -L${LIB_INSTALL_DIR} -l${PROJECT_NAME} +Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/lib-src/libsoxr/src/vr32.c b/lib-src/libsoxr/src/vr32.c index de6e8f930..f804db5d0 100644 --- a/lib-src/libsoxr/src/vr32.c +++ b/lib-src/libsoxr/src/vr32.c @@ -1,771 +1,771 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Experimental variable-rate resampling. */ - -#include -#include -#if !defined M_PI -#define M_PI 3.14159265358979323846 -#endif -#if !defined M_LN2 -#define M_LN2 0.69314718055994530942 -#endif -#include -#include -#include "internal.h" -#define FIFO_SIZE_T int -#define FIFO_MIN 0x8000 -#include "fifo.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 PHASES0_D 12 -#define POLY_FIR_LEN_D 20 -#define PHASES0_U 6 -#define POLY_FIR_LEN_U 12 - -#define MULT32 (65536. * 65536.) -#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 \ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - -#define HALF_FIR_LEN_2 (iAL(half_fir_coefs) - 1) -#define HALF_FIR_LEN_4 (HALF_FIR_LEN_2 / 2) - -#define _ sum += (input[-i] + input[i]) * half_fir_coefs[i], ++i; -static float half_fir(float const * input) -{ - long i = 1; - float sum = input[0] * half_fir_coefs[0]; - CONVOLVE CONVOLVE - assert(i == HALF_FIR_LEN_2 + 1); - return (float)sum; -} -#undef _ - -#define _ sum += (input[-i] + input[i]) * half_fir_coefs[2*i], ++i; -static float double_fir0(float const * input) -{ - int i = 1; - float sum = input[0] * half_fir_coefs[0]; - CONVOLVE - assert(i == HALF_FIR_LEN_4 + 1); - return (float)(sum * 2); -} -#undef _ - -#define _ sum += (input[-i] + input[1+i]) * half_fir_coefs[2*i+1], ++i; -static float double_fir1(float const * input) -{ - int i = 0; - float sum = 0; - CONVOLVE - assert(i == HALF_FIR_LEN_4 + 0); - return (float)(sum * 2); -} -#undef _ - -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; - _ _ _ _ _ _ -#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; - -typedef struct {float x[2], y[AL(iir_coefs)];} half_iir_t; - -static float half_iir1(half_iir_t * p, float in0, float in1) -{ - int i = 0; - float tmp0, tmp1; - tmp0 = p->x[0], p->x[0] = in0; - tmp1 = p->x[1], p->x[1] = in1; - IIR_FILTER - p->y[i] = in1 = (in1 - p->y[i]) * iir_coefs[i] + tmp1; - return in1 + in0; -} -#undef _ - -static void half_iir(half_iir_t * p, float * obuf, float const * ibuf, int olen) -{ - int i; - for (i=0; i < olen; obuf[i] = (float)half_iir1(p, ibuf[i*2], ibuf[i*2+1]),++i); -} - -static void half_phase(half_iir_t * p, float * buf, int len) -{ - float const small_normal = 1/MULT32/MULT32; /* To quash denormals on path 0.*/ - int i; - for (i = 0; i < len; buf[i] = (float)half_iir1(p, buf[i], 0), ++i); -#define _ p->y[i] += small_normal, i += 2; - i = 0, _ IIR_FILTER -#undef _ -#define _ p->y[i] -= small_normal, i += 2; - i = 0, _ IIR_FILTER -#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) -{ - 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; - - for (j = 0; j < iAL(k); k[j] = COEF(coefs0, length0, j - K0), ++j); - for (pos = i = 0; i < length0 / 2; ++i) { - double b=(1/24.)*(k[0]+k[4]+6*k[2]-4*(k[1]+k[3])),d=.5*(k[1]+k[3])-k[2]-b; - double a=(1/120.)*(k[5]-k[2]-9*(9*b+d)+2.5*(k[3]-k[1])-2*(k[4]-k[0])); - 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); - } - 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]; - 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; - coef(coefs, 1, n, j, 0, i) = (float)f0; - coef(coefs, 1, n, j, 1, i) = (float)(f1 - f0); - } - free(coefs1); -} - -#define _ sum += (b *x + a)*input[i], ++i; -#define a (coef(poly_fir_coefs_d, 1, POLY_FIR_LEN_D, phase, 0,i)) -#define b (coef(poly_fir_coefs_d, 1, POLY_FIR_LEN_D, phase, 1,i)) -static float poly_fir_coefs_d[POLY_FIR_LEN_D * PHASES_D * 2]; - -static float poly_fir1_d(float const * input, uint32_t frac) -{ - int i = 0, phase = (int)(frac >> (32 - PHASE_BITS_D)); - float sum = 0, x = (float)(frac << PHASE_BITS_D) * (float)(1 / MULT32); - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - assert(i == POLY_FIR_LEN_D); - return (float)sum; -} -#undef a -#undef b -#define a (coef(poly_fir_coefs_u, 1, POLY_FIR_LEN_U, phase, 0,i)) -#define b (coef(poly_fir_coefs_u, 1, POLY_FIR_LEN_U, phase, 1,i)) -static float poly_fir_coefs_u[POLY_FIR_LEN_U * PHASES_U * 2]; - -static float poly_fir1_u(float const * input, uint32_t frac) -{ - int i = 0, phase = (int)(frac >> (32 - PHASE_BITS_U)); - float sum = 0, x = (float)(frac << PHASE_BITS_U) * (float)(1 / MULT32); - _ _ _ _ _ _ _ _ _ _ _ _ - assert(i == POLY_FIR_LEN_U); - return (float)sum; -} -#undef a -#undef b -#undef _ - -#define ADD_TO(x,y) x.all += y.all -#define SUBTRACT_FROM(x,y) x.all -= y.all -#define FRAC(x) x.part.frac -#define INT(x) x.part.integer - -typedef struct { - union { - int64_t all; -#if WORDS_BIGENDIAN - struct {int32_t integer; uint32_t frac;} part; -#else - struct {uint32_t frac; int32_t integer;} part; -#endif - } at, step, step_step; - float const * input; - int len, stage_num; - bool is_d; /* true: downsampling at x2 rate; false: upsampling at 1x rate. */ - double step_mult; -} stream_t; - -static int poly_fir_d(stream_t * s, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_D / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; ++i) { - output[i] = poly_fir1_d(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - if (!(INT(s->at) < s->len)) { - SUBTRACT_FROM(s->at, s->step); - break; - } - output[++i] = poly_fir1_d(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -static int poly_fir_fade_d( - stream_t * s, float const * vol, int step, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_D / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; ++i, vol += step) { - output[i] += *vol * poly_fir1_d(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - if (!(INT(s->at) < s->len)) { - SUBTRACT_FROM(s->at, s->step); - break; - } - output[++i] += *(vol += step) * poly_fir1_d(input + INT(s->at),FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -static int poly_fir_u(stream_t * s, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_U / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; ++i) { - output[i] = poly_fir1_u(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -static int poly_fir_fade_u( - stream_t * s, float const * vol, int step, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_U / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; i += 2, vol += step) { - output[i] += *vol * poly_fir1_u(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -#define shiftr(x,by) ((by) < 0? (x) << (-(by)) : (x) >> (by)) -#define shiftl(x,by) shiftr(x,-(by)) -#define stage_occupancy(s) (fifo_occupancy(&(s)->fifo) - 4*HALF_FIR_LEN_2) -#define stage_read_p(s) ((float *)fifo_read_ptr(&(s)->fifo) + 2*HALF_FIR_LEN_2) -#define stage_preload(s) memset(fifo_reserve(&(s)->fifo, (s)->preload), \ - 0, sizeof(float) * (size_t)(s)->preload); - -typedef struct { - fifo_t fifo; - double step_mult; - int is_fast, x_fade_len, preload; -} stage_t; - -typedef struct { - int num_stages0, num_stages, flushing; - int fade_len, slew_len, xfade, stage_inc, switch_stage_num; - double new_io_ratio, default_io_ratio; - stage_t * stages; - fifo_t output_fifo; - half_iir_t halfer; - stream_t current, fadeout; /* Current/fade-in, fadeout streams. */ -} rate_t; - -static float fade_coefs[(2 << FADE_LEN_BITS) + 1]; - -static void vr_init(rate_t * p, double default_io_ratio, int num_stages, double mult) -{ - int i; - assert(num_stages >= 0); - memset(p, 0, sizeof(*p)); - - p->num_stages0 = num_stages; - p->num_stages = num_stages = max(num_stages, 1); - p->stages = (stage_t *)calloc((unsigned)num_stages + 1, sizeof(*p->stages)) + 1; - for (i = -1; i < p->num_stages; ++i) { - stage_t * s = &p->stages[i]; - fifo_create(&s->fifo, sizeof(float)); - s->step_mult = 2 * MULT32 / shiftl(2, i); - s->preload = i < 0? 0 : i == 0? 2 * HALF_FIR_LEN_2 : 3 * HALF_FIR_LEN_2 / 2; - stage_preload(s); - s->is_fast = true; - lsx_debug("%-3i preload=%i", i, s->preload); - } - fifo_create(&p->output_fifo, sizeof(float)); - p->default_io_ratio = default_io_ratio; - if (!fade_coefs[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); - prepare_coefs(poly_fir_coefs_d, POLY_FIR_LEN_D, PHASES0_D, PHASES_D, coefs0_d, mult *.5); - } - assert(fade_coefs[0]); -} - -static void enter_new_stage(rate_t * p, int occupancy0) -{ - p->current.len = shiftr(occupancy0, p->current.stage_num); - p->current.input = stage_read_p(&p->stages[p->current.stage_num]); - - p->current.step_mult = p->stages[p->current.stage_num].step_mult; - p->current.is_d = p->current.stage_num >= 0; - if (p->current.is_d) - p->current.step_mult *= .5; -} - -static void set_step(stream_t * p, double io_ratio) -{ - p->step.all = (int64_t)(io_ratio * p->step_mult + .5); -} - -static bool set_step_step(stream_t * p, double io_ratio, int slew_len) -{ - int64_t dif; - int difi; - stream_t tmp = *p; - set_step(&tmp, io_ratio); - dif = tmp.step.all - p->step.all; - dif = dif < 0? dif - (slew_len >> 1) : dif + (slew_len >> 1); - difi = (int)dif; /* Try to avoid int64_t div. */ - p->step_step.all = difi == dif? difi / slew_len : dif / slew_len; - return p->step_step.all != 0; -} - -static void vr_set_io_ratio(rate_t * p, double io_ratio, size_t slew_len) -{ - assert(io_ratio > 0); - if (slew_len) { - if (!set_step_step(&p->current, io_ratio, p->slew_len = (int)slew_len)) - p->slew_len = 0, p->new_io_ratio = 0, p->fadeout.step_step.all = 0; - else { - p->new_io_ratio = io_ratio; - if (p->fade_len) - set_step_step(&p->fadeout, io_ratio, p->slew_len); - } - } - else { - if (p->default_io_ratio) { /* 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); - } - 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; - p->default_io_ratio = 0; - } -} - -static bool do_input_stage(rate_t * p, int stage_num, int sign, int min_stage_num) -{ - int i = 0; - float * dest; - stage_t * s = &p->stages[stage_num]; - stage_t * s1 = &p->stages[stage_num - sign]; - float const * src = (float *)fifo_read_ptr(&s1->fifo) + HALF_FIR_LEN_2; - int len = shiftr(fifo_occupancy(&s1->fifo) - HALF_FIR_LEN_2 * 2, sign); - int already_done = fifo_occupancy(&s->fifo) - s->preload; - if ((len -= already_done) <= 0) - return false; - src += shiftl(already_done, sign); - - dest = fifo_reserve(&s->fifo, len); - if (stage_num < 0) for (; i < len; ++src) - dest[i++] = double_fir0(src), dest[i++] = double_fir1(src); - else { - bool should_be_fast = p->stage_inc; - if (!s->x_fade_len && stage_num == p->switch_stage_num) { - p->switch_stage_num = 0; - if (s->is_fast != should_be_fast) { - s->x_fade_len = 1 << FADE_LEN_BITS, s->is_fast = should_be_fast, ++p->xfade; - lsx_debug("xfade level %i, inc?=%i", stage_num, p->stage_inc); - } - } - if (s->x_fade_len) { - float const * vol1 = fade_coefs + (s->x_fade_len << 1); - float const * vol2 = fade_coefs + (((1 << FADE_LEN_BITS) - s->x_fade_len) << 1); - int n = min(len, s->x_fade_len); - /*lsx_debug("xfade level %i, inc?=%i len=%i n=%i", stage_num, p->stage_inc, s->x_fade_len, n);*/ - if (should_be_fast) - for (; i < n; vol2 += 2, vol1 -= 2, src += 2) - dest[i++] = *vol1 * fast_half_fir(src) + *vol2 * half_fir(src); - else for (; i < n; vol2 += 2, vol1 -= 2, src += 2) - dest[i++] = *vol2 * fast_half_fir(src) + *vol1 * half_fir(src); - s->x_fade_len -= n; - p->xfade -= !s->x_fade_len; - } - if (stage_num < min_stage_num) - for (; i < len; dest[i++] = fast_half_fir(src), src += 2); - else for (; i < len; dest[i++] = half_fir(src), src += 2); - } - if (p->flushing > 0) - stage_preload(s); - return true; -} - -static int vr_process(rate_t * p, int olen0) -{ - assert(p->num_stages > 0); - if (p->default_io_ratio) - vr_set_io_ratio(p, p->default_io_ratio, 0); - { - float * output = fifo_reserve(&p->output_fifo, olen0); - int j, odone0 = 0, min_stage_num = p->current.stage_num; - int occupancy0, max_stage_num = min_stage_num; - if (p->fade_len) { - min_stage_num = min(min_stage_num, p->fadeout.stage_num); - max_stage_num = max(max_stage_num, p->fadeout.stage_num); - } - - for (j = min(min_stage_num, 0); j <= max_stage_num; ++j) - if (j && !do_input_stage(p, j, j < 0? -1 : 1, min_stage_num)) - break; - if (p->flushing > 0) - p->flushing = -1; - - occupancy0 = shiftl(max(0,stage_occupancy(&p->stages[max_stage_num])), max_stage_num); - p->current.len = shiftr(occupancy0, p->current.stage_num); - p->current.input = stage_read_p(&p->stages[p->current.stage_num]); - if (p->fade_len) { - p->fadeout.len = shiftr(occupancy0, p->fadeout.stage_num); - p->fadeout.input = stage_read_p(&p->stages[p->fadeout.stage_num]); - } - - while (odone0 < olen0) { - int odone, odone2, olen = olen0 - odone0, stage_dif = 0, shift; - float buf[64 << 1]; - - olen = min(olen, (int)(AL(buf) >> 1)); - if (p->slew_len) - olen = min(olen, p->slew_len); - else if (p->new_io_ratio) { - 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; - p->new_io_ratio = 0; - } - if (!p->flushing && !p->fade_len && !p->xfade) { - if (p->current.is_d) { - if (INT(p->current.step) && FRAC(p->current.step)) - stage_dif = 1, ++max_stage_num; - else if (!INT(p->current.step) && FRAC(p->current.step) < (1u << 31)) - stage_dif = -1, --min_stage_num; - } else if (INT(p->current.step) > 1 && FRAC(p->current.step)) - stage_dif = 1, ++max_stage_num; - } - if (stage_dif) { - int n = p->current.stage_num + stage_dif; - if (n >= p->num_stages) - --max_stage_num; - else { - p->stage_inc = stage_dif > 0; - p->fadeout = p->current; - p->current.stage_num += stage_dif; - if (!p->stage_inc) - p->switch_stage_num = p->current.stage_num; - if ((p->current.stage_num < 0 && stage_dif < 0) || - (p->current.stage_num > 0 && stage_dif > 0)) { - stage_t * s = &p->stages[p->current.stage_num]; - fifo_clear(&s->fifo); - stage_preload(s); - s->is_fast = false; - do_input_stage(p, p->current.stage_num, stage_dif, p->current.stage_num); - } - if (p->current.stage_num > 0 && stage_dif < 0) { - int idone = INT(p->current.at); - stage_t * s = &p->stages[p->current.stage_num]; - fifo_trim_to(&s->fifo, 2 * HALF_FIR_LEN_2 + idone + (POLY_FIR_LEN_D >> 1)); - do_input_stage(p, p->current.stage_num, 1, p->current.stage_num); - } - enter_new_stage(p, occupancy0); - shift = -stage_dif; -#define lshift(x,by) (x)=(by)>0?(x)<<(by):(x)>>-(by) - lshift(p->current.at.all, shift); - shift += p->fadeout.is_d - p->current.is_d; - lshift(p->current.step.all, shift); - lshift(p->current.step_step.all, shift); - p->fade_len = AL(fade_coefs) - 1; - lsx_debug("switch from stage %i to %i, x2 from %i to %i", p->fadeout.stage_num, p->current.stage_num, p->fadeout.is_d, p->current.is_d); - } - } - - if (p->fade_len) { - float const * vol1 = fade_coefs + p->fade_len; - float const * vol2 = fade_coefs + (iAL(fade_coefs) - 1 - p->fade_len); - int olen2 = (olen = min(olen, p->fade_len >> 1)) << 1; - - /* x2 is more fine-grained so may fail to produce a pair of samples - * where x1 would not (the x1 second sample is a zero so is always - * available). So do x2 first, then feed odone to the second one. */ - memset(buf, 0, sizeof(*buf) * (size_t)olen2); - if (p->current.is_d && p->fadeout.is_d) { - odone = poly_fir_fade_d(&p->current, vol1,-1, buf, olen2); - odone2 = poly_fir_fade_d(&p->fadeout, vol2, 1, buf, odone); - } else if (p->current.is_d) { - odone = poly_fir_fade_d(&p->current, vol1,-1, buf, olen2); - odone2 = poly_fir_fade_u(&p->fadeout, vol2, 2, buf, odone); - } else { - assert(p->fadeout.is_d); - odone = poly_fir_fade_d(&p->fadeout, vol2, 1, buf, olen2); - odone2 = poly_fir_fade_u(&p->current, vol1,-2, buf, odone); - } - assert(odone == odone2); - (void)odone2; - p->fade_len -= odone; - if (!p->fade_len) { - if (p->stage_inc) - p->switch_stage_num = min_stage_num++; - else - --max_stage_num; - } - half_iir(&p->halfer, &output[odone0], buf, odone >>= 1); - } - else if (p->current.is_d) { - odone = poly_fir_d(&p->current, buf, olen << 1) >> 1; - half_iir(&p->halfer, &output[odone0], buf, odone); - } - else { - odone = poly_fir_u(&p->current, &output[odone0], olen); - if (p->num_stages0) - half_phase(&p->halfer, &output[odone0], odone); - } - odone0 += odone; - if (p->slew_len) - p->slew_len -= odone; - if (odone != olen) - break; /* Need more input. */ - } { - int from = max(0, max_stage_num), to = min(0, min_stage_num); - int i, idone = shiftr(INT(p->current.at), from - p->current.stage_num); - INT(p->current.at) -= shiftl(idone, from - p->current.stage_num); - if (p->fade_len) - INT(p->fadeout.at) -= shiftl(idone, from - p->fadeout.stage_num); - for (i = from; i >= to; --i, idone <<= 1) - fifo_read(&p->stages[i].fifo, idone, NULL); - } - fifo_trim_by(&p->output_fifo, olen0 - odone0); - return odone0; - } -} - -static float * vr_input(rate_t * p, float const * input, size_t n) -{ - return fifo_write(&p->stages[0].fifo, (int)n, input); -} - -static float const * vr_output(rate_t * p, float * output, size_t * n) -{ - fifo_t * fifo = &p->output_fifo; - if (1 || !p->num_stages0) - return fifo_read(fifo, (int)(*n = min(*n, (size_t)fifo_occupancy(fifo))), output); - else { /* Ignore this complication for now. */ - int const IIR_DELAY = 2; - float * ptr = fifo_read_ptr(fifo); - int olen = min((int)*n, max(0, fifo_occupancy(fifo) - IIR_DELAY)); - *n = (size_t)olen; - if (output) - memcpy(output, ptr + IIR_DELAY, *n * sizeof(*output)); - fifo_read(fifo, olen, NULL); - return ptr + IIR_DELAY; - } -} - -static void vr_flush(rate_t * p) -{ - if (!p->flushing) { - stage_preload(&p->stages[0]); - ++p->flushing; - } -} - -static void vr_close(rate_t * p) -{ - int i; - - fifo_delete(&p->output_fifo); - for (i = -1; i < p->num_stages; ++i) { - stage_t * s = &p->stages[i]; - fifo_delete(&s->fifo); - } - free(p->stages - 1); -} - -static double vr_delay(rate_t * p) -{ - return 100; /* TODO */ - (void)p; -} - -static void vr_sizes(size_t * shared, size_t * channel) -{ - *shared = 0; - *channel = sizeof(rate_t); -} - -static char const * vr_create(void * channel, void * shared,double max_io_ratio, - void * q_spec, void * r_spec, double scale) -{ - double x = max_io_ratio; - int n; - for (n = 0; x > 1; x *= .5, ++n); - vr_init(channel, max_io_ratio, n, scale); - return 0; - (void)shared, (void)q_spec, (void)r_spec; -} - -static char const * vr_id(void) -{ - return "single-precision variable-rate"; -} - -typedef void (* fn_t)(void); -fn_t _soxr_vr32_cb[] = { - (fn_t)vr_input, - (fn_t)vr_process, - (fn_t)vr_output, - (fn_t)vr_flush, - (fn_t)vr_close, - (fn_t)vr_delay, - (fn_t)vr_sizes, - (fn_t)vr_create, - (fn_t)vr_set_io_ratio, - (fn_t)vr_id, -}; +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Experimental variable-rate resampling. */ + +#include +#include +#if !defined M_PI +#define M_PI 3.14159265358979323846 +#endif +#if !defined M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#include +#include +#include "internal.h" +#define FIFO_SIZE_T int +#define FIFO_MIN 0x8000 +#include "fifo.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 PHASES0_D 12 +#define POLY_FIR_LEN_D 20 +#define PHASES0_U 6 +#define POLY_FIR_LEN_U 12 + +#define MULT32 (65536. * 65536.) +#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 \ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + +#define HALF_FIR_LEN_2 (iAL(half_fir_coefs) - 1) +#define HALF_FIR_LEN_4 (HALF_FIR_LEN_2 / 2) + +#define _ sum += (input[-i] + input[i]) * half_fir_coefs[i], ++i; +static float half_fir(float const * input) +{ + long i = 1; + float sum = input[0] * half_fir_coefs[0]; + CONVOLVE CONVOLVE + assert(i == HALF_FIR_LEN_2 + 1); + return (float)sum; +} +#undef _ + +#define _ sum += (input[-i] + input[i]) * half_fir_coefs[2*i], ++i; +static float double_fir0(float const * input) +{ + int i = 1; + float sum = input[0] * half_fir_coefs[0]; + CONVOLVE + assert(i == HALF_FIR_LEN_4 + 1); + return (float)(sum * 2); +} +#undef _ + +#define _ sum += (input[-i] + input[1+i]) * half_fir_coefs[2*i+1], ++i; +static float double_fir1(float const * input) +{ + int i = 0; + float sum = 0; + CONVOLVE + assert(i == HALF_FIR_LEN_4 + 0); + return (float)(sum * 2); +} +#undef _ + +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; + _ _ _ _ _ _ +#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; + +typedef struct {float x[2], y[AL(iir_coefs)];} half_iir_t; + +static float half_iir1(half_iir_t * p, float in0, float in1) +{ + int i = 0; + float tmp0, tmp1; + tmp0 = p->x[0], p->x[0] = in0; + tmp1 = p->x[1], p->x[1] = in1; + IIR_FILTER + p->y[i] = in1 = (in1 - p->y[i]) * iir_coefs[i] + tmp1; + return in1 + in0; +} +#undef _ + +static void half_iir(half_iir_t * p, float * obuf, float const * ibuf, int olen) +{ + int i; + for (i=0; i < olen; obuf[i] = (float)half_iir1(p, ibuf[i*2], ibuf[i*2+1]),++i); +} + +static void half_phase(half_iir_t * p, float * buf, int len) +{ + float const small_normal = 1/MULT32/MULT32; /* To quash denormals on path 0.*/ + int i; + for (i = 0; i < len; buf[i] = (float)half_iir1(p, buf[i], 0), ++i); +#define _ p->y[i] += small_normal, i += 2; + i = 0, _ IIR_FILTER +#undef _ +#define _ p->y[i] -= small_normal, i += 2; + i = 0, _ IIR_FILTER +#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) +{ + 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; + + for (j = 0; j < iAL(k); k[j] = COEF(coefs0, length0, j - K0), ++j); + for (pos = i = 0; i < length0 / 2; ++i) { + double b=(1/24.)*(k[0]+k[4]+6*k[2]-4*(k[1]+k[3])),d=.5*(k[1]+k[3])-k[2]-b; + double a=(1/120.)*(k[5]-k[2]-9*(9*b+d)+2.5*(k[3]-k[1])-2*(k[4]-k[0])); + 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); + } + 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]; + 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; + coef(coefs, 1, n, j, 0, i) = (float)f0; + coef(coefs, 1, n, j, 1, i) = (float)(f1 - f0); + } + free(coefs1); +} + +#define _ sum += (b *x + a)*input[i], ++i; +#define a (coef(poly_fir_coefs_d, 1, POLY_FIR_LEN_D, phase, 0,i)) +#define b (coef(poly_fir_coefs_d, 1, POLY_FIR_LEN_D, phase, 1,i)) +static float poly_fir_coefs_d[POLY_FIR_LEN_D * PHASES_D * 2]; + +static float poly_fir1_d(float const * input, uint32_t frac) +{ + int i = 0, phase = (int)(frac >> (32 - PHASE_BITS_D)); + float sum = 0, x = (float)(frac << PHASE_BITS_D) * (float)(1 / MULT32); + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + assert(i == POLY_FIR_LEN_D); + return (float)sum; +} +#undef a +#undef b +#define a (coef(poly_fir_coefs_u, 1, POLY_FIR_LEN_U, phase, 0,i)) +#define b (coef(poly_fir_coefs_u, 1, POLY_FIR_LEN_U, phase, 1,i)) +static float poly_fir_coefs_u[POLY_FIR_LEN_U * PHASES_U * 2]; + +static float poly_fir1_u(float const * input, uint32_t frac) +{ + int i = 0, phase = (int)(frac >> (32 - PHASE_BITS_U)); + float sum = 0, x = (float)(frac << PHASE_BITS_U) * (float)(1 / MULT32); + _ _ _ _ _ _ _ _ _ _ _ _ + assert(i == POLY_FIR_LEN_U); + return (float)sum; +} +#undef a +#undef b +#undef _ + +#define ADD_TO(x,y) x.all += y.all +#define SUBTRACT_FROM(x,y) x.all -= y.all +#define FRAC(x) x.part.frac +#define INT(x) x.part.integer + +typedef struct { + union { + int64_t all; +#if WORDS_BIGENDIAN + struct {int32_t integer; uint32_t frac;} part; +#else + struct {uint32_t frac; int32_t integer;} part; +#endif + } at, step, step_step; + float const * input; + int len, stage_num; + bool is_d; /* true: downsampling at x2 rate; false: upsampling at 1x rate. */ + double step_mult; +} stream_t; + +static int poly_fir_d(stream_t * s, float * output, int olen) +{ + int i; + float const * input = s->input - POLY_FIR_LEN_D / 2 + 1; + for (i = 0; i < olen && INT(s->at) < s->len; ++i) { + output[i] = poly_fir1_d(input + INT(s->at), FRAC(s->at)); + ADD_TO(s->at, s->step); + if (!(INT(s->at) < s->len)) { + SUBTRACT_FROM(s->at, s->step); + break; + } + output[++i] = poly_fir1_d(input + INT(s->at), FRAC(s->at)); + ADD_TO(s->at, s->step); + ADD_TO(s->step, s->step_step); + } + return i; +} + +static int poly_fir_fade_d( + stream_t * s, float const * vol, int step, float * output, int olen) +{ + int i; + float const * input = s->input - POLY_FIR_LEN_D / 2 + 1; + for (i = 0; i < olen && INT(s->at) < s->len; ++i, vol += step) { + output[i] += *vol * poly_fir1_d(input + INT(s->at), FRAC(s->at)); + ADD_TO(s->at, s->step); + if (!(INT(s->at) < s->len)) { + SUBTRACT_FROM(s->at, s->step); + break; + } + output[++i] += *(vol += step) * poly_fir1_d(input + INT(s->at),FRAC(s->at)); + ADD_TO(s->at, s->step); + ADD_TO(s->step, s->step_step); + } + return i; +} + +static int poly_fir_u(stream_t * s, float * output, int olen) +{ + int i; + float const * input = s->input - POLY_FIR_LEN_U / 2 + 1; + for (i = 0; i < olen && INT(s->at) < s->len; ++i) { + output[i] = poly_fir1_u(input + INT(s->at), FRAC(s->at)); + ADD_TO(s->at, s->step); + ADD_TO(s->step, s->step_step); + } + return i; +} + +static int poly_fir_fade_u( + stream_t * s, float const * vol, int step, float * output, int olen) +{ + int i; + float const * input = s->input - POLY_FIR_LEN_U / 2 + 1; + for (i = 0; i < olen && INT(s->at) < s->len; i += 2, vol += step) { + output[i] += *vol * poly_fir1_u(input + INT(s->at), FRAC(s->at)); + ADD_TO(s->at, s->step); + ADD_TO(s->step, s->step_step); + } + return i; +} + +#define shiftr(x,by) ((by) < 0? (x) << (-(by)) : (x) >> (by)) +#define shiftl(x,by) shiftr(x,-(by)) +#define stage_occupancy(s) (fifo_occupancy(&(s)->fifo) - 4*HALF_FIR_LEN_2) +#define stage_read_p(s) ((float *)fifo_read_ptr(&(s)->fifo) + 2*HALF_FIR_LEN_2) +#define stage_preload(s) memset(fifo_reserve(&(s)->fifo, (s)->preload), \ + 0, sizeof(float) * (size_t)(s)->preload); + +typedef struct { + fifo_t fifo; + double step_mult; + int is_fast, x_fade_len, preload; +} stage_t; + +typedef struct { + int num_stages0, num_stages, flushing; + int fade_len, slew_len, xfade, stage_inc, switch_stage_num; + double new_io_ratio, default_io_ratio; + stage_t * stages; + fifo_t output_fifo; + half_iir_t halfer; + stream_t current, fadeout; /* Current/fade-in, fadeout streams. */ +} rate_t; + +static float fade_coefs[(2 << FADE_LEN_BITS) + 1]; + +static void vr_init(rate_t * p, double default_io_ratio, int num_stages, double mult) +{ + int i; + assert(num_stages >= 0); + memset(p, 0, sizeof(*p)); + + p->num_stages0 = num_stages; + p->num_stages = num_stages = max(num_stages, 1); + p->stages = (stage_t *)calloc((unsigned)num_stages + 1, sizeof(*p->stages)) + 1; + for (i = -1; i < p->num_stages; ++i) { + stage_t * s = &p->stages[i]; + fifo_create(&s->fifo, sizeof(float)); + s->step_mult = 2 * MULT32 / shiftl(2, i); + s->preload = i < 0? 0 : i == 0? 2 * HALF_FIR_LEN_2 : 3 * HALF_FIR_LEN_2 / 2; + stage_preload(s); + s->is_fast = true; + lsx_debug("%-3i preload=%i", i, s->preload); + } + fifo_create(&p->output_fifo, sizeof(float)); + p->default_io_ratio = default_io_ratio; + if (!fade_coefs[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); + prepare_coefs(poly_fir_coefs_d, POLY_FIR_LEN_D, PHASES0_D, PHASES_D, coefs0_d, mult *.5); + } + assert(fade_coefs[0]); +} + +static void enter_new_stage(rate_t * p, int occupancy0) +{ + p->current.len = shiftr(occupancy0, p->current.stage_num); + p->current.input = stage_read_p(&p->stages[p->current.stage_num]); + + p->current.step_mult = p->stages[p->current.stage_num].step_mult; + p->current.is_d = p->current.stage_num >= 0; + if (p->current.is_d) + p->current.step_mult *= .5; +} + +static void set_step(stream_t * p, double io_ratio) +{ + p->step.all = (int64_t)(io_ratio * p->step_mult + .5); +} + +static bool set_step_step(stream_t * p, double io_ratio, int slew_len) +{ + int64_t dif; + int difi; + stream_t tmp = *p; + set_step(&tmp, io_ratio); + dif = tmp.step.all - p->step.all; + dif = dif < 0? dif - (slew_len >> 1) : dif + (slew_len >> 1); + difi = (int)dif; /* Try to avoid int64_t div. */ + p->step_step.all = difi == dif? difi / slew_len : dif / slew_len; + return p->step_step.all != 0; +} + +static void vr_set_io_ratio(rate_t * p, double io_ratio, size_t slew_len) +{ + assert(io_ratio > 0); + if (slew_len) { + if (!set_step_step(&p->current, io_ratio, p->slew_len = (int)slew_len)) + p->slew_len = 0, p->new_io_ratio = 0, p->fadeout.step_step.all = 0; + else { + p->new_io_ratio = io_ratio; + if (p->fade_len) + set_step_step(&p->fadeout, io_ratio, p->slew_len); + } + } + else { + if (p->default_io_ratio) { /* 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); + } + 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; + p->default_io_ratio = 0; + } +} + +static bool do_input_stage(rate_t * p, int stage_num, int sign, int min_stage_num) +{ + int i = 0; + float * dest; + stage_t * s = &p->stages[stage_num]; + stage_t * s1 = &p->stages[stage_num - sign]; + float const * src = (float *)fifo_read_ptr(&s1->fifo) + HALF_FIR_LEN_2; + int len = shiftr(fifo_occupancy(&s1->fifo) - HALF_FIR_LEN_2 * 2, sign); + int already_done = fifo_occupancy(&s->fifo) - s->preload; + if ((len -= already_done) <= 0) + return false; + src += shiftl(already_done, sign); + + dest = fifo_reserve(&s->fifo, len); + if (stage_num < 0) for (; i < len; ++src) + dest[i++] = double_fir0(src), dest[i++] = double_fir1(src); + else { + bool should_be_fast = p->stage_inc; + if (!s->x_fade_len && stage_num == p->switch_stage_num) { + p->switch_stage_num = 0; + if (s->is_fast != should_be_fast) { + s->x_fade_len = 1 << FADE_LEN_BITS, s->is_fast = should_be_fast, ++p->xfade; + lsx_debug("xfade level %i, inc?=%i", stage_num, p->stage_inc); + } + } + if (s->x_fade_len) { + float const * vol1 = fade_coefs + (s->x_fade_len << 1); + float const * vol2 = fade_coefs + (((1 << FADE_LEN_BITS) - s->x_fade_len) << 1); + int n = min(len, s->x_fade_len); + /*lsx_debug("xfade level %i, inc?=%i len=%i n=%i", stage_num, p->stage_inc, s->x_fade_len, n);*/ + if (should_be_fast) + for (; i < n; vol2 += 2, vol1 -= 2, src += 2) + dest[i++] = *vol1 * fast_half_fir(src) + *vol2 * half_fir(src); + else for (; i < n; vol2 += 2, vol1 -= 2, src += 2) + dest[i++] = *vol2 * fast_half_fir(src) + *vol1 * half_fir(src); + s->x_fade_len -= n; + p->xfade -= !s->x_fade_len; + } + if (stage_num < min_stage_num) + for (; i < len; dest[i++] = fast_half_fir(src), src += 2); + else for (; i < len; dest[i++] = half_fir(src), src += 2); + } + if (p->flushing > 0) + stage_preload(s); + return true; +} + +static int vr_process(rate_t * p, int olen0) +{ + assert(p->num_stages > 0); + if (p->default_io_ratio) + vr_set_io_ratio(p, p->default_io_ratio, 0); + { + float * output = fifo_reserve(&p->output_fifo, olen0); + int j, odone0 = 0, min_stage_num = p->current.stage_num; + int occupancy0, max_stage_num = min_stage_num; + if (p->fade_len) { + min_stage_num = min(min_stage_num, p->fadeout.stage_num); + max_stage_num = max(max_stage_num, p->fadeout.stage_num); + } + + for (j = min(min_stage_num, 0); j <= max_stage_num; ++j) + if (j && !do_input_stage(p, j, j < 0? -1 : 1, min_stage_num)) + break; + if (p->flushing > 0) + p->flushing = -1; + + occupancy0 = shiftl(max(0,stage_occupancy(&p->stages[max_stage_num])), max_stage_num); + p->current.len = shiftr(occupancy0, p->current.stage_num); + p->current.input = stage_read_p(&p->stages[p->current.stage_num]); + if (p->fade_len) { + p->fadeout.len = shiftr(occupancy0, p->fadeout.stage_num); + p->fadeout.input = stage_read_p(&p->stages[p->fadeout.stage_num]); + } + + while (odone0 < olen0) { + int odone, odone2, olen = olen0 - odone0, stage_dif = 0, shift; + float buf[64 << 1]; + + olen = min(olen, (int)(AL(buf) >> 1)); + if (p->slew_len) + olen = min(olen, p->slew_len); + else if (p->new_io_ratio) { + 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; + p->new_io_ratio = 0; + } + if (!p->flushing && !p->fade_len && !p->xfade) { + if (p->current.is_d) { + if (INT(p->current.step) && FRAC(p->current.step)) + stage_dif = 1, ++max_stage_num; + else if (!INT(p->current.step) && FRAC(p->current.step) < (1u << 31)) + stage_dif = -1, --min_stage_num; + } else if (INT(p->current.step) > 1 && FRAC(p->current.step)) + stage_dif = 1, ++max_stage_num; + } + if (stage_dif) { + int n = p->current.stage_num + stage_dif; + if (n >= p->num_stages) + --max_stage_num; + else { + p->stage_inc = stage_dif > 0; + p->fadeout = p->current; + p->current.stage_num += stage_dif; + if (!p->stage_inc) + p->switch_stage_num = p->current.stage_num; + if ((p->current.stage_num < 0 && stage_dif < 0) || + (p->current.stage_num > 0 && stage_dif > 0)) { + stage_t * s = &p->stages[p->current.stage_num]; + fifo_clear(&s->fifo); + stage_preload(s); + s->is_fast = false; + do_input_stage(p, p->current.stage_num, stage_dif, p->current.stage_num); + } + if (p->current.stage_num > 0 && stage_dif < 0) { + int idone = INT(p->current.at); + stage_t * s = &p->stages[p->current.stage_num]; + fifo_trim_to(&s->fifo, 2 * HALF_FIR_LEN_2 + idone + (POLY_FIR_LEN_D >> 1)); + do_input_stage(p, p->current.stage_num, 1, p->current.stage_num); + } + enter_new_stage(p, occupancy0); + shift = -stage_dif; +#define lshift(x,by) (x)=(by)>0?(x)<<(by):(x)>>-(by) + lshift(p->current.at.all, shift); + shift += p->fadeout.is_d - p->current.is_d; + lshift(p->current.step.all, shift); + lshift(p->current.step_step.all, shift); + p->fade_len = AL(fade_coefs) - 1; + lsx_debug("switch from stage %i to %i, x2 from %i to %i", p->fadeout.stage_num, p->current.stage_num, p->fadeout.is_d, p->current.is_d); + } + } + + if (p->fade_len) { + float const * vol1 = fade_coefs + p->fade_len; + float const * vol2 = fade_coefs + (iAL(fade_coefs) - 1 - p->fade_len); + int olen2 = (olen = min(olen, p->fade_len >> 1)) << 1; + + /* x2 is more fine-grained so may fail to produce a pair of samples + * where x1 would not (the x1 second sample is a zero so is always + * available). So do x2 first, then feed odone to the second one. */ + memset(buf, 0, sizeof(*buf) * (size_t)olen2); + if (p->current.is_d && p->fadeout.is_d) { + odone = poly_fir_fade_d(&p->current, vol1,-1, buf, olen2); + odone2 = poly_fir_fade_d(&p->fadeout, vol2, 1, buf, odone); + } else if (p->current.is_d) { + odone = poly_fir_fade_d(&p->current, vol1,-1, buf, olen2); + odone2 = poly_fir_fade_u(&p->fadeout, vol2, 2, buf, odone); + } else { + assert(p->fadeout.is_d); + odone = poly_fir_fade_d(&p->fadeout, vol2, 1, buf, olen2); + odone2 = poly_fir_fade_u(&p->current, vol1,-2, buf, odone); + } + assert(odone == odone2); + (void)odone2; + p->fade_len -= odone; + if (!p->fade_len) { + if (p->stage_inc) + p->switch_stage_num = min_stage_num++; + else + --max_stage_num; + } + half_iir(&p->halfer, &output[odone0], buf, odone >>= 1); + } + else if (p->current.is_d) { + odone = poly_fir_d(&p->current, buf, olen << 1) >> 1; + half_iir(&p->halfer, &output[odone0], buf, odone); + } + else { + odone = poly_fir_u(&p->current, &output[odone0], olen); + if (p->num_stages0) + half_phase(&p->halfer, &output[odone0], odone); + } + odone0 += odone; + if (p->slew_len) + p->slew_len -= odone; + if (odone != olen) + break; /* Need more input. */ + } { + int from = max(0, max_stage_num), to = min(0, min_stage_num); + int i, idone = shiftr(INT(p->current.at), from - p->current.stage_num); + INT(p->current.at) -= shiftl(idone, from - p->current.stage_num); + if (p->fade_len) + INT(p->fadeout.at) -= shiftl(idone, from - p->fadeout.stage_num); + for (i = from; i >= to; --i, idone <<= 1) + fifo_read(&p->stages[i].fifo, idone, NULL); + } + fifo_trim_by(&p->output_fifo, olen0 - odone0); + return odone0; + } +} + +static float * vr_input(rate_t * p, float const * input, size_t n) +{ + return fifo_write(&p->stages[0].fifo, (int)n, input); +} + +static float const * vr_output(rate_t * p, float * output, size_t * n) +{ + fifo_t * fifo = &p->output_fifo; + if (1 || !p->num_stages0) + return fifo_read(fifo, (int)(*n = min(*n, (size_t)fifo_occupancy(fifo))), output); + else { /* Ignore this complication for now. */ + int const IIR_DELAY = 2; + float * ptr = fifo_read_ptr(fifo); + int olen = min((int)*n, max(0, fifo_occupancy(fifo) - IIR_DELAY)); + *n = (size_t)olen; + if (output) + memcpy(output, ptr + IIR_DELAY, *n * sizeof(*output)); + fifo_read(fifo, olen, NULL); + return ptr + IIR_DELAY; + } +} + +static void vr_flush(rate_t * p) +{ + if (!p->flushing) { + stage_preload(&p->stages[0]); + ++p->flushing; + } +} + +static void vr_close(rate_t * p) +{ + int i; + + fifo_delete(&p->output_fifo); + for (i = -1; i < p->num_stages; ++i) { + stage_t * s = &p->stages[i]; + fifo_delete(&s->fifo); + } + free(p->stages - 1); +} + +static double vr_delay(rate_t * p) +{ + return 100; /* TODO */ + (void)p; +} + +static void vr_sizes(size_t * shared, size_t * channel) +{ + *shared = 0; + *channel = sizeof(rate_t); +} + +static char const * vr_create(void * channel, void * shared,double max_io_ratio, + void * q_spec, void * r_spec, double scale) +{ + double x = max_io_ratio; + int n; + for (n = 0; x > 1; x *= .5, ++n); + vr_init(channel, max_io_ratio, n, scale); + return 0; + (void)shared, (void)q_spec, (void)r_spec; +} + +static char const * vr_id(void) +{ + return "single-precision variable-rate"; +} + +typedef void (* fn_t)(void); +fn_t _soxr_vr32_cb[] = { + (fn_t)vr_input, + (fn_t)vr_process, + (fn_t)vr_output, + (fn_t)vr_flush, + (fn_t)vr_close, + (fn_t)vr_delay, + (fn_t)vr_sizes, + (fn_t)vr_create, + (fn_t)vr_set_io_ratio, + (fn_t)vr_id, +}; diff --git a/lib-src/libsoxr/tests/CMakeLists.txt b/lib-src/libsoxr/tests/CMakeLists.txt index b0003cf39..277fc5587 100644 --- a/lib-src/libsoxr/tests/CMakeLists.txt +++ b/lib-src/libsoxr/tests/CMakeLists.txt @@ -1,50 +1,50 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -add_definitions (${PROJECT_C_FLAGS}) -link_libraries (${PROJECT_NAME}) - -file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c) -foreach (fe ${SOURCES}) - get_filename_component (f ${fe} NAME_WE) - add_executable (${f} ${fe}) -endforeach () - -enable_testing () - -set (sweep_to_freq 22050) -set (leader 1) -set (len 16) -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}) - 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}) -endmacro () - -unset (test_bits) -if (WITH_SINGLE_PRECISION) - set (test_bits 20) -endif () -if (WITH_DOUBLE_PRECISION) - set (test_bits ${test_bits} 24) -endif () - -foreach (b ${test_bits}) - foreach (r 96000 65537) - add_cmp_test (${base_rate} ${r} ${b}) - add_cmp_test (${r} ${base_rate} ${b}) - endforeach () -endforeach () - -add_custom_target (test-vectors ALL DEPENDS ${vectors}) +# 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}) + +file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c) +foreach (fe ${SOURCES}) + get_filename_component (f ${fe} NAME_WE) + add_executable (${f} ${fe}) +endforeach () + +enable_testing () + +set (sweep_to_freq 22050) +set (leader 1) +set (len 16) +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}) + 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}) +endmacro () + +unset (test_bits) +if (WITH_SINGLE_PRECISION) + set (test_bits 20) +endif () +if (WITH_DOUBLE_PRECISION) + set (test_bits ${test_bits} 24) +endif () + +foreach (b ${test_bits}) + foreach (r 96000 65537) + add_cmp_test (${base_rate} ${r} ${b}) + add_cmp_test (${r} ${base_rate} ${b}) + endforeach () +endforeach () + +add_custom_target (test-vectors ALL DEPENDS ${vectors}) diff --git a/lib-src/libsoxr/tests/README b/lib-src/libsoxr/tests/README index ff959b8a9..44460d630 100644 --- a/lib-src/libsoxr/tests/README +++ b/lib-src/libsoxr/tests/README @@ -1 +1 @@ -A few tests on the pass-band performance; not a comprehensive test suite. +A few tests on the pass-band performance; not a comprehensive test suite. diff --git a/lib-src/libsoxr/tests/cmp-test.cmake b/lib-src/libsoxr/tests/cmp-test.cmake index 3b27f5f42..8db76c58f 100644 --- a/lib-src/libsoxr/tests/cmp-test.cmake +++ b/lib-src/libsoxr/tests/cmp-test.cmake @@ -1,28 +1,30 @@ -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -if (${bits} STREQUAL 24) - set (quality 45) -else () - set (quality 44) -endif () - -execute_process(COMMAND ${EXAMPLES_BIN}3-options-input-fn ${from} ${to} 1 2 2 ${quality} a - INPUT_FILE ref-${from}.s32 - OUTPUT_FILE ${from}-${to}.s32 - ERROR_VARIABLE test_error - RESULT_VARIABLE test_result) - -if (test_result) - message (FATAL_ERROR "Resampling failure: ${test_error}") -endif () - -execute_process(COMMAND ${BIN}vector-cmp ref-${to}.s32 ${from}-${to}.s32 ${to} ${leader} ${len} ${bits} 98 - OUTPUT_VARIABLE test_output - RESULT_VARIABLE test_result) - -if (test_result) - message (FATAL_ERROR ${test_output}) -else () - message (STATUS ${test_output}) -endif () +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +if (${bits} STREQUAL 24) + set (quality 45) +else () + set (quality 44) +endif () + +set (output ${from}-${to}-${quality}.s32) + +execute_process(COMMAND ${EXAMPLES_BIN}3-options-input-fn ${from} ${to} 1 2 2 ${quality} a + INPUT_FILE ref-${from}.s32 + OUTPUT_FILE ${output} + ERROR_VARIABLE test_error + RESULT_VARIABLE test_result) + +if (test_result) + message (FATAL_ERROR "Resampling failure: ${test_error}") +endif () + +execute_process(COMMAND ${BIN}vector-cmp ref-${to}.s32 ${output} ${to} ${leader} ${len} ${bits} 98 + OUTPUT_VARIABLE test_output + RESULT_VARIABLE test_result) + +if (test_result) + message (FATAL_ERROR ${test_output}) +else () + message (STATUS ${test_output}) +endif () diff --git a/lib-src/libsoxr/tests/eg-test b/lib-src/libsoxr/tests/eg-test index 80dc7fa67..797c71598 100644 --- a/lib-src/libsoxr/tests/eg-test +++ b/lib-src/libsoxr/tests/eg-test @@ -1,29 +1,29 @@ -#!/bin/bash -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -len=8 -#vg="valgrind --leak-check=full --show-reachable=yes" - -$vg ./1-single-block - -ir=96000 -or=44100 -for i in 1 2; do - prev="" - sox -r $ir -n 0.f32 synth $len sin 0+`expr $ir / 2` - for f in `find . -type f -executable -name "[2-4]*"`; do - $vg $f $ir $or < 0.f32 > $f.f32 - test x$prev != x && cmp $f.f32 $prev - prev=$f.f32 - done - or=96000 - ir=44100 -done -rm *.f32 - -rm ?.png -for n in 0 1 2 3; do - $vg ./5-variable-rate $n | sox -tf32 -r44100 -c1 - -n spectrogram -hwk -o $n.png -X 50 - vg="" -done +#!/bin/bash +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +len=8 +#vg="valgrind --leak-check=full --show-reachable=yes" + +$vg ./1-single-block + +ir=96000 +or=44100 +for i in 1 2; do + prev="" + sox -r $ir -n 0.f32 synth $len sin 0+`expr $ir / 2` + for f in `find . -type f -executable -name "[2-4]*"`; do + $vg $f $ir $or < 0.f32 > $f.f32 + test x$prev != x && cmp $f.f32 $prev + prev=$f.f32 + done + or=96000 + ir=44100 +done +rm *.f32 + +rm ?.png +for n in 0 1 2 3; do + $vg ./5-variable-rate $n | sox -tf32 -r44100 -c1 - -n spectrogram -hwk -o $n.png -X 50 + vg="" +done diff --git a/lib-src/libsoxr/tests/io-test b/lib-src/libsoxr/tests/io-test index eafb1bd67..537f896df 100644 --- a/lib-src/libsoxr/tests/io-test +++ b/lib-src/libsoxr/tests/io-test @@ -1,40 +1,40 @@ -#!/bin/bash -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -ir=96000 -or=44100 -len=16 -f=0+48k -g=48k+0 -ex=./3-options-input-fn - -types=(f32 f64 s32 s16) - -do_one() { - $ex $ir $or $c $1 $2 $3 < $c.${types[$1]} | - sox -t ${types[$2]} -r $or -c $c - -n spectrogram -X50 -hwk -z180 -o io$n$c.png - n=`expr $n + 1` -} - -rm io??.png - -j=2; test z$1 != z && j=$1 - -for c in `seq 1 $j`; do - for n in `seq 0 3`; do - sox -r $ir -n $c.${types[$n]} synth $len sin $f gain -.1 - done - - n=0 - for m in `seq 0 3`; do do_one $m $m 4; done - do_one 1 2 5 - do_one 2 0 5 - do_one 3 2 4 - do_one 0 3 4 - - f="$f sin $g" - g=48k:0 -done - -rm ?.[sf][0-9][0-9] +#!/bin/bash +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +ir=96000 +or=44100 +len=16 +f=0+48k +g=48k+0 +ex=./3-options-input-fn + +types=(f32 f64 s32 s16) + +do_one() { + $ex $ir $or $c $1 $2 $3 < $c.${types[$1]} | + sox -t ${types[$2]} -r $or -c $c - -n spectrogram -X50 -hwk -z180 -o io$n$c.png + n=`expr $n + 1` +} + +rm io??.png + +j=2; test z$1 != z && j=$1 + +for c in `seq 1 $j`; do + for n in `seq 0 3`; do + sox -r $ir -n $c.${types[$n]} synth $len sin $f gain -.1 + done + + n=0 + for m in `seq 0 3`; do do_one $m $m 4; done + do_one 1 2 5 + do_one 2 0 5 + do_one 3 2 4 + do_one 0 3 4 + + f="$f sin $g" + g=48k:0 +done + +rm ?.[sf][0-9][0-9] diff --git a/lib-src/libsoxr/tests/large-ratio b/lib-src/libsoxr/tests/large-ratio index 9084ea050..a12bda91c 100644 --- a/lib-src/libsoxr/tests/large-ratio +++ b/lib-src/libsoxr/tests/large-ratio @@ -1,21 +1,22 @@ -#!/bin/sh -# SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Warning: the intermediate signal (piped) is 3.2 Gbytes so may slug the -# system somewhat. - -ex=./3-options-input-fn -q=6 - -rm lr.png - -./vector-gen 1000 0 8 500 .9375 1.s32 - -$ex 1 1e5 1 2 1 $q < 1.s32 | $ex 1e5 1 1 1 2 $q > 2.s32 - -/usr/bin/sox -M -r 1k 1.s32 -r 1k 2.s32 -n spectrogram -hwk -z180 -o lr.png - -display lr.png & - -rm [12].s32 +#!/bin/sh +# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net +# Licence for this file: LGPL v2.1 See LICENCE for details. + +# Warning: the intermediate signal (piped) is 3.2 Gbytes so may slug the +# system somewhat. + +ex=../examples/3-options-input-fn +q=6 +r=1e5 + +rm lr.png + +../tests/vector-gen 1000 0 8 500 .9375 1.s32 + +$ex 1 $r 1 2 1 $q < 1.s32 | $ex $r 1 1 1 2 $q > 2.s32 + +sox -M -r 1k 1.s32 -r 1k 2.s32 -n spectrogram -hwk -z180 -o lr.png + +display lr.png & + +rm [12].s32 diff --git a/lib-src/libsoxr/tests/vector-cmp.c b/lib-src/libsoxr/tests/vector-cmp.c index 527a504b9..6edd2d5d9 100644 --- a/lib-src/libsoxr/tests/vector-cmp.c +++ b/lib-src/libsoxr/tests/vector-cmp.c @@ -1,53 +1,53 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Utility used to help test the library; not for general consumption. - * - * Compare two swept-sine files. */ - -#include -#include -#include -#include "../src/rint.h" - -int main(int bit, char const * arg[]) -{ - FILE * f1 = fopen(arg[1], "rb"), - * f2 = fopen(arg[2], "rb"); - double rate = atof (arg[3]), /* Rate for this vector */ - leader_len = atof (arg[4]), /* Leader length in seconds */ - len = atof (arg[5]), /* Sweep length (excl. leader_len) */ - expect_bits= atof (arg[6]), - expect_bw = atof (arg[7]); - - int32_t s1, s2; - long count = 0; - static long thresh[32]; - double bw, prev = 0; - - for (; fread(&s1, sizeof(s1), 1, f1) == 1 && - fread(&s2, sizeof(s2), 1, f2) == 1; ++count) { - long diff = abs((int)(s1 - s2)); - for (bit = 0; diff && bit < 32; bit++, diff >>= 1) - if ((diff & 1) && !thresh[bit]) - thresh[bit] = count + 1; - } - - if (count != (long)((leader_len + len) * rate + .5)) { - printf("incorrect file length\n"); - exit(1); - } - - for (bit = 0; bit < 32; ++bit) { - bw = ((double)thresh[bit] - 1) / rate - leader_len; - if (bit && bw >= 0 && (bw - prev) * 100 / len < .08) { - --bit; - break; - } - prev = bw; - } - bit = 32 - bit; - bw = bw * 100 / len; - printf("Bit perfect to %i bits, from DC to %.2f%% nyquist.\n", bit, bw); - return !(bit >= expect_bits && bw >= expect_bw); -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Utility used to help test the library; not for general consumption. + * + * Compare two swept-sine files. */ + +#include +#include +#include +#include "../src/rint.h" + +int main(int bit, char const * arg[]) +{ + FILE * f1 = fopen(arg[1], "rb"), + * f2 = fopen(arg[2], "rb"); + double rate = atof (arg[3]), /* Rate for this vector */ + leader_len = atof (arg[4]), /* Leader length in seconds */ + len = atof (arg[5]), /* Sweep length (excl. leader_len) */ + expect_bits= atof (arg[6]), + expect_bw = atof (arg[7]); + + int32_t s1, s2; + long count = 0; + static long thresh[32]; + double bw, prev = 0; + + for (; fread(&s1, sizeof(s1), 1, f1) == 1 && + fread(&s2, sizeof(s2), 1, f2) == 1; ++count) { + long diff = abs((int)(s1 - s2)); + for (bit = 0; diff && bit < 32; bit++, diff >>= 1) + if ((diff & 1) && !thresh[bit]) + thresh[bit] = count + 1; + } + + if (count != (long)((leader_len + len) * rate + .5)) { + printf("incorrect file length\n"); + exit(1); + } + + for (bit = 0; bit < 32; ++bit) { + bw = ((double)thresh[bit] - 1) / rate - leader_len; + if (bit && bw >= 0 && (bw - prev) * 100 / len < .08) { + --bit; + break; + } + prev = bw; + } + bit = 32 - bit; + bw = bw * 100 / len; + printf("Bit perfect to %i bits, from DC to %.2f%% nyquist.\n", bit, bw); + return !(bit >= expect_bits && bw >= expect_bw); +} diff --git a/lib-src/libsoxr/tests/vector-gen.c b/lib-src/libsoxr/tests/vector-gen.c index d541b0d5f..06d4bac9f 100644 --- a/lib-src/libsoxr/tests/vector-gen.c +++ b/lib-src/libsoxr/tests/vector-gen.c @@ -1,56 +1,56 @@ -/* SoX Resampler Library Copyright (c) 2007-12 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Utility used to help test the library; not for general consumption. - * - * Generate a swept sine to a file, with faded `lead-in' section. */ - -#define QUAD 0 - -#if QUAD - #include -#endif - -#include "../examples/examples-common.h" - -#if QUAD - #define modf modfq - #define cos cosq - #define sin sinq - #undef M_PI - #define M_PI M_PIq - #define real __float128 - #define atof(x) strtoflt128(x, 0) -#else - #define real double - #include "rint.h" -#endif - -int main(int i, char const * argv[]) -{ - real rate = atof(argv[1]), /* Rate for this vector */ - lead_in_len = atof(argv[2]), /* Lead-in length in seconds */ - len = atof(argv[3]), /* Sweep length (excl. lead_in_len) */ - sweep_to_freq = atof(argv[4]), /* Sweep from DC to this freq. */ - multiplier = atof(argv[5]), /* For headroom */ - f1 = -sweep_to_freq / len * lead_in_len, f2 = sweep_to_freq, - n1 = rate * -lead_in_len, n2 = rate * len, - m = (f2 - f1) / (n2 - n1) / 2, dummy; - FILE * file = fopen(argv[6], "wb"); - i = (int)n1; - if (!file || i != n1) - exit(1); - for (; i < (int)(n2 + .5); ++i) { - double d1 = multiplier * sin(2 * M_PI * modf(i * m * i / rate, &dummy)); - double d = i < 0? d1 * (1 - cos(M_PI * (i + n1) / n1)) * .5 : d1; -#if QUAD - size_t actual = fwrite(&d, sizeof(d), 1, file); -#else - int32_t out = rint32(d * (32768. * 65536 - 1)); - size_t actual = fwrite(&out, sizeof(out), 1, file); -#endif - if (actual != 1) - return 1; - } - return 0; -} +/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net + * Licence for this file: LGPL v2.1 See LICENCE for details. */ + +/* Utility used to help test the library; not for general consumption. + * + * Generate a swept sine to a file, with faded `lead-in' section. */ + +#define QUAD 0 + +#if QUAD + #include +#endif + +#include "../examples/examples-common.h" + +#if QUAD + #define modf modfq + #define cos cosq + #define sin sinq + #undef M_PI + #define M_PI M_PIq + #define real __float128 + #define atof(x) strtoflt128(x, 0) +#else + #define real double + #include "rint.h" +#endif + +int main(int i, char const * argv[]) +{ + real rate = atof(argv[1]), /* Rate for this vector */ + lead_in_len = atof(argv[2]), /* Lead-in length in seconds */ + len = atof(argv[3]), /* Sweep length (excl. lead_in_len) */ + sweep_to_freq = atof(argv[4]), /* Sweep from DC to this freq. */ + multiplier = atof(argv[5]), /* For headroom */ + f1 = -sweep_to_freq / len * lead_in_len, f2 = sweep_to_freq, + n1 = rate * -lead_in_len, n2 = rate * len, + m = (f2 - f1) / (n2 - n1) / 2, dummy; + FILE * file = fopen(argv[6], "wb"); + i = (int)n1; + if (!file || i != n1) + exit(1); + for (; i < (int)(n2 + .5); ++i) { + double d1 = multiplier * sin(2 * M_PI * modf(i * m * i / rate, &dummy)); + double d = i < 0? d1 * (1 - cos(M_PI * (i + n1) / n1)) * .5 : d1; +#if QUAD + size_t actual = fwrite(&d, sizeof(d), 1, file); +#else + int32_t out = rint32(d * (32768. * 65536 - 1)); + size_t actual = fwrite(&out, sizeof(out), 1, file); +#endif + if (actual != 1) + return 1; + } + return 0; +}