mirror of https://github.com/AxioDL/boo.git
Update soxr to 0.1.3; make wasm compatible
This commit is contained in:
parent
6e4030212c
commit
39eb95a824
|
@ -73,7 +73,7 @@ endif ()
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
add_subdirectory(soxr/src)
|
add_subdirectory(soxr)
|
||||||
|
|
||||||
add_library(boo
|
add_library(boo
|
||||||
lib/audiodev/Common.hpp
|
lib/audiodev/Common.hpp
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Release*/
|
||||||
|
Debug*/
|
|
@ -1,30 +1,36 @@
|
||||||
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
cmake_minimum_required (VERSION 2.8 FATAL_ERROR)
|
cmake_minimum_required (VERSION 3.1 FATAL_ERROR)
|
||||||
cmake_policy(SET CMP0075 OLD)
|
project (soxr C)
|
||||||
|
set (DESCRIPTION_SUMMARY
|
||||||
#project (soxr C)
|
"High quality, one-dimensional sample-rate conversion library")
|
||||||
#set (DESCRIPTION_SUMMARY "High quality, one-dimensional sample-rate conversion library")
|
|
||||||
|
|
||||||
|
cmake_policy(SET CMP0075 NEW)
|
||||||
|
cmake_policy(SET CMP0115 OLD)
|
||||||
|
cmake_policy(SET CMP0127 OLD)
|
||||||
|
|
||||||
|
|
||||||
# Release versioning:
|
# Release versioning:
|
||||||
|
|
||||||
set (PROJECT_VERSION_MAJOR 0)
|
set (PROJECT_VERSION_MAJOR 0)
|
||||||
set (PROJECT_VERSION_MINOR 1)
|
set (PROJECT_VERSION_MINOR 1)
|
||||||
set (PROJECT_VERSION_PATCH 2)
|
set (PROJECT_VERSION_PATCH 3)
|
||||||
|
|
||||||
# For shared-object; if, since the last public release:
|
# For shared-object; if, since the last public release:
|
||||||
# * library code changed at all: ++revision
|
# 1) library code changed at all: ++revision
|
||||||
# * interfaces changed at all: ++current, revision = 0
|
# 2) interfaces changed at all: ++current, revision = 0
|
||||||
# * interfaces added: ++age
|
# 3) interfaces added: ++age
|
||||||
# * interfaces removed: age = 0
|
# 4) interfaces removed: age = 0
|
||||||
|
|
||||||
set (SO_VERSION_CURRENT 1)
|
set (SO_VERSION_CURRENT 1)
|
||||||
set (SO_VERSION_REVISION 1)
|
set (SO_VERSION_REVISION 2)
|
||||||
set (SO_VERSION_AGE 1)
|
set (SO_VERSION_AGE 1)
|
||||||
|
|
||||||
|
math (EXPR SO_VERSION_MAJOR "${SO_VERSION_CURRENT} - ${SO_VERSION_AGE}")
|
||||||
|
math (EXPR SO_VERSION_MINOR "${SO_VERSION_AGE}")
|
||||||
|
math (EXPR SO_VERSION_PATCH "${SO_VERSION_REVISION}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Main options:
|
# Main options:
|
||||||
|
@ -32,112 +38,147 @@ set (SO_VERSION_AGE 1)
|
||||||
include (CMakeDependentOption)
|
include (CMakeDependentOption)
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
set (CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
set (CMAKE_BUILD_TYPE Release CACHE STRING
|
||||||
|
"Build type, one of: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
#option (BUILD_TESTS "Build sanity-tests." ON)
|
option (BUILD_TESTS "Build sanity-tests." OFF)
|
||||||
#option (BUILD_SHARED_LIBS "Build shared libraries." ON)
|
option (BUILD_EXAMPLES "Build examples." OFF)
|
||||||
#option (BUILD_EXAMPLES "Build examples." OFF)
|
option (WITH_OPENMP "Include OpenMP threading." OFF)
|
||||||
option (WITH_LSR_BINDINGS "Include a `libsamplerate'-like interface." ON)
|
option (WITH_LSR_BINDINGS "Include a `libsamplerate'-like interface." OFF)
|
||||||
cmake_dependent_option (WITH_SINGLE_PRECISION "Build with single precision (for up to 20-bit accuracy)." ON
|
|
||||||
"WITH_DOUBLE_PRECISION" ON)
|
cmake_dependent_option (BUILD_SHARED_LIBS
|
||||||
cmake_dependent_option (WITH_DOUBLE_PRECISION "Build with double precision (for up to 32-bit accuracy)." ON
|
"Build shared (dynamic) soxr libraries." OFF
|
||||||
"WITH_SINGLE_PRECISION" ON)
|
"NOT WITH_DEV_GPROF" OFF)
|
||||||
cmake_dependent_option (WITH_SIMD "Use SIMD (for faster single precision)." ON
|
cmake_dependent_option (WITH_VR32
|
||||||
"WITH_SINGLE_PRECISION" OFF)
|
"Include HQ variable-rate resampling engine." ON
|
||||||
cmake_dependent_option (WITH_AVFFT "Use libavcodec (LGPL) for SIMD DFT." OFF
|
"WITH_CR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S OR NOT DEFINED WITH_VR32" ON)
|
||||||
"WITH_SIMD;NOT WITH_PFFFT" OFF)
|
cmake_dependent_option (WITH_CR32
|
||||||
cmake_dependent_option (WITH_PFFFT "Use PFFFT (BSD-like licence) for SIMD DFT." ON
|
"Include HQ constant-rate resampling engine." ON
|
||||||
"WITH_SIMD;NOT WITH_AVFFT" OFF)
|
"WITH_VR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S" ON)
|
||||||
option (SOXR_SILENT "Disable debug messages, even in debug mode" OFF)
|
cmake_dependent_option (WITH_CR64
|
||||||
if (UNIX)
|
"Include VHQ constant-rate resampling engine." ON
|
||||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/lsr-tests)
|
"WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64S" ON)
|
||||||
cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF
|
cmake_dependent_option (WITH_CR64S
|
||||||
"WITH_LSR_BINDINGS" OFF)
|
"Include VHQ SIMD constant-rate resampling engine." ON
|
||||||
endif ()
|
"WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64" ON)
|
||||||
endif ()
|
cmake_dependent_option (WITH_CR32S
|
||||||
|
"Include HQ SIMD constant-rate resampling engine." ON
|
||||||
|
"WITH_VR32 OR WITH_CR64 OR WITH_CR32 OR WITH_CR64S" ON)
|
||||||
|
cmake_dependent_option (WITH_PFFFT
|
||||||
|
"Use PFFFT (BSD-like licence) for HQ SIMD DFT." ON
|
||||||
|
"WITH_CR32S;NOT WITH_AVFFT" OFF)
|
||||||
|
cmake_dependent_option (WITH_AVFFT
|
||||||
|
"Use libavcodec (LGPL) for HQ SIMD DFT." OFF
|
||||||
|
"WITH_CR32S;NOT WITH_PFFFT" OFF)
|
||||||
|
cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF
|
||||||
|
"UNIX;NOT CMAKE_CROSSCOMPILING;EXISTS ${PROJECT_SOURCE_DIR}/lsr-tests;WITH_LSR_BINDINGS" OFF)
|
||||||
|
|
||||||
|
option (WITH_HI_PREC_CLOCK "Enable high-precision time-base." ON)
|
||||||
|
option (WITH_FLOAT_STD_PREC_CLOCK
|
||||||
|
"Use floating-point for standard-precision time-base." OFF)
|
||||||
|
option (WITH_DEV_TRACE "Enable developer trace capability." ON)
|
||||||
|
option (WITH_DEV_GPROF "Enable developer grpof output." OFF)
|
||||||
|
mark_as_advanced (WITH_HI_PREC_CLOCK WITH_FLOAT_STD_PREC_CLOCK
|
||||||
|
WITH_DEV_TRACE WITH_DEV_GPROF)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Introspection:
|
# Introspection:
|
||||||
|
|
||||||
list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
|
list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
|
||||||
|
|
||||||
include (CheckFunctionExists)
|
include (CheckFunctionExists)
|
||||||
include (CheckIncludeFiles)
|
include (CheckIncludeFiles)
|
||||||
include (CheckLibraryExists)
|
include (CheckLibraryExists)
|
||||||
include (TestBigEndian)
|
include (SetSystemProcessor)
|
||||||
|
if (NOT EMSCRIPTEN)
|
||||||
|
include(TestBigEndian)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set_system_processor ()
|
||||||
|
|
||||||
check_library_exists (m pow "" NEED_LIBM)
|
check_library_exists (m pow "" NEED_LIBM)
|
||||||
if (NEED_LIBM)
|
if (NEED_LIBM)
|
||||||
set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}")
|
set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}")
|
||||||
link_libraries (m)
|
set (LIBM_LIBRARIES m)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
#if (WITH_OPENMP)
|
if (${BUILD_EXAMPLES})
|
||||||
# find_package (OpenMP)
|
project (${PROJECT_NAME}) # Adds c++ compiler
|
||||||
# if (OPENMP_FOUND)
|
endif ()
|
||||||
# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
|
||||||
# set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
|
|
||||||
# set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_SHARED_LINKER_FLAGS}")
|
|
||||||
# endif ()
|
|
||||||
#endif ()
|
|
||||||
|
|
||||||
if (WITH_SIMD)
|
if (WITH_OPENMP)
|
||||||
find_package (SIMD)
|
find_package (OpenMP)
|
||||||
if (SIMD_FOUND)
|
if (OPENMP_FOUND)
|
||||||
set (HAVE_SIMD 1)
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||||
|
if (MINGW) # Is this still needed?
|
||||||
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
|
||||||
|
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
|
||||||
endif ()
|
endif ()
|
||||||
|
endif()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_SINGLE_PRECISION)
|
if (WITH_CR32S)
|
||||||
set (HAVE_SINGLE_PRECISION 1)
|
find_package (SIMD32)
|
||||||
|
set (WITH_CR32S ${SIMD32_FOUND})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_DOUBLE_PRECISION)
|
if (WITH_CR64S)
|
||||||
set (HAVE_DOUBLE_PRECISION 1)
|
find_package (SIMD64)
|
||||||
|
set (WITH_CR64S ${SIMD64_FOUND})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_AVFFT)
|
if (WITH_AVFFT)
|
||||||
find_package (LibAVCodec)
|
find_package (LibAVCodec REQUIRED)
|
||||||
if (AVCODEC_FOUND)
|
if (AVCODEC_FOUND)
|
||||||
include_directories (${AVCODEC_INCLUDE_DIRS})
|
include_directories (${AVCODEC_INCLUDE_DIRS})
|
||||||
link_libraries (${AVCODEC_LIBRARIES})
|
set (LIBS ${LIBS} ${AVCODEC_LIBRARIES})
|
||||||
set (HAVE_AVFFT 1)
|
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (SOXR_SILENT)
|
if (WITH_AVFFT OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND SIMD32_FOUND AND WITH_CR32))
|
||||||
add_definitions (-DSOXR_SILENT=1)
|
find_package (LibAVUtil)
|
||||||
|
if (AVUTIL_FOUND)
|
||||||
|
include_directories (${AVUTIL_INCLUDE_DIRS})
|
||||||
|
set (LIBS ${LIBS} ${AVUTIL_LIBRARIES})
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
check_function_exists (lrint HAVE_LRINT)
|
check_function_exists (lrint HAVE_LRINT)
|
||||||
check_include_files (fenv.h HAVE_FENV_H)
|
check_include_files (fenv.h HAVE_FENV_H)
|
||||||
test_big_endian (WORDS_BIGENDIAN)
|
check_include_files (stdbool.h HAVE_STDBOOL_H)
|
||||||
|
check_include_files (stdint.h HAVE_STDINT_H)
|
||||||
macro (make_exist)
|
if (EMSCRIPTEN)
|
||||||
foreach (x ${ARGN})
|
set(HAVE_BIGENDIAN OFF)
|
||||||
if (NOT ${x})
|
else()
|
||||||
set (${x} 0)
|
test_big_endian (HAVE_BIGENDIAN)
|
||||||
endif ()
|
endif()
|
||||||
endforeach ()
|
|
||||||
endmacro ()
|
|
||||||
|
|
||||||
make_exist (HAVE_LRINT HAVE_FENV_H WORDS_BIGENDIAN HAVE_SIMD)
|
|
||||||
make_exist (HAVE_SINGLE_PRECISION HAVE_DOUBLE_PRECISION HAVE_AVFFT)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Compiler configuration:
|
# Compiler configuration:
|
||||||
|
|
||||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
set (PROJECT_CXX_FLAGS "-Wconversion -Wall -W -Wundef -Wcast-align -Wpointer-arith -Wno-long-long")
|
set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wconversion -Wall -Wextra \
|
||||||
set (PROJECT_C_FLAGS "${PROJECT_CXX_FLAGS} -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes")
|
-pedantic -Wundef -Wpointer-arith -Wno-long-long")
|
||||||
|
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
|
set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wno-keyword-macro")
|
||||||
|
endif ()
|
||||||
|
if (WITH_DEV_GPROF)
|
||||||
|
set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -pg")
|
||||||
|
endif ()
|
||||||
|
# Can use std=c89, but gnu89 should give faster sinf, cosf, etc.:
|
||||||
|
set (PROJECT_C_FLAGS "${PROJECT_CXX_FLAGS} \
|
||||||
|
-std=gnu89 -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes")
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s") # strip
|
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s") # strip
|
||||||
endif ()
|
endif ()
|
||||||
cmake_dependent_option (VISIBILITY_HIDDEN "Build with -fvisibility=hidden." ON
|
cmake_dependent_option (VISIBILITY_HIDDEN
|
||||||
|
"Build shared libraries with -fvisibility=hidden." ON
|
||||||
"BUILD_SHARED_LIBS" OFF)
|
"BUILD_SHARED_LIBS" OFF)
|
||||||
|
mark_as_advanced (VISIBILITY_HIDDEN)
|
||||||
if (VISIBILITY_HIDDEN)
|
if (VISIBILITY_HIDDEN)
|
||||||
add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY)
|
add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY)
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -145,9 +186,14 @@ endif ()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
add_definitions (-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS)
|
add_definitions (-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS)
|
||||||
option (ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically." OFF)
|
option (BUILD_SHARED_RUNTIME "MSVC, link with runtime dynamically." ON)
|
||||||
if (ENABLE_STATIC_RUNTIME)
|
if (NOT BUILD_SHARED_RUNTIME)
|
||||||
foreach (flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
foreach (flag_var
|
||||||
|
CMAKE_C_FLAGS CMAKE_CXX_FLAGS
|
||||||
|
CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||||
string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||||
endforeach ()
|
endforeach ()
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -161,8 +207,9 @@ endif ()
|
||||||
|
|
||||||
# Build configuration:
|
# Build configuration:
|
||||||
|
|
||||||
if (${BUILD_SHARED_LIBS} AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows) # Allow exes to find dlls:
|
if (${BUILD_SHARED_LIBS} AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows)
|
||||||
set (BIN ${CMAKE_CURRENT_BINARY_DIR}/bin/)
|
# Allow exes to find dlls:
|
||||||
|
set (BIN ${PROJECT_BINARY_DIR}/bin/)
|
||||||
set (EXAMPLES_BIN ${BIN})
|
set (EXAMPLES_BIN ${BIN})
|
||||||
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN})
|
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN})
|
||||||
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN})
|
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN})
|
||||||
|
@ -179,6 +226,10 @@ if (BUILD_SHARED_LIBS)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "None") # As used by some distros.
|
||||||
|
add_definitions (-DNDEBUG)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Installation configuration:
|
# Installation configuration:
|
||||||
|
@ -194,7 +245,7 @@ if (NOT DEFINED INCLUDE_INSTALL_DIR)
|
||||||
endif ()
|
endif ()
|
||||||
if (NOT DEFINED DOC_INSTALL_DIR)
|
if (NOT DEFINED DOC_INSTALL_DIR)
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/libsoxr")
|
set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/lib${PROJECT_NAME}")
|
||||||
else ()
|
else ()
|
||||||
set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/doc")
|
set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/doc")
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -202,25 +253,24 @@ endif ()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
option (BUILD_FRAMEWORK "Build an OS X framework." OFF)
|
option (BUILD_FRAMEWORK "Build an OS X framework." OFF)
|
||||||
set (FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
|
set (FRAMEWORK_INSTALL_DIR
|
||||||
|
"/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Top-level:
|
# Top-level:
|
||||||
|
|
||||||
set (PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
|
set (PROJECT_VERSION
|
||||||
math (EXPR SO_VERSION_MAJOR "${SO_VERSION_CURRENT} - ${SO_VERSION_AGE}")
|
${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
|
||||||
math (EXPR SO_VERSION_MINOR "${SO_VERSION_AGE}")
|
|
||||||
math (EXPR SO_VERSION_PATCH "${SO_VERSION_REVISION}")
|
|
||||||
set (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH})
|
set (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH})
|
||||||
|
|
||||||
configure_file (
|
configure_file (
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/soxr-config.h.in
|
${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-config.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/soxr-config.h)
|
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.h)
|
||||||
include_directories (${CMAKE_CURRENT_BINARY_DIR})
|
include_directories (${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
if (BUILD_TESTS OR BUILD_LSR_TESTS)
|
if (NOT CMAKE_CROSSCOMPILING AND (BUILD_TESTS OR BUILD_LSR_TESTS))
|
||||||
enable_testing ()
|
enable_testing ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -234,7 +284,7 @@ install (FILES
|
||||||
|
|
||||||
# Subdirectories:
|
# Subdirectories:
|
||||||
|
|
||||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src)
|
include_directories (${PROJECT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
add_subdirectory (src)
|
add_subdirectory (src)
|
||||||
if (BUILD_TESTS)
|
if (BUILD_TESTS)
|
||||||
|
@ -249,55 +299,45 @@ endif ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Rough-and-ready distclean for anyone still doing in-tree builds:
|
# GNU Autotools compatibility; 'make check':
|
||||||
|
|
||||||
#if (UNIX)
|
add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||||
# add_custom_target (distclean
|
|
||||||
# COMMAND make clean && rm -rf
|
|
||||||
# CMakeCache.txt
|
|
||||||
# CMakeFiles
|
# GNU Autotools compatibility; 'make distclean':
|
||||||
# cmake_install.cmake
|
|
||||||
# CPackConfig.cmake
|
if (UNIX)
|
||||||
# CPackSourceConfig.cmake
|
add_custom_target (distclean COMMAND make clean && find .
|
||||||
# deinstall.cmake
|
\\! -path \\*/Modules/\\* \\! -name cmp-test.cmake -a -name \\*.cmake
|
||||||
# Makefile
|
-o -name CMakeFiles -o -name Makefile -o -name CMakeCache.txt -o -name
|
||||||
# soxr-config.h
|
Testing -o -name cmake_install.cmake -o -name install_manifest.txt -o
|
||||||
# src/CMakeFiles
|
-path ./soxr-config.h -o -name config.h -o -name \\*.pc -o -name \\*.s32
|
||||||
# src/cmake_install.cmake
|
| xargs rm -rf)
|
||||||
# src/libsoxr-dev.src
|
endif ()
|
||||||
# src/libsoxr-lsr.pc
|
|
||||||
# src/libsoxr.pc
|
|
||||||
# src/libsoxr.src
|
|
||||||
# src/Makefile)
|
|
||||||
#endif ()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Deinstallation:
|
# Deinstallation:
|
||||||
|
|
||||||
#configure_file (
|
configure_file (
|
||||||
# "${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in"
|
"${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in"
|
||||||
# "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake"
|
||||||
# IMMEDIATE @ONLY)
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
#add_custom_target (deinstall
|
add_custom_target (deinstall
|
||||||
# COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake")
|
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Packaging:
|
# Packaging:
|
||||||
|
|
||||||
#if (UNIX)
|
if (UNIX)
|
||||||
# set (CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
set (CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||||
# set (CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
set (CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||||
# set (CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
set (CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
||||||
#
|
set (CPACK_SOURCE_GENERATOR "TXZ")
|
||||||
# set (CPACK_SOURCE_GENERATOR "TGZ")
|
set (CPACK_SOURCE_IGNORE_FILES
|
||||||
# set (CPACK_SOURCE_IGNORE_FILES "dist;/lsr-tests/;/Debug/;/Release/;/cpack/;\\\\.swp$;\\\\.gitignore;/\\\\.git/")
|
"dist;/lsr-tests/;/Debug.*/;/Release.*/;\\\\.swp$;\\\\.git.*;/\\\\.git/")
|
||||||
#
|
include (CPack)
|
||||||
# include (CPack)
|
endif ()
|
||||||
#
|
|
||||||
# if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cpack)
|
|
||||||
# add_subdirectory (cpack)
|
|
||||||
# endif ()
|
|
||||||
#endif ()
|
|
||||||
|
|
96
soxr/INSTALL
96
soxr/INSTALL
|
@ -1,11 +1,12 @@
|
||||||
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
|
||||||
INSTALLATION GUIDE CONTENTS
|
INSTALLATION GUIDE CONTENTS
|
||||||
|
|
||||||
* Standard build
|
* Standard build
|
||||||
* Build customisation
|
* Build customisation
|
||||||
* Cross-compiling with mingw (linux host)
|
* Cross-compilation
|
||||||
* Integration with other build systems
|
* Integration with other build systems
|
||||||
|
* Run-time configuration
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ STANDARD BUILD
|
||||||
|
|
||||||
* A 'make' utility (most compiler installations already have one of these).
|
* A 'make' utility (most compiler installations already have one of these).
|
||||||
|
|
||||||
* CMake: http://www.cmake.org/cmake/resources/software.html
|
* CMake v3.0 or newer: https://cmake.org/download/
|
||||||
|
|
||||||
|
|
||||||
2. Build:
|
2. Build:
|
||||||
|
@ -30,7 +31,7 @@ STANDARD BUILD
|
||||||
|
|
||||||
go (on MS-Windows with nmake)
|
go (on MS-Windows with nmake)
|
||||||
or
|
or
|
||||||
./go (on unix-like systems)
|
./go (on Unix-like systems)
|
||||||
|
|
||||||
This should build the library and run a few sanity tests.
|
This should build the library and run a few sanity tests.
|
||||||
|
|
||||||
|
@ -38,14 +39,14 @@ STANDARD BUILD
|
||||||
3. Installation:
|
3. Installation:
|
||||||
|
|
||||||
Note that this step may need to be performed by a system
|
Note that this step may need to be performed by a system
|
||||||
adminstrator. Enter:
|
administrator. Enter:
|
||||||
|
|
||||||
nmake install (on MS-Windows)
|
nmake install (on MS-Windows)
|
||||||
or
|
or
|
||||||
cd Release; make install (on unix)
|
cd Release; make install (on Unix-like)
|
||||||
|
|
||||||
|
|
||||||
4. Configuration:
|
4. Preparation for use:
|
||||||
|
|
||||||
To use the library you may need to set up appropriate paths to the
|
To use the library you may need to set up appropriate paths to the
|
||||||
library and its header file in your development environment.
|
library and its header file in your development environment.
|
||||||
|
@ -60,38 +61,74 @@ STANDARD BUILD
|
||||||
|
|
||||||
BUILD CUSTOMISATION
|
BUILD CUSTOMISATION
|
||||||
|
|
||||||
If it is necessary to customise the build, then steps 2 and 3 above may be
|
If it is necessary to customise the build, then steps 2 and 3 above should be
|
||||||
substituted as follows. Change directory to the one containing this file,
|
substituted as follows: change directory to the one containing this file, then
|
||||||
then enter commands along the lines of:
|
enter commands along the lines:
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake [OPTIONS] ..
|
cmake -Wno-dev -DCMAKE_BUILD_TYPE=Release [OPTIONS] ..
|
||||||
make
|
make
|
||||||
make test
|
make test
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
||||||
|
N.B. The CMAKE_BUILD_TYPE to use for library deployment is Release.
|
||||||
|
|
||||||
To list help on the available options, enter:
|
To list help on the available options, enter:
|
||||||
|
|
||||||
cmake -LH ..
|
cmake -LH ..
|
||||||
|
|
||||||
Options, if given, should be preceded with '-D', e.g.
|
Options, if given, should be preceded with '-D', e.g.
|
||||||
|
|
||||||
cmake -DWITH_SIMD:BOOL=OFF ..
|
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CROSS-COMPILING WITH MINGW (LINUX HOST)
|
Resampling engines
|
||||||
|
|
||||||
For example:
|
As available on a given system, options for including up-to five resampling
|
||||||
|
‘engines’ are available (per above) as follows:
|
||||||
|
|
||||||
|
WITH_CR32: for constant-rate HQ resampling,
|
||||||
|
WITH_CR32S: SIMD variant of previous,
|
||||||
|
WITH_CR64: for constant-rate VHQ resampling,
|
||||||
|
WITH_CR64S: SIMD variant of previous,
|
||||||
|
WITH_VR32: for variable-rate HQ resampling.
|
||||||
|
|
||||||
|
By default, these options are all set to ON.
|
||||||
|
|
||||||
|
When both SIMD and non-SIMD engine variants are included, run-time selection
|
||||||
|
is automatic (based on CPU capability) for x86 CPUs, and can be automatic for
|
||||||
|
ARM CPUs if the 3rd-party library `libavutil' is available at libsoxr
|
||||||
|
build-time. Which engine has been selected for a specific configuration and
|
||||||
|
invocation of the library can be checked using example #3, which reports it.
|
||||||
|
See also Run-time Configuration, below.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CROSS-COMPILATION
|
||||||
|
|
||||||
|
E.g. targeting a Linux ARM system:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_SYSTEM_NAME=Linux \
|
||||||
|
-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
|
||||||
|
..
|
||||||
|
or, also building the examples (one of which uses C++):
|
||||||
|
|
||||||
|
cmake -DCMAKE_SYSTEM_NAME=Linux \
|
||||||
|
-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \
|
||||||
|
-DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \
|
||||||
|
-DBUILD_EXAMPLES=1 \
|
||||||
|
..
|
||||||
|
|
||||||
|
E.g. with Mingw (Linux host), using a tool-chain file:
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-x86_64-mingw-w64-mingw32.cmake \
|
cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-x86_64-mingw-w64-mingw32.cmake \
|
||||||
-DCMAKE_INSTALL_PREFIX=install \
|
-DCMAKE_INSTALL_PREFIX=install \
|
||||||
-DHAVE_WORDS_BIGENDIAN_EXITCODE=1 \
|
|
||||||
-DBUILD_TESTS=0 \
|
|
||||||
-DBUILD_EXAMPLES=1 \
|
|
||||||
..
|
..
|
||||||
make
|
make
|
||||||
|
|
||||||
|
@ -120,4 +157,27 @@ Autotools-based systems might find it useful to create a file called
|
||||||
cmake -DBUILD_SHARED_LIBS=OFF .
|
cmake -DBUILD_SHARED_LIBS=OFF .
|
||||||
(or with other build options as required).
|
(or with other build options as required).
|
||||||
|
|
||||||
For MS visual studio, see msvc/README
|
For MS Visual Studio, see msvc/README.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RUN-TIME CONFIGURATION
|
||||||
|
|
||||||
|
The libsoxr API structure ‘soxr_runtime_spec_t’ allows application developers
|
||||||
|
to optimise some aspects of libsoxr’s operation for a particular application.
|
||||||
|
Optimal performance however, might depend on an individual end-user’s run-
|
||||||
|
time system and the end-user’s preferences. Hence environment variables are
|
||||||
|
available to set (override) run-time parameters as follows:
|
||||||
|
|
||||||
|
Env. variable Equivalent soxr_runtime_spec_t item (see soxr.h)
|
||||||
|
------------------ -----------------------------------
|
||||||
|
SOXR_COEFS_SIZE coef_size_kbytes
|
||||||
|
SOXR_COEF_INTERP SOXR_COEF_INTERP_xxx
|
||||||
|
SOXR_LARGE_DFT_SIZE log2_large_dft_size
|
||||||
|
SOXR_MIN_DFT_SIZE log2_min_dft_size
|
||||||
|
SOXR_NUM_THREADS num_threads
|
||||||
|
|
||||||
|
Additionally, the SOXR_USE_SIMD32 and SOXR_USE_SIMD64 boolean environment
|
||||||
|
variables can be used to override automatic selection (or to provide manual
|
||||||
|
selection where automatic selection is not available) between SIMD and
|
||||||
|
non-SIMD engine variants.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or modify it
|
This library is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU Lesser General Public License as published by
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -11,8 +11,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||||
General Public License for more details.
|
General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this library; if not, write to the Free Software Foundation,
|
along with this library; if not, see <https://www.gnu.org/licenses/>.
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
Version 0.1.3 (2018-02-24)
|
||||||
|
* SIMD enhancements: SSE, AVX, Neon.
|
||||||
|
* Improve support for clang, ARM, and cross-compilation.
|
||||||
|
* Provide env. var. override of runtime parameters.
|
||||||
|
* Build fix re cmake variables AVCODEC_INCLUDE_DIRS & AVUTIL_INCLUDE_DIRS.
|
||||||
|
* Build options WITH_SINGLE_PRECISION, WITH_DOUBLE_PRECISION & WITH_SIMD have
|
||||||
|
been removed; replacement options are detailed in INSTALL, `Resampling
|
||||||
|
engines'.
|
||||||
|
|
||||||
Version 0.1.2 (2015-09-05)
|
Version 0.1.2 (2015-09-05)
|
||||||
* Fix conversion failure when I/O types differ but I/O rates don't.
|
* Fix conversion failure when I/O types differ but I/O rates don't.
|
||||||
* Fix #defines for interpolation order selection.
|
* Fix #defines for interpolation order selection.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
|
|
||||||
The SoX Resampler library `libsoxr' performs one-dimensional sample-rate
|
The SoX Resampler library `libsoxr' performs one-dimensional sample-rate
|
||||||
conversion -- it may be used, for example, to resample PCM-encoded audio.
|
conversion -- it may be used, for example, to resample PCM-encoded audio.
|
||||||
|
@ -46,7 +46,7 @@ size configuration parameters may be used to reduce this figure).
|
||||||
For build and installation instructions, see the file `INSTALL'; for
|
For build and installation instructions, see the file `INSTALL'; for
|
||||||
copyright and licensing information, see the file `LICENCE'.
|
copyright and licensing information, see the file `LICENCE'.
|
||||||
|
|
||||||
For support and new versions, see http://soxr.sourceforge.net
|
For support and new versions, see https://soxr.sourceforge.net
|
||||||
________
|
________
|
||||||
¹ For example, multi-channel resampling can utilise multiple CPU-cores.
|
¹ For example, multi-channel resampling can utilise multiple CPU-cores.
|
||||||
² Bit-perfect within practical occupied-bandwidth limits.
|
² Bit-perfect within practical occupied-bandwidth limits.
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
* SOXR_ALLOW_ALIASING
|
* vr32s
|
||||||
* Explicit flush API fn, perhaps.
|
* vr32 with 1-delay-clear
|
||||||
* More SIMD.
|
* fir_to_phase with RDFT32
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# - Function to find C compiler feature flags
|
||||||
|
|
||||||
|
include (CheckCSourceCompiles)
|
||||||
|
include (FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
function (FindCFlags PKG_NAME PKG_DESC TRIAL_C_FLAGS TEST_C_SOURCE)
|
||||||
|
|
||||||
|
foreach (TRIAL_C_FLAG ${TRIAL_C_FLAGS})
|
||||||
|
message (STATUS "Trying ${PKG_NAME} C flags: ${TRIAL_C_FLAG}")
|
||||||
|
unset (DETECT_${PKG_NAME}_C_FLAGS CACHE) #displayed by check_c_source_compiles
|
||||||
|
|
||||||
|
set (TMP "${CMAKE_REQUIRED_FLAGS}")
|
||||||
|
set (CMAKE_REQUIRED_FLAGS "${TRIAL_C_FLAG}")
|
||||||
|
check_c_source_compiles ("${TEST_C_SOURCE}" DETECT_${PKG_NAME}_C_FLAGS)
|
||||||
|
set (CMAKE_REQUIRED_FLAGS "${TMP}")
|
||||||
|
|
||||||
|
if (DETECT_${PKG_NAME}_C_FLAGS)
|
||||||
|
set (DETECTED_C_FLAGS "${TRIAL_C_FLAG}")
|
||||||
|
break ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# N.B. Will not overwrite existing cache variable:
|
||||||
|
set (${PKG_NAME}_C_FLAGS "${DETECTED_C_FLAGS}"
|
||||||
|
CACHE STRING "C compiler flags for ${PKG_DESC}")
|
||||||
|
|
||||||
|
find_package_handle_standard_args (
|
||||||
|
${PKG_NAME} DEFAULT_MSG ${PKG_NAME}_C_FLAGS ${PKG_NAME}_C_FLAGS)
|
||||||
|
mark_as_advanced (${PKG_NAME}_C_FLAGS)
|
||||||
|
set (${PKG_NAME}_FOUND ${${PKG_NAME}_FOUND} PARENT_SCOPE)
|
||||||
|
|
||||||
|
endfunction ()
|
|
@ -1,23 +1,23 @@
|
||||||
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
# - Find AVCODEC
|
# - Find AVCODEC
|
||||||
# Find the native installation of this package: includes and libraries.
|
# Find the installation of this package: include-dirs and libraries.
|
||||||
#
|
#
|
||||||
# AVCODEC_INCLUDES - where to find headers for this package.
|
# AVCODEC_INCLUDE_DIRS - where to find headers for this package.
|
||||||
# AVCODEC_LIBRARIES - List of libraries when using this package.
|
# AVCODEC_LIBRARIES - libraries to link to when using this package.
|
||||||
# AVCODEC_FOUND - True if this package can be found.
|
# AVCODEC_FOUND - true iff this package can be found.
|
||||||
|
|
||||||
if (AVCODEC_INCLUDES)
|
if (AVCODEC_INCLUDE_DIRS)
|
||||||
set (AVCODEC_FIND_QUIETLY TRUE)
|
set (AVCODEC_FIND_QUIETLY TRUE)
|
||||||
endif (AVCODEC_INCLUDES)
|
endif ()
|
||||||
|
|
||||||
find_path (AVCODEC_INCLUDES libavcodec/avcodec.h)
|
find_path (AVCODEC_INCLUDE_DIRS libavcodec/avcodec.h)
|
||||||
|
|
||||||
find_library (AVCODEC_LIBRARIES NAMES avcodec)
|
find_library (AVCODEC_LIBRARIES NAMES avcodec)
|
||||||
|
|
||||||
include (FindPackageHandleStandardArgs)
|
include (FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args (
|
find_package_handle_standard_args (
|
||||||
AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDES)
|
AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIRS)
|
||||||
|
|
||||||
mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDES)
|
mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIRS)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# - Find AVUTIL
|
||||||
|
# Find the installation of this package: includes and libraries.
|
||||||
|
#
|
||||||
|
# AVUTIL_INCLUDE_DIRS - where to find headers for this package.
|
||||||
|
# AVUTIL_LIBRARIES - libraries to link to when using this package.
|
||||||
|
# AVUTIL_FOUND - true iff this package can be found.
|
||||||
|
|
||||||
|
if (AVUTIL_INCLUDE_DIRS)
|
||||||
|
set (AVUTIL_FIND_QUIETLY TRUE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_path (AVUTIL_INCLUDE_DIRS libavutil/cpu.h)
|
||||||
|
|
||||||
|
find_library (AVUTIL_LIBRARIES NAMES avutil)
|
||||||
|
|
||||||
|
include (FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args (
|
||||||
|
AVUTIL DEFAULT_MSG AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
mark_as_advanced (AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIRS)
|
|
@ -1,115 +0,0 @@
|
||||||
# - Finds OpenMP support
|
|
||||||
# This module can be used to detect OpenMP support in a compiler.
|
|
||||||
# If the compiler supports OpenMP, the flags required to compile with
|
|
||||||
# openmp support are set.
|
|
||||||
#
|
|
||||||
# The following variables are set:
|
|
||||||
# OpenMP_C_FLAGS - flags to add to the C compiler for OpenMP support
|
|
||||||
# OPENMP_FOUND - true if openmp is detected
|
|
||||||
#
|
|
||||||
# Supported compilers can be found at http://openmp.org/wp/openmp-compilers/
|
|
||||||
#
|
|
||||||
# Modifications for soxr:
|
|
||||||
# * don't rely on presence of C++ compiler
|
|
||||||
# * support MINGW
|
|
||||||
#
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2009 Kitware, Inc.
|
|
||||||
# Copyright 2008-2009 André Rigland Brodtkorb <Andre.Brodtkorb@ifi.uio.no>
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are
|
|
||||||
# met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# * The names of Kitware, Inc., the Insight Consortium, or the names of
|
|
||||||
# any consortium members, or of any contributors, may not be used to
|
|
||||||
# endorse or promote products derived from this software without
|
|
||||||
# specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
include (CheckCSourceCompiles)
|
|
||||||
include (FindPackageHandleStandardArgs)
|
|
||||||
|
|
||||||
set (OpenMP_C_FLAG_CANDIDATES
|
|
||||||
#Gnu
|
|
||||||
"-fopenmp"
|
|
||||||
#Microsoft Visual Studio
|
|
||||||
"/openmp"
|
|
||||||
#Intel windows
|
|
||||||
"-Qopenmp"
|
|
||||||
#Intel
|
|
||||||
"-openmp"
|
|
||||||
#Empty, if compiler automatically accepts openmp
|
|
||||||
" "
|
|
||||||
#Sun
|
|
||||||
"-xopenmp"
|
|
||||||
#HP
|
|
||||||
"+Oopenmp"
|
|
||||||
#IBM XL C/c++
|
|
||||||
"-qsmp"
|
|
||||||
#Portland Group
|
|
||||||
"-mp"
|
|
||||||
)
|
|
||||||
|
|
||||||
# sample openmp source code to test
|
|
||||||
set (OpenMP_C_TEST_SOURCE
|
|
||||||
"
|
|
||||||
#include <omp.h>
|
|
||||||
int main() {
|
|
||||||
#ifdef _OPENMP
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
breaks_on_purpose
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
")
|
|
||||||
# if these are set then do not try to find them again,
|
|
||||||
# by avoiding any try_compiles for the flags
|
|
||||||
if (DEFINED OpenMP_C_FLAGS)
|
|
||||||
set (OpenMP_C_FLAG_CANDIDATES)
|
|
||||||
endif (DEFINED OpenMP_C_FLAGS)
|
|
||||||
|
|
||||||
# check c compiler
|
|
||||||
foreach (FLAG ${OpenMP_C_FLAG_CANDIDATES})
|
|
||||||
set (SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
|
||||||
set (CMAKE_REQUIRED_FLAGS "${FLAG}")
|
|
||||||
unset (OpenMP_FLAG_DETECTED CACHE)
|
|
||||||
message (STATUS "Try OpenMP C flag = [${FLAG}]")
|
|
||||||
check_c_source_compiles ("${OpenMP_C_TEST_SOURCE}" OpenMP_FLAG_DETECTED)
|
|
||||||
set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
|
||||||
if (OpenMP_FLAG_DETECTED)
|
|
||||||
set (OpenMP_C_FLAGS_INTERNAL "${FLAG}")
|
|
||||||
break ()
|
|
||||||
endif (OpenMP_FLAG_DETECTED)
|
|
||||||
endforeach (FLAG ${OpenMP_C_FLAG_CANDIDATES})
|
|
||||||
|
|
||||||
set (OpenMP_C_FLAGS "${OpenMP_C_FLAGS_INTERNAL}"
|
|
||||||
CACHE STRING "C compiler flags for OpenMP parallization")
|
|
||||||
|
|
||||||
# handle the standard arguments for find_package
|
|
||||||
find_package_handle_standard_args (OpenMP DEFAULT_MSG
|
|
||||||
OpenMP_C_FLAGS)
|
|
||||||
|
|
||||||
if (MINGW)
|
|
||||||
set (OpenMP_SHARED_LINKER_FLAGS "${OpenMP_SHARED_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
|
|
||||||
set (OpenMP_EXE_LINKER_FLAGS "${OpenMP_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
mark_as_advanced (OpenMP_C_FLAGS OpenMP_SHARED_LINKER_FLAGS OpenMP_EXE_LINKER_FLAGS)
|
|
|
@ -1,94 +0,0 @@
|
||||||
# - Finds SIMD support
|
|
||||||
#
|
|
||||||
# The following variables are set:
|
|
||||||
# SIMD_C_FLAGS - flags to add to the C compiler for this package.
|
|
||||||
# SIMD_FOUND - true if support for this package is found.
|
|
||||||
#
|
|
||||||
#=============================================================================
|
|
||||||
# Based on FindOpenMP.cmake, which is:
|
|
||||||
#
|
|
||||||
# Copyright 2009 Kitware, Inc.
|
|
||||||
# Copyright 2008-2009 André Rigland Brodtkorb <Andre.Brodtkorb@ifi.uio.no>
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are
|
|
||||||
# met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# * The names of Kitware, Inc., the Insight Consortium, or the names of
|
|
||||||
# any consortium members, or of any contributors, may not be used to
|
|
||||||
# endorse or promote products derived from this software without
|
|
||||||
# specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
include (CheckCSourceCompiles)
|
|
||||||
include (FindPackageHandleStandardArgs)
|
|
||||||
|
|
||||||
if (WIN32) # Safety for when mixed lib/app compilers (but performance hit)
|
|
||||||
set (GCC_WIN32_SIMD_OPTS "-mincoming-stack-boundary=2")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set (SIMD_C_FLAG_CANDIDATES
|
|
||||||
# x64
|
|
||||||
" "
|
|
||||||
# Microsoft Visual Studio x86
|
|
||||||
"/arch:SSE /fp:fast -D__SSE__"
|
|
||||||
# Gcc x86
|
|
||||||
"-msse -mfpmath=sse ${GCC_WIN32_SIMD_OPTS}"
|
|
||||||
# Gcc x86 (old versions)
|
|
||||||
"-msse -mfpmath=sse"
|
|
||||||
)
|
|
||||||
|
|
||||||
set (SIMD_C_TEST_SOURCE
|
|
||||||
"
|
|
||||||
#include <xmmintrin.h>
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
__m128 a, b;
|
|
||||||
float vals[4] = {0};
|
|
||||||
a = _mm_loadu_ps (vals);
|
|
||||||
b = a;
|
|
||||||
b = _mm_add_ps (a,b);
|
|
||||||
_mm_storeu_ps (vals,b);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
")
|
|
||||||
|
|
||||||
if (DEFINED SIMD_C_FLAGS)
|
|
||||||
set (SIMD_C_FLAG_CANDIDATES)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
foreach (FLAG ${SIMD_C_FLAG_CANDIDATES})
|
|
||||||
set (SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
|
||||||
set (CMAKE_REQUIRED_FLAGS "${FLAG}")
|
|
||||||
unset (SIMD_FLAG_DETECTED CACHE)
|
|
||||||
message (STATUS "Try SIMD C flag = [${FLAG}]")
|
|
||||||
check_c_source_compiles ("${SIMD_C_TEST_SOURCE}" SIMD_FLAG_DETECTED)
|
|
||||||
set (CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
|
||||||
if (SIMD_FLAG_DETECTED)
|
|
||||||
set (SIMD_C_FLAGS_INTERNAL "${FLAG}")
|
|
||||||
break ()
|
|
||||||
endif ()
|
|
||||||
endforeach ()
|
|
||||||
|
|
||||||
set (SIMD_C_FLAGS "${SIMD_C_FLAGS_INTERNAL}"
|
|
||||||
CACHE STRING "C compiler flags for SIMD vectorization")
|
|
||||||
|
|
||||||
find_package_handle_standard_args (SIMD DEFAULT_MSG SIMD_C_FLAGS SIMD_C_FLAGS)
|
|
||||||
mark_as_advanced (SIMD_C_FLAGS)
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# - Finds SIMD32 support
|
||||||
|
#
|
||||||
|
# The following variables are set:
|
||||||
|
# SIMD32_C_FLAGS - flags to add to the C compiler for this package.
|
||||||
|
# SIMD32_FOUND - true if support for this package is found.
|
||||||
|
|
||||||
|
if (DEFINED SIMD32_C_FLAGS)
|
||||||
|
set (TRIAL_C_FLAGS)
|
||||||
|
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
|
||||||
|
set (TRIAL_C_FLAGS
|
||||||
|
# Gcc
|
||||||
|
"-mfpu=neon-vfpv4 -mcpu=cortex-a7"
|
||||||
|
"-mfpu=neon -mfloat-abi=hard"
|
||||||
|
"-mfpu=neon -mfloat-abi=softfp"
|
||||||
|
"-mfpu=neon -mfloat-abi=soft"
|
||||||
|
)
|
||||||
|
set (TEST_C_SOURCE "
|
||||||
|
#include <arm_neon.h>
|
||||||
|
int main(int c, char * * v) {
|
||||||
|
float32x4_t a = vdupq_n_f32((float)c), b = vdupq_n_f32((float)!!v);
|
||||||
|
return !vgetq_lane_u32(vceqq_f32(a,b),0);
|
||||||
|
}
|
||||||
|
")
|
||||||
|
else ()
|
||||||
|
if (WIN32) # Safety for when mixed lib/app compilers (but performance hit)
|
||||||
|
set (GCC_WIN32_SIMD32_OPTS "-mincoming-stack-boundary=2")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set (TRIAL_C_FLAGS
|
||||||
|
# x64
|
||||||
|
" "
|
||||||
|
# MSVC x86
|
||||||
|
"/arch:SSE /fp:fast -D__SSE__"
|
||||||
|
# Gcc x86
|
||||||
|
"-msse -mfpmath=sse ${GCC_WIN32_SIMD32_OPTS}"
|
||||||
|
# Gcc x86 (old versions)
|
||||||
|
"-msse -mfpmath=sse"
|
||||||
|
)
|
||||||
|
set (TEST_C_SOURCE "
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
int main(int c, char * * v) {
|
||||||
|
__m128 a = _mm_set_ss((float)c), b = _mm_set_ss((float)!!v);
|
||||||
|
return _mm_comineq_ss(a,b);
|
||||||
|
}
|
||||||
|
")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include (FindCFlags)
|
||||||
|
|
||||||
|
FindCFlags ("SIMD32" "FLOAT-32 (single-precision) SIMD vectorization"
|
||||||
|
"${TRIAL_C_FLAGS}" "${TEST_C_SOURCE}")
|
|
@ -0,0 +1,29 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# - Finds SIMD64 support
|
||||||
|
#
|
||||||
|
# The following variables are set:
|
||||||
|
# SIMD64_C_FLAGS - flags to add to the C compiler for this package.
|
||||||
|
# SIMD64_FOUND - true if support for this package is found.
|
||||||
|
|
||||||
|
if (DEFINED SIMD64_C_FLAGS OR CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
|
||||||
|
set (TRIAL_C_FLAGS)
|
||||||
|
else ()
|
||||||
|
set (TRIAL_C_FLAGS
|
||||||
|
"-mavx" # Gcc
|
||||||
|
"/arch:AVX" # MSVC
|
||||||
|
)
|
||||||
|
set (TEST_C_SOURCE "
|
||||||
|
#ifndef __AVX__
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
#include <immintrin.h>
|
||||||
|
int main() {return 0;}
|
||||||
|
")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include (FindCFlags)
|
||||||
|
|
||||||
|
FindCFlags ("SIMD64" "FLOAT-64 (double-precision) SIMD vectorization"
|
||||||
|
"${TRIAL_C_FLAGS}" "${TEST_C_SOURCE}")
|
|
@ -0,0 +1,37 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# Sets CMAKE_SYSTEM_PROCESSOR for cross-compiling.
|
||||||
|
|
||||||
|
macro (set_system_processor)
|
||||||
|
if (CMAKE_CROSSCOMPILING)
|
||||||
|
if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "unknown")
|
||||||
|
unset(CMAKE_SYSTEM_PROCESSOR)
|
||||||
|
endif ()
|
||||||
|
if (NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
|
||||||
|
include (CheckCSourceCompiles)
|
||||||
|
set (CPU_LINES
|
||||||
|
"#if defined __x86_64__ || defined _M_X64 /*\;x86_64\;*/"
|
||||||
|
"#if defined __i386__ || defined _M_IX86 /*\;x86_32\;*/"
|
||||||
|
"#if defined __arm__ || defined _M_ARM /*\;arm\;*/"
|
||||||
|
)
|
||||||
|
foreach (CPU_LINE ${CPU_LINES})
|
||||||
|
string (CONCAT CPU_SOURCE "${CPU_LINE}" "
|
||||||
|
int main() {return 0;}
|
||||||
|
#endif
|
||||||
|
")
|
||||||
|
unset (SYSTEM_PROCESSOR_DETECTED CACHE)
|
||||||
|
check_c_source_compiles ("${CPU_SOURCE}" SYSTEM_PROCESSOR_DETECTED)
|
||||||
|
if (SYSTEM_PROCESSOR_DETECTED)
|
||||||
|
list (GET CPU_LINE 1 CMAKE_SYSTEM_PROCESSOR)
|
||||||
|
message (STATUS "CMAKE_SYSTEM_PROCESSOR is ${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
break ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# N.B. Will not overwrite existing cache variable:
|
||||||
|
set (CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}"
|
||||||
|
CACHE STRING "Target system processor")
|
||||||
|
endif ()
|
||||||
|
endmacro ()
|
|
@ -1,15 +0,0 @@
|
||||||
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
|
||||||
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
|
||||||
|
|
||||||
# - Macro to determine endian type
|
|
||||||
# test_big_endian (VARIABLE)
|
|
||||||
# VARIABLE - variable to store the result to
|
|
||||||
|
|
||||||
macro (test_big_endian VARIABLE)
|
|
||||||
if ("${HAVE_${VARIABLE}}" MATCHES "^${HAVE_${VARIABLE}}$")
|
|
||||||
include (CheckCSourceRuns)
|
|
||||||
check_c_source_runs ("int main() {union {long i; char c[sizeof(long)];}
|
|
||||||
const u = {1}; return !!u.c[0];}" HAVE_${VARIABLE})
|
|
||||||
set (${VARIABLE} "${HAVE_${VARIABLE}}" CACHE INTERNAL "1 if system is big endian" FORCE)
|
|
||||||
endif ()
|
|
||||||
endmacro ()
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# Makes the distribution tarball
|
||||||
|
|
||||||
|
test $# = 1 -o `git status -s|wc -c` = 0
|
||||||
|
rm -rf Release
|
||||||
|
./go -j4
|
||||||
|
cd Release
|
||||||
|
make package_source
|
|
@ -25,7 +25,7 @@ const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */
|
||||||
|
|
||||||
int main(int argc, char const * arg[])
|
int main(int argc, char const * arg[])
|
||||||
{
|
{
|
||||||
double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */
|
double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */
|
||||||
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
|
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
|
||||||
|
|
||||||
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */
|
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */
|
||||||
|
|
|
@ -12,7 +12,7 @@ float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */
|
||||||
|
|
||||||
int main(int argc, char const * arg[])
|
int main(int argc, char const * arg[])
|
||||||
{
|
{
|
||||||
double irate = argc > 1? atof(arg[1]) : 1; /* Default to upsampling */
|
double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */
|
||||||
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
|
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
|
||||||
|
|
||||||
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */
|
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
/* Example 3: extends example 2 with multiple channels, multiple datatypes,
|
/* Example 3: extends example 2 with multiple channels, multiple datatypes,
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
* OUTPUT-RATE Ditto
|
* OUTPUT-RATE Ditto
|
||||||
* NUM-CHANNELS Number of interleaved channels
|
* NUM-CHANNELS Number of interleaved channels
|
||||||
* IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16
|
* IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16
|
||||||
* OUT-DATATYPE# Ditto
|
* OUT-DATATYPE# Ditto; or 11 for un-dithered int16
|
||||||
* Q-RECIPE Quality recipe (in hex) See soxr.h
|
* Q-RECIPE Quality recipe (in hex) See soxr.h
|
||||||
* Q-FLAGS Quality flags (in hex) See soxr.h
|
* Q-FLAGS Quality flags (in hex) See soxr.h
|
||||||
* PASSBAND-END %
|
* PASSBAND-END %
|
||||||
|
@ -42,7 +42,7 @@ static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len)
|
||||||
|
|
||||||
int main(int n, char const * arg[])
|
int main(int n, char const * arg[])
|
||||||
{
|
{
|
||||||
char const * const arg0 = n? --n, *arg++ : "";
|
char const * const arg0 = n? --n, *arg++ : "", * engine = "";
|
||||||
double const irate = n? --n, atof(*arg++) : 96000.;
|
double const irate = n? --n, atof(*arg++) : 96000.;
|
||||||
double const orate = n? --n, atof(*arg++) : 44100.;
|
double const orate = n? --n, atof(*arg++) : 44100.;
|
||||||
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
|
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
|
||||||
|
@ -94,6 +94,7 @@ int main(int n, char const * arg[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error) { /* If all is well, run the resampler: */
|
if (!error) { /* If all is well, run the resampler: */
|
||||||
|
engine = soxr_engine(soxr);
|
||||||
USE_STD_STDIO;
|
USE_STD_STDIO;
|
||||||
/* Resample in blocks: */
|
/* Resample in blocks: */
|
||||||
do odone = soxr_output(soxr, obuf, olen);
|
do odone = soxr_output(soxr, obuf, olen);
|
||||||
|
@ -106,8 +107,8 @@ int main(int n, char const * arg[])
|
||||||
soxr_delete(soxr);
|
soxr_delete(soxr);
|
||||||
free(obuf), free(ibuf);
|
free(obuf), free(ibuf);
|
||||||
/* Diagnostics: */
|
/* Diagnostics: */
|
||||||
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n",
|
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%s)\n",
|
||||||
arg0, soxr_strerror(error), (long unsigned)clips,
|
arg0, soxr_strerror(error), (long unsigned)clips,
|
||||||
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error");
|
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine);
|
||||||
return !!error;
|
return !!error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
/* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels.
|
/* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels.
|
||||||
|
@ -13,6 +13,8 @@
|
||||||
*
|
*
|
||||||
* Note also (not shown in the examples) that split/interleaved channels may
|
* Note also (not shown in the examples) that split/interleaved channels may
|
||||||
* be used for input and output independently.
|
* be used for input and output independently.
|
||||||
|
*
|
||||||
|
* Arguments are as example 3.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <soxr.h>
|
#include <soxr.h>
|
||||||
|
@ -73,13 +75,17 @@ int main(int n, char const * arg[])
|
||||||
double const orate = n? --n, atof(*arg++) : 44100.;
|
double const orate = n? --n, atof(*arg++) : 44100.;
|
||||||
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
|
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
|
||||||
soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
||||||
soxr_datatype_t const otype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
||||||
unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ;
|
unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ;
|
||||||
unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0;
|
unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0;
|
||||||
|
double const passband_end = n? --n, atof(*arg++) : 0;
|
||||||
|
double const stopband_begin = n? --n, atof(*arg++) : 0;
|
||||||
|
double const phase_response = n? --n, atof(*arg++) : -1;
|
||||||
int const use_threads = n? --n, atoi(*arg++) : 1;
|
int const use_threads = n? --n, atoi(*arg++) : 1;
|
||||||
|
soxr_datatype_t const otype = ospec & 3;
|
||||||
|
|
||||||
soxr_quality_spec_t const q_spec = soxr_quality_spec(q_recipe, q_flags);
|
soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags);
|
||||||
soxr_io_spec_t const io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT);
|
soxr_io_spec_t io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT);
|
||||||
soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads);
|
soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads);
|
||||||
|
|
||||||
/* Allocate resampling input and output buffers in proportion to the input
|
/* Allocate resampling input and output buffers in proportion to the input
|
||||||
|
@ -102,11 +108,18 @@ int main(int n, char const * arg[])
|
||||||
|
|
||||||
size_t odone, written, need_input = 1, clips = 0;
|
size_t odone, written, need_input = 1, clips = 0;
|
||||||
soxr_error_t error;
|
soxr_error_t error;
|
||||||
|
soxr_t soxr;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
soxr_t soxr = soxr_create(
|
/* Overrides (if given): */
|
||||||
|
if (passband_end > 0) q_spec.passband_end = passband_end / 100;
|
||||||
|
if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100;
|
||||||
|
if (phase_response >=0) q_spec.phase_response = phase_response;
|
||||||
|
io_spec.flags = ospec & ~7u;
|
||||||
|
|
||||||
|
soxr = soxr_create(
|
||||||
irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec);
|
irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec);
|
||||||
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < chans; ++i) {
|
for (i = 0; i < chans; ++i) {
|
||||||
ibuf_ptrs[i] = iptr;
|
ibuf_ptrs[i] = iptr;
|
||||||
obuf_ptrs[i] = optr;
|
obuf_ptrs[i] = optr;
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
if (${BUILD_EXAMPLES})
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
|
||||||
project (soxr) # Adds c++ compiler
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}")
|
||||||
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/[1-9]-*.[cC])
|
link_libraries (${PROJECT_NAME} ${LIBM_LIBRARIES})
|
||||||
elseif (${BUILD_TESTS})
|
|
||||||
file (GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/3*.c)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (${BUILD_EXAMPLES} OR ${BUILD_TESTS})
|
if (${BUILD_EXAMPLES} OR ${BUILD_TESTS})
|
||||||
|
set (SOURCES 3-options-input-fn)
|
||||||
if (${WITH_LSR_BINDINGS})
|
if (${WITH_LSR_BINDINGS})
|
||||||
set (LSR_SOURCES 1a-lsr.c)
|
set (LSR_SOURCES 1a-lsr)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT BUILD_SHARED_LIBS AND OPENMP_FOUND)
|
if (${BUILD_EXAMPLES})
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_C_FLAGS}")
|
list (APPEND SOURCES 1-single-block 2-stream 4-split-channels)
|
||||||
|
if (${WITH_VR32})
|
||||||
|
list (APPEND SOURCES 5-variable-rate)
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}")
|
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}")
|
|
||||||
link_libraries (soxr)
|
|
||||||
|
|
||||||
foreach (fe ${SOURCES} ${LSR_SOURCES})
|
foreach (fe ${SOURCES} ${LSR_SOURCES})
|
||||||
get_filename_component (f ${fe} NAME_WE)
|
get_filename_component (f ${fe} NAME_WE)
|
||||||
|
@ -34,4 +32,5 @@ if (${BUILD_TESTS} AND ${WITH_LSR_BINDINGS})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
file (GLOB INSTALL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cCh])
|
file (GLOB INSTALL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cCh])
|
||||||
install (FILES ${INSTALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/README DESTINATION ${DOC_INSTALL_DIR}/examples)
|
install (FILES ${INSTALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/README
|
||||||
|
DESTINATION ${DOC_INSTALL_DIR}/examples)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
/* Common includes etc. for the examples. */
|
/* Common includes etc. for the examples. */
|
||||||
|
@ -17,10 +17,7 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \
|
#define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \
|
||||||
_setmode(_fileno(stdin ), _O_BINARY);
|
_setmode(_fileno(stdin ), _O_BINARY)
|
||||||
/* Sometimes missing, so ensure that it is defined: */
|
|
||||||
#undef M_PI
|
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#else
|
#else
|
||||||
#define USE_STD_STDIO
|
#define USE_STD_STDIO
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,8 +35,13 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
|
||||||
#define min(x,y) ((x)<(y)?(x):(y))
|
#define min(x,y) ((x)<(y)?(x):(y))
|
||||||
|
|
||||||
|
#undef max
|
||||||
#define max(x,y) ((x)>(y)?(x):(y))
|
#define max(x,y) ((x)>(y)?(x):(y))
|
||||||
|
|
||||||
|
#undef AL
|
||||||
#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */
|
#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */
|
||||||
|
|
||||||
|
#undef M_PI /* Sometimes missing, so ensure that it is defined: */
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
case "$1" in -j*) j="$1"; shift;; esac # Support -jX for parallel build/test
|
||||||
|
|
||||||
|
test x"$1" = x && build=Release || build="$1"
|
||||||
|
|
||||||
|
rm -f CMakeCache.txt # Prevent interference from any in-tree build
|
||||||
|
|
||||||
|
mkdir -p "$build"
|
||||||
|
cd "$build"
|
||||||
|
|
||||||
|
cmake -Wno-dev -DCMAKE_BUILD_TYPE="$build" ..
|
||||||
|
make $j
|
||||||
|
ctest $j || echo "FAILURE details in $build/Testing/Temporary/LastTest.log"
|
|
@ -0,0 +1,27 @@
|
||||||
|
@echo off
|
||||||
|
rem SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
rem Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
set build=%1
|
||||||
|
if x%build% == x set build=Release
|
||||||
|
|
||||||
|
rem Prevent interference from any in-tree build
|
||||||
|
del/f CMakeCache.txt
|
||||||
|
|
||||||
|
mkdir %build%
|
||||||
|
cd %build%
|
||||||
|
|
||||||
|
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% -Wno-dev ..
|
||||||
|
if errorlevel 1 goto end
|
||||||
|
|
||||||
|
nmake
|
||||||
|
if errorlevel 1 goto end
|
||||||
|
|
||||||
|
nmake test
|
||||||
|
if errorlevel 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
echo FAILURE details in Testing\Temporary\LastTest.log
|
||||||
|
|
||||||
|
:end
|
|
@ -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
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# Sanity-check of sub-library installed on unix-like system
|
||||||
|
|
||||||
|
arg="$1" # path to installed examples (if dev pkg installed); otherwise omitted
|
||||||
|
dir="$(dirname $(readlink -f $0))"
|
||||||
|
|
||||||
|
# Find the examples:
|
||||||
|
src="$arg"
|
||||||
|
test x"$src" = x && src="$dir/examples"
|
||||||
|
cd $src
|
||||||
|
|
||||||
|
# Somewhere to put the binaries:
|
||||||
|
tmp=`mktemp -d`
|
||||||
|
|
||||||
|
build_examples() {
|
||||||
|
if [ x"$arg" = x ]; then
|
||||||
|
echo "Examples in `pwd`; using local headers:" # for when dev pkg not installed
|
||||||
|
libs=-l$1
|
||||||
|
cflags=-I$dir/src
|
||||||
|
else
|
||||||
|
echo "Examples in `pwd`; using pkg-config:"
|
||||||
|
libs=$(pkg-config --libs $1)
|
||||||
|
cflags=$(pkg-config --cflags $1)
|
||||||
|
fi
|
||||||
|
for f in ?$2-*.[cC]; do
|
||||||
|
cc=cc; echo $f | grep -q C$ && cc=c++
|
||||||
|
out=$tmp/`echo $f | sed "s/.[cC]$//"`
|
||||||
|
cmd="$cc $cflags -o $out $f $libs -lm"
|
||||||
|
echo $cmd; $cmd
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine library:
|
||||||
|
if [ `basename $0` = inst-check-soxr ]; then
|
||||||
|
build_examples soxr
|
||||||
|
gen="dd if=/dev/urandom count=1000"
|
||||||
|
$tmp/1-single-block 1 2 .
|
||||||
|
$gen 2> /dev/null | $tmp/2-stream 2>&1 >$tmp/stdout
|
||||||
|
$gen 2> /dev/null | $tmp/3-options-input-fn 6 7 2 2 0 2>&1 >$tmp/stdout
|
||||||
|
$gen 2> /dev/null | $tmp/4-split-channels 7 6 2 2 3 2>&1 >$tmp/stdout # Clipping expected here
|
||||||
|
$gen 2> /dev/null | $tmp/5-variable-rate 2>&1 >$tmp/stdout
|
||||||
|
else
|
||||||
|
build_examples soxr-lsr a # lsr has 'a' suffix on example number.
|
||||||
|
$tmp/1a-lsr 1 2 .
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tidy up:
|
||||||
|
rm -rf $tmp
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# Sanity-check of sub-library installed on unix-like system
|
||||||
|
|
||||||
|
arg="$1" # path to installed examples (if dev pkg installed); otherwise omitted
|
||||||
|
dir="$(dirname $(readlink -f $0))"
|
||||||
|
|
||||||
|
# Find the examples:
|
||||||
|
src="$arg"
|
||||||
|
test x"$src" = x && src="$dir/examples"
|
||||||
|
cd $src
|
||||||
|
|
||||||
|
# Somewhere to put the binaries:
|
||||||
|
tmp=`mktemp -d`
|
||||||
|
|
||||||
|
build_examples() {
|
||||||
|
if [ x"$arg" = x ]; then
|
||||||
|
echo "Examples in `pwd`; using local headers:" # for when dev pkg not installed
|
||||||
|
libs=-l$1
|
||||||
|
cflags=-I$dir/src
|
||||||
|
else
|
||||||
|
echo "Examples in `pwd`; using pkg-config:"
|
||||||
|
libs=$(pkg-config --libs $1)
|
||||||
|
cflags=$(pkg-config --cflags $1)
|
||||||
|
fi
|
||||||
|
for f in ?$2-*.[cC]; do
|
||||||
|
cc=cc; echo $f | grep -q C$ && cc=c++
|
||||||
|
out=$tmp/`echo $f | sed "s/.[cC]$//"`
|
||||||
|
cmd="$cc $cflags -o $out $f $libs -lm"
|
||||||
|
echo $cmd; $cmd
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine library:
|
||||||
|
if [ `basename $0` = inst-check-soxr ]; then
|
||||||
|
build_examples soxr
|
||||||
|
gen="dd if=/dev/urandom count=1000"
|
||||||
|
$tmp/1-single-block 1 2 .
|
||||||
|
$gen 2> /dev/null | $tmp/2-stream 2>&1 >$tmp/stdout
|
||||||
|
$gen 2> /dev/null | $tmp/3-options-input-fn 6 7 2 2 0 2>&1 >$tmp/stdout
|
||||||
|
$gen 2> /dev/null | $tmp/4-split-channels 7 6 2 2 3 2>&1 >$tmp/stdout # Clipping expected here
|
||||||
|
$gen 2> /dev/null | $tmp/5-variable-rate 2>&1 >$tmp/stdout
|
||||||
|
else
|
||||||
|
build_examples soxr-lsr a # lsr has 'a' suffix on example number.
|
||||||
|
$tmp/1a-lsr 1 2 .
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tidy up:
|
||||||
|
rm -rf $tmp
|
|
@ -0,0 +1,50 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
|
||||||
|
|
||||||
|
find_package (FFTW)
|
||||||
|
if (FFTW_FOUND)
|
||||||
|
include_directories (${FFTW_INCLUDE_DIRS})
|
||||||
|
link_libraries (${FFTW_LIBRARIES})
|
||||||
|
set (HAVE_FFTW3 1)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_package (sndfile)
|
||||||
|
if (SNDFILE_FOUND)
|
||||||
|
include_directories (${SNDFILE_INCLUDE_DIRS})
|
||||||
|
link_libraries (${SNDFILE_LIBRARIES})
|
||||||
|
set (HAVE_SNDFILE 1)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
check_function_exists (lrintf HAVE_LRINTF)
|
||||||
|
check_function_exists (alarm HAVE_ALARM)
|
||||||
|
check_function_exists (signal HAVE_SIGNAL)
|
||||||
|
check_include_files (sys/times.h HAVE_SYS_TIMES_H)
|
||||||
|
|
||||||
|
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
include_directories (${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
add_library (tests_lib STATIC util calc_snr)
|
||||||
|
|
||||||
|
link_libraries (tests_lib ${PROJECT_NAME}-lsr ${LIBM_LIBRARIES})
|
||||||
|
|
||||||
|
enable_testing ()
|
||||||
|
|
||||||
|
set (tests
|
||||||
|
callback_hang_test callback_test downsample_test
|
||||||
|
float_short_test misc_test multi_channel_test
|
||||||
|
reset_test simple_test termination_test varispeed_test)
|
||||||
|
if (WITH_CR64 OR WITH_CR64S)
|
||||||
|
set (tests ${tests} snr_bw_test)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
foreach (test ${tests})
|
||||||
|
add_executable (${test} ${test})
|
||||||
|
add_test (lsr-${test} ${BIN}${test})
|
||||||
|
set_property (TEST lsr-${test} PROPERTY ENVIRONMENT "SOXR_LSR_STRICT=1")
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
add_executable (multichan_throughput_test multichan_throughput_test)
|
||||||
|
add_executable (throughput_test throughput_test )
|
||||||
|
add_executable (sndfile-resample sndfile-resample)
|
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
|
@ -0,0 +1,8 @@
|
||||||
|
The C source and header files in this directory have been copied from
|
||||||
|
the `libsamplerate' project and are copyrighted by its authors -- see
|
||||||
|
the notices within the files and the file `COPYING' for details.
|
||||||
|
|
||||||
|
They are used here to test libsoxr's optional libsamplerate-like
|
||||||
|
wrapper. The only modifications made are to the file `snr_bw_test.c' to
|
||||||
|
remove reliance on certain frequency response troughs that are specific
|
||||||
|
to libsamplerate.
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#if (HAVE_FFTW3 == 1)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <fftw3.h>
|
||||||
|
|
||||||
|
#define MAX_SPEC_LEN (1<<18)
|
||||||
|
#define MAX_PEAKS 10
|
||||||
|
|
||||||
|
static void log_mag_spectrum (double *input, int len, double *magnitude) ;
|
||||||
|
static void smooth_mag_spectrum (double *magnitude, int len) ;
|
||||||
|
static double find_snr (const double *magnitude, int len, int expected_peaks) ;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ double peak ;
|
||||||
|
int index ;
|
||||||
|
} PEAK_DATA ;
|
||||||
|
|
||||||
|
double
|
||||||
|
calculate_snr (float *data, int len, int expected_peaks)
|
||||||
|
{ static double magnitude [MAX_SPEC_LEN] ;
|
||||||
|
static double datacopy [MAX_SPEC_LEN] ;
|
||||||
|
|
||||||
|
double snr = 200.0 ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
if (len > MAX_SPEC_LEN)
|
||||||
|
{ printf ("%s : line %d : data length too large.\n", __FILE__, __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < len ; k++)
|
||||||
|
datacopy [k] = data [k] ;
|
||||||
|
|
||||||
|
/* Pad the data just a little to speed up the FFT. */
|
||||||
|
while ((len & 0x1F) && len < MAX_SPEC_LEN)
|
||||||
|
{ datacopy [len] = 0.0 ;
|
||||||
|
len ++ ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
log_mag_spectrum (datacopy, len, magnitude) ;
|
||||||
|
smooth_mag_spectrum (magnitude, len / 2) ;
|
||||||
|
|
||||||
|
snr = find_snr (magnitude, len, expected_peaks) ;
|
||||||
|
|
||||||
|
return snr ;
|
||||||
|
} /* calculate_snr */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
** There is a slight problem with trying to measure SNR with the method used
|
||||||
|
** here; the side lobes of the windowed FFT can look like a noise/aliasing peak.
|
||||||
|
** The solution is to smooth the magnitude spectrum by wiping out troughs
|
||||||
|
** between adjacent peaks as done here.
|
||||||
|
** This removes side lobe peaks without affecting noise/aliasing peaks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller) ;
|
||||||
|
|
||||||
|
static void
|
||||||
|
smooth_mag_spectrum (double *mag, int len)
|
||||||
|
{ PEAK_DATA peaks [2] ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
memset (peaks, 0, sizeof (peaks)) ;
|
||||||
|
|
||||||
|
/* Find first peak. */
|
||||||
|
for (k = 1 ; k < len - 1 ; k++)
|
||||||
|
{ if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1])
|
||||||
|
{ peaks [0].peak = mag [k] ;
|
||||||
|
peaks [0].index = k ;
|
||||||
|
break ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Find subsequent peaks ans smooth between peaks. */
|
||||||
|
for (k = peaks [0].index + 1 ; k < len - 1 ; k++)
|
||||||
|
{ if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1])
|
||||||
|
{ peaks [1].peak = mag [k] ;
|
||||||
|
peaks [1].index = k ;
|
||||||
|
|
||||||
|
if (peaks [1].peak > peaks [0].peak)
|
||||||
|
linear_smooth (mag, &peaks [1], &peaks [0]) ;
|
||||||
|
else
|
||||||
|
linear_smooth (mag, &peaks [0], &peaks [1]) ;
|
||||||
|
peaks [0] = peaks [1] ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
} /* smooth_mag_spectrum */
|
||||||
|
|
||||||
|
static void
|
||||||
|
linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller)
|
||||||
|
{ int k ;
|
||||||
|
|
||||||
|
if (smaller->index < larger->index)
|
||||||
|
{ for (k = smaller->index + 1 ; k < larger->index ; k++)
|
||||||
|
mag [k] = (mag [k] < mag [k - 1]) ? 0.999 * mag [k - 1] : mag [k] ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ for (k = smaller->index - 1 ; k >= larger->index ; k--)
|
||||||
|
mag [k] = (mag [k] < mag [k + 1]) ? 0.999 * mag [k + 1] : mag [k] ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
} /* linear_smooth */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
peak_compare (const void *vp1, const void *vp2)
|
||||||
|
{ const PEAK_DATA *peak1, *peak2 ;
|
||||||
|
|
||||||
|
peak1 = (const PEAK_DATA*) vp1 ;
|
||||||
|
peak2 = (const PEAK_DATA*) vp2 ;
|
||||||
|
|
||||||
|
return (peak1->peak < peak2->peak) ? 1 : -1 ;
|
||||||
|
} /* peak_compare */
|
||||||
|
|
||||||
|
static double
|
||||||
|
find_snr (const double *magnitude, int len, int expected_peaks)
|
||||||
|
{ PEAK_DATA peaks [MAX_PEAKS] ;
|
||||||
|
|
||||||
|
int k, peak_count = 0 ;
|
||||||
|
double snr ;
|
||||||
|
|
||||||
|
memset (peaks, 0, sizeof (peaks)) ;
|
||||||
|
|
||||||
|
/* Find the MAX_PEAKS largest peaks. */
|
||||||
|
for (k = 1 ; k < len - 1 ; k++)
|
||||||
|
{ if (magnitude [k - 1] < magnitude [k] && magnitude [k] >= magnitude [k + 1])
|
||||||
|
{ if (peak_count < MAX_PEAKS)
|
||||||
|
{ peaks [peak_count].peak = magnitude [k] ;
|
||||||
|
peaks [peak_count].index = k ;
|
||||||
|
peak_count ++ ;
|
||||||
|
qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ;
|
||||||
|
}
|
||||||
|
else if (magnitude [k] > peaks [MAX_PEAKS - 1].peak)
|
||||||
|
{ peaks [MAX_PEAKS - 1].peak = magnitude [k] ;
|
||||||
|
peaks [MAX_PEAKS - 1].index = k ;
|
||||||
|
qsort (peaks, MAX_PEAKS, sizeof (PEAK_DATA), peak_compare) ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (peak_count < expected_peaks)
|
||||||
|
{ printf ("\n%s : line %d : bad peak_count (%d), expected %d.\n\n", __FILE__, __LINE__, peak_count, expected_peaks) ;
|
||||||
|
return -1.0 ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Sort the peaks. */
|
||||||
|
qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ;
|
||||||
|
|
||||||
|
snr = peaks [0].peak ;
|
||||||
|
for (k = 1 ; k < peak_count ; k++)
|
||||||
|
if (fabs (snr - peaks [k].peak) > 10.0)
|
||||||
|
return fabs (peaks [k].peak) ;
|
||||||
|
|
||||||
|
return snr ;
|
||||||
|
} /* find_snr */
|
||||||
|
|
||||||
|
static void
|
||||||
|
log_mag_spectrum (double *input, int len, double *magnitude)
|
||||||
|
{ fftw_plan plan = NULL ;
|
||||||
|
|
||||||
|
double maxval ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
if (input == NULL || magnitude == NULL)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
plan = fftw_plan_r2r_1d (len, input, magnitude, FFTW_R2HC, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT) ;
|
||||||
|
if (plan == NULL)
|
||||||
|
{ printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
fftw_execute (plan) ;
|
||||||
|
|
||||||
|
fftw_destroy_plan (plan) ;
|
||||||
|
|
||||||
|
/* (k < N/2 rounded up) */
|
||||||
|
maxval = 0.0 ;
|
||||||
|
for (k = 1 ; k < len / 2 ; k++)
|
||||||
|
{ magnitude [k] = sqrt (magnitude [k] * magnitude [k] + magnitude [len - k - 1] * magnitude [len - k - 1]) ;
|
||||||
|
maxval = (maxval < magnitude [k]) ? magnitude [k] : maxval ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
memset (magnitude + len / 2, 0, len / 2 * sizeof (magnitude [0])) ;
|
||||||
|
|
||||||
|
/* Don't care about DC component. Make it zero. */
|
||||||
|
magnitude [0] = 0.0 ;
|
||||||
|
|
||||||
|
/* log magnitude. */
|
||||||
|
for (k = 0 ; k < len ; k++)
|
||||||
|
{ magnitude [k] = magnitude [k] / maxval ;
|
||||||
|
magnitude [k] = (magnitude [k] < 1e-15) ? -200.0 : 20.0 * log10 (magnitude [k]) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* log_mag_spectrum */
|
||||||
|
|
||||||
|
#else /* ! (HAVE_LIBFFTW && HAVE_LIBRFFTW) */
|
||||||
|
|
||||||
|
double
|
||||||
|
calculate_snr (float *data, int len, int expected_peaks)
|
||||||
|
{ double snr = 200.0 ;
|
||||||
|
|
||||||
|
data = data ;
|
||||||
|
len = len ;
|
||||||
|
expected_peaks = expected_peaks ;
|
||||||
|
|
||||||
|
return snr ;
|
||||||
|
} /* calculate_snr */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#if HAVE_ALARM && HAVE_SIGNAL && HAVE_SIGALRM
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define SHORT_BUFFER_LEN 512
|
||||||
|
#define LONG_BUFFER_LEN (1 << 14)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ double ratio ;
|
||||||
|
int count ;
|
||||||
|
} SRC_PAIR ;
|
||||||
|
|
||||||
|
static void callback_hang_test (int converter) ;
|
||||||
|
|
||||||
|
static void alarm_handler (int number) ;
|
||||||
|
static long input_callback (void *cb_data, float **data) ;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
/* Set up SIGALRM handler. */
|
||||||
|
signal (SIGALRM, alarm_handler) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
callback_hang_test (SRC_ZERO_ORDER_HOLD) ;
|
||||||
|
callback_hang_test (SRC_LINEAR) ;
|
||||||
|
callback_hang_test (SRC_SINC_FASTEST) ;
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
callback_hang_test (int converter)
|
||||||
|
{ static float output [LONG_BUFFER_LEN] ;
|
||||||
|
static SRC_PAIR pairs [] =
|
||||||
|
{
|
||||||
|
{ 1.2, 5 }, { 1.1, 1 }, { 1.0, 1 }, { 3.0, 1 }, { 2.0, 1 }, { 0.3, 1 },
|
||||||
|
{ 1.2, 0 }, { 1.1, 10 }, { 1.0, 1 }
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
|
||||||
|
double src_ratio = 1.0 ;
|
||||||
|
int k, error ;
|
||||||
|
|
||||||
|
printf ("\tcallback_hang_test (%-28s) ....... ", src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
/* Perform sample rate conversion. */
|
||||||
|
src_state = src_callback_new (input_callback, converter, 1, &error, NULL) ;
|
||||||
|
if (src_state == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_callback_new () failed : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (pairs) ; k++)
|
||||||
|
{ alarm (1) ;
|
||||||
|
src_ratio = pairs [k].ratio ;
|
||||||
|
src_callback_read (src_state, src_ratio, pairs [k].count, output) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
alarm (0) ;
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* callback_hang_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
alarm_handler (int number)
|
||||||
|
{
|
||||||
|
(void) number ;
|
||||||
|
printf ("\n\n Error : Hang inside src_callback_read() detected. Exiting!\n\n") ;
|
||||||
|
exit (1) ;
|
||||||
|
} /* alarm_handler */
|
||||||
|
|
||||||
|
static long
|
||||||
|
input_callback (void *cb_data, float **data)
|
||||||
|
{
|
||||||
|
static float buffer [20] ;
|
||||||
|
|
||||||
|
(void) cb_data ;
|
||||||
|
*data = buffer ;
|
||||||
|
|
||||||
|
return ARRAY_LEN (buffer) ;
|
||||||
|
} /* input_callback */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
puts ("\tCan't run this test on this platform.") ;
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN 10000
|
||||||
|
#define CB_READ_LEN 256
|
||||||
|
|
||||||
|
static void callback_test (int converter, double ratio) ;
|
||||||
|
static void end_of_stream_test (int converter) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{ static double src_ratios [] =
|
||||||
|
{ 1.0, 0.099, 0.1, 0.33333333, 0.789, 1.0001, 1.9, 3.1, 9.9
|
||||||
|
} ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
puts (" Zero Order Hold interpolator :") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
callback_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts (" Linear interpolator :") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
callback_test (SRC_LINEAR, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts (" Sinc interpolator :") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
callback_test (SRC_SINC_FASTEST, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
puts (" End of stream test :") ;
|
||||||
|
end_of_stream_test (SRC_ZERO_ORDER_HOLD) ;
|
||||||
|
end_of_stream_test (SRC_LINEAR) ;
|
||||||
|
end_of_stream_test (SRC_SINC_FASTEST) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
/*=====================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ int channels ;
|
||||||
|
long count, total ;
|
||||||
|
int end_of_data ;
|
||||||
|
float data [BUFFER_LEN] ;
|
||||||
|
} TEST_CB_DATA ;
|
||||||
|
|
||||||
|
static long
|
||||||
|
test_callback_func (void *cb_data, float **data)
|
||||||
|
{ TEST_CB_DATA *pcb_data ;
|
||||||
|
|
||||||
|
long frames ;
|
||||||
|
|
||||||
|
if ((pcb_data = cb_data) == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if (pcb_data->total - pcb_data->count > CB_READ_LEN)
|
||||||
|
frames = CB_READ_LEN / pcb_data->channels ;
|
||||||
|
else
|
||||||
|
frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ;
|
||||||
|
|
||||||
|
*data = pcb_data->data + pcb_data->count ;
|
||||||
|
pcb_data->count += frames ;
|
||||||
|
|
||||||
|
return frames ;
|
||||||
|
} /* test_callback_func */
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
callback_test (int converter, double src_ratio)
|
||||||
|
{ static TEST_CB_DATA test_callback_data ;
|
||||||
|
static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
|
||||||
|
long read_count, read_total ;
|
||||||
|
int error ;
|
||||||
|
|
||||||
|
printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
test_callback_data.channels = 2 ;
|
||||||
|
test_callback_data.count = 0 ;
|
||||||
|
test_callback_data.end_of_data = 0 ;
|
||||||
|
test_callback_data.total = ARRAY_LEN (test_callback_data.data) ;
|
||||||
|
|
||||||
|
if ((src_state = src_callback_new (test_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
read_total = 0 ;
|
||||||
|
do
|
||||||
|
{ /* We will be throwing away output data, so just grab as much as possible. */
|
||||||
|
read_count = ARRAY_LEN (output) / test_callback_data.channels ;
|
||||||
|
read_count = src_callback_read (src_state, src_ratio, read_count, output) ;
|
||||||
|
read_total += read_count ;
|
||||||
|
}
|
||||||
|
while (read_count > 0) ;
|
||||||
|
|
||||||
|
if ((error = src_error (src_state)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (fabs (read_total / src_ratio - ARRAY_LEN (test_callback_data.data)) > 2.0)
|
||||||
|
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
|
||||||
|
printf (" input len : %d\n", ARRAY_LEN (test_callback_data.data)) ;
|
||||||
|
printf (" output len : %ld (should be %g +/- 2)\n\n", read_total,
|
||||||
|
floor (0.5 + src_ratio * ARRAY_LEN (test_callback_data.data))) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* callback_test */
|
||||||
|
|
||||||
|
/*=====================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static long
|
||||||
|
eos_callback_func (void *cb_data, float **data)
|
||||||
|
{
|
||||||
|
TEST_CB_DATA *pcb_data ;
|
||||||
|
long frames ;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if ((pcb_data = cb_data) == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return immediately if there is no more data.
|
||||||
|
** In this case, the output pointer 'data' will not be set and
|
||||||
|
** valgrind should not warn about it.
|
||||||
|
*/
|
||||||
|
if (pcb_data->end_of_data)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if (pcb_data->total - pcb_data->count > CB_READ_LEN)
|
||||||
|
frames = CB_READ_LEN / pcb_data->channels ;
|
||||||
|
else
|
||||||
|
frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ;
|
||||||
|
|
||||||
|
*data = pcb_data->data + pcb_data->count ;
|
||||||
|
pcb_data->count += frames ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Set end_of_data so that the next call to the callback function will
|
||||||
|
** return zero ocunt without setting the 'data' pointer.
|
||||||
|
*/
|
||||||
|
if (pcb_data->total < 2 * pcb_data->count)
|
||||||
|
pcb_data->end_of_data = 1 ;
|
||||||
|
|
||||||
|
return frames ;
|
||||||
|
} /* eos_callback_data */
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
end_of_stream_test (int converter)
|
||||||
|
{ static TEST_CB_DATA test_callback_data ;
|
||||||
|
static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
|
||||||
|
double src_ratio = 0.3 ;
|
||||||
|
long read_count, read_total ;
|
||||||
|
int error ;
|
||||||
|
|
||||||
|
printf ("\t%-30s ........... ", src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
test_callback_data.channels = 2 ;
|
||||||
|
test_callback_data.count = 0 ;
|
||||||
|
test_callback_data.end_of_data = 0 ;
|
||||||
|
test_callback_data.total = ARRAY_LEN (test_callback_data.data) ;
|
||||||
|
|
||||||
|
if ((src_state = src_callback_new (eos_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
read_total = 0 ;
|
||||||
|
do
|
||||||
|
{ /* We will be throwing away output data, so just grab as much as possible. */
|
||||||
|
read_count = ARRAY_LEN (output) / test_callback_data.channels ;
|
||||||
|
read_count = src_callback_read (src_state, src_ratio, read_count, output) ;
|
||||||
|
read_total += read_count ;
|
||||||
|
}
|
||||||
|
while (read_count > 0) ;
|
||||||
|
|
||||||
|
if ((error = src_error (src_state)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (test_callback_data.end_of_data == 0)
|
||||||
|
{ printf ("\n\nLine %d : test_callback_data.end_of_data should not be 0."
|
||||||
|
" This is a bug in the test.\n\n", __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
return ;
|
||||||
|
} /* end_of_stream_test */
|
|
@ -0,0 +1,23 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# - Find FFTW
|
||||||
|
# Find the native installation of this package: includes and libraries.
|
||||||
|
#
|
||||||
|
# FFTW_INCLUDES - where to find headers for this package.
|
||||||
|
# FFTW_LIBRARIES - List of libraries when using this package.
|
||||||
|
# FFTW_FOUND - True if this package can be found.
|
||||||
|
|
||||||
|
if (FFTW_INCLUDES)
|
||||||
|
set (FFTW_FIND_QUIETLY TRUE)
|
||||||
|
endif (FFTW_INCLUDES)
|
||||||
|
|
||||||
|
find_path (FFTW_INCLUDES fftw3.h)
|
||||||
|
|
||||||
|
find_library (FFTW_LIBRARIES NAMES fftw3)
|
||||||
|
|
||||||
|
include (FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args (
|
||||||
|
FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES)
|
||||||
|
|
||||||
|
mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES)
|
|
@ -0,0 +1,23 @@
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
# - Find SNDFILE
|
||||||
|
# Find the native installation of this package: includes and libraries.
|
||||||
|
#
|
||||||
|
# SNDFILE_INCLUDES - where to find headers for this package.
|
||||||
|
# SNDFILE_LIBRARIES - List of libraries when using this package.
|
||||||
|
# SNDFILE_FOUND - True if this package can be found.
|
||||||
|
|
||||||
|
if (SNDFILE_INCLUDES)
|
||||||
|
set (SNDFILE_FIND_QUIETLY TRUE)
|
||||||
|
endif (SNDFILE_INCLUDES)
|
||||||
|
|
||||||
|
find_path (SNDFILE_INCLUDES sndfile.h)
|
||||||
|
|
||||||
|
find_library (SNDFILE_LIBRARIES NAMES sndfile)
|
||||||
|
|
||||||
|
include (FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args (
|
||||||
|
SNDFILE DEFAULT_MSG SNDFILE_LIBRARIES SNDFILE_INCLUDES)
|
||||||
|
|
||||||
|
mark_as_advanced (SNDFILE_LIBRARIES SNDFILE_INCLUDES)
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if !defined soxsrc_lsr_tests_config_included
|
||||||
|
#define soxsrc_lsr_tests_config_included
|
||||||
|
|
||||||
|
#cmakedefine01 HAVE_ALARM
|
||||||
|
#cmakedefine01 HAVE_FFTW3
|
||||||
|
#cmakedefine01 HAVE_LRINTF
|
||||||
|
#cmakedefine01 HAVE_LRINT
|
||||||
|
#cmakedefine01 HAVE_SIGNAL
|
||||||
|
#cmakedefine01 HAVE_SNDFILE
|
||||||
|
#cmakedefine01 HAVE_SYS_TIMES_H
|
||||||
|
|
||||||
|
#if HAVE_SIGNAL
|
||||||
|
#include <signal.h>
|
||||||
|
#if defined SIGALRM
|
||||||
|
#define HAVE_SIGALRM 1
|
||||||
|
#else
|
||||||
|
#define HAVE_SIGALRM 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
downsample_test (int converter)
|
||||||
|
{ static float in [1000], out [10] ;
|
||||||
|
SRC_DATA data ;
|
||||||
|
|
||||||
|
printf (" downsample_test (%-28s) ....... ", src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
data.src_ratio = 1.0 / 255.0 ;
|
||||||
|
data.input_frames = ARRAY_LEN (in) ;
|
||||||
|
data.output_frames = ARRAY_LEN (out) ;
|
||||||
|
data.data_in = in ;
|
||||||
|
data.data_out = out ;
|
||||||
|
|
||||||
|
if (src_simple (&data, converter, 1))
|
||||||
|
{ puts ("src_simple failed.") ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
} /* downsample_test */
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
downsample_test (SRC_ZERO_ORDER_HOLD) ;
|
||||||
|
downsample_test (SRC_LINEAR) ;
|
||||||
|
downsample_test (SRC_SINC_FASTEST) ;
|
||||||
|
downsample_test (SRC_SINC_MEDIUM_QUALITY) ;
|
||||||
|
downsample_test (SRC_SINC_BEST_QUALITY) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU Lesser General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU Lesser General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Version 1.5 */
|
||||||
|
|
||||||
|
#ifndef FLOAT_CAST_HEADER
|
||||||
|
#define FLOAT_CAST_HEADER
|
||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
** On Intel Pentium processors (especially PIII and probably P4), converting
|
||||||
|
** from float to int is very slow. To meet the C specs, the code produced by
|
||||||
|
** most C compilers targeting Pentium needs to change the FPU rounding mode
|
||||||
|
** before the float to int conversion is performed.
|
||||||
|
**
|
||||||
|
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
|
||||||
|
** is this flushing of the pipeline which is so slow.
|
||||||
|
**
|
||||||
|
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
|
||||||
|
** llrint and llrintf which fix this problem as a side effect.
|
||||||
|
**
|
||||||
|
** On Unix-like systems, the configure process should have detected the
|
||||||
|
** presence of these functions. If they weren't found we have to replace them
|
||||||
|
** here with a standard C cast.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The C99 prototypes for lrint and lrintf are as follows:
|
||||||
|
**
|
||||||
|
** long int lrintf (float x) ;
|
||||||
|
** long int lrint (double x) ;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The presence of the required functions are detected during the configure
|
||||||
|
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
|
||||||
|
** the config.h file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_LRINT_REPLACEMENT 0
|
||||||
|
|
||||||
|
#if (HAVE_LRINT && HAVE_LRINTF)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** These defines enable functionality introduced with the 1999 ISO C
|
||||||
|
** standard. They must be defined before the inclusion of math.h to
|
||||||
|
** engage them. If optimisation is enabled, these functions will be
|
||||||
|
** inlined. With optimisation switched off, you have to link in the
|
||||||
|
** maths library using -lm.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _ISOC9X_SOURCE 1
|
||||||
|
#define _ISOC99_SOURCE 1
|
||||||
|
|
||||||
|
#define __USE_ISOC9X 1
|
||||||
|
#define __USE_ISOC99 1
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#elif (defined (__CYGWIN__))
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#undef HAVE_LRINT_REPLACEMENT
|
||||||
|
#define HAVE_LRINT_REPLACEMENT 1
|
||||||
|
|
||||||
|
#undef lrint
|
||||||
|
#undef lrintf
|
||||||
|
|
||||||
|
#define lrint double2int
|
||||||
|
#define lrintf float2int
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The native CYGWIN lrint and lrintf functions are buggy:
|
||||||
|
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
|
||||||
|
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
|
||||||
|
** and slow.
|
||||||
|
** These functions (pulled from the Public Domain MinGW math.h header)
|
||||||
|
** replace the native versions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline long double2int (double in)
|
||||||
|
{ long retval ;
|
||||||
|
|
||||||
|
__asm__ __volatile__
|
||||||
|
( "fistpl %0"
|
||||||
|
: "=m" (retval)
|
||||||
|
: "t" (in)
|
||||||
|
: "st"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return retval ;
|
||||||
|
} /* double2int */
|
||||||
|
|
||||||
|
static inline long float2int (float in)
|
||||||
|
{ long retval ;
|
||||||
|
|
||||||
|
__asm__ __volatile__
|
||||||
|
( "fistpl %0"
|
||||||
|
: "=m" (retval)
|
||||||
|
: "t" (in)
|
||||||
|
: "st"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return retval ;
|
||||||
|
} /* float2int */
|
||||||
|
|
||||||
|
#elif (defined (WIN64) || defined(_WIN64))
|
||||||
|
|
||||||
|
/* Win64 section should be places before Win32 one, because
|
||||||
|
** most likely both WIN32 and WIN64 will be defined in 64-bit case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Win64 doesn't seem to have these functions, nor inline assembly.
|
||||||
|
** Therefore implement inline versions of these functions here.
|
||||||
|
*/
|
||||||
|
#include <emmintrin.h>
|
||||||
|
#include <mmintrin.h>
|
||||||
|
|
||||||
|
__inline long int
|
||||||
|
lrint(double flt)
|
||||||
|
{
|
||||||
|
return _mm_cvtsd_si32(_mm_load_sd(&flt));
|
||||||
|
}
|
||||||
|
|
||||||
|
__inline long int
|
||||||
|
lrintf(float flt)
|
||||||
|
{
|
||||||
|
return _mm_cvtss_si32(_mm_load_ss(&flt));
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif (defined (WIN32) || defined (_WIN32))
|
||||||
|
|
||||||
|
#undef HAVE_LRINT_REPLACEMENT
|
||||||
|
#define HAVE_LRINT_REPLACEMENT 1
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Win32 doesn't seem to have these functions.
|
||||||
|
** Therefore implement inline versions of these functions here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__inline long int
|
||||||
|
lrint (double flt)
|
||||||
|
{ int intgr ;
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{ fld flt
|
||||||
|
fistp intgr
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return intgr ;
|
||||||
|
}
|
||||||
|
|
||||||
|
__inline long int
|
||||||
|
lrintf (float flt)
|
||||||
|
{ int intgr ;
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{ fld flt
|
||||||
|
fistp intgr
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return intgr ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif (defined (__MWERKS__) && defined (macintosh))
|
||||||
|
|
||||||
|
/* This MacOS 9 solution was provided by Stephane Letz */
|
||||||
|
|
||||||
|
#undef HAVE_LRINT_REPLACEMENT
|
||||||
|
#define HAVE_LRINT_REPLACEMENT 1
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#undef lrint
|
||||||
|
#undef lrintf
|
||||||
|
|
||||||
|
#define lrint double2int
|
||||||
|
#define lrintf float2int
|
||||||
|
|
||||||
|
inline int
|
||||||
|
float2int (register float in)
|
||||||
|
{ long res [2] ;
|
||||||
|
|
||||||
|
asm
|
||||||
|
{ fctiw in, in
|
||||||
|
stfd in, res
|
||||||
|
}
|
||||||
|
return res [1] ;
|
||||||
|
} /* float2int */
|
||||||
|
|
||||||
|
inline int
|
||||||
|
double2int (register double in)
|
||||||
|
{ long res [2] ;
|
||||||
|
|
||||||
|
asm
|
||||||
|
{ fctiw in, in
|
||||||
|
stfd in, res
|
||||||
|
}
|
||||||
|
return res [1] ;
|
||||||
|
} /* double2int */
|
||||||
|
|
||||||
|
#elif (defined (__MACH__) && defined (__APPLE__))
|
||||||
|
|
||||||
|
/* For Apple MacOSX. */
|
||||||
|
|
||||||
|
#undef HAVE_LRINT_REPLACEMENT
|
||||||
|
#define HAVE_LRINT_REPLACEMENT 1
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#undef lrint
|
||||||
|
#undef lrintf
|
||||||
|
|
||||||
|
#define lrint double2int
|
||||||
|
#define lrintf float2int
|
||||||
|
|
||||||
|
inline static long
|
||||||
|
float2int (register float in)
|
||||||
|
{ int res [2] ;
|
||||||
|
|
||||||
|
__asm__ __volatile__
|
||||||
|
( "fctiw %1, %1\n\t"
|
||||||
|
"stfd %1, %0"
|
||||||
|
: "=m" (res) /* Output */
|
||||||
|
: "f" (in) /* Input */
|
||||||
|
: "memory"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return res [1] ;
|
||||||
|
} /* lrintf */
|
||||||
|
|
||||||
|
inline static long
|
||||||
|
double2int (register double in)
|
||||||
|
{ int res [2] ;
|
||||||
|
|
||||||
|
__asm__ __volatile__
|
||||||
|
( "fctiw %1, %1\n\t"
|
||||||
|
"stfd %1, %0"
|
||||||
|
: "=m" (res) /* Output */
|
||||||
|
: "f" (in) /* Input */
|
||||||
|
: "memory"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return res [1] ;
|
||||||
|
} /* lrint */
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifndef __sgi
|
||||||
|
#warning "Don't have the functions lrint() and lrintf()."
|
||||||
|
#warning "Replacing these functions with a standard C cast."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define lrint(dbl) ((long) (dbl))
|
||||||
|
#define lrintf(flt) ((long) (flt))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FLOAT_CAST_HEADER */
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN 10000
|
||||||
|
|
||||||
|
static void float_to_short_test (void) ;
|
||||||
|
static void short_to_float_test (void) ;
|
||||||
|
|
||||||
|
static void float_to_int_test (void) ;
|
||||||
|
static void int_to_float_test (void) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
float_to_short_test () ;
|
||||||
|
short_to_float_test () ;
|
||||||
|
|
||||||
|
float_to_int_test () ;
|
||||||
|
int_to_float_test () ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
/*=====================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
float_to_short_test (void)
|
||||||
|
{
|
||||||
|
static float fpos [] =
|
||||||
|
{ 0.95, 0.99, 1.0, 1.01, 1.1, 2.0, 11.1, 111.1, 2222.2, 33333.3
|
||||||
|
} ;
|
||||||
|
static float fneg [] =
|
||||||
|
{ -0.95, -0.99, -1.0, -1.01, -1.1, -2.0, -11.1, -111.1, -2222.2, -33333.3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static short out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("\tfloat_to_short_test ............................. ") ;
|
||||||
|
|
||||||
|
src_float_to_short_array (fpos, out, ARRAY_LEN (fpos)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (fpos) ; k++)
|
||||||
|
if (out [k] < 30000)
|
||||||
|
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_float_to_short_array (fneg, out, ARRAY_LEN (fneg)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (fneg) ; k++)
|
||||||
|
if (out [k] > -30000)
|
||||||
|
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* float_to_short_test */
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
short_to_float_test (void)
|
||||||
|
{
|
||||||
|
static short input [BUFFER_LEN] ;
|
||||||
|
static short output [BUFFER_LEN] ;
|
||||||
|
static float temp [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("\tshort_to_float_test ............................. ") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
|
||||||
|
input [k] = (k * 0x8000) / ARRAY_LEN (input) ;
|
||||||
|
|
||||||
|
src_short_to_float_array (input, temp, ARRAY_LEN (temp)) ;
|
||||||
|
src_float_to_short_array (temp, output, ARRAY_LEN (output)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
|
||||||
|
if (ABS (input [k] - output [k]) > 0)
|
||||||
|
{ printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* short_to_float_test */
|
||||||
|
|
||||||
|
/*=====================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
float_to_int_test (void)
|
||||||
|
{
|
||||||
|
static float fpos [] =
|
||||||
|
{ 0.95, 0.99, 1.0, 1.01, 1.1, 2.0, 11.1, 111.1, 2222.2, 33333.3
|
||||||
|
} ;
|
||||||
|
static float fneg [] =
|
||||||
|
{ -0.95, -0.99, -1.0, -1.01, -1.1, -2.0, -11.1, -111.1, -2222.2, -33333.3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static int out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("\tfloat_to_int_test ............................... ") ;
|
||||||
|
|
||||||
|
src_float_to_int_array (fpos, out, ARRAY_LEN (fpos)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (fpos) ; k++)
|
||||||
|
if (out [k] < 30000 * 0x10000)
|
||||||
|
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_float_to_int_array (fneg, out, ARRAY_LEN (fneg)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (fneg) ; k++)
|
||||||
|
if (out [k] > -30000 * 0x1000)
|
||||||
|
{ printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* float_to_int_test */
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
int_to_float_test (void)
|
||||||
|
{
|
||||||
|
static int input [BUFFER_LEN] ;
|
||||||
|
static int output [BUFFER_LEN] ;
|
||||||
|
static float temp [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("\tint_to_float_test ............................... ") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
|
||||||
|
input [k] = (k * 0x80000000) / ARRAY_LEN (input) ;
|
||||||
|
|
||||||
|
src_int_to_float_array (input, temp, ARRAY_LEN (temp)) ;
|
||||||
|
src_float_to_int_array (temp, output, ARRAY_LEN (output)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
|
||||||
|
if (ABS (input [k] - output [k]) > 0)
|
||||||
|
{ printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* int_to_float_test */
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void name_test (void) ;
|
||||||
|
static void error_test (void) ;
|
||||||
|
static void src_ratio_test (void) ;
|
||||||
|
static void zero_input_test (int converter) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
printf (" version : %s\n\n", src_get_version ()) ;
|
||||||
|
|
||||||
|
/* Current max converter is SRC_LINEAR. */
|
||||||
|
name_test () ;
|
||||||
|
|
||||||
|
error_test () ;
|
||||||
|
|
||||||
|
src_ratio_test () ;
|
||||||
|
|
||||||
|
zero_input_test (SRC_ZERO_ORDER_HOLD) ;
|
||||||
|
zero_input_test (SRC_LINEAR) ;
|
||||||
|
zero_input_test (SRC_SINC_FASTEST) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
static void
|
||||||
|
name_test (void)
|
||||||
|
{ const char *name ;
|
||||||
|
int k = 0 ;
|
||||||
|
|
||||||
|
puts (" name_test :") ;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{ name = src_get_name (k) ;
|
||||||
|
if (name == NULL)
|
||||||
|
break ;
|
||||||
|
printf ("\tName %d : %s\n", k, name) ;
|
||||||
|
printf ("\tDesc %d : %s\n", k, src_get_description (k)) ;
|
||||||
|
k ++ ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* name_test */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ double ratio ;
|
||||||
|
int should_pass ;
|
||||||
|
} RATIO_TEST ;
|
||||||
|
|
||||||
|
static RATIO_TEST ratio_test [] =
|
||||||
|
{ { 1.0 / 256.1, 0 },
|
||||||
|
{ 1.0 / 256.0, 1 },
|
||||||
|
{ 1.0, 1 },
|
||||||
|
{ 256.0, 1 },
|
||||||
|
{ 256.1, 0 },
|
||||||
|
{ -1.0, 0 }
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static void
|
||||||
|
src_ratio_test (void)
|
||||||
|
{ int k ;
|
||||||
|
|
||||||
|
puts (" src_ratio_test (SRC ratio must be in range [1/256, 256]):" ) ;
|
||||||
|
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (ratio_test) ; k++)
|
||||||
|
{ if (ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) == 0)
|
||||||
|
{ printf ("\n\nLine %d : SRC ratio %f should have passed.\n\n", __LINE__, ratio_test [k].ratio) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
if (! ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) != 0)
|
||||||
|
{ printf ("\n\nLine %d : SRC ratio %f should not have passed.\n\n", __LINE__, ratio_test [k].ratio) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
printf ("\t SRC ratio (%9.5f) : %s ................... ok\n", ratio_test [k].ratio,
|
||||||
|
(ratio_test [k].should_pass ? "pass" : "fail")) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* src_ratio_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
error_test (void)
|
||||||
|
{ const char *errorstr ;
|
||||||
|
int k, errors = 0 ;
|
||||||
|
|
||||||
|
puts (" error_test :") ;
|
||||||
|
|
||||||
|
for (k = 0 ; 1 ; k++)
|
||||||
|
{ errorstr = src_strerror (k) ;
|
||||||
|
printf ("\t%-2d : %s\n", k, errorstr) ;
|
||||||
|
if (errorstr == NULL)
|
||||||
|
{ errors ++ ;
|
||||||
|
continue ;
|
||||||
|
} ;
|
||||||
|
if (strstr (errorstr, "Placeholder.") == errorstr)
|
||||||
|
break ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (errors != 0)
|
||||||
|
{ printf ("\n\nLine %d : Missing error numbers above.\n\n", __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* error_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
zero_input_test (int converter)
|
||||||
|
{ SRC_DATA data ;
|
||||||
|
SRC_STATE *state ;
|
||||||
|
float out [100] ;
|
||||||
|
int error ;
|
||||||
|
|
||||||
|
printf (" %s (%-26s) ........ ", __func__, src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
if ((state = src_new (converter, 1, &error)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
data.data_in = (float *) 0xdeadbeef ;
|
||||||
|
data.input_frames = 0 ;
|
||||||
|
data.data_out = out ;
|
||||||
|
data.output_frames = ARRAY_LEN (out) ;
|
||||||
|
data.end_of_input = 0 ;
|
||||||
|
data.src_ratio = 1.0 ;
|
||||||
|
|
||||||
|
if ((error = src_process (state, &data)))
|
||||||
|
{ printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
state = src_delete (state) ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
} /* zero_input_test */
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#define BUFFER_LEN 50000
|
||||||
|
#define BLOCK_LEN (12)
|
||||||
|
|
||||||
|
#define MAX_CHANNELS 10
|
||||||
|
|
||||||
|
static void simple_test (int converter, int channel_count, double target_snr) ;
|
||||||
|
static void process_test (int converter, int channel_count, double target_snr) ;
|
||||||
|
static void callback_test (int converter, int channel_count, double target_snr) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{ double target ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
puts ("\n Zero Order Hold interpolator :") ;
|
||||||
|
target = 38.0 ;
|
||||||
|
for (k = 1 ; k <= 3 ; k++)
|
||||||
|
{ simple_test (SRC_ZERO_ORDER_HOLD, k, target) ;
|
||||||
|
process_test (SRC_ZERO_ORDER_HOLD, k, target) ;
|
||||||
|
callback_test (SRC_ZERO_ORDER_HOLD, k, target) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("\n Linear interpolator :") ;
|
||||||
|
target = 79.0 ;
|
||||||
|
for (k = 1 ; k <= 3 ; k++)
|
||||||
|
{ simple_test (SRC_LINEAR, k, target) ;
|
||||||
|
process_test (SRC_LINEAR, k, target) ;
|
||||||
|
callback_test (SRC_LINEAR, k, target) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("\n Sinc interpolator :") ;
|
||||||
|
target = 100.0 ;
|
||||||
|
for (k = 1 ; k <= MAX_CHANNELS ; k++)
|
||||||
|
{ simple_test (SRC_SINC_FASTEST, k, target) ;
|
||||||
|
process_test (SRC_SINC_FASTEST, k, target) ;
|
||||||
|
callback_test (SRC_SINC_FASTEST, k, target) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static float input_serial [BUFFER_LEN * MAX_CHANNELS] ;
|
||||||
|
static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
|
||||||
|
static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
|
||||||
|
static float output_serial [BUFFER_LEN * MAX_CHANNELS] ;
|
||||||
|
|
||||||
|
static void
|
||||||
|
simple_test (int converter, int channel_count, double target_snr)
|
||||||
|
{ SRC_DATA src_data ;
|
||||||
|
|
||||||
|
double freq, snr ;
|
||||||
|
int ch, error, frames ;
|
||||||
|
|
||||||
|
printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
assert (channel_count <= MAX_CHANNELS) ;
|
||||||
|
|
||||||
|
memset (input_serial, 0, sizeof (input_serial)) ;
|
||||||
|
memset (input_interleaved, 0, sizeof (input_interleaved)) ;
|
||||||
|
memset (output_interleaved, 0, sizeof (output_interleaved)) ;
|
||||||
|
memset (output_serial, 0, sizeof (output_serial)) ;
|
||||||
|
|
||||||
|
frames = BUFFER_LEN ;
|
||||||
|
|
||||||
|
/* Calculate channel_count separate windowed sine waves. */
|
||||||
|
for (ch = 0 ; ch < channel_count ; ch++)
|
||||||
|
{ freq = (200.0 + 33.333333333 * ch) / 44100.0 ;
|
||||||
|
gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Interleave the data in preparation for SRC. */
|
||||||
|
interleave_data (input_serial, input_interleaved, frames, channel_count) ;
|
||||||
|
|
||||||
|
/* Choose a converstion ratio <= 1.0. */
|
||||||
|
src_data.src_ratio = 0.95 ;
|
||||||
|
|
||||||
|
src_data.data_in = input_interleaved ;
|
||||||
|
src_data.input_frames = frames ;
|
||||||
|
|
||||||
|
src_data.data_out = output_interleaved ;
|
||||||
|
src_data.output_frames = frames ;
|
||||||
|
|
||||||
|
if ((error = src_simple (&src_data, converter, channel_count)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2)
|
||||||
|
{ printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__,
|
||||||
|
src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ;
|
||||||
|
printf ("\tinput_len : %ld\n", src_data.input_frames) ;
|
||||||
|
printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* De-interleave data so SNR can be calculated for each channel. */
|
||||||
|
deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
|
||||||
|
|
||||||
|
for (ch = 0 ; ch < channel_count ; ch++)
|
||||||
|
{ snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
|
||||||
|
if (snr < target_snr)
|
||||||
|
{ printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
|
||||||
|
save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* simple_test */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_test (int converter, int channel_count, double target_snr)
|
||||||
|
{ SRC_STATE *src_state ;
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
|
||||||
|
double freq, snr ;
|
||||||
|
int ch, error, frames, current_in, current_out ;
|
||||||
|
|
||||||
|
printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
assert (channel_count <= MAX_CHANNELS) ;
|
||||||
|
|
||||||
|
memset (input_serial, 0, sizeof (input_serial)) ;
|
||||||
|
memset (input_interleaved, 0, sizeof (input_interleaved)) ;
|
||||||
|
memset (output_interleaved, 0, sizeof (output_interleaved)) ;
|
||||||
|
memset (output_serial, 0, sizeof (output_serial)) ;
|
||||||
|
|
||||||
|
frames = BUFFER_LEN ;
|
||||||
|
|
||||||
|
/* Calculate channel_count separate windowed sine waves. */
|
||||||
|
for (ch = 0 ; ch < channel_count ; ch++)
|
||||||
|
{ freq = (400.0 + 11.333333333 * ch) / 44100.0 ;
|
||||||
|
gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Interleave the data in preparation for SRC. */
|
||||||
|
interleave_data (input_serial, input_interleaved, frames, channel_count) ;
|
||||||
|
|
||||||
|
/* Perform sample rate conversion. */
|
||||||
|
if ((src_state = src_new (converter, channel_count, &error)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 0 ; /* Set this later. */
|
||||||
|
|
||||||
|
/* Choose a converstion ratio < 1.0. */
|
||||||
|
src_data.src_ratio = 0.95 ;
|
||||||
|
|
||||||
|
src_data.data_in = input_interleaved ;
|
||||||
|
src_data.data_out = output_interleaved ;
|
||||||
|
|
||||||
|
current_in = current_out = 0 ;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{ src_data.input_frames = MAX (MIN (BLOCK_LEN, frames - current_in), 0) ;
|
||||||
|
src_data.output_frames = MAX (MIN (BLOCK_LEN, frames - current_out), 0) ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.end_of_input && src_data.output_frames_gen == 0)
|
||||||
|
break ;
|
||||||
|
|
||||||
|
current_in += src_data.input_frames_used ;
|
||||||
|
current_out += src_data.output_frames_gen ;
|
||||||
|
|
||||||
|
src_data.data_in += src_data.input_frames_used * channel_count ;
|
||||||
|
src_data.data_out += src_data.output_frames_gen * channel_count ;
|
||||||
|
|
||||||
|
src_data.end_of_input = (current_in >= frames) ? 1 : 0 ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (fabs (current_out - src_data.src_ratio * current_in) > 2)
|
||||||
|
{ printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__,
|
||||||
|
current_out, (int) floor (src_data.src_ratio * current_in)) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ;
|
||||||
|
printf ("\tinput_len : %d\n", frames) ;
|
||||||
|
printf ("\toutput_len : %d\n\n", current_out) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* De-interleave data so SNR can be calculated for each channel. */
|
||||||
|
deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
|
||||||
|
|
||||||
|
for (ch = 0 ; ch < channel_count ; ch++)
|
||||||
|
{ snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
|
||||||
|
if (snr < target_snr)
|
||||||
|
{ printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
|
||||||
|
save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* process_test */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ int channels ;
|
||||||
|
long total_frames ;
|
||||||
|
long current_frame ;
|
||||||
|
float *data ;
|
||||||
|
} TEST_CB_DATA ;
|
||||||
|
|
||||||
|
static long
|
||||||
|
test_callback_func (void *cb_data, float **data)
|
||||||
|
{ TEST_CB_DATA *pcb_data ;
|
||||||
|
|
||||||
|
long frames ;
|
||||||
|
|
||||||
|
if ((pcb_data = cb_data) == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
*data = pcb_data->data + (pcb_data->current_frame * pcb_data->channels) ;
|
||||||
|
|
||||||
|
if (pcb_data->total_frames - pcb_data->current_frame < BLOCK_LEN)
|
||||||
|
frames = pcb_data->total_frames - pcb_data->current_frame ;
|
||||||
|
else
|
||||||
|
frames = BLOCK_LEN ;
|
||||||
|
|
||||||
|
pcb_data->current_frame += frames ;
|
||||||
|
|
||||||
|
return frames ;
|
||||||
|
} /* test_callback_func */
|
||||||
|
|
||||||
|
static void
|
||||||
|
callback_test (int converter, int channel_count, double target_snr)
|
||||||
|
{ TEST_CB_DATA test_callback_data ;
|
||||||
|
SRC_STATE *src_state = NULL ;
|
||||||
|
|
||||||
|
double freq, snr, src_ratio ;
|
||||||
|
int ch, error, frames, read_total, read_count ;
|
||||||
|
|
||||||
|
printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
assert (channel_count <= MAX_CHANNELS) ;
|
||||||
|
|
||||||
|
memset (input_serial, 0, sizeof (input_serial)) ;
|
||||||
|
memset (input_interleaved, 0, sizeof (input_interleaved)) ;
|
||||||
|
memset (output_interleaved, 0, sizeof (output_interleaved)) ;
|
||||||
|
memset (output_serial, 0, sizeof (output_serial)) ;
|
||||||
|
memset (&test_callback_data, 0, sizeof (test_callback_data)) ;
|
||||||
|
|
||||||
|
frames = BUFFER_LEN ;
|
||||||
|
|
||||||
|
/* Calculate channel_count separate windowed sine waves. */
|
||||||
|
for (ch = 0 ; ch < channel_count ; ch++)
|
||||||
|
{ freq = (200.0 + 33.333333333 * ch) / 44100.0 ;
|
||||||
|
gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Interleave the data in preparation for SRC. */
|
||||||
|
interleave_data (input_serial, input_interleaved, frames, channel_count) ;
|
||||||
|
|
||||||
|
/* Perform sample rate conversion. */
|
||||||
|
src_ratio = 0.95 ;
|
||||||
|
test_callback_data.channels = channel_count ;
|
||||||
|
test_callback_data.total_frames = frames ;
|
||||||
|
test_callback_data.current_frame = 0 ;
|
||||||
|
test_callback_data.data = input_interleaved ;
|
||||||
|
|
||||||
|
if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
read_total = 0 ;
|
||||||
|
while (read_total < frames)
|
||||||
|
{ read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ;
|
||||||
|
|
||||||
|
if (read_count <= 0)
|
||||||
|
break ;
|
||||||
|
|
||||||
|
read_total += read_count ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if ((error = src_error (src_state)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (fabs (read_total - src_ratio * frames) > 2)
|
||||||
|
{ printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__,
|
||||||
|
read_total, (int) floor (src_ratio * frames)) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
|
||||||
|
printf ("\tinput_len : %d\n", frames) ;
|
||||||
|
printf ("\toutput_len : %d\n\n", read_total) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* De-interleave data so SNR can be calculated for each channel. */
|
||||||
|
deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
|
||||||
|
|
||||||
|
for (ch = 0 ; ch < channel_count ; ch++)
|
||||||
|
{ snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
|
||||||
|
if (snr < target_snr)
|
||||||
|
{ printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
|
||||||
|
save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* callback_test */
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "float_cast.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN (1<<17)
|
||||||
|
|
||||||
|
static float input [BUFFER_LEN] ;
|
||||||
|
static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
static long
|
||||||
|
throughput_test (int converter, int channels, long best_throughput)
|
||||||
|
{ SRC_DATA src_data ;
|
||||||
|
clock_t start_time, clock_time ;
|
||||||
|
double duration ;
|
||||||
|
long total_frames = 0, throughput ;
|
||||||
|
int error ;
|
||||||
|
|
||||||
|
printf (" %-30s %2d ", src_get_name (converter), channels) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
src_data.input_frames = ARRAY_LEN (input) / channels ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) / channels ;
|
||||||
|
|
||||||
|
src_data.src_ratio = 0.99 ;
|
||||||
|
|
||||||
|
sleep (2) ;
|
||||||
|
|
||||||
|
start_time = clock () ;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((error = src_simple (&src_data, converter, channels)) != 0)
|
||||||
|
{ puts (src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
total_frames += src_data.output_frames_gen ;
|
||||||
|
|
||||||
|
clock_time = clock () - start_time ;
|
||||||
|
duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
|
||||||
|
}
|
||||||
|
while (duration < 5.0) ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used != src_data.input_frames)
|
||||||
|
{ printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
|
||||||
|
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
|
||||||
|
printf (" input len : %d\n", ARRAY_LEN (input) / channels) ;
|
||||||
|
printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
|
||||||
|
floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
throughput = lrint (floor (total_frames / duration)) ;
|
||||||
|
|
||||||
|
if (best_throughput == 0)
|
||||||
|
{ best_throughput = MAX (throughput, best_throughput) ;
|
||||||
|
printf ("%5.2f %10ld\n", duration, throughput) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ best_throughput = MAX (throughput, best_throughput) ;
|
||||||
|
printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return best_throughput ;
|
||||||
|
} /* throughput_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
single_run (void)
|
||||||
|
{ const int max_channels = 10 ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
"\n"
|
||||||
|
" Converter Channels Duration Throughput\n"
|
||||||
|
" ---------------------------------------------------------------------"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
for (k = 1 ; k <= max_channels / 2 ; k++)
|
||||||
|
throughput_test (SRC_SINC_FASTEST, k, 0) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
for (k = 1 ; k <= max_channels / 2 ; k++)
|
||||||
|
throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
for (k = 1 ; k <= max_channels ; k++)
|
||||||
|
throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
return ;
|
||||||
|
} /* single_run */
|
||||||
|
|
||||||
|
static void
|
||||||
|
multi_run (int run_count)
|
||||||
|
{ int k, ch ;
|
||||||
|
|
||||||
|
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
"\n"
|
||||||
|
" Converter Channels Duration Throughput Best Throughput\n"
|
||||||
|
" ----------------------------------------------------------------------------------------"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
for (ch = 1 ; ch <= 5 ; ch++)
|
||||||
|
{ long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < run_count ; k++)
|
||||||
|
{ sinc_fastest = throughput_test (SRC_SINC_FASTEST, ch, sinc_fastest) ;
|
||||||
|
sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, sinc_medium) ;
|
||||||
|
sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, ch, sinc_best) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
/* Let the CPU cool down. We might be running on a laptop. */
|
||||||
|
sleep (10) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
"\n"
|
||||||
|
" Converter Best Throughput\n"
|
||||||
|
" ------------------------------------------------"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
} /* multi_run */
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage_exit (const char * argv0)
|
||||||
|
{ const char * cptr ;
|
||||||
|
|
||||||
|
if ((cptr = strrchr (argv0, '/')) != NULL)
|
||||||
|
argv0 = cptr ;
|
||||||
|
|
||||||
|
printf (
|
||||||
|
"Usage :\n"
|
||||||
|
" %s - Single run of the throughput test.\n"
|
||||||
|
" %s --best-of N - Do N runs of test a print bext result.\n"
|
||||||
|
"\n",
|
||||||
|
argv0, argv0) ;
|
||||||
|
|
||||||
|
exit (0) ;
|
||||||
|
} /* usage_exit */
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char ** argv)
|
||||||
|
{ double freq ;
|
||||||
|
|
||||||
|
memset (input, 0, sizeof (input)) ;
|
||||||
|
freq = 0.01 ;
|
||||||
|
gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
single_run () ;
|
||||||
|
else if (argc == 3 && strcmp (argv [1], "--best-of") == 0)
|
||||||
|
{ int run_count = atoi (argv [2]) ;
|
||||||
|
|
||||||
|
if (run_count < 1 || run_count > 20)
|
||||||
|
{ printf ("Please be sensible. Run count should be in range (1, 10].\n") ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
multi_run (run_count) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usage_exit (argv [0]) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
" Duration is in seconds.\n"
|
||||||
|
" Throughput is in frames/sec (more is better).\n"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN 2048
|
||||||
|
#define CB_READ_LEN 256
|
||||||
|
|
||||||
|
static void process_reset_test (int converter) ;
|
||||||
|
static void callback_reset_test (int converter) ;
|
||||||
|
|
||||||
|
static float data_one [BUFFER_LEN] ;
|
||||||
|
static float data_zero [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
process_reset_test (SRC_ZERO_ORDER_HOLD) ;
|
||||||
|
process_reset_test (SRC_LINEAR) ;
|
||||||
|
process_reset_test (SRC_SINC_FASTEST) ;
|
||||||
|
|
||||||
|
callback_reset_test (SRC_ZERO_ORDER_HOLD) ;
|
||||||
|
callback_reset_test (SRC_LINEAR) ;
|
||||||
|
callback_reset_test (SRC_SINC_FASTEST) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_reset_test (int converter)
|
||||||
|
{ static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
int k, error ;
|
||||||
|
|
||||||
|
printf ("\tprocess_reset_test (%-28s) ....... ", src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < BUFFER_LEN ; k++)
|
||||||
|
{ data_one [k] = 1.0 ;
|
||||||
|
data_zero [k] = 0.0 ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Get a converter. */
|
||||||
|
if ((src_state = src_new (converter, 1, &error)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Process a bunch of 1.0 valued samples. */
|
||||||
|
src_data.data_in = data_one ;
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.input_frames = BUFFER_LEN ;
|
||||||
|
src_data.output_frames = BUFFER_LEN ;
|
||||||
|
src_data.src_ratio = 0.9 ;
|
||||||
|
src_data.end_of_input = 1 ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Reset the state of the converter.*/
|
||||||
|
src_reset (src_state) ;
|
||||||
|
|
||||||
|
/* Now process some zero data. */
|
||||||
|
src_data.data_in = data_zero ;
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.input_frames = BUFFER_LEN ;
|
||||||
|
src_data.output_frames = BUFFER_LEN ;
|
||||||
|
src_data.src_ratio = 0.9 ;
|
||||||
|
src_data.end_of_input = 1 ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Finally make sure that the output data is zero ie reset was sucessful. */
|
||||||
|
for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
|
||||||
|
if (output [k] != 0.0)
|
||||||
|
{ printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n", __LINE__, k, output [k]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Make sure that this function has been exported. */
|
||||||
|
src_set_ratio (src_state, 1.0) ;
|
||||||
|
|
||||||
|
/* Delete converter. */
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
} /* process_reset_test */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ int channels ;
|
||||||
|
long count, total ;
|
||||||
|
float *data ;
|
||||||
|
} TEST_CB_DATA ;
|
||||||
|
|
||||||
|
static long
|
||||||
|
test_callback_func (void *cb_data, float **data)
|
||||||
|
{ TEST_CB_DATA *pcb_data ;
|
||||||
|
|
||||||
|
long frames ;
|
||||||
|
|
||||||
|
if ((pcb_data = cb_data) == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if (pcb_data->total - pcb_data->count > 0)
|
||||||
|
frames = pcb_data->total - pcb_data->count ;
|
||||||
|
else
|
||||||
|
frames = 0 ;
|
||||||
|
|
||||||
|
*data = pcb_data->data + pcb_data->count ;
|
||||||
|
pcb_data->count += frames ;
|
||||||
|
|
||||||
|
return frames ;
|
||||||
|
} /* test_callback_func */
|
||||||
|
|
||||||
|
static void
|
||||||
|
callback_reset_test (int converter)
|
||||||
|
{ static TEST_CB_DATA test_callback_data ;
|
||||||
|
|
||||||
|
static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
|
||||||
|
double src_ratio = 1.1 ;
|
||||||
|
long read_count, read_total ;
|
||||||
|
int k, error ;
|
||||||
|
|
||||||
|
printf ("\tcallback_reset_test (%-28s) ....... ", src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (data_one) ; k++)
|
||||||
|
{ data_one [k] = 1.0 ;
|
||||||
|
data_zero [k] = 0.0 ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Process a bunch of 1.0 valued samples. */
|
||||||
|
test_callback_data.channels = 1 ;
|
||||||
|
test_callback_data.count = 0 ;
|
||||||
|
test_callback_data.total = ARRAY_LEN (data_one) ;
|
||||||
|
test_callback_data.data = data_one ;
|
||||||
|
|
||||||
|
read_total = 0 ;
|
||||||
|
do
|
||||||
|
{ read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ;
|
||||||
|
read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ;
|
||||||
|
read_total += read_count ;
|
||||||
|
}
|
||||||
|
while (read_count > 0) ;
|
||||||
|
|
||||||
|
/* Check for errors. */
|
||||||
|
if ((error = src_error (src_state)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Reset the state of the converter.*/
|
||||||
|
src_reset (src_state) ;
|
||||||
|
|
||||||
|
/* Process a bunch of 0.0 valued samples. */
|
||||||
|
test_callback_data.channels = 1 ;
|
||||||
|
test_callback_data.count = 0 ;
|
||||||
|
test_callback_data.total = ARRAY_LEN (data_zero) ;
|
||||||
|
test_callback_data.data = data_zero ;
|
||||||
|
|
||||||
|
/* Now process some zero data. */
|
||||||
|
read_total = 0 ;
|
||||||
|
do
|
||||||
|
{ read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ;
|
||||||
|
read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ;
|
||||||
|
read_total += read_count ;
|
||||||
|
}
|
||||||
|
while (read_count > 0) ;
|
||||||
|
|
||||||
|
/* Check for errors. */
|
||||||
|
if ((error = src_error (src_state)) != 0)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Finally make sure that the output data is zero ie reset was sucessful. */
|
||||||
|
for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
|
||||||
|
if (output [k] != 0.0)
|
||||||
|
{ printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n\n", __LINE__, k, output [k]) ;
|
||||||
|
save_oct_float ("output.dat", data_one, ARRAY_LEN (data_one), output, ARRAY_LEN (output)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Make sure that this function has been exported. */
|
||||||
|
src_set_ratio (src_state, 1.0) ;
|
||||||
|
|
||||||
|
/* Delete converter. */
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
} /* callback_reset_test */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN 2048
|
||||||
|
|
||||||
|
static void simple_test (int converter, double ratio) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{ static double src_ratios [] =
|
||||||
|
{ 1.0001, 0.099, 0.1, 0.33333333, 0.789, 1.9, 3.1, 9.9
|
||||||
|
} ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
puts (" Zero Order Hold interpolator :") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
simple_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts (" Linear interpolator :") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
simple_test (SRC_LINEAR, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts (" Sinc interpolator :") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
simple_test (SRC_SINC_FASTEST, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
static void
|
||||||
|
simple_test (int converter, double src_ratio)
|
||||||
|
{ static float input [BUFFER_LEN], output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
|
||||||
|
int input_len, output_len, error, terminate ;
|
||||||
|
|
||||||
|
printf ("\tsimple_test (SRC ratio = %6.4f) ........... ", src_ratio) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
/* Calculate maximun input and output lengths. */
|
||||||
|
if (src_ratio >= 1.0)
|
||||||
|
{ output_len = BUFFER_LEN ;
|
||||||
|
input_len = (int) floor (BUFFER_LEN / src_ratio) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ input_len = BUFFER_LEN ;
|
||||||
|
output_len = (int) floor (BUFFER_LEN * src_ratio) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Reduce input_len by 10 so output is longer than necessary. */
|
||||||
|
input_len -= 10 ;
|
||||||
|
|
||||||
|
if (output_len > BUFFER_LEN)
|
||||||
|
{ printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
memset (&src_data, 0, sizeof (src_data)) ;
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
src_data.input_frames = input_len ;
|
||||||
|
|
||||||
|
src_data.src_ratio = src_ratio ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = BUFFER_LEN ;
|
||||||
|
|
||||||
|
if ((error = src_simple (&src_data, converter, 1)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ;
|
||||||
|
|
||||||
|
if (fabs (src_data.output_frames_gen - src_ratio * input_len) > 2 * terminate)
|
||||||
|
{ printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__,
|
||||||
|
src_data.output_frames_gen, (int) floor (src_ratio * input_len)) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
|
||||||
|
printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* simple_test */
|
||||||
|
|
|
@ -0,0 +1,332 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#if (HAVE_SNDFILE)
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
#include <sndfile.h>
|
||||||
|
|
||||||
|
#define DEFAULT_CONVERTER SRC_SINC_MEDIUM_QUALITY
|
||||||
|
|
||||||
|
#define BUFFER_LEN 4096 /*-(1<<16)-*/
|
||||||
|
|
||||||
|
static void usage_exit (const char *progname) ;
|
||||||
|
static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain) ;
|
||||||
|
static double apply_gain (float * data, long frames, int channels, double max, double gain) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv [])
|
||||||
|
{ SNDFILE *infile, *outfile = NULL ;
|
||||||
|
SF_INFO sfinfo ;
|
||||||
|
|
||||||
|
sf_count_t count ;
|
||||||
|
double src_ratio = -1.0, gain = 1.0 ;
|
||||||
|
int new_sample_rate = -1, k, converter, max_speed = SF_FALSE ;
|
||||||
|
|
||||||
|
if (argc == 2 && strcmp (argv [1], "--version") == 0)
|
||||||
|
{ char buffer [64], *cptr ;
|
||||||
|
|
||||||
|
if ((cptr = strrchr (argv [0], '/')) != NULL)
|
||||||
|
argv [0] = cptr + 1 ;
|
||||||
|
if ((cptr = strrchr (argv [0], '\\')) != NULL)
|
||||||
|
argv [0] = cptr + 1 ;
|
||||||
|
|
||||||
|
sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
|
||||||
|
|
||||||
|
printf ("%s (%s,%s)\n", argv [0], src_get_version (), buffer) ;
|
||||||
|
exit (0) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (argc != 5 && argc != 7 && argc != 8)
|
||||||
|
usage_exit (argv [0]) ;
|
||||||
|
|
||||||
|
/* Set default converter. */
|
||||||
|
converter = DEFAULT_CONVERTER ;
|
||||||
|
|
||||||
|
for (k = 1 ; k < argc - 2 ; k++)
|
||||||
|
{ if (strcmp (argv [k], "--max-speed") == 0)
|
||||||
|
max_speed = SF_TRUE ;
|
||||||
|
else if (strcmp (argv [k], "-to") == 0)
|
||||||
|
{ k ++ ;
|
||||||
|
new_sample_rate = atoi (argv [k]) ;
|
||||||
|
}
|
||||||
|
else if (strcmp (argv [k], "-by") == 0)
|
||||||
|
{ k ++ ;
|
||||||
|
src_ratio = atof (argv [k]) ;
|
||||||
|
}
|
||||||
|
else if (strcmp (argv [k], "-c") == 0)
|
||||||
|
{ k ++ ;
|
||||||
|
converter = atoi (argv [k]) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usage_exit (argv [0]) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (new_sample_rate <= 0 && src_ratio <= 0.0)
|
||||||
|
usage_exit (argv [0]) ;
|
||||||
|
|
||||||
|
if (src_get_name (converter) == NULL)
|
||||||
|
{ printf ("Error : bad converter number.\n") ;
|
||||||
|
usage_exit (argv [0]) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (strcmp (argv [argc - 2], argv [argc - 1]) == 0)
|
||||||
|
{ printf ("Error : input and output file names are the same.\n") ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL)
|
||||||
|
{ printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
printf ("Input File : %s\n", argv [argc - 2]) ;
|
||||||
|
printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
|
||||||
|
printf ("Input Frames : %ld\n\n", (long) sfinfo.frames) ;
|
||||||
|
|
||||||
|
if (new_sample_rate > 0)
|
||||||
|
{ src_ratio = (1.0 * new_sample_rate) / sfinfo.samplerate ;
|
||||||
|
sfinfo.samplerate = new_sample_rate ;
|
||||||
|
}
|
||||||
|
else if (src_is_valid_ratio (src_ratio))
|
||||||
|
sfinfo.samplerate = (int) floor (sfinfo.samplerate * src_ratio) ;
|
||||||
|
else
|
||||||
|
{ printf ("Not able to determine new sample rate. Exiting.\n") ;
|
||||||
|
sf_close (infile) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (fabs (src_ratio - 1.0) < 1e-20)
|
||||||
|
{ printf ("Target samplerate and input samplerate are the same. Exiting.\n") ;
|
||||||
|
sf_close (infile) ;
|
||||||
|
exit (0) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
printf ("SRC Ratio : %f\n", src_ratio) ;
|
||||||
|
printf ("Converter : %s\n\n", src_get_name (converter)) ;
|
||||||
|
|
||||||
|
if (src_is_valid_ratio (src_ratio) == 0)
|
||||||
|
{ printf ("Error : Sample rate change out of valid range.\n") ;
|
||||||
|
sf_close (infile) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Delete the output file length to zero if already exists. */
|
||||||
|
remove (argv [argc - 1]) ;
|
||||||
|
|
||||||
|
printf ("Output file : %s\n", argv [argc - 1]) ;
|
||||||
|
printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
|
||||||
|
|
||||||
|
do
|
||||||
|
{ sf_close (outfile) ;
|
||||||
|
|
||||||
|
if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
|
||||||
|
{ printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ;
|
||||||
|
sf_close (infile) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (max_speed)
|
||||||
|
{ /* This is mainly for the comparison program tests/src-evaluate.c */
|
||||||
|
sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* Update the file header after every write. */
|
||||||
|
sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
|
||||||
|
|
||||||
|
count = sample_rate_convert (infile, outfile, converter, src_ratio, sfinfo.channels, &gain) ;
|
||||||
|
}
|
||||||
|
while (count < 0) ;
|
||||||
|
|
||||||
|
printf ("Output Frames : %ld\n\n", (long) count) ;
|
||||||
|
|
||||||
|
sf_close (infile) ;
|
||||||
|
sf_close (outfile) ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static sf_count_t
|
||||||
|
sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain)
|
||||||
|
{ static float input [BUFFER_LEN] ;
|
||||||
|
static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
int error ;
|
||||||
|
double max = 0.0 ;
|
||||||
|
sf_count_t output_count = 0 ;
|
||||||
|
|
||||||
|
sf_seek (infile, 0, SEEK_SET) ;
|
||||||
|
sf_seek (outfile, 0, SEEK_SET) ;
|
||||||
|
|
||||||
|
/* Initialize the sample rate converter. */
|
||||||
|
if ((src_state = src_new (converter, channels, &error)) == NULL)
|
||||||
|
{ printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 0 ; /* Set this later. */
|
||||||
|
|
||||||
|
/* Start with zero to force load in while loop. */
|
||||||
|
src_data.input_frames = 0 ;
|
||||||
|
src_data.data_in = input ;
|
||||||
|
|
||||||
|
src_data.src_ratio = src_ratio ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = BUFFER_LEN /channels ;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* If the input buffer is empty, refill it. */
|
||||||
|
if (src_data.input_frames == 0)
|
||||||
|
{ src_data.input_frames = sf_readf_float (infile, input, BUFFER_LEN / channels) ;
|
||||||
|
src_data.data_in = input ;
|
||||||
|
|
||||||
|
/* The last read will not be a full buffer, so snd_of_input. */
|
||||||
|
if (src_data.input_frames < BUFFER_LEN / channels)
|
||||||
|
src_data.end_of_input = SF_TRUE ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)))
|
||||||
|
{ printf ("\nError : %s\n", src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Terminate if done. */
|
||||||
|
if (src_data.end_of_input && src_data.output_frames_gen == 0)
|
||||||
|
break ;
|
||||||
|
|
||||||
|
max = apply_gain (src_data.data_out, src_data.output_frames_gen, channels, max, *gain) ;
|
||||||
|
|
||||||
|
/* Write output. */
|
||||||
|
sf_writef_float (outfile, output, src_data.output_frames_gen) ;
|
||||||
|
output_count += src_data.output_frames_gen ;
|
||||||
|
|
||||||
|
src_data.data_in += src_data.input_frames_used * channels ;
|
||||||
|
src_data.input_frames -= src_data.input_frames_used ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (max > 1.0)
|
||||||
|
{ *gain = 1.0 / max ;
|
||||||
|
printf ("\nOutput has clipped. Restarting conversion to prevent clipping.\n\n") ;
|
||||||
|
return -1 ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return output_count ;
|
||||||
|
} /* sample_rate_convert */
|
||||||
|
|
||||||
|
static double
|
||||||
|
apply_gain (float * data, long frames, int channels, double max, double gain)
|
||||||
|
{
|
||||||
|
long k ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < frames * channels ; k++)
|
||||||
|
{ data [k] *= gain ;
|
||||||
|
|
||||||
|
if (fabs (data [k]) > max)
|
||||||
|
max = fabs (data [k]) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return max ;
|
||||||
|
} /* apply_gain */
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage_exit (const char *progname)
|
||||||
|
{ char lsf_ver [128] ;
|
||||||
|
const char *cptr ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
if ((cptr = strrchr (progname, '/')) != NULL)
|
||||||
|
progname = cptr + 1 ;
|
||||||
|
|
||||||
|
if ((cptr = strrchr (progname, '\\')) != NULL)
|
||||||
|
progname = cptr + 1 ;
|
||||||
|
|
||||||
|
|
||||||
|
sf_command (NULL, SFC_GET_LIB_VERSION, lsf_ver, sizeof (lsf_ver)) ;
|
||||||
|
|
||||||
|
printf ("\n"
|
||||||
|
" A Sample Rate Converter using libsndfile for file I/O and Secret \n"
|
||||||
|
" Rabbit Code (aka libsamplerate) for performing the conversion.\n"
|
||||||
|
" It works on any file format supported by libsndfile with any \n"
|
||||||
|
" number of channels (limited only by host memory).\n"
|
||||||
|
"\n"
|
||||||
|
" %s\n"
|
||||||
|
" %s\n"
|
||||||
|
"\n"
|
||||||
|
" Usage : \n"
|
||||||
|
" %s -to <new sample rate> [-c <number>] <input file> <output file>\n"
|
||||||
|
" %s -by <amount> [-c <number>] <input file> <output file>\n"
|
||||||
|
"\n", src_get_version (), lsf_ver, progname, progname) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
" The optional -c argument allows the converter type to be chosen from\n"
|
||||||
|
" the following list :"
|
||||||
|
"\n"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++)
|
||||||
|
printf (" %d : %s%s\n", k, cptr, k == DEFAULT_CONVERTER ? " (default)" : "") ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
exit (1) ;
|
||||||
|
} /* usage_exit */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#else /* (HAVE_SNFILE == 0) */
|
||||||
|
|
||||||
|
/* Alternative main function when libsndfile is not available. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{ puts (
|
||||||
|
"\n"
|
||||||
|
"****************************************************************\n"
|
||||||
|
" This example program was compiled without libsndfile \n"
|
||||||
|
" (http://www.mega-nerd.com/libsndfile/).\n"
|
||||||
|
" It is therefore completely broken and non-functional.\n"
|
||||||
|
"****************************************************************\n"
|
||||||
|
"\n"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,401 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if (HAVE_FFTW3)
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN 50000
|
||||||
|
#define MAX_FREQS 4
|
||||||
|
#define MAX_RATIOS 6
|
||||||
|
#define MAX_SPEC_LEN (1<<15)
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846264338
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{ BOOLEAN_FALSE = 0,
|
||||||
|
BOOLEAN_TRUE = 1
|
||||||
|
} ;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ int freq_count ;
|
||||||
|
double freqs [MAX_FREQS] ;
|
||||||
|
|
||||||
|
double src_ratio ;
|
||||||
|
int pass_band_peaks ;
|
||||||
|
|
||||||
|
double snr ;
|
||||||
|
double peak_value ;
|
||||||
|
} SINGLE_TEST ;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ int converter ;
|
||||||
|
int tests ;
|
||||||
|
int do_bandwidth_test ;
|
||||||
|
SINGLE_TEST test_data [10] ;
|
||||||
|
} CONVERTER_TEST ;
|
||||||
|
|
||||||
|
static double snr_test (SINGLE_TEST *snr_test_data, int number, int converter, int verbose) ;
|
||||||
|
static double find_peak (float *output, int output_len) ;
|
||||||
|
static double bandwidth_test (int converter, int verbose) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv [])
|
||||||
|
{ CONVERTER_TEST snr_test_data [] =
|
||||||
|
{
|
||||||
|
{ SRC_ZERO_ORDER_HOLD,
|
||||||
|
8,
|
||||||
|
BOOLEAN_FALSE,
|
||||||
|
{ { 1, { 0.01111111111 }, 3.0, 1, 28.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.6, 1, 36.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.3, 1, 36.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.001, 1, 38.0, 1.0 },
|
||||||
|
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 14.0, .96 },
|
||||||
|
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 12.0, .96 },
|
||||||
|
{ 1, { 0.3511111111 }, 1.33, 1, 10.0, 1.0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{ SRC_LINEAR,
|
||||||
|
8,
|
||||||
|
BOOLEAN_FALSE,
|
||||||
|
{ { 1, { 0.01111111111 }, 3.0, 1, 73.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.6, 1, 73.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.3, 1, 73.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.001, 1, 77.0, 1.0 },
|
||||||
|
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 16.0, 0.96 },
|
||||||
|
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 26.0, 0.96 },
|
||||||
|
{ 1, { 0.3511111111 }, 1.33, 1, 14.4, 0.99 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{ SRC_SINC_FASTEST,
|
||||||
|
9,
|
||||||
|
BOOLEAN_TRUE,
|
||||||
|
{ { 1, { 0.01111111111 }, 3.0, 1, 100.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.6, 1, 99.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.3, 1, 100.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.001, 1, 100.0, 1.0 },
|
||||||
|
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 97.0, 1.0 },
|
||||||
|
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 100.0, 0.5 },
|
||||||
|
{ 2, { 0.011111, 0.45 }, 0.6, 1, 97.0, 0.5 },
|
||||||
|
{ 1, { 0.3511111111 }, 1.33, 1, 97.0, 1.0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{ SRC_SINC_MEDIUM_QUALITY,
|
||||||
|
9,
|
||||||
|
BOOLEAN_TRUE,
|
||||||
|
{ { 1, { 0.01111111111 }, 3.0, 1, 130.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.6, 1, 132.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.3, 1, 135.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.001, 1, 133.0, 1.0 },
|
||||||
|
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 127.0, 1.0 },
|
||||||
|
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 124.0, 0.5 },
|
||||||
|
{ 2, { 0.011111, 0.45 }, 0.6, 1, 126.0, 0.5 },
|
||||||
|
{ 1, { 0.43111111111 }, 1.33, 1, 121.0, 1.0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{ SRC_SINC_BEST_QUALITY,
|
||||||
|
9,
|
||||||
|
BOOLEAN_TRUE,
|
||||||
|
{ { 1, { 0.01111111111 }, 3.0, 1, 147.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.6, 1, 147.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 0.3, 1, 147.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 },
|
||||||
|
{ 1, { 0.01111111111 }, 1.001, 1, 146.0, 1.0 },
|
||||||
|
{ 2, { 0.011111, 0.324 }, 1.9999, 2, 147.0, 1.0 },
|
||||||
|
{ 2, { 0.012345, 0.457 }, 0.456789, 1, 148.0, 0.5 },
|
||||||
|
{ 2, { 0.011111, 0.45 }, 0.6, 1, 145.0, 0.5 },
|
||||||
|
{ 1, { 0.43111111111 }, 1.33, 1, 145.0, 1.0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} ; /* snr_test_data */
|
||||||
|
|
||||||
|
double best_snr, snr, freq3dB ;
|
||||||
|
int j, k, converter, verbose = 0 ;
|
||||||
|
|
||||||
|
if (argc == 2 && strcmp (argv [1], "--verbose") == 0)
|
||||||
|
verbose = 1 ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
for (j = 0 ; j < ARRAY_LEN (snr_test_data) ; j++)
|
||||||
|
{ best_snr = 5000.0 ;
|
||||||
|
|
||||||
|
converter = snr_test_data [j].converter ;
|
||||||
|
|
||||||
|
printf (" Converter %d : %s\n", converter, src_get_name (converter)) ;
|
||||||
|
printf (" %s\n", src_get_description (converter)) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < snr_test_data [j].tests ; k++)
|
||||||
|
{ snr = snr_test (&(snr_test_data [j].test_data [k]), k, converter, verbose) ;
|
||||||
|
if (best_snr > snr)
|
||||||
|
best_snr = snr ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
printf (" Worst case Signal-to-Noise Ratio : %.2f dB.\n", best_snr) ;
|
||||||
|
|
||||||
|
if (snr_test_data [j].do_bandwidth_test == BOOLEAN_FALSE)
|
||||||
|
{ puts (" Bandwith test not performed on this converter.\n") ;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
|
||||||
|
freq3dB = bandwidth_test (converter, verbose) ;
|
||||||
|
|
||||||
|
printf (" Measured -3dB rolloff point : %5.2f %%.\n\n", freq3dB) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static double
|
||||||
|
snr_test (SINGLE_TEST *test_data, int number, int converter, int verbose)
|
||||||
|
{ static float data [BUFFER_LEN + 1] ;
|
||||||
|
static float output [MAX_SPEC_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
|
||||||
|
double output_peak, snr ;
|
||||||
|
int k, output_len, input_len, error ;
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
{ printf ("\tSignal-to-Noise Ratio Test %d.\n"
|
||||||
|
"\t=====================================\n", number) ;
|
||||||
|
printf ("\tFrequencies : [ ") ;
|
||||||
|
for (k = 0 ; k < test_data->freq_count ; k++)
|
||||||
|
printf ("%6.4f ", test_data->freqs [k]) ;
|
||||||
|
|
||||||
|
printf ("]\n\tSRC Ratio : %8.4f\n", test_data->src_ratio) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ printf ("\tSignal-to-Noise Ratio Test %d : ", number) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Set up the output array. */
|
||||||
|
if (test_data->src_ratio >= 1.0)
|
||||||
|
{ output_len = MAX_SPEC_LEN ;
|
||||||
|
input_len = (int) ceil (MAX_SPEC_LEN / test_data->src_ratio) ;
|
||||||
|
if (input_len > BUFFER_LEN)
|
||||||
|
input_len = BUFFER_LEN ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ input_len = BUFFER_LEN ;
|
||||||
|
output_len = (int) ceil (BUFFER_LEN * test_data->src_ratio) ;
|
||||||
|
output_len &= ((-1) << 4) ;
|
||||||
|
if (output_len > MAX_SPEC_LEN)
|
||||||
|
output_len = MAX_SPEC_LEN ;
|
||||||
|
input_len = (int) ceil (output_len / test_data->src_ratio) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
memset (output, 0, sizeof (output)) ;
|
||||||
|
|
||||||
|
/* Generate input data array. */
|
||||||
|
gen_windowed_sines (test_data->freq_count, test_data->freqs, 1.0, data, input_len) ;
|
||||||
|
|
||||||
|
/* Perform sample rate conversion. */
|
||||||
|
if ((src_state = src_new (converter, 1, &error)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 1 ; /* Only one buffer worth of input. */
|
||||||
|
|
||||||
|
src_data.data_in = data ;
|
||||||
|
src_data.input_frames = input_len ;
|
||||||
|
|
||||||
|
src_data.src_ratio = test_data->src_ratio ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = output_len ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf ("\tOutput Len : %ld\n", src_data.output_frames_gen) ;
|
||||||
|
|
||||||
|
if (abs (src_data.output_frames_gen - output_len) > 4)
|
||||||
|
{ printf ("\n\nLine %d : output data length should be %d.\n\n", __LINE__, output_len) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Check output peak. */
|
||||||
|
output_peak = find_peak (output, src_data.output_frames_gen) ;
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf ("\tOutput Peak : %6.4f\n", output_peak) ;
|
||||||
|
|
||||||
|
if (fabs (output_peak - test_data->peak_value) > 0.01)
|
||||||
|
{ printf ("\n\nLine %d : output peak (%6.4f) should be %6.4f\n\n", __LINE__, output_peak, test_data->peak_value) ;
|
||||||
|
save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, output_len) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Calculate signal-to-noise ratio. */
|
||||||
|
snr = calculate_snr (output, src_data.output_frames_gen, test_data->pass_band_peaks) ;
|
||||||
|
|
||||||
|
if (snr < 0.0)
|
||||||
|
{ /* An error occurred. */
|
||||||
|
save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, src_data.output_frames_gen) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf ("\tSNR Ratio : %.2f dB\n", snr) ;
|
||||||
|
|
||||||
|
if (snr < test_data->snr)
|
||||||
|
{ printf ("\n\nLine %d : SNR (%5.2f) should be > %6.2f dB\n\n", __LINE__, snr, test_data->snr) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
puts ("\t-------------------------------------\n\tPass\n") ;
|
||||||
|
else
|
||||||
|
puts ("Pass") ;
|
||||||
|
|
||||||
|
return snr ;
|
||||||
|
} /* snr_test */
|
||||||
|
|
||||||
|
static double
|
||||||
|
find_peak (float *data, int len)
|
||||||
|
{ double peak = 0.0 ;
|
||||||
|
int k = 0 ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < len ; k++)
|
||||||
|
if (fabs (data [k]) > peak)
|
||||||
|
peak = fabs (data [k]) ;
|
||||||
|
|
||||||
|
return peak ;
|
||||||
|
} /* find_peak */
|
||||||
|
|
||||||
|
|
||||||
|
static double
|
||||||
|
find_attenuation (double freq, int converter, int verbose)
|
||||||
|
{ static float input [BUFFER_LEN] ;
|
||||||
|
static float output [2 * BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
double output_peak ;
|
||||||
|
int error ;
|
||||||
|
|
||||||
|
gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 1 ; /* Only one buffer worth of input. */
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
src_data.input_frames = BUFFER_LEN ;
|
||||||
|
|
||||||
|
src_data.src_ratio = 1.999 ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) ;
|
||||||
|
|
||||||
|
if ((error = src_simple (&src_data, converter, 1)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
output_peak = find_peak (output, ARRAY_LEN (output)) ;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf ("\tFreq : %6f InPeak : %6f OutPeak : %6f Atten : %6.2f dB\n",
|
||||||
|
freq, 1.0, output_peak, 20.0 * log10 (1.0 / output_peak)) ;
|
||||||
|
|
||||||
|
return 20.0 * log10 (1.0 / output_peak) ;
|
||||||
|
} /* find_attenuation */
|
||||||
|
|
||||||
|
static double
|
||||||
|
bandwidth_test (int converter, int verbose)
|
||||||
|
{ double f1, f2, a1, a2 ;
|
||||||
|
double freq, atten ;
|
||||||
|
|
||||||
|
f1 = 0.35 ;
|
||||||
|
a1 = find_attenuation (f1, converter, verbose) ;
|
||||||
|
|
||||||
|
f2 = 0.495 ;
|
||||||
|
a2 = find_attenuation (f2, converter, verbose) ;
|
||||||
|
|
||||||
|
if (a1 > 3.0 || a2 < 3.0)
|
||||||
|
{ printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
while (a2 - a1 > 1.0)
|
||||||
|
{ freq = f1 + 0.5 * (f2 - f1) ;
|
||||||
|
atten = find_attenuation (freq, converter, verbose) ;
|
||||||
|
|
||||||
|
if (atten < 3.0)
|
||||||
|
{ f1 = freq ;
|
||||||
|
a1 = atten ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ f2 = freq ;
|
||||||
|
a2 = atten ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ;
|
||||||
|
|
||||||
|
return 200.0 * freq ;
|
||||||
|
} /* bandwidth_test */
|
||||||
|
|
||||||
|
#else /* (HAVE_FFTW3) == 0 */
|
||||||
|
|
||||||
|
/* Alternative main function when librfftw is not available. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{ puts ("\n"
|
||||||
|
"****************************************************************\n"
|
||||||
|
" This test cannot be run without FFTW (http://www.fftw.org/).\n"
|
||||||
|
" Both the real and the complex versions of the library are\n"
|
||||||
|
" required.") ;
|
||||||
|
puts ("****************************************************************\n") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,339 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define SHORT_BUFFER_LEN 2048
|
||||||
|
#define LONG_BUFFER_LEN ((1 << 16) - 20)
|
||||||
|
|
||||||
|
static void simple_test (int converter) ;
|
||||||
|
static void stream_test (int converter, double ratio) ;
|
||||||
|
static void init_term_test (int converter, double ratio) ;
|
||||||
|
|
||||||
|
static int next_block_length (int reset) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{ static double src_ratios [] =
|
||||||
|
{ 0.999900, 1.000100, 0.789012, 1.200000, 0.333333, 3.100000,
|
||||||
|
0.125000, 8.000000, 0.099900, 9.990000, 0.100000, 10.00000
|
||||||
|
} ;
|
||||||
|
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
puts ("\n Zero Order Hold interpolator:") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
init_term_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
|
||||||
|
puts ("") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ;
|
||||||
|
|
||||||
|
|
||||||
|
puts ("\n Linear interpolator:") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
init_term_test (SRC_LINEAR, src_ratios [k]) ;
|
||||||
|
puts ("") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
stream_test (SRC_LINEAR, src_ratios [k]) ;
|
||||||
|
|
||||||
|
|
||||||
|
puts ("\n Sinc interpolator:") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
init_term_test (SRC_SINC_FASTEST, src_ratios [k]) ;
|
||||||
|
puts ("") ;
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++)
|
||||||
|
stream_test (SRC_SINC_FASTEST, src_ratios [k]) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
simple_test (SRC_SINC_FASTEST) ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
static void
|
||||||
|
simple_test (int converter)
|
||||||
|
{
|
||||||
|
int ilen = 199030, olen = 1000, error ;
|
||||||
|
|
||||||
|
{
|
||||||
|
float in [ilen] ;
|
||||||
|
float out [olen] ;
|
||||||
|
double ratio = (1.0 * olen) / ilen ;
|
||||||
|
SRC_DATA src_data =
|
||||||
|
{ in, out,
|
||||||
|
ilen, olen,
|
||||||
|
0, 0, 0,
|
||||||
|
ratio
|
||||||
|
} ;
|
||||||
|
|
||||||
|
error = src_simple (&src_data, converter, 1) ;
|
||||||
|
if (error)
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* simple_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_term_test (int converter, double src_ratio)
|
||||||
|
{ static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
|
||||||
|
int k, input_len, output_len, error, terminate ;
|
||||||
|
|
||||||
|
printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
/* Calculate maximun input and output lengths. */
|
||||||
|
if (src_ratio >= 1.0)
|
||||||
|
{ output_len = SHORT_BUFFER_LEN ;
|
||||||
|
input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ input_len = SHORT_BUFFER_LEN ;
|
||||||
|
output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Reduce input_len by 10 so output is longer than necessary. */
|
||||||
|
input_len -= 10 ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < ARRAY_LEN (input) ; k++)
|
||||||
|
input [k] = 1.0 ;
|
||||||
|
|
||||||
|
if (output_len > SHORT_BUFFER_LEN)
|
||||||
|
{ printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
src_data.input_frames = input_len ;
|
||||||
|
|
||||||
|
src_data.src_ratio = src_ratio ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = SHORT_BUFFER_LEN ;
|
||||||
|
|
||||||
|
if ((error = src_simple (&src_data, converter, 1)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ;
|
||||||
|
|
||||||
|
if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate)
|
||||||
|
{ printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ;
|
||||||
|
printf ("\tterminate : %d\n", terminate) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
|
||||||
|
printf ("\tinput_len : %d\n"
|
||||||
|
"\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ;
|
||||||
|
printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (abs (src_data.input_frames_used - input_len) > 1)
|
||||||
|
{ printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n",
|
||||||
|
__LINE__, input_len, src_data.input_frames_used) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
|
||||||
|
printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (fabs (output [0]) < 0.1)
|
||||||
|
{ printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ;
|
||||||
|
printf ("\toutput [0] == %f\n\n", output [0]) ;
|
||||||
|
exit (1) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* init_term_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
stream_test (int converter, double src_ratio)
|
||||||
|
{ static float input [LONG_BUFFER_LEN], output [LONG_BUFFER_LEN] ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
|
||||||
|
int input_len, output_len, current_in, current_out ;
|
||||||
|
int k, error, terminate ;
|
||||||
|
|
||||||
|
printf ("\tstream_test (SRC ratio = %7.4f) .......... ", src_ratio) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
/* Erik */
|
||||||
|
for (k = 0 ; k < LONG_BUFFER_LEN ; k++) input [k] = k * 1.0 ;
|
||||||
|
|
||||||
|
/* Calculate maximun input and output lengths. */
|
||||||
|
if (src_ratio >= 1.0)
|
||||||
|
{ output_len = LONG_BUFFER_LEN ;
|
||||||
|
input_len = (int) floor (LONG_BUFFER_LEN / src_ratio) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ input_len = LONG_BUFFER_LEN ;
|
||||||
|
output_len = (int) floor (LONG_BUFFER_LEN * src_ratio) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Reduce input_len by 10 so output is longer than necessary. */
|
||||||
|
input_len -= 20 ;
|
||||||
|
|
||||||
|
if (output_len > LONG_BUFFER_LEN)
|
||||||
|
{ printf ("\n\nLine %d : output_len > LONG_BUFFER_LEN\n\n", __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
current_in = current_out = 0 ;
|
||||||
|
|
||||||
|
/* Perform sample rate conversion. */
|
||||||
|
if ((src_state = src_new (converter, 1, &error)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 0 ; /* Set this later. */
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
|
||||||
|
src_data.src_ratio = src_ratio ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) / 10 ;
|
||||||
|
|
||||||
|
terminate = 1 + (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
src_data.input_frames = next_block_length (0) ;
|
||||||
|
src_data.input_frames = MIN (src_data.input_frames, input_len - current_in) ;
|
||||||
|
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) - current_out ;
|
||||||
|
/*-Erik MIN (src_data.output_frames, output_len - current_out) ;-*/
|
||||||
|
|
||||||
|
src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
|
||||||
|
printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.end_of_input && src_data.output_frames_gen == 0)
|
||||||
|
break ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used > src_data.input_frames)
|
||||||
|
{ printf ("\n\nLine %d : input_frames_used > input_frames\n\n", __LINE__) ;
|
||||||
|
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
|
||||||
|
printf (" src_data.input_frames_used : %ld\n", src_data.input_frames_used) ;
|
||||||
|
printf (" src_data.output_frames : %ld\n", src_data.output_frames) ;
|
||||||
|
printf (" src_data.output_frames_gen : %ld\n\n", src_data.output_frames_gen) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used < 0)
|
||||||
|
{ printf ("\n\nLine %d : input_frames_used (%ld) < 0\n\n", __LINE__, src_data.input_frames_used) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.output_frames_gen < 0)
|
||||||
|
{ printf ("\n\nLine %d : output_frames_gen (%ld) < 0\n\n", __LINE__, src_data.output_frames_gen) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
current_in += src_data.input_frames_used ;
|
||||||
|
current_out += src_data.output_frames_gen ;
|
||||||
|
|
||||||
|
if (current_in > input_len + terminate)
|
||||||
|
{ printf ("\n\nLine %d : current_in (%d) > input_len (%d + %d)\n\n", __LINE__, current_in, input_len, terminate) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (current_out > output_len)
|
||||||
|
{ printf ("\n\nLine %d : current_out (%d) > output_len (%d)\n\n", __LINE__, current_out, output_len) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used > input_len)
|
||||||
|
{ printf ("\n\nLine %d : input_frames_used (%ld) > %d\n\n", __LINE__, src_data.input_frames_used, input_len) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.output_frames_gen > output_len)
|
||||||
|
{ printf ("\n\nLine %d : output_frames_gen (%ld) > %d\n\n", __LINE__, src_data.output_frames_gen, output_len) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.data_in == NULL && src_data.output_frames_gen == 0)
|
||||||
|
break ;
|
||||||
|
|
||||||
|
|
||||||
|
src_data.data_in += src_data.input_frames_used ;
|
||||||
|
src_data.data_out += src_data.output_frames_gen ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
if (fabs (current_out - src_ratio * input_len) > terminate)
|
||||||
|
{ printf ("\n\nLine %d : bad output data length %d should be %2.1f +/- %d.\n", __LINE__,
|
||||||
|
current_out, src_ratio * input_len, terminate) ;
|
||||||
|
printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
|
||||||
|
printf ("\tinput_len : %d\n\tinput_used : %d\n", input_len, current_in) ;
|
||||||
|
printf ("\toutput_len : %d\n\toutput_gen : %d\n\n", output_len, current_out) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (current_in != input_len)
|
||||||
|
{ printf ("\n\nLine %d : unused input.\n", __LINE__) ;
|
||||||
|
printf ("\tinput_len : %d\n", input_len) ;
|
||||||
|
printf ("\tinput_frames_used : %d\n\n", current_in) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* stream_test */
|
||||||
|
|
||||||
|
static int
|
||||||
|
next_block_length (int reset)
|
||||||
|
{ static int block_lengths [] = /* Should be an odd length. */
|
||||||
|
{ /*-2, 500, 5, 400, 10, 300, 20, 200, 50, 100, 70 -*/
|
||||||
|
5, 400, 10, 300, 20, 200, 50, 100, 70
|
||||||
|
} ;
|
||||||
|
static int block_len_index = 0 ;
|
||||||
|
|
||||||
|
if (reset)
|
||||||
|
block_len_index = 0 ;
|
||||||
|
else
|
||||||
|
block_len_index = (block_len_index + 1) % ARRAY_LEN (block_lengths) ;
|
||||||
|
|
||||||
|
return block_lengths [block_len_index] ;
|
||||||
|
} /* next_block_length */
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2004-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "float_cast.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN (1<<16)
|
||||||
|
|
||||||
|
static float input [BUFFER_LEN] ;
|
||||||
|
static float output [BUFFER_LEN] ;
|
||||||
|
|
||||||
|
static long
|
||||||
|
throughput_test (int converter, long best_throughput)
|
||||||
|
{ SRC_DATA src_data ;
|
||||||
|
clock_t start_time, clock_time ;
|
||||||
|
double duration ;
|
||||||
|
long total_frames = 0, throughput ;
|
||||||
|
int error ;
|
||||||
|
|
||||||
|
printf (" %-30s ", src_get_name (converter)) ;
|
||||||
|
fflush (stdout) ;
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
src_data.input_frames = ARRAY_LEN (input) ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) ;
|
||||||
|
|
||||||
|
src_data.src_ratio = 0.99 ;
|
||||||
|
|
||||||
|
sleep (2) ;
|
||||||
|
|
||||||
|
start_time = clock () ;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((error = src_simple (&src_data, converter, 1)) != 0)
|
||||||
|
{ puts (src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
total_frames += src_data.output_frames_gen ;
|
||||||
|
|
||||||
|
clock_time = clock () - start_time ;
|
||||||
|
duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
|
||||||
|
}
|
||||||
|
while (duration < 3.0) ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used != ARRAY_LEN (input))
|
||||||
|
{ printf ("\n\nLine %d : input frames used %ld should be %d\n", __LINE__, src_data.input_frames_used, ARRAY_LEN (input)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
|
||||||
|
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
|
||||||
|
printf (" input len : %d\n", ARRAY_LEN (input)) ;
|
||||||
|
printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
|
||||||
|
floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
throughput = lrint (floor (total_frames / duration)) ;
|
||||||
|
|
||||||
|
if (best_throughput == 0)
|
||||||
|
{ best_throughput = MAX (throughput, best_throughput) ;
|
||||||
|
printf ("%5.2f %10ld\n", duration, throughput) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ best_throughput = MAX (throughput, best_throughput) ;
|
||||||
|
printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return best_throughput ;
|
||||||
|
} /* throughput_test */
|
||||||
|
|
||||||
|
static void
|
||||||
|
single_run (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
"\n"
|
||||||
|
" Converter Duration Throughput\n"
|
||||||
|
" -----------------------------------------------------------"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
throughput_test (SRC_ZERO_ORDER_HOLD, 0) ;
|
||||||
|
throughput_test (SRC_LINEAR, 0) ;
|
||||||
|
throughput_test (SRC_SINC_FASTEST, 0) ;
|
||||||
|
throughput_test (SRC_SINC_MEDIUM_QUALITY, 0) ;
|
||||||
|
throughput_test (SRC_SINC_BEST_QUALITY, 0) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
return ;
|
||||||
|
} /* single_run */
|
||||||
|
|
||||||
|
static void
|
||||||
|
multi_run (int run_count)
|
||||||
|
{ long zero_order_hold = 0, linear = 0 ;
|
||||||
|
long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
"\n"
|
||||||
|
" Converter Duration Throughput Best Throughput\n"
|
||||||
|
" --------------------------------------------------------------------------------"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < run_count ; k++)
|
||||||
|
{ zero_order_hold = throughput_test (SRC_ZERO_ORDER_HOLD, zero_order_hold) ;
|
||||||
|
linear = throughput_test (SRC_LINEAR, linear) ;
|
||||||
|
sinc_fastest = throughput_test (SRC_SINC_FASTEST, sinc_fastest) ;
|
||||||
|
sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, sinc_medium) ;
|
||||||
|
sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, sinc_best) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
/* Let the CPU cool down. We might be running on a laptop. */
|
||||||
|
sleep (10) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
printf ("\n CPU name : %s\n", get_cpu_name ()) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
"\n"
|
||||||
|
" Converter Best Throughput\n"
|
||||||
|
" ------------------------------------------------"
|
||||||
|
) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_ZERO_ORDER_HOLD), zero_order_hold) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_LINEAR), linear) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ;
|
||||||
|
printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
} /* multi_run */
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage_exit (const char * argv0)
|
||||||
|
{ const char * cptr ;
|
||||||
|
|
||||||
|
if ((cptr = strrchr (argv0, '/')) != NULL)
|
||||||
|
argv0 = cptr ;
|
||||||
|
|
||||||
|
printf (
|
||||||
|
"Usage :\n"
|
||||||
|
" %s - Single run of the throughput test.\n"
|
||||||
|
" %s --best-of N - Do N runs of test a print bext result.\n"
|
||||||
|
"\n",
|
||||||
|
argv0, argv0) ;
|
||||||
|
|
||||||
|
exit (0) ;
|
||||||
|
} /* usage_exit */
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char ** argv)
|
||||||
|
{ double freq ;
|
||||||
|
|
||||||
|
memset (input, 0, sizeof (input)) ;
|
||||||
|
freq = 0.01 ;
|
||||||
|
gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
single_run () ;
|
||||||
|
else if (argc == 3 && strcmp (argv [1], "--best-of") == 0)
|
||||||
|
{ int run_count = atoi (argv [2]) ;
|
||||||
|
|
||||||
|
if (run_count < 1 || run_count > 20)
|
||||||
|
{ printf ("Please be sensible. Run count should be in range (1, 10].\n") ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
multi_run (run_count) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usage_exit (argv [0]) ;
|
||||||
|
|
||||||
|
puts (
|
||||||
|
" Duration is in seconds.\n"
|
||||||
|
" Throughput is in samples/sec (more is better).\n"
|
||||||
|
) ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846264338
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len)
|
||||||
|
{ int k, freq ;
|
||||||
|
double amplitude, phase ;
|
||||||
|
|
||||||
|
amplitude = max / freq_count ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < output_len ; k++)
|
||||||
|
output [k] = 0.0 ;
|
||||||
|
|
||||||
|
for (freq = 0 ; freq < freq_count ; freq++)
|
||||||
|
{ phase = 0.9 * M_PI / freq_count ;
|
||||||
|
|
||||||
|
if (freqs [freq] <= 0.0 || freqs [freq] >= 0.5)
|
||||||
|
{ printf ("\n%s : Error : freq [%d] == %g is out of range. Should be < 0.5.\n", __FILE__, freq, freqs [freq]) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < output_len ; k++)
|
||||||
|
output [k] += amplitude * sin (freqs [freq] * (2 * k) * M_PI + phase) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Apply Hanning Window. */
|
||||||
|
for (k = 0 ; k < output_len ; k++)
|
||||||
|
output [k] *= 0.5 - 0.5 * cos ((2 * k) * M_PI / (output_len - 1)) ;
|
||||||
|
|
||||||
|
/* data [k] *= 0.3635819 - 0.4891775 * cos ((2 * k) * M_PI / (output_len - 1))
|
||||||
|
+ 0.1365995 * cos ((4 * k) * M_PI / (output_len - 1))
|
||||||
|
- 0.0106411 * cos ((6 * k) * M_PI / (output_len - 1)) ;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* gen_windowed_sines */
|
||||||
|
|
||||||
|
void
|
||||||
|
save_oct_float (char *filename, float *input, int in_len, float *output, int out_len)
|
||||||
|
{ FILE *file ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("Dumping input and output data to file : %s.\n\n", filename) ;
|
||||||
|
|
||||||
|
if (! (file = fopen (filename, "w")))
|
||||||
|
return ;
|
||||||
|
|
||||||
|
fprintf (file, "# Not created by Octave\n") ;
|
||||||
|
|
||||||
|
fprintf (file, "# name: input\n") ;
|
||||||
|
fprintf (file, "# type: matrix\n") ;
|
||||||
|
fprintf (file, "# rows: %d\n", in_len) ;
|
||||||
|
fprintf (file, "# columns: 1\n") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < in_len ; k++)
|
||||||
|
fprintf (file, "% g\n", input [k]) ;
|
||||||
|
|
||||||
|
fprintf (file, "# name: output\n") ;
|
||||||
|
fprintf (file, "# type: matrix\n") ;
|
||||||
|
fprintf (file, "# rows: %d\n", out_len) ;
|
||||||
|
fprintf (file, "# columns: 1\n") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < out_len ; k++)
|
||||||
|
fprintf (file, "% g\n", output [k]) ;
|
||||||
|
|
||||||
|
fclose (file) ;
|
||||||
|
return ;
|
||||||
|
} /* save_oct_float */
|
||||||
|
|
||||||
|
void
|
||||||
|
save_oct_double (char *filename, double *input, int in_len, double *output, int out_len)
|
||||||
|
{ FILE *file ;
|
||||||
|
int k ;
|
||||||
|
|
||||||
|
printf ("Dumping input and output data to file : %s.\n\n", filename) ;
|
||||||
|
|
||||||
|
if (! (file = fopen (filename, "w")))
|
||||||
|
return ;
|
||||||
|
|
||||||
|
fprintf (file, "# Not created by Octave\n") ;
|
||||||
|
|
||||||
|
fprintf (file, "# name: input\n") ;
|
||||||
|
fprintf (file, "# type: matrix\n") ;
|
||||||
|
fprintf (file, "# rows: %d\n", in_len) ;
|
||||||
|
fprintf (file, "# columns: 1\n") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < in_len ; k++)
|
||||||
|
fprintf (file, "% g\n", input [k]) ;
|
||||||
|
|
||||||
|
fprintf (file, "# name: output\n") ;
|
||||||
|
fprintf (file, "# type: matrix\n") ;
|
||||||
|
fprintf (file, "# rows: %d\n", out_len) ;
|
||||||
|
fprintf (file, "# columns: 1\n") ;
|
||||||
|
|
||||||
|
for (k = 0 ; k < out_len ; k++)
|
||||||
|
fprintf (file, "% g\n", output [k]) ;
|
||||||
|
|
||||||
|
fclose (file) ;
|
||||||
|
return ;
|
||||||
|
} /* save_oct_double */
|
||||||
|
|
||||||
|
void
|
||||||
|
interleave_data (const float *in, float *out, int frames, int channels)
|
||||||
|
{ int fr, ch ;
|
||||||
|
|
||||||
|
for (fr = 0 ; fr < frames ; fr++)
|
||||||
|
for (ch = 0 ; ch < channels ; ch++)
|
||||||
|
out [ch + channels * fr] = in [fr + frames * ch] ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* interleave_data */
|
||||||
|
|
||||||
|
void
|
||||||
|
deinterleave_data (const float *in, float *out, int frames, int channels)
|
||||||
|
{ int fr, ch ;
|
||||||
|
|
||||||
|
for (ch = 0 ; ch < channels ; ch++)
|
||||||
|
for (fr = 0 ; fr < frames ; fr++)
|
||||||
|
out [fr + frames * ch] = in [ch + channels * fr] ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* deinterleave_data */
|
||||||
|
|
||||||
|
void
|
||||||
|
reverse_data (float *data, int datalen)
|
||||||
|
{ int left, right ;
|
||||||
|
float temp ;
|
||||||
|
|
||||||
|
left = 0 ;
|
||||||
|
right = datalen - 1 ;
|
||||||
|
|
||||||
|
while (left < right)
|
||||||
|
{ temp = data [left] ;
|
||||||
|
data [left] = data [right] ;
|
||||||
|
data [right] = temp ;
|
||||||
|
left ++ ;
|
||||||
|
right -- ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
} /* reverse_data */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_cpu_name (void)
|
||||||
|
{
|
||||||
|
const char *name = "Unknown", *search = NULL ;
|
||||||
|
static char buffer [512] ;
|
||||||
|
FILE * file = NULL ;
|
||||||
|
int is_pipe = 0 ;
|
||||||
|
|
||||||
|
#if defined (__linux__)
|
||||||
|
file = fopen ("/proc/cpuinfo", "r") ;
|
||||||
|
search = "model name" ;
|
||||||
|
#elif defined (__APPLE__)
|
||||||
|
file = popen ("/usr/sbin/system_profiler -detailLevel full SPHardwareDataType", "r") ;
|
||||||
|
search = "Processor Name" ;
|
||||||
|
is_pipe = 1 ;
|
||||||
|
#elif defined (__FreeBSD__)
|
||||||
|
file = popen ("sysctl -a", "r") ;
|
||||||
|
search = "hw.model" ;
|
||||||
|
is_pipe = 1 ;
|
||||||
|
#else
|
||||||
|
file = NULL ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (file == NULL)
|
||||||
|
return name ;
|
||||||
|
|
||||||
|
if (search == NULL)
|
||||||
|
{ printf ("Error : search is NULL in function %s.\n", __func__) ;
|
||||||
|
return name ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
while (fgets (buffer, sizeof (buffer), file) != NULL)
|
||||||
|
if (strstr (buffer, search))
|
||||||
|
{ char *src, *dest ;
|
||||||
|
|
||||||
|
if ((src = strchr (buffer, ':')) != NULL)
|
||||||
|
{ src ++ ;
|
||||||
|
while (isspace (src [0]))
|
||||||
|
src ++ ;
|
||||||
|
name = src ;
|
||||||
|
|
||||||
|
/* Remove consecutive spaces. */
|
||||||
|
src ++ ;
|
||||||
|
for (dest = src ; src [0] ; src ++)
|
||||||
|
{ if (isspace (src [0]) && isspace (dest [-1]))
|
||||||
|
continue ;
|
||||||
|
dest [0] = src [0] ;
|
||||||
|
dest ++ ;
|
||||||
|
} ;
|
||||||
|
dest [0] = 0 ;
|
||||||
|
break ;
|
||||||
|
} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (is_pipe)
|
||||||
|
pclose (file) ;
|
||||||
|
else
|
||||||
|
fclose (file) ;
|
||||||
|
|
||||||
|
return name ;
|
||||||
|
} /* get_cpu_name */
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ABS(a) (((a) < 0) ? - (a) : (a))
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
|
||||||
|
|
||||||
|
void gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len) ;
|
||||||
|
|
||||||
|
void save_oct_float (char *filename, float *input, int in_len, float *output, int out_len) ;
|
||||||
|
void save_oct_double (char *filename, double *input, int in_len, double *output, int out_len) ;
|
||||||
|
|
||||||
|
void interleave_data (const float *in, float *out, int frames, int channels) ;
|
||||||
|
|
||||||
|
void deinterleave_data (const float *in, float *out, int frames, int channels) ;
|
||||||
|
|
||||||
|
void reverse_data (float *data, int datalen) ;
|
||||||
|
|
||||||
|
double calculate_snr (float *data, int len, int expected_peaks) ;
|
||||||
|
|
||||||
|
const char * get_cpu_name (void) ;
|
||||||
|
|
||||||
|
#if OS_IS_WIN32
|
||||||
|
/*
|
||||||
|
** Extra Win32 hacks.
|
||||||
|
**
|
||||||
|
** Despite Microsoft claim of windows being POSIX compatibile it has '_sleep'
|
||||||
|
** instead of 'sleep'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define sleep _sleep
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation; either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software
|
||||||
|
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUFFER_LEN (1 << 16)
|
||||||
|
|
||||||
|
static void varispeed_test (int converter, double target_snr) ;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
puts ("") ;
|
||||||
|
printf (" Zero Order Hold interpolator : ") ;
|
||||||
|
varispeed_test (SRC_ZERO_ORDER_HOLD, 10.0) ;
|
||||||
|
|
||||||
|
printf (" Linear interpolator : ") ;
|
||||||
|
varispeed_test (SRC_LINEAR, 10.0) ;
|
||||||
|
|
||||||
|
printf (" Sinc interpolator : ") ;
|
||||||
|
varispeed_test (SRC_SINC_FASTEST, 115.0) ;
|
||||||
|
|
||||||
|
puts ("") ;
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
} /* main */
|
||||||
|
|
||||||
|
static void
|
||||||
|
varispeed_test (int converter, double target_snr)
|
||||||
|
{ static float input [BUFFER_LEN], output [BUFFER_LEN] ;
|
||||||
|
double sine_freq, snr ;
|
||||||
|
|
||||||
|
SRC_STATE *src_state ;
|
||||||
|
SRC_DATA src_data ;
|
||||||
|
|
||||||
|
int input_len, error ;
|
||||||
|
|
||||||
|
memset (input, 0, sizeof (input)) ;
|
||||||
|
|
||||||
|
input_len = ARRAY_LEN (input) / 2 ;
|
||||||
|
|
||||||
|
sine_freq = 0.0111 ;
|
||||||
|
gen_windowed_sines (1, &sine_freq, 1.0, input, input_len) ;
|
||||||
|
|
||||||
|
/* Perform sample rate conversion. */
|
||||||
|
if ((src_state = src_new (converter, 1, &error)) == NULL)
|
||||||
|
{ printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 1 ;
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
src_data.input_frames = input_len ;
|
||||||
|
|
||||||
|
src_data.src_ratio = 3.0 ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) ;
|
||||||
|
|
||||||
|
if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
|
||||||
|
printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used != input_len)
|
||||||
|
{ printf ("\n\nLine %d : unused input.\n", __LINE__) ;
|
||||||
|
printf ("\tinput_len : %d\n", input_len) ;
|
||||||
|
printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* Copy the last output to the input. */
|
||||||
|
memcpy (input, output, sizeof (input)) ;
|
||||||
|
reverse_data (input, src_data.output_frames_gen) ;
|
||||||
|
|
||||||
|
if ((error = src_reset (src_state)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_data.end_of_input = 1 ;
|
||||||
|
|
||||||
|
src_data.data_in = input ;
|
||||||
|
input_len = src_data.input_frames = src_data.output_frames_gen ;
|
||||||
|
|
||||||
|
src_data.data_out = output ;
|
||||||
|
src_data.output_frames = ARRAY_LEN (output) ;
|
||||||
|
|
||||||
|
if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if ((error = src_process (src_state, &src_data)))
|
||||||
|
{ printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
|
||||||
|
printf (" src_data.input_frames : %ld\n", src_data.input_frames) ;
|
||||||
|
printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
if (src_data.input_frames_used != input_len)
|
||||||
|
{ printf ("\n\nLine %d : unused input.\n", __LINE__) ;
|
||||||
|
printf ("\tinput_len : %d\n", input_len) ;
|
||||||
|
printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
src_state = src_delete (src_state) ;
|
||||||
|
|
||||||
|
snr = calculate_snr (output, src_data.output_frames_gen, 1) ;
|
||||||
|
|
||||||
|
if (target_snr > snr)
|
||||||
|
{ printf ("\n\nLine %d : snr (%3.1f) does not meet target (%3.1f)\n\n", __LINE__, snr, target_snr) ;
|
||||||
|
save_oct_float ("varispeed.mat", input, src_data.input_frames, output, src_data.output_frames_gen) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
puts ("ok") ;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
} /* varispeed_test */
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
|
||||||
|
Cmake is the recommended way to configure, build (as either a DLL or a static
|
||||||
|
library), and install libsoxr for general use on MS-Windows, as on other OSs.
|
||||||
|
|
||||||
|
However, building within MS Visual Studio is also possible, as exemplified by
|
||||||
|
the accompanying files:
|
||||||
|
|
||||||
|
* soxr-config.h Pre-configured for a modern Win32 system.
|
||||||
|
|
||||||
|
* libsoxr.vcproj Builds the library as a DLL, per above.
|
||||||
|
|
||||||
|
* libsoxr.sln, Build an example exe using the above.
|
||||||
|
example1.vcproj
|
||||||
|
|
||||||
|
The following notes apply to adaptation of these files:
|
||||||
|
|
||||||
|
* For a system without AVX support, set WITH_CR64S to 0 in
|
||||||
|
soxr-config.h and exclude the three files ...64s.c from the build.
|
||||||
|
|
||||||
|
* If changing libsoxr.vcproj to build a static library, then also
|
||||||
|
remove the preprocessor definition: SOXR_DLL.
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="example1"
|
||||||
|
ProjectGUID="{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}"
|
||||||
|
RootNamespace="soxr"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform Name="Win32" />
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<File RelativePath="..\examples\1-single-block.c" />
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual C++ Express 2008
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example1", "example1.vcproj", "{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB} = {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsoxr", "libsoxr.vcproj", "{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="libsoxr"
|
||||||
|
ProjectGUID="{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}"
|
||||||
|
RootNamespace="libsoxr"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform Name="Win32" />
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="2"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="."
|
||||||
|
PreprocessorDefinitions="_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;SOXR_DLL;soxr_EXPORTS"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="2"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
AdditionalIncludeDirectories="."
|
||||||
|
PreprocessorDefinitions="NDEBUG;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;SOXR_DLL;soxr_EXPORTS"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="2"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<File RelativePath="..\src\cr.c" />
|
||||||
|
<File RelativePath="..\src\cr32.c" />
|
||||||
|
<File RelativePath="..\src\cr32s.c" />
|
||||||
|
<File RelativePath="..\src\cr64.c" />
|
||||||
|
<File RelativePath="..\src\cr64s.c" />
|
||||||
|
<File RelativePath="..\src\data-io.c" />
|
||||||
|
<File RelativePath="..\src\dbesi0.c" />
|
||||||
|
<File RelativePath="..\src\fft4g32.c" />
|
||||||
|
<File RelativePath="..\src\fft4g64.c" />
|
||||||
|
<File RelativePath="..\src\filter.c" />
|
||||||
|
<File RelativePath="..\src\pffft32s.c" />
|
||||||
|
<File RelativePath="..\src\pffft64s.c" />
|
||||||
|
<File RelativePath="..\src\util32s.c" />
|
||||||
|
<File RelativePath="..\src\util64s.c" />
|
||||||
|
<File RelativePath="..\src\soxr.c" />
|
||||||
|
<File RelativePath="..\src\vr32.c" />
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
/* N.B. Pre-configured for modern MS-Windows systems. However, the normal
|
||||||
|
* procedure is to use the cmake configuration and build system. See INSTALL. */
|
||||||
|
|
||||||
|
#if !defined soxr_config_included
|
||||||
|
#define soxr_config_included
|
||||||
|
|
||||||
|
#define AVCODEC_FOUND 0
|
||||||
|
#define AVUTIL_FOUND 0
|
||||||
|
#define WITH_PFFFT 1
|
||||||
|
|
||||||
|
#define HAVE_FENV_H 1
|
||||||
|
#define HAVE_STDBOOL_H 1
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
#define HAVE_LRINT 1
|
||||||
|
#define HAVE_BIGENDIAN 0
|
||||||
|
|
||||||
|
#define WITH_CR32 1
|
||||||
|
#define WITH_CR32S 1
|
||||||
|
#define WITH_CR64 1
|
||||||
|
#define WITH_CR64S 1
|
||||||
|
#define WITH_VR32 1
|
||||||
|
|
||||||
|
#define WITH_HI_PREC_CLOCK 1
|
||||||
|
#define WITH_FLOAT_STD_PREC_CLOCK 0
|
||||||
|
#define WITH_DEV_TRACE 1
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
rm -f CMakeCache.txt # Prevent interference from any in-tree build
|
||||||
|
|
||||||
|
j=-j4
|
||||||
|
build=Release
|
||||||
|
|
||||||
|
for n in \
|
||||||
|
cc: \
|
||||||
|
clang: \
|
||||||
|
arm-linux-gnueabi-gcc:Linux \
|
||||||
|
x86_64-w64-mingw32-gcc:Windows \
|
||||||
|
i686-w64-mingw32-gcc:Windows \
|
||||||
|
; do
|
||||||
|
compiler=$(echo $n | sed 's/:.*//')
|
||||||
|
system=$(echo $n | sed 's/.*://')
|
||||||
|
dir=$build-$compiler
|
||||||
|
which $compiler > /dev/null || echo $compiler not found && (
|
||||||
|
echo "***" $dir
|
||||||
|
mkdir -p $dir
|
||||||
|
cd $dir
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=$build -DCMAKE_C_COMPILER=$compiler -DCMAKE_SYSTEM_NAME="$system" -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF ..
|
||||||
|
make $j && [ /$system = / ] && ctest -j || true
|
||||||
|
cd tests
|
||||||
|
../../tests/throughput-test && SOXR_THROUGHPUT_GAIN=.6 ../../tests/throughput-test 2 3 || true
|
||||||
|
)
|
||||||
|
done
|
|
@ -1,46 +1,27 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#if !defined soxr_config_included
|
#if !defined soxr_config_included
|
||||||
#define soxr_config_included
|
#define soxr_config_included
|
||||||
|
|
||||||
#define HAVE_SINGLE_PRECISION @HAVE_SINGLE_PRECISION@
|
#cmakedefine01 AVCODEC_FOUND
|
||||||
#define HAVE_DOUBLE_PRECISION @HAVE_DOUBLE_PRECISION@
|
#cmakedefine01 AVUTIL_FOUND
|
||||||
#define HAVE_AVFFT @HAVE_AVFFT@
|
#cmakedefine01 WITH_PFFFT
|
||||||
#define HAVE_SIMD @HAVE_SIMD@
|
|
||||||
#define HAVE_FENV_H @HAVE_FENV_H@
|
|
||||||
#define HAVE_LRINT @HAVE_LRINT@
|
|
||||||
#define WORDS_BIGENDIAN @WORDS_BIGENDIAN@
|
|
||||||
|
|
||||||
#include <limits.h>
|
#cmakedefine01 HAVE_FENV_H
|
||||||
|
#cmakedefine01 HAVE_STDBOOL_H
|
||||||
|
#cmakedefine01 HAVE_STDINT_H
|
||||||
|
#cmakedefine01 HAVE_LRINT
|
||||||
|
#cmakedefine01 HAVE_BIGENDIAN
|
||||||
|
|
||||||
#undef bool
|
#cmakedefine01 WITH_CR32
|
||||||
#undef false
|
#cmakedefine01 WITH_CR32S
|
||||||
#undef true
|
#cmakedefine01 WITH_CR64
|
||||||
#define bool int
|
#cmakedefine01 WITH_CR64S
|
||||||
#define false 0
|
#cmakedefine01 WITH_VR32
|
||||||
#define true 1
|
|
||||||
|
|
||||||
#undef int16_t
|
#cmakedefine01 WITH_HI_PREC_CLOCK
|
||||||
#undef int32_t
|
#cmakedefine01 WITH_FLOAT_STD_PREC_CLOCK
|
||||||
#undef int64_t
|
#cmakedefine01 WITH_DEV_TRACE
|
||||||
#undef uint32_t
|
|
||||||
#undef uint64_t
|
|
||||||
#define int16_t short
|
|
||||||
#if LONG_MAX > 2147483647L
|
|
||||||
#define int32_t int
|
|
||||||
#define int64_t long
|
|
||||||
#elif LONG_MAX < 2147483647L
|
|
||||||
#error this library requires that 'long int' has at least 32-bits
|
|
||||||
#else
|
|
||||||
#define int32_t long
|
|
||||||
#if defined _MSC_VER
|
|
||||||
#define int64_t __int64
|
|
||||||
#else
|
|
||||||
#define int64_t long long
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#define uint32_t unsigned int32_t
|
|
||||||
#define uint64_t unsigned int64_t
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
# Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,90 +7,89 @@
|
||||||
|
|
||||||
if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vr-coefs.h)
|
if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vr-coefs.h)
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
set_property(SOURCE vr32.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h)
|
set_property(SOURCE vr32.c
|
||||||
|
APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h)
|
||||||
add_executable (vr-coefs vr-coefs.c)
|
add_executable (vr-coefs vr-coefs.c)
|
||||||
|
target_link_libraries (vr-coefs ${LIBM_LIBRARIES})
|
||||||
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
|
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
|
||||||
COMMAND vr-coefs > ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
|
COMMAND vr-coefs > ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h
|
||||||
DEPENDS vr-coefs)
|
DEPENDS vr-coefs)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
# Minimalist boo configuration:
|
|
||||||
add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB -DSOXR_SILENT=1)
|
|
||||||
include (CheckFunctionExists)
|
|
||||||
include (CheckIncludeFiles)
|
|
||||||
|
|
||||||
set(WITH_LSR_BINDINGS OFF)
|
add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB)
|
||||||
set(WITH_SINGLE_PRECISION ON)
|
|
||||||
set(WITH_DOUBLE_PRECISION OFF)
|
|
||||||
set(WITH_SIMD ON)
|
|
||||||
set(HAVE_SINGLE_PRECISION "1")
|
|
||||||
set(HAVE_DOUBLE_PRECISION "0")
|
|
||||||
set(HAVE_AVFFT "0")
|
|
||||||
set(HAVE_SIMD "1")
|
|
||||||
check_function_exists (lrint HAVE_LRINT)
|
|
||||||
if(NOT HAVE_LRINT)
|
|
||||||
set(HAVE_LRINT "0")
|
|
||||||
endif()
|
|
||||||
check_include_files (fenv.h HAVE_FENV_H)
|
|
||||||
if(NOT HAVE_FENV_H)
|
|
||||||
set(HAVE_FENV_H "0")
|
|
||||||
endif()
|
|
||||||
set(WORDS_BIGENDIAN "0")
|
|
||||||
|
|
||||||
configure_file (
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../soxr-config.h.in
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/soxr-config.h)
|
|
||||||
include_directories (${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
# Libsoxr configuration:
|
# Libsoxr configuration:
|
||||||
|
|
||||||
set (RDFT32 fft4g32.c)
|
set (RDFT32 fft4g32)
|
||||||
if (WITH_AVFFT AND AVCODEC_FOUND)
|
if (AVCODEC_FOUND)
|
||||||
set (RDFT32 avfft32.c)
|
set (RDFT32 avfft32)
|
||||||
set (RDFT32S avfft32s.c)
|
set (RDFT32S avfft32s)
|
||||||
elseif (WITH_PFFFT)
|
elseif (WITH_PFFFT)
|
||||||
#set (RDFT32 pffft32.c)
|
#set (RDFT32 pffft32)
|
||||||
set (RDFT32S pffft32s.c)
|
set (RDFT32S pffft32s)
|
||||||
elseif (WITH_SIMD)
|
elseif (WITH_CR32S)
|
||||||
set (RDFT32S fft4g32s.c)
|
set (RDFT32S fft4g32s)
|
||||||
|
if (NOT WITH_CR32)
|
||||||
|
list (APPEND RDFT32S fft4g32)
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_DOUBLE_PRECISION)
|
set (SOURCES ${PROJECT_NAME}.c data-io)
|
||||||
set (DP_SOURCES rate64.c)
|
|
||||||
|
if (WITH_CR32 OR WITH_CR32S OR WITH_CR64 OR WITH_CR64S)
|
||||||
|
list (APPEND SOURCES dbesi0 filter fft4g64 cr)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_SINGLE_PRECISION)
|
if (WITH_CR32)
|
||||||
set (SP_SOURCES rate32.c ${RDFT32})
|
list (APPEND SOURCES cr32 ${RDFT32})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (HAVE_SIMD)
|
if (WITH_CR64)
|
||||||
set (SIMD_SOURCES rate32s.c vr32s.c ${RDFT32S} simd.c)
|
list (APPEND SOURCES cr64)
|
||||||
foreach (source ${SIMD_SOURCES})
|
endif ()
|
||||||
set_property (SOURCE ${source} PROPERTY COMPILE_FLAGS ${SIMD_C_FLAGS})
|
|
||||||
|
if (WITH_VR32)
|
||||||
|
list (APPEND SOURCES vr32)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (WITH_CR32S)
|
||||||
|
foreach (source cr32s ${RDFT32S} util32s)
|
||||||
|
list (APPEND SOURCES ${source})
|
||||||
|
set_property (SOURCE ${source}
|
||||||
|
APPEND_STRING PROPERTY COMPILE_FLAGS ${SIMD32_C_FLAGS})
|
||||||
|
endforeach ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (WITH_CR64S)
|
||||||
|
foreach (source cr64s pffft64s util64s)
|
||||||
|
list (APPEND SOURCES ${source})
|
||||||
|
set_property (SOURCE ${source}
|
||||||
|
APPEND_STRING PROPERTY COMPILE_FLAGS ${SIMD64_C_FLAGS})
|
||||||
endforeach ()
|
endforeach ()
|
||||||
else ()
|
|
||||||
set (SIMD_SOURCES vr32.c)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Libsoxr:
|
# Libsoxr:
|
||||||
|
|
||||||
add_library (soxr ${LIB_TYPE} soxr.c data-io.c dbesi0.c filter.c fft4g64.c
|
add_library (${PROJECT_NAME} ${LIB_TYPE} ${SOURCES})
|
||||||
${SP_SOURCES} ${DP_SOURCES} ${SIMD_SOURCES})
|
target_link_libraries (${PROJECT_NAME} PRIVATE ${LIBS} ${LIBM_LIBRARIES})
|
||||||
set_target_properties (soxr PROPERTIES
|
set_target_properties (${PROJECT_NAME} PROPERTIES
|
||||||
VERSION "${SO_VERSION}"
|
VERSION "${SO_VERSION}"
|
||||||
SOVERSION ${SO_VERSION_MAJOR}
|
SOVERSION ${SO_VERSION_MAJOR}
|
||||||
INSTALL_NAME_DIR ${LIB_INSTALL_DIR}
|
INSTALL_NAME_DIR ${LIB_INSTALL_DIR}
|
||||||
LINK_INTERFACE_LIBRARIES ""
|
LINK_INTERFACE_LIBRARIES ""
|
||||||
PUBLIC_HEADER "soxr.h")
|
PUBLIC_HEADER "${PROJECT_NAME}.h")
|
||||||
if (BUILD_FRAMEWORK)
|
if (BUILD_FRAMEWORK)
|
||||||
set_target_properties (soxr PROPERTIES FRAMEWORK TRUE)
|
set_target_properties (${PROJECT_NAME} PROPERTIES FRAMEWORK TRUE)
|
||||||
elseif (NOT WIN32)
|
elseif (NOT WIN32)
|
||||||
# set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/soxr.pc)
|
set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc)
|
||||||
# configure_file (${CMAKE_CURRENT_SOURCE_DIR}/soxr.pc.in ${TARGET_PCS})
|
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${TARGET_PCS})
|
||||||
# install (FILES ${CMAKE_CURRENT_BINARY_DIR}/soxr.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,11 +97,11 @@ endif ()
|
||||||
# LSR bindings:
|
# LSR bindings:
|
||||||
|
|
||||||
if (WITH_LSR_BINDINGS)
|
if (WITH_LSR_BINDINGS)
|
||||||
set (LSR soxr-lsr)
|
set (LSR ${PROJECT_NAME}-lsr)
|
||||||
set (LSR_SO_VERSION 0.1.9)
|
set (LSR_SO_VERSION 0.1.9)
|
||||||
set (LSR_SO_VERSION_MAJOR 0)
|
set (LSR_SO_VERSION_MAJOR 0)
|
||||||
add_library (${LSR} ${LIB_TYPE} lsr)
|
add_library (${LSR} ${LIB_TYPE} ${LSR})
|
||||||
target_link_libraries (${LSR} soxr)
|
target_link_libraries (${LSR} ${PROJECT_NAME})
|
||||||
set_target_properties (${LSR} PROPERTIES
|
set_target_properties (${LSR} PROPERTIES
|
||||||
VERSION "${LSR_SO_VERSION}"
|
VERSION "${LSR_SO_VERSION}"
|
||||||
SOVERSION ${LSR_SO_VERSION_MAJOR}
|
SOVERSION ${LSR_SO_VERSION_MAJOR}
|
||||||
|
@ -112,9 +111,9 @@ if (WITH_LSR_BINDINGS)
|
||||||
if (BUILD_FRAMEWORK)
|
if (BUILD_FRAMEWORK)
|
||||||
set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE)
|
set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE)
|
||||||
elseif (NOT WIN32)
|
elseif (NOT WIN32)
|
||||||
# set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc")
|
set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc")
|
||||||
# configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc)
|
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc)
|
||||||
# install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -122,29 +121,9 @@ endif ()
|
||||||
|
|
||||||
# Installation (from build from source):
|
# Installation (from build from source):
|
||||||
|
|
||||||
#install (TARGETS soxr ${LSR}
|
install (TARGETS ${PROJECT_NAME} ${LSR}
|
||||||
# FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
|
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
|
||||||
# LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||||
# RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||||
# ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||||
# PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR})
|
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Packaging (for unix-like distributions):
|
|
||||||
|
|
||||||
#get_property (LIB1 TARGET soxr PROPERTY LOCATION)
|
|
||||||
#if (BUILD_SHARED_LIBS)
|
|
||||||
# set (LIB1 ${LIB1}.${SO_VERSION_MAJOR} ${LIB1}.${SO_VERSION})
|
|
||||||
#endif ()
|
|
||||||
#list (APPEND TARGET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/soxr.h")
|
|
||||||
#if (WITH_LSR_BINDINGS)
|
|
||||||
# get_property (LIB2 TARGET ${LSR} PROPERTY LOCATION)
|
|
||||||
# if (BUILD_SHARED_LIBS)
|
|
||||||
# set (LIB2 ${LIB2}.${LSR_SO_VERSION_MAJOR} ${LIB2}.${LSR_SO_VERSION})
|
|
||||||
# endif ()
|
|
||||||
# list (APPEND TARGET_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.h")
|
|
||||||
#endif ()
|
|
||||||
#set (TARGET_LIBS ${LIB1} ${LIB2})
|
|
||||||
#configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libsoxr.src.in ${CMAKE_CURRENT_BINARY_DIR}/libsoxr.src)
|
|
||||||
#configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libsoxr-dev.src.in ${CMAKE_CURRENT_BINARY_DIR}/libsoxr-dev.src)
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#if defined SOXR_LIB
|
#if defined SOXR_LIB
|
||||||
|
@ -18,8 +18,10 @@
|
||||||
#define lsx_dfst_f _soxr_dfst_f
|
#define lsx_dfst_f _soxr_dfst_f
|
||||||
#define lsx_dfst _soxr_dfst
|
#define lsx_dfst _soxr_dfst
|
||||||
#define lsx_fir_to_phase _soxr_fir_to_phase
|
#define lsx_fir_to_phase _soxr_fir_to_phase
|
||||||
|
#define lsx_f_resp _soxr_f_resp
|
||||||
#define lsx_init_fft_cache_f _soxr_init_fft_cache_f
|
#define lsx_init_fft_cache_f _soxr_init_fft_cache_f
|
||||||
#define lsx_init_fft_cache _soxr_init_fft_cache
|
#define lsx_init_fft_cache _soxr_init_fft_cache
|
||||||
|
#define lsx_inv_f_resp _soxr_inv_f_resp
|
||||||
#define lsx_kaiser_beta _soxr_kaiser_beta
|
#define lsx_kaiser_beta _soxr_kaiser_beta
|
||||||
#define lsx_kaiser_params _soxr_kaiser_params
|
#define lsx_kaiser_params _soxr_kaiser_params
|
||||||
#define lsx_make_lpf _soxr_make_lpf
|
#define lsx_make_lpf _soxr_make_lpf
|
||||||
|
|
|
@ -1,27 +1,33 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <libavcodec/avfft.h>
|
#include <libavcodec/avfft.h>
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "rdft_t.h"
|
||||||
|
|
||||||
static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);}
|
static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);}
|
||||||
static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);}
|
static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);}
|
||||||
static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;}
|
static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;}
|
||||||
static int multiplier(void) {return 2;}
|
static int multiplier(void) {return 2;}
|
||||||
static void nothing(void) {}
|
static void nothing(void) {}
|
||||||
|
static int flags(void) {return 0;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft32_cb = {
|
||||||
fn_t _soxr_rdft32_cb[] = {
|
forward_setup,
|
||||||
(fn_t)forward_setup,
|
backward_setup,
|
||||||
(fn_t)backward_setup,
|
av_rdft_end,
|
||||||
(fn_t)av_rdft_end,
|
rdft,
|
||||||
(fn_t)rdft,
|
rdft,
|
||||||
(fn_t)rdft,
|
rdft,
|
||||||
(fn_t)rdft,
|
rdft,
|
||||||
(fn_t)rdft,
|
_soxr_ordered_convolve_f,
|
||||||
(fn_t)_soxr_ordered_convolve_f,
|
_soxr_ordered_partial_convolve_f,
|
||||||
(fn_t)_soxr_ordered_partial_convolve_f,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
nothing,
|
||||||
(fn_t)nothing,
|
malloc,
|
||||||
|
calloc,
|
||||||
|
free,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,25 +3,30 @@
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <libavcodec/avfft.h>
|
#include <libavcodec/avfft.h>
|
||||||
#include "simd.h"
|
#include "util32s.h"
|
||||||
|
#include "rdft_t.h"
|
||||||
|
|
||||||
static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);}
|
static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);}
|
||||||
static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);}
|
static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);}
|
||||||
static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;}
|
static void rdft(int length, void * setup, void * H, void * scratch) {av_rdft_calc(setup, H); (void)length; (void)scratch;}
|
||||||
static int multiplier(void) {return 2;}
|
static int multiplier(void) {return 2;}
|
||||||
static void nothing(void) {}
|
static void nothing2(int u1, void *u2, void *u3, void *u4) {(void)u1; (void)u2; (void)u3; (void)u4;}
|
||||||
|
static int flags(void) {return RDFT_IS_SIMD;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft32s_cb = {
|
||||||
fn_t _soxr_rdft32s_cb[] = {
|
forward_setup,
|
||||||
(fn_t)forward_setup,
|
backward_setup,
|
||||||
(fn_t)backward_setup,
|
av_rdft_end,
|
||||||
(fn_t)av_rdft_end,
|
rdft,
|
||||||
(fn_t)rdft,
|
rdft,
|
||||||
(fn_t)rdft,
|
rdft,
|
||||||
(fn_t)rdft,
|
rdft,
|
||||||
(fn_t)rdft,
|
ORDERED_CONVOLVE_SIMD,
|
||||||
(fn_t)_soxr_ordered_convolve_simd,
|
ORDERED_PARTIAL_CONVOLVE_SIMD,
|
||||||
(fn_t)_soxr_ordered_partial_convolve_simd,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
nothing2,
|
||||||
(fn_t)nothing,
|
SIMD_ALIGNED_MALLOC,
|
||||||
|
SIMD_ALIGNED_CALLOC,
|
||||||
|
SIMD_ALIGNED_FREE,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void * (*input)(void *, void * samples, size_t n);
|
||||||
|
void (*process)(void *, size_t);
|
||||||
|
void const * (*output)(void *, void * samples, size_t * n);
|
||||||
|
void (*flush)(void *);
|
||||||
|
void (*close)(void *);
|
||||||
|
double (*delay)(void *);
|
||||||
|
void (*sizes)(size_t * shared, size_t * channel);
|
||||||
|
char const * (*create)(void * channel, void * shared, double io_ratio, void * q_spec, void * r_spec, double scale);
|
||||||
|
void (*set_io_ratio)(void *, double io_ratio, size_t len);
|
||||||
|
char const * (*id)(void);
|
||||||
|
} control_block_t;
|
||||||
|
|
||||||
|
#define resampler_input p->control_block.input
|
||||||
|
#define resampler_process p->control_block.process
|
||||||
|
#define resampler_output p->control_block.output
|
||||||
|
#define resampler_flush p->control_block.flush
|
||||||
|
#define resampler_close p->control_block.close
|
||||||
|
#define resampler_delay p->control_block.delay
|
||||||
|
#define resampler_sizes p->control_block.sizes
|
||||||
|
#define resampler_create p->control_block.create
|
||||||
|
#define resampler_set_io_ratio p->control_block.set_io_ratio
|
||||||
|
#define resampler_id p->control_block.id
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */
|
/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */
|
||||||
|
|
||||||
#if !defined ccrw2_included
|
#if !defined soxr_ccrw2_included
|
||||||
#define ccrw2_included
|
#define soxr_ccrw2_included
|
||||||
|
|
||||||
#if defined SOXR_LIB
|
#if defined SOXR_LIB
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
|
@ -0,0 +1,316 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
*
|
||||||
|
* Constant-rate resampling engine-specific code. */
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
|
#if defined SOXR_LIB
|
||||||
|
#include "internal.h"
|
||||||
|
#include "cr.h"
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
typedef double sample_t;
|
||||||
|
#if CORE_TYPE & CORE_SIMD_DFT
|
||||||
|
#define RDFT_CB _soxr_rdft64s_cb
|
||||||
|
#else
|
||||||
|
#define RDFT_CB _soxr_rdft64_cb
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
typedef float sample_t;
|
||||||
|
#if CORE_TYPE & CORE_SIMD_DFT
|
||||||
|
#define RDFT_CB _soxr_rdft32s_cb
|
||||||
|
#else
|
||||||
|
#define RDFT_CB _soxr_rdft32_cb
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_TYPE & (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
#include "util64s.h"
|
||||||
|
#include "dev64s.h"
|
||||||
|
#else
|
||||||
|
#include "util32s.h"
|
||||||
|
#include "dev32s.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern rdft_cb_table RDFT_CB;
|
||||||
|
#else
|
||||||
|
#define RDFT_CB 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void cubic_stage_fn(stage_t * p, fifo_t * output_fifo)
|
||||||
|
{
|
||||||
|
sample_t const * input = stage_read_p(p);
|
||||||
|
int num_in = min(stage_occupancy(p), p->input_size);
|
||||||
|
int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio);
|
||||||
|
sample_t * output = fifo_reserve(output_fifo, max_num_out);
|
||||||
|
|
||||||
|
for (i = 0; p->at.integer < num_in; ++i, p->at.whole += p->step.whole) {
|
||||||
|
sample_t const * s = input + p->at.integer;
|
||||||
|
double x = p->at.fraction * (1 / MULT32);
|
||||||
|
double b = .5*(s[1]+s[-1])-*s, a = (1/6.)*(s[2]-s[1]+s[-1]-*s-4*b);
|
||||||
|
double c = s[1]-*s-a-b;
|
||||||
|
output[i] = (sample_t)(p->mult * (((a*x + b)*x + c)*x + *s));
|
||||||
|
}
|
||||||
|
assert(max_num_out - i >= 0);
|
||||||
|
fifo_trim_by(output_fifo, max_num_out - i);
|
||||||
|
fifo_read(&p->fifo, p->at.integer, NULL);
|
||||||
|
p->at.integer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined __AVX__
|
||||||
|
#define DEFINED_AVX 1
|
||||||
|
#else
|
||||||
|
#define DEFINED_AVX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86
|
||||||
|
#define DEFINED_X86 1
|
||||||
|
#else
|
||||||
|
#define DEFINED_X86 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __arm__
|
||||||
|
#define DEFINED_ARM 1
|
||||||
|
#else
|
||||||
|
#define DEFINED_ARM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
#define SIMD_AVX ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_AVX)
|
||||||
|
#define SIMD_SSE 0
|
||||||
|
#else
|
||||||
|
#define SIMD_SSE ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_X86)
|
||||||
|
#define SIMD_AVX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_ARM)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "half-coefs.h"
|
||||||
|
|
||||||
|
#if !(CORE_TYPE & CORE_SIMD_HALF)
|
||||||
|
#define FUNCTION_H h7
|
||||||
|
#define CONVOLVE ____ __ _
|
||||||
|
#include "half-fir.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FUNCTION_H h8
|
||||||
|
#define CONVOLVE ____ ____
|
||||||
|
#include "half-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION_H h9
|
||||||
|
#define CONVOLVE ____ ____ _
|
||||||
|
#include "half-fir.h"
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
#define FUNCTION_H h10
|
||||||
|
#define CONVOLVE ____ ____ __
|
||||||
|
#include "half-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION_H h11
|
||||||
|
#define CONVOLVE ____ ____ __ _
|
||||||
|
#include "half-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION_H h12
|
||||||
|
#define CONVOLVE ____ ____ ____
|
||||||
|
#include "half-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION_H h13
|
||||||
|
#define CONVOLVE ____ ____ ____ _
|
||||||
|
#include "half-fir.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static half_fir_info_t const half_firs[] = {
|
||||||
|
#if !(CORE_TYPE & CORE_SIMD_HALF)
|
||||||
|
{ 7, half_fir_coefs_7 , h7 , 0 , 120.65f},
|
||||||
|
#endif
|
||||||
|
{ 8, half_fir_coefs_8 , h8 , 0 , 136.51f},
|
||||||
|
{ 9, half_fir_coefs_9 , h9 , 0 , 152.32f},
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
{10, half_fir_coefs_10, h10, 0 , 168.08f},
|
||||||
|
{11, half_fir_coefs_11, h11, 0 , 183.79f},
|
||||||
|
{12, half_fir_coefs_12, h12, 0 , 199.46f},
|
||||||
|
{13, half_fir_coefs_13, h13, 0 , 215.12f},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef SIMD_AVX
|
||||||
|
#undef SIMD_NEON
|
||||||
|
#undef SIMD_SSE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
#define SIMD_AVX ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_AVX)
|
||||||
|
#define SIMD_SSE 0
|
||||||
|
#else
|
||||||
|
#define SIMD_SSE ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_X86)
|
||||||
|
#define SIMD_AVX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_ARM)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define COEFS (sample_t * __restrict)p->shared->poly_fir_coefs
|
||||||
|
#define VAR_LENGTH p->n
|
||||||
|
#define VAR_CONVOLVE(n) while (j < (n)) _
|
||||||
|
#define VAR_POLY_PHASE_BITS p->phase_bits
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define FUNCTION vpoly0
|
||||||
|
#define FIR_LENGTH VAR_LENGTH
|
||||||
|
#define CONVOLVE(n) VAR_CONVOLVE(n)
|
||||||
|
#include "poly-fir0.h"
|
||||||
|
|
||||||
|
#define FUNCTION vpoly1
|
||||||
|
#define COEF_INTERP 1
|
||||||
|
#define PHASE_BITS VAR_POLY_PHASE_BITS
|
||||||
|
#define FIR_LENGTH VAR_LENGTH
|
||||||
|
#define CONVOLVE(n) VAR_CONVOLVE(n)
|
||||||
|
#include "poly-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION vpoly2
|
||||||
|
#define COEF_INTERP 2
|
||||||
|
#define PHASE_BITS VAR_POLY_PHASE_BITS
|
||||||
|
#define FIR_LENGTH VAR_LENGTH
|
||||||
|
#define CONVOLVE(n) VAR_CONVOLVE(n)
|
||||||
|
#include "poly-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION vpoly3
|
||||||
|
#define COEF_INTERP 3
|
||||||
|
#define PHASE_BITS VAR_POLY_PHASE_BITS
|
||||||
|
#define FIR_LENGTH VAR_LENGTH
|
||||||
|
#define CONVOLVE(n) VAR_CONVOLVE(n)
|
||||||
|
#include "poly-fir.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !(CORE_TYPE & CORE_SIMD_POLY)
|
||||||
|
|
||||||
|
#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
#define FUNCTION U100_0
|
||||||
|
#define FIR_LENGTH U100_l
|
||||||
|
#define CONVOLVE(n) poly_fir_convolve_U100
|
||||||
|
#include "poly-fir0.h"
|
||||||
|
|
||||||
|
#define u100_l 11
|
||||||
|
#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
#define FUNCTION u100_0
|
||||||
|
#define FIR_LENGTH u100_l
|
||||||
|
#define CONVOLVE(n) poly_fir_convolve_u100
|
||||||
|
#include "poly-fir0.h"
|
||||||
|
|
||||||
|
#define FUNCTION u100_1
|
||||||
|
#define COEF_INTERP 1
|
||||||
|
#define PHASE_BITS 8
|
||||||
|
#define FIR_LENGTH u100_l
|
||||||
|
#define CONVOLVE(n) poly_fir_convolve_u100
|
||||||
|
#include "poly-fir.h"
|
||||||
|
|
||||||
|
#define FUNCTION u100_2
|
||||||
|
#define COEF_INTERP 2
|
||||||
|
#define PHASE_BITS 6
|
||||||
|
#define FIR_LENGTH u100_l
|
||||||
|
#define CONVOLVE(n) poly_fir_convolve_u100
|
||||||
|
#include "poly-fir.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define u100_1_b 8
|
||||||
|
#define u100_2_b 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static poly_fir_t const poly_firs[] = {
|
||||||
|
{-1, {{0, vpoly0}, { 7.2f, vpoly1}, {5.0f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, { 9.4f, vpoly1}, {6.7f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, {12.4f, vpoly1}, {7.8f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, {13.6f, vpoly1}, {9.3f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, {10.5f, vpoly2}, {8.4f, vpoly3}}},
|
||||||
|
{-1, {{0, vpoly0}, {11.85f,vpoly2}, {9.0f, vpoly3}}},
|
||||||
|
|
||||||
|
{-1, {{0, vpoly0}, { 8.0f, vpoly1}, {5.3f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, { 8.6f, vpoly1}, {5.7f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, {10.6f, vpoly1}, {6.75f,vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, {12.6f, vpoly1}, {8.6f, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, { 9.6f, vpoly2}, {7.6f, vpoly3}}},
|
||||||
|
{-1, {{0, vpoly0}, {11.4f, vpoly2}, {8.65f,vpoly3}}},
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_SIMD_POLY
|
||||||
|
{10.62f, {{0, vpoly0}, {0, 0}, {0, 0}}},
|
||||||
|
{-1, {{0, vpoly0}, {u100_1_b, vpoly1}, {u100_2_b, vpoly2}}},
|
||||||
|
#else
|
||||||
|
{10.62f, {{U100_l, U100_0}, {0, 0}, {0, 0}}},
|
||||||
|
{11.28f, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}},
|
||||||
|
#endif
|
||||||
|
{-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}},
|
||||||
|
{-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}},
|
||||||
|
{-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static cr_core_t const cr_core = {
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_SIMD_POLY
|
||||||
|
{SIMD_ALIGNED_MALLOC, SIMD_ALIGNED_CALLOC, SIMD_ALIGNED_FREE},
|
||||||
|
#else
|
||||||
|
{malloc, calloc, free},
|
||||||
|
#endif
|
||||||
|
half_firs, array_length(half_firs),
|
||||||
|
0, 0,
|
||||||
|
cubic_stage_fn,
|
||||||
|
poly_firs, &RDFT_CB
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined SOXR_LIB
|
||||||
|
|
||||||
|
#include "soxr.h"
|
||||||
|
|
||||||
|
static char const * rate_create(void * channel, void * shared, double io_ratio,
|
||||||
|
void * q_spec, void * r_spec, double scale)
|
||||||
|
{
|
||||||
|
return _soxr_init(channel, shared, io_ratio, q_spec, r_spec, scale,
|
||||||
|
&cr_core, CORE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char const * id(void) {return CORE_STR;}
|
||||||
|
|
||||||
|
#include "cb_t.h"
|
||||||
|
|
||||||
|
control_block_t RATE_CB = {
|
||||||
|
_soxr_input,
|
||||||
|
_soxr_process,
|
||||||
|
_soxr_output,
|
||||||
|
_soxr_flush,
|
||||||
|
_soxr_close,
|
||||||
|
_soxr_delay,
|
||||||
|
_soxr_sizes,
|
||||||
|
rate_create,
|
||||||
|
0,
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,600 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details.
|
||||||
|
*
|
||||||
|
* Constant-rate resampling common code. */
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
|
#if defined SOXR_LIB
|
||||||
|
#include "internal.h"
|
||||||
|
#define STATIC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cr.h"
|
||||||
|
|
||||||
|
#define num_coefs4 ((core_flags&CORE_SIMD_POLY)? ((num_coefs+3)&~3) : num_coefs)
|
||||||
|
|
||||||
|
#define coef_coef(C,T,x) \
|
||||||
|
C((T*)result, interp_order, num_coefs4, j, x, num_coefs4 - 1 - i)
|
||||||
|
|
||||||
|
#define STORE(C,T) { \
|
||||||
|
if (interp_order > 2) coef_coef(C,T,3) = (T)d; \
|
||||||
|
if (interp_order > 1) coef_coef(C,T,2) = (T)c; \
|
||||||
|
if (interp_order > 0) coef_coef(C,T,1) = (T)b; \
|
||||||
|
coef_coef(C,T,0) = (T)f0;}
|
||||||
|
|
||||||
|
static real * prepare_poly_fir_coefs(double const * coefs, int num_coefs,
|
||||||
|
int num_phases, int interp_order, double multiplier,
|
||||||
|
core_flags_t core_flags, alloc_t const * mem)
|
||||||
|
{
|
||||||
|
int i, j, length = num_coefs4 * num_phases * (interp_order + 1);
|
||||||
|
real * result = mem->calloc(1,(size_t)length << LOG2_SIZEOF_REAL(core_flags));
|
||||||
|
double fm1 = coefs[0], f1 = 0, f2 = 0;
|
||||||
|
|
||||||
|
for (i = num_coefs - 1; i >= 0; --i)
|
||||||
|
for (j = num_phases - 1; j >= 0; --j) {
|
||||||
|
double f0 = fm1, b = 0, c = 0, d = 0; /* = 0 to kill compiler warning */
|
||||||
|
int pos = i * num_phases + j - 1;
|
||||||
|
fm1 = pos > 0 ? coefs[pos - 1] * multiplier : 0;
|
||||||
|
switch (interp_order) {
|
||||||
|
case 1: b = f1 - f0; break;
|
||||||
|
case 2: b = f1 - (.5 * (f2+f0) - f1) - f0; c = .5 * (f2+f0) - f1; break;
|
||||||
|
case 3: c=.5*(f1+fm1)-f0;d=(1/6.)*(f2-f1+fm1-f0-4*c);b=f1-f0-d-c; break;
|
||||||
|
default: assert(!interp_order);
|
||||||
|
}
|
||||||
|
switch (core_flags & 3) {
|
||||||
|
case 0: if (WITH_CR32 ) STORE(coef , float ); break;
|
||||||
|
case 1: if (WITH_CR64 ) STORE(coef , double); break;
|
||||||
|
case 2: if (WITH_CR32S) STORE(coef4, float ); break;
|
||||||
|
default:if (WITH_CR64S) STORE(coef4, double); break;
|
||||||
|
}
|
||||||
|
f2 = f1, f1 = f0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef STORE
|
||||||
|
#undef coef_coef
|
||||||
|
|
||||||
|
#define IS_FLOAT32 (WITH_CR32 || WITH_CR32S) && \
|
||||||
|
(!(WITH_CR64 || WITH_CR64S) || sizeof_real == sizeof(float))
|
||||||
|
#define WITH_FLOAT64 WITH_CR64 || WITH_CR64S
|
||||||
|
|
||||||
|
static void dft_stage_fn(stage_t * p, fifo_t * output_fifo)
|
||||||
|
{
|
||||||
|
real * output, * dft_out;
|
||||||
|
int i, j, num_in = max(0, fifo_occupancy(&p->fifo));
|
||||||
|
rate_shared_t const * s = p->shared;
|
||||||
|
dft_filter_t const * f = &s->dft_filter[p->dft_filter_num];
|
||||||
|
int const overlap = f->num_taps - 1;
|
||||||
|
|
||||||
|
if (p->at.integer + p->L * num_in >= f->dft_length) {
|
||||||
|
rdft_cb_table const * const RDFT_CB = p->rdft_cb;
|
||||||
|
size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(p->core_flags);
|
||||||
|
div_t divd = div(f->dft_length - overlap - p->at.integer + p->L - 1, p->L);
|
||||||
|
real const * input = fifo_read_ptr(&p->fifo);
|
||||||
|
fifo_read(&p->fifo, divd.quot, NULL);
|
||||||
|
num_in -= divd.quot;
|
||||||
|
|
||||||
|
output = fifo_reserve(output_fifo, f->dft_length);
|
||||||
|
dft_out = (p->core_flags & CORE_SIMD_DFT)? p->dft_out : output;
|
||||||
|
|
||||||
|
if (lsx_is_power_of_2(p->L)) { /* F-domain */
|
||||||
|
int portion = f->dft_length / p->L;
|
||||||
|
memcpy(dft_out, input, (unsigned)portion * sizeof_real);
|
||||||
|
rdft_oforward(portion, f->dft_forward_setup, dft_out, p->dft_scratch);
|
||||||
|
if (IS_FLOAT32) {
|
||||||
|
#define dft_out ((float *)dft_out)
|
||||||
|
for (i = portion + 2; i < (portion << 1); i += 2) /* Mirror image. */
|
||||||
|
dft_out[i] = dft_out[(portion << 1) - i],
|
||||||
|
dft_out[i+1] = -dft_out[(portion << 1) - i + 1];
|
||||||
|
dft_out[portion] = dft_out[1];
|
||||||
|
dft_out[portion + 1] = 0;
|
||||||
|
dft_out[1] = dft_out[0];
|
||||||
|
#undef dft_out
|
||||||
|
}
|
||||||
|
else if (WITH_FLOAT64) {
|
||||||
|
#define dft_out ((double *)dft_out)
|
||||||
|
for (i = portion + 2; i < (portion << 1); i += 2) /* Mirror image. */
|
||||||
|
dft_out[i] = dft_out[(portion << 1) - i],
|
||||||
|
dft_out[i+1] = -dft_out[(portion << 1) - i + 1];
|
||||||
|
dft_out[portion] = dft_out[1];
|
||||||
|
dft_out[portion + 1] = 0;
|
||||||
|
dft_out[1] = dft_out[0];
|
||||||
|
#undef dft_out
|
||||||
|
}
|
||||||
|
|
||||||
|
for (portion <<= 1; i < f->dft_length; i += portion, portion <<= 1) {
|
||||||
|
memcpy((char *)dft_out + (size_t)i * sizeof_real, dft_out, (size_t)portion * sizeof_real);
|
||||||
|
if (IS_FLOAT32)
|
||||||
|
#define dft_out ((float *)dft_out)
|
||||||
|
dft_out[i + 1] = 0;
|
||||||
|
#undef dft_out
|
||||||
|
else if (WITH_FLOAT64)
|
||||||
|
#define dft_out ((double *)dft_out)
|
||||||
|
dft_out[i + 1] = 0;
|
||||||
|
#undef dft_out
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->step.integer > 0) {
|
||||||
|
rdft_reorder_back(f->dft_length, f->dft_backward_setup, dft_out, p->dft_scratch);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p->L == 1)
|
||||||
|
memcpy(dft_out, input, (size_t)f->dft_length * sizeof_real);
|
||||||
|
else {
|
||||||
|
|
||||||
|
memset(dft_out, 0, (size_t)f->dft_length * sizeof_real);
|
||||||
|
if (IS_FLOAT32)
|
||||||
|
for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L)
|
||||||
|
((float *)dft_out)[i] = ((float *)input)[j];
|
||||||
|
else if (WITH_FLOAT64)
|
||||||
|
for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L)
|
||||||
|
((double *)dft_out)[i] = ((double *)input)[j];
|
||||||
|
p->at.integer = p->L - 1 - divd.rem;
|
||||||
|
}
|
||||||
|
if (p->step.integer > 0)
|
||||||
|
rdft_forward(f->dft_length, f->dft_forward_setup, dft_out, p->dft_scratch);
|
||||||
|
else
|
||||||
|
rdft_oforward(f->dft_length, f->dft_forward_setup, dft_out, p->dft_scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->step.integer > 0) {
|
||||||
|
rdft_convolve(f->dft_length, f->dft_backward_setup, dft_out, f->coefs);
|
||||||
|
rdft_backward(f->dft_length, f->dft_backward_setup, dft_out, p->dft_scratch);
|
||||||
|
if ((p->core_flags & CORE_SIMD_DFT) && p->step.integer == 1)
|
||||||
|
memcpy(output, dft_out, (size_t)f->dft_length * sizeof_real);
|
||||||
|
if (p->step.integer != 1) {
|
||||||
|
if (IS_FLOAT32)
|
||||||
|
for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j,
|
||||||
|
i += p->step.integer)
|
||||||
|
((float *)output)[j] = ((float *)dft_out)[i];
|
||||||
|
else if (WITH_FLOAT64)
|
||||||
|
for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j,
|
||||||
|
i += p->step.integer)
|
||||||
|
((double *)output)[j] = ((double *)dft_out)[i];
|
||||||
|
p->remM = i - (f->dft_length - overlap);
|
||||||
|
fifo_trim_by(output_fifo, f->dft_length - j);
|
||||||
|
}
|
||||||
|
else fifo_trim_by(output_fifo, overlap);
|
||||||
|
}
|
||||||
|
else { /* F-domain */
|
||||||
|
int m = -p->step.integer;
|
||||||
|
rdft_convolve_portion(f->dft_length >> m, dft_out, f->coefs);
|
||||||
|
rdft_obackward(f->dft_length >> m, f->dft_backward_setup, dft_out, p->dft_scratch);
|
||||||
|
if (p->core_flags & CORE_SIMD_DFT)
|
||||||
|
memcpy(output, dft_out, (size_t)(f->dft_length >> m) * sizeof_real);
|
||||||
|
fifo_trim_by(output_fifo, (((1 << m) - 1) * f->dft_length + overlap) >>m);
|
||||||
|
}
|
||||||
|
(rdft_cb_table const *)RDFT_CB;
|
||||||
|
}
|
||||||
|
p->input_size = (f->dft_length - p->at.integer + p->L - 1) / p->L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set to 4 x nearest power of 2 or half of that */
|
||||||
|
/* if danger of causing too many cache misses. */
|
||||||
|
static int set_dft_length(int num_taps, int min, int large)
|
||||||
|
{
|
||||||
|
double d = log((double)num_taps) / log(2.);
|
||||||
|
return 1 << range_limit((int)(d + 2.77), min, max((int)(d + 1.77), large));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dft_stage_init(
|
||||||
|
unsigned instance, double Fp, double Fs, double Fn, double att,
|
||||||
|
double phase_response, stage_t * p, int L, int M, double * multiplier,
|
||||||
|
unsigned min_dft_size, unsigned large_dft_size, core_flags_t core_flags,
|
||||||
|
rdft_cb_table const * rdft_table)
|
||||||
|
{
|
||||||
|
rdft_cb_table const * const RDFT_CB = rdft_table;
|
||||||
|
dft_filter_t * f = &p->shared->dft_filter[instance];
|
||||||
|
int num_taps = 0, dft_length = f->dft_length, i, offset;
|
||||||
|
bool f_domain_m = abs(3-M) == 1 && Fs <= 1;
|
||||||
|
size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(core_flags);
|
||||||
|
|
||||||
|
if (!dft_length) {
|
||||||
|
int k = phase_response == 50 && lsx_is_power_of_2(L) && Fn == L? L << 1 : 4;
|
||||||
|
double m, * h = lsx_design_lpf(Fp, Fs, Fn, att, &num_taps, -k, -1.);
|
||||||
|
|
||||||
|
if (phase_response != 50)
|
||||||
|
lsx_fir_to_phase(&h, &num_taps, &f->post_peak, phase_response);
|
||||||
|
else f->post_peak = num_taps / 2;
|
||||||
|
|
||||||
|
dft_length = set_dft_length(num_taps, (int)min_dft_size, (int)large_dft_size);
|
||||||
|
f->coefs = rdft_calloc((size_t)dft_length, sizeof_real);
|
||||||
|
offset = dft_length - num_taps + 1;
|
||||||
|
m = (1. / dft_length) * rdft_multiplier() * L * *multiplier;
|
||||||
|
if (IS_FLOAT32) for (i = 0; i < num_taps; ++i)
|
||||||
|
((float *)f->coefs)[(i + offset) & (dft_length - 1)] =(float)(h[i] * m);
|
||||||
|
else if (WITH_FLOAT64) for (i = 0; i < num_taps; ++i)
|
||||||
|
((double *)f->coefs)[(i + offset) & (dft_length - 1)] = h[i] * m;
|
||||||
|
free(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdft_flags() & RDFT_IS_SIMD)
|
||||||
|
p->dft_out = rdft_malloc(sizeof_real * (size_t)dft_length);
|
||||||
|
if (rdft_flags() & RDFT_NEEDS_SCRATCH)
|
||||||
|
p->dft_scratch = rdft_malloc(2 * sizeof_real * (size_t)dft_length);
|
||||||
|
|
||||||
|
if (!f->dft_length) {
|
||||||
|
void * coef_setup = rdft_forward_setup(dft_length);
|
||||||
|
int Lp = lsx_is_power_of_2(L)? L : 1;
|
||||||
|
int Mp = f_domain_m? M : 1;
|
||||||
|
f->dft_forward_setup = rdft_forward_setup(dft_length / Lp);
|
||||||
|
f->dft_backward_setup = rdft_backward_setup(dft_length / Mp);
|
||||||
|
if (Mp == 1)
|
||||||
|
rdft_forward(dft_length, coef_setup, f->coefs, p->dft_scratch);
|
||||||
|
else
|
||||||
|
rdft_oforward(dft_length, coef_setup, f->coefs, p->dft_scratch);
|
||||||
|
rdft_delete_setup(coef_setup);
|
||||||
|
f->num_taps = num_taps;
|
||||||
|
f->dft_length = dft_length;
|
||||||
|
lsx_debug("fir_len=%i dft_length=%i Fp=%g Fs=%g Fn=%g att=%g %i/%i",
|
||||||
|
num_taps, dft_length, Fp, Fs, Fn, att, L, M);
|
||||||
|
}
|
||||||
|
*multiplier = 1;
|
||||||
|
p->out_in_ratio = (double)L / M;
|
||||||
|
p->core_flags = core_flags;
|
||||||
|
p->rdft_cb = rdft_table;
|
||||||
|
p->fn = dft_stage_fn;
|
||||||
|
p->preload = f->post_peak / L;
|
||||||
|
p->at.integer = f->post_peak % L;
|
||||||
|
p->L = L;
|
||||||
|
p->step.integer = f_domain_m? -M/2 : M;
|
||||||
|
p->dft_filter_num = instance;
|
||||||
|
p->block_len = f->dft_length - (f->num_taps - 1);
|
||||||
|
p->phase0 = p->at.integer / p->L;
|
||||||
|
p->input_size = (f->dft_length - p->at.integer + p->L - 1) / p->L;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct half_fir_info const * find_half_fir(
|
||||||
|
struct half_fir_info const * firs, size_t len, double att)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i + 1 < len && att > firs[i].att; ++i);
|
||||||
|
return &firs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
#define have_pre_stage (preM * preL != 1)
|
||||||
|
#define have_arb_stage (arbM * arbL != 1)
|
||||||
|
#define have_post_stage (postM * postL != 1)
|
||||||
|
|
||||||
|
#include "soxr.h"
|
||||||
|
|
||||||
|
STATIC char const * _soxr_init(
|
||||||
|
rate_t * const p, /* Per audio channel. */
|
||||||
|
rate_shared_t * const shared, /* By channels undergoing same rate change. */
|
||||||
|
double const io_ratio, /* Input rate divided by output rate. */
|
||||||
|
soxr_quality_spec_t const * const q_spec,
|
||||||
|
soxr_runtime_spec_t const * const r_spec,
|
||||||
|
double multiplier, /* Linear gain to apply during conversion. */
|
||||||
|
cr_core_t const * const core,
|
||||||
|
core_flags_t const core_flags)
|
||||||
|
{
|
||||||
|
size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(core_flags);
|
||||||
|
double const tolerance = 1 + 1e-5;
|
||||||
|
|
||||||
|
double bits = q_spec->precision;
|
||||||
|
rolloff_t const rolloff = (rolloff_t)(q_spec->flags & 3);
|
||||||
|
int interpolator = (int)(r_spec->flags & 3) - 1;
|
||||||
|
double const Fp0 = q_spec->passband_end, Fs0 = q_spec->stopband_begin;
|
||||||
|
double const phase_response = q_spec->phase_response, tbw0 = Fs0-Fp0;
|
||||||
|
|
||||||
|
bool const maintain_3dB_pt = !!(q_spec->flags & SOXR_MAINTAIN_3DB_PT);
|
||||||
|
double tbw_tighten = 1, alpha;
|
||||||
|
#define tighten(x) (Fs0-(Fs0-(x))*tbw_tighten)
|
||||||
|
|
||||||
|
double arbM = io_ratio, Fn1, Fp1 = Fp0, Fs1 = Fs0, bits1 = min(bits,33);
|
||||||
|
double att = (bits1 + 1) * linear_to_dB(2.), attArb = att; /* +1: pass+stop */
|
||||||
|
int preL = 1, preM = 1, shr = 0, arbL = 1, postL = 1, postM = 1;
|
||||||
|
bool upsample=false, rational=false, iOpt=!(r_spec->flags&SOXR_NOSMALLINTOPT);
|
||||||
|
bool lq_bits= (q_spec->flags & SOXR_PROMOTE_TO_LQ)? bits <= 16 : bits == 16;
|
||||||
|
bool lq_Fp0 = (q_spec->flags & SOXR_PROMOTE_TO_LQ)? Fp0<=lq_bw0 : Fp0==lq_bw0;
|
||||||
|
int n = 0, i, mode = lq_bits && rolloff == rolloff_medium? io_ratio > 1 ||
|
||||||
|
phase_response != 50 || !lq_Fp0 || Fs0 != 1 : ((int)ceil(bits1) - 6) / 4;
|
||||||
|
struct half_fir_info const * half_fir_info;
|
||||||
|
stage_t * s;
|
||||||
|
|
||||||
|
if (io_ratio < 1 && Fs0 - 1 > 1 - Fp0 / tolerance)
|
||||||
|
return "imaging greater than rolloff";
|
||||||
|
if (.002 / tolerance > tbw0 || tbw0 > .5 * tolerance)
|
||||||
|
return "transition bandwidth not in [0.2,50] % of nyquist";
|
||||||
|
if (.5 / tolerance > Fp0 || Fs0 > 1.5 * tolerance)
|
||||||
|
return "transition band not within [50,150] % of nyquist";
|
||||||
|
if (bits!=0 && (15 > bits || bits > 33))
|
||||||
|
return "precision not in [15,33] bits";
|
||||||
|
if (io_ratio <= 0)
|
||||||
|
return "resampling factor not positive";
|
||||||
|
if (0 > phase_response || phase_response > 100)
|
||||||
|
return "phase response not in [0=min-phase,100=max-phase] %";
|
||||||
|
|
||||||
|
p->core = core;
|
||||||
|
p->io_ratio = io_ratio;
|
||||||
|
if (bits!=0) while (!n++) { /* Determine stages: */
|
||||||
|
int try, L, M, x, maxL = interpolator > 0? 1 : mode? 2048 :
|
||||||
|
(int)ceil(r_spec->coef_size_kbytes * 1000. / (U100_l * (int)sizeof_real));
|
||||||
|
double d, epsilon = 0, frac;
|
||||||
|
upsample = arbM < 1;
|
||||||
|
for (i = (int)(.5 * arbM), shr = 0; i >>= 1; arbM *= .5, ++shr);
|
||||||
|
preM = upsample || (arbM > 1.5 && arbM < 2);
|
||||||
|
postM = 1 + (arbM > 1 && preM), arbM /= postM;
|
||||||
|
preL = 1 + (!preM && arbM < 2) + (upsample && mode), arbM *= preL;
|
||||||
|
if ((frac = arbM - (int)arbM)!=0)
|
||||||
|
epsilon = fabs(floor(frac * MULT32 + .5) / (frac * MULT32) - 1);
|
||||||
|
for (i = 1, rational = frac==0; i <= maxL && !rational; ++i) {
|
||||||
|
d = frac * i, try = (int)(d + .5);
|
||||||
|
if ((rational = fabs(try / d - 1) <= epsilon)) { /* No long doubles! */
|
||||||
|
if (try == i)
|
||||||
|
arbM = ceil(arbM), shr += x = arbM > 3, arbM /= 1 + x;
|
||||||
|
else arbM = i * (int)arbM + try, arbL = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
L = preL * arbL, M = (int)(arbM * postM), x = (L|M)&1, L >>= !x, M >>= !x;
|
||||||
|
if (iOpt && postL == 1 && (d = preL * arbL / arbM) > 4 && d != 5) {
|
||||||
|
for (postL = 4, i = (int)(d / 16); (i >>= 1) && postL < 256; postL <<= 1);
|
||||||
|
arbM = arbM * postL / arbL / preL, arbL = 1, n = 0;
|
||||||
|
} else if (rational && (max(L, M) < 3 + 2 * iOpt || L * M < 6 * iOpt))
|
||||||
|
preL = L, preM = M, arbM = arbL = postM = 1;
|
||||||
|
if (!mode && (!rational || !n))
|
||||||
|
++mode, n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->num_stages = shr + have_pre_stage + have_arb_stage + have_post_stage;
|
||||||
|
if (!p->num_stages && multiplier != 1) {
|
||||||
|
bits = arbL = 0; /* Use cubic_stage in this case. */
|
||||||
|
++p->num_stages;
|
||||||
|
}
|
||||||
|
p->stages = calloc((size_t)p->num_stages + 1, sizeof(*p->stages));
|
||||||
|
if (!p->stages)
|
||||||
|
return "out of memory";
|
||||||
|
for (i = 0; i < p->num_stages; ++i) {
|
||||||
|
p->stages[i].num = i;
|
||||||
|
p->stages[i].shared = shared;
|
||||||
|
p->stages[i].input_size = 8192;
|
||||||
|
}
|
||||||
|
p->stages[0].is_input = true;
|
||||||
|
|
||||||
|
alpha = postM / (io_ratio * (postL << 0));
|
||||||
|
|
||||||
|
if ((n = p->num_stages) > 1) { /* Att. budget: */
|
||||||
|
if (have_arb_stage)
|
||||||
|
att += linear_to_dB(2.), attArb = att, --n;
|
||||||
|
att += linear_to_dB((double)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
half_fir_info = find_half_fir(core->half_firs, core->half_firs_len, att);
|
||||||
|
for (i = 0, s = p->stages; i < shr; ++i, ++s) {
|
||||||
|
s->fn = half_fir_info->fn;
|
||||||
|
s->coefs = half_fir_info->coefs;
|
||||||
|
s->n = half_fir_info->num_coefs;
|
||||||
|
s->pre_post = 4 * s->n;
|
||||||
|
s->preload = s->pre = s->pre_post >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_pre_stage) {
|
||||||
|
if (maintain_3dB_pt && have_post_stage) { /* Trans. bands overlapping. */
|
||||||
|
double x = tbw0 * lsx_inv_f_resp(-3., att);
|
||||||
|
x = -lsx_f_resp(x / (max(2 * alpha - Fs0, alpha) - Fp0), att);
|
||||||
|
if (x > .035) {
|
||||||
|
tbw_tighten = ((4.3074e-3 - 3.9121e-4 * x) * x - .040009) * x + 1.0014;
|
||||||
|
lsx_debug("tbw_tighten=%g (%gdB)", tbw_tighten, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fn1 = preM? max(preL, preM) : arbM / arbL;
|
||||||
|
dft_stage_init(0, tighten(Fp1), Fs1, Fn1, att, phase_response, s++, preL,
|
||||||
|
max(preM, 1), &multiplier, r_spec->log2_min_dft_size,
|
||||||
|
r_spec->log2_large_dft_size, core_flags, core->rdft_cb);
|
||||||
|
Fp1 /= Fn1, Fs1 /= Fn1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits==0 && have_arb_stage) { /* `Quick' cubic arb stage: */
|
||||||
|
s->fn = core->cubic_stage_fn;
|
||||||
|
s->mult = multiplier, multiplier = 1;
|
||||||
|
s->step.whole = (int64_t)(arbM * MULT32 + .5);
|
||||||
|
s->pre_post = max(3, s->step.integer);
|
||||||
|
s->preload = s->pre = 1;
|
||||||
|
s->out_in_ratio = MULT32 / (double)s->step.whole;
|
||||||
|
}
|
||||||
|
else if (have_arb_stage) { /* Higher quality arb stage: */
|
||||||
|
static const float rolloffs[] = {-.01f, -.3f, 0, -.103f};
|
||||||
|
poly_fir_t const * f = &core->poly_firs[6*(upsample+!!preM)+mode-!upsample];
|
||||||
|
int order, num_coefs = (int)f->interp[0].scalar, phase_bits, phases;
|
||||||
|
size_t coefs_size;
|
||||||
|
double at, Fp = Fp1, Fs, Fn, mult = upsample? 1 : arbM / arbL;
|
||||||
|
poly_fir1_t const * f1;
|
||||||
|
|
||||||
|
if (!upsample && preM)
|
||||||
|
Fn = 2 * mult, Fs = 3 + fabs(Fs1 - 1);
|
||||||
|
else Fn = 1, Fs = 2 - (mode? Fp1 + (Fs1 - Fp1) * .7 : Fs1);
|
||||||
|
|
||||||
|
if (mode)
|
||||||
|
Fp = Fs - (Fs - Fp) / (1 - lsx_inv_f_resp(rolloffs[rolloff], attArb));
|
||||||
|
|
||||||
|
i = (interpolator < 0? !rational : max(interpolator, !rational)) - 1;
|
||||||
|
do {
|
||||||
|
f1 = &f->interp[++i];
|
||||||
|
assert(f1->fn);
|
||||||
|
if (i)
|
||||||
|
arbM /= arbL, arbL = 1, rational = false;
|
||||||
|
phase_bits = (int)ceil(f1->scalar - log(mult)/log(2.));
|
||||||
|
phases = !rational? (1 << phase_bits) : arbL;
|
||||||
|
if (f->interp[0].scalar==0) {
|
||||||
|
int phases0 = max(phases, 19), n0 = 0;
|
||||||
|
lsx_design_lpf(Fp, Fs, -Fn, attArb, &n0, phases0, f->beta);
|
||||||
|
num_coefs = n0 / phases0 + 1, num_coefs += num_coefs & !preM;
|
||||||
|
}
|
||||||
|
if ((num_coefs & 1) && rational && (arbL & 1))
|
||||||
|
phases <<= 1, arbL <<= 1, arbM *= 2;
|
||||||
|
at = arbL * (s->phase0 = .5 * (num_coefs & 1));
|
||||||
|
order = i + (i && mode > 4);
|
||||||
|
coefs_size = (size_t)(num_coefs4 * phases * (order+1)) * sizeof_real;
|
||||||
|
} while (interpolator < 0 && i < 2 && f->interp[i+1].fn &&
|
||||||
|
coefs_size / 1000 > r_spec->coef_size_kbytes);
|
||||||
|
|
||||||
|
if (!s->shared->poly_fir_coefs) {
|
||||||
|
int num_taps = num_coefs * phases - 1;
|
||||||
|
double * coefs = lsx_design_lpf(
|
||||||
|
Fp, Fs, Fn, attArb, &num_taps, phases, f->beta);
|
||||||
|
s->shared->poly_fir_coefs = prepare_poly_fir_coefs(
|
||||||
|
coefs, num_coefs, phases, order, multiplier, core_flags, &core->mem);
|
||||||
|
lsx_debug("fir_len=%i phases=%i coef_interp=%i size=%.3gk",
|
||||||
|
num_coefs, phases, order, (double)coefs_size / 1000.);
|
||||||
|
free(coefs);
|
||||||
|
}
|
||||||
|
multiplier = 1;
|
||||||
|
s->fn = f1->fn;
|
||||||
|
s->pre_post = num_coefs4 - 1;
|
||||||
|
s->preload = ((num_coefs - 1) >> 1) + (num_coefs4 - num_coefs);
|
||||||
|
s->n = num_coefs4;
|
||||||
|
s->phase_bits = phase_bits;
|
||||||
|
s->L = arbL;
|
||||||
|
s->use_hi_prec_clock =
|
||||||
|
mode>1 && (q_spec->flags & SOXR_HI_PREC_CLOCK) && !rational;
|
||||||
|
#if WITH_FLOAT_STD_PREC_CLOCK
|
||||||
|
if (order && !s->use_hi_prec_clock) {
|
||||||
|
s->at.flt = at;
|
||||||
|
s->step.flt = arbM;
|
||||||
|
s->out_in_ratio = (double)(arbL / s->step.flt);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
s->at.whole = (int64_t)(at * MULT32 + .5);
|
||||||
|
#if WITH_HI_PREC_CLOCK
|
||||||
|
if (s->use_hi_prec_clock) {
|
||||||
|
double M = arbM * MULT32;
|
||||||
|
s->at.fix.ls.parts.ms = 0x80000000ul;
|
||||||
|
s->step.whole = (int64_t)M;
|
||||||
|
M -= (double)s->step.whole;
|
||||||
|
M *= MULT32 * MULT32;
|
||||||
|
s->step.fix.ls.all = (uint64_t)M;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
s->step.whole = (int64_t)(arbM * MULT32 + .5);
|
||||||
|
s->out_in_ratio = MULT32 * arbL / (double)s->step.whole;
|
||||||
|
}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_post_stage)
|
||||||
|
dft_stage_init(1, tighten(Fp0 / (upsample? alpha : 1)), upsample? max(2 -
|
||||||
|
Fs0 / alpha, 1) : Fs0, (double)max(postL, postM), att, phase_response,
|
||||||
|
s++, postL, postM, &multiplier, r_spec->log2_min_dft_size,
|
||||||
|
r_spec->log2_large_dft_size, core_flags, core->rdft_cb);
|
||||||
|
|
||||||
|
lsx_debug("%g: >>%i %i/%i %i/%g %i/%i (%x)", 1/io_ratio,
|
||||||
|
shr, preL, preM, arbL, arbM, postL, postM, core_flags);
|
||||||
|
|
||||||
|
for (i = 0, s = p->stages; i < p->num_stages; ++i, ++s) {
|
||||||
|
fifo_create(&s->fifo, (int)sizeof_real);
|
||||||
|
memset(fifo_reserve(&s->fifo, s->preload), 0,
|
||||||
|
sizeof_real * (size_t)s->preload);
|
||||||
|
lsx_debug_more("%5i|%-5i preload=%i remL=%i",
|
||||||
|
s->pre, s->pre_post-s->pre, s->preload, s->at.integer);
|
||||||
|
}
|
||||||
|
fifo_create(&s->fifo, (int)sizeof_real);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool stage_process(stage_t * stage, bool flushing)
|
||||||
|
{
|
||||||
|
fifo_t * fifo = &stage->fifo;
|
||||||
|
bool done = false;
|
||||||
|
int want;
|
||||||
|
while (!done && (want = stage->input_size - fifo_occupancy(fifo)) > 0) {
|
||||||
|
if (stage->is_input) {
|
||||||
|
if (flushing)
|
||||||
|
memset(fifo_reserve(fifo, want), 0, fifo->item_size * (size_t)want);
|
||||||
|
else done = true;
|
||||||
|
}
|
||||||
|
else done = stage_process(stage - 1, flushing);
|
||||||
|
}
|
||||||
|
stage->fn(stage, &stage[1].fifo);
|
||||||
|
return done && fifo_occupancy(fifo) < stage->input_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void _soxr_process(void * P, size_t olen)
|
||||||
|
{
|
||||||
|
rate_t *p = P;
|
||||||
|
int const n = p->flushing? min(-(int)p->samples_out, (int)olen) : (int)olen;
|
||||||
|
stage_t * stage = &p->stages[p->num_stages];
|
||||||
|
fifo_t * fifo = &stage->fifo;
|
||||||
|
bool done = false;
|
||||||
|
while (!done && fifo_occupancy(fifo) < (int)n)
|
||||||
|
done = stage->is_input || stage_process(stage - 1, p->flushing);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void * _soxr_input(void * P, void * samples, size_t n)
|
||||||
|
{
|
||||||
|
rate_t *p = P;
|
||||||
|
if (p->flushing)
|
||||||
|
return 0;
|
||||||
|
p->samples_in += (int64_t)n;
|
||||||
|
return fifo_write(&p->stages[0].fifo, (int)n, samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void const * _soxr_output(void * P, void * samples, size_t * n0)
|
||||||
|
{
|
||||||
|
rate_t *p = P;
|
||||||
|
fifo_t * fifo = &p->stages[p->num_stages].fifo;
|
||||||
|
int n = p->flushing? min(-(int)p->samples_out, (int)*n0) : (int)*n0;
|
||||||
|
p->samples_out += n = min(n, fifo_occupancy(fifo));
|
||||||
|
return fifo_read(fifo, (int)(*n0 = (size_t)n), samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void _soxr_flush(void * P)
|
||||||
|
{
|
||||||
|
rate_t *p = P;
|
||||||
|
if (p->flushing) return;
|
||||||
|
p->samples_out -= (int64_t)((double)p->samples_in / p->io_ratio + .5);
|
||||||
|
p->samples_in = 0;
|
||||||
|
p->flushing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void _soxr_close(void * P)
|
||||||
|
{
|
||||||
|
rate_t *p = P;
|
||||||
|
if (p->stages) {
|
||||||
|
rdft_cb_table const * const RDFT_CB = p->core->rdft_cb;
|
||||||
|
rate_shared_t * shared = p->stages[0].shared;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i <= p->num_stages; ++i) {
|
||||||
|
stage_t * s = &p->stages[i];
|
||||||
|
rdft_free(s->dft_scratch);
|
||||||
|
rdft_free(s->dft_out);
|
||||||
|
fifo_delete(&s->fifo);
|
||||||
|
}
|
||||||
|
if (shared) {
|
||||||
|
for (i = 0; i < 2; ++i) {
|
||||||
|
dft_filter_t * f= &shared->dft_filter[i];
|
||||||
|
rdft_free(f->coefs);
|
||||||
|
rdft_delete_setup(f->dft_forward_setup);
|
||||||
|
rdft_delete_setup(f->dft_backward_setup);
|
||||||
|
}
|
||||||
|
p->core->mem.free(shared->poly_fir_coefs);
|
||||||
|
memset(shared, 0, sizeof(*shared));
|
||||||
|
}
|
||||||
|
free(p->stages);
|
||||||
|
(rdft_cb_table const *)RDFT_CB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined SOXR_LIB
|
||||||
|
STATIC double _soxr_delay(void * P)
|
||||||
|
{
|
||||||
|
rate_t *p = P;
|
||||||
|
return (double)p->samples_in / p->io_ratio - (double)p->samples_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void _soxr_sizes(size_t * shared, size_t * channel)
|
||||||
|
{
|
||||||
|
*shared = sizeof(rate_shared_t);
|
||||||
|
*channel = sizeof(rate_t);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if !defined soxr_cr_included
|
||||||
|
#define soxr_cr_included
|
||||||
|
|
||||||
|
#define FIFO_SIZE_T int
|
||||||
|
#include "fifo.h"
|
||||||
|
|
||||||
|
typedef void real; /* float or double */
|
||||||
|
struct stage;
|
||||||
|
typedef void (* stage_fn_t)(struct stage * input, fifo_t * output);
|
||||||
|
typedef struct half_fir_info {
|
||||||
|
int num_coefs;
|
||||||
|
real const * coefs;
|
||||||
|
stage_fn_t fn, dfn;
|
||||||
|
float att;
|
||||||
|
} half_fir_info_t;
|
||||||
|
typedef struct {float scalar; stage_fn_t fn;} poly_fir1_t;
|
||||||
|
typedef struct {float beta; poly_fir1_t interp[3];} poly_fir_t;
|
||||||
|
|
||||||
|
#define U100_l 42
|
||||||
|
#define MULT32 (65536. * 65536.)
|
||||||
|
|
||||||
|
/* Conceptually: coef_p is &coefs[num_phases][fir_len][interp_order+1]: */
|
||||||
|
#define coef(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) (coef_p)[\
|
||||||
|
(fir_len) * ((interp_order) + 1) * (phase_num) + \
|
||||||
|
((interp_order) + 1) * (fir_coef_num) + \
|
||||||
|
((interp_order) - (coef_interp_num))]
|
||||||
|
|
||||||
|
/* Conceptually: coef_p is &coefs[num_phases][fir_len/4][interp_order+1][4]: */
|
||||||
|
#define coef4(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) (coef_p)[\
|
||||||
|
(fir_len) * ((interp_order) + 1) * (phase_num) + \
|
||||||
|
((interp_order) + 1) * ((fir_coef_num) & ~3) + \
|
||||||
|
4 * ((interp_order) - (coef_interp_num)) + \
|
||||||
|
((fir_coef_num) & 3)]
|
||||||
|
|
||||||
|
typedef union { /* Int64 in parts */
|
||||||
|
#if HAVE_BIGENDIAN
|
||||||
|
struct {int32_t ms; uint32_t ls;} parts;
|
||||||
|
#else
|
||||||
|
struct {uint32_t ls; int32_t ms;} parts;
|
||||||
|
#endif
|
||||||
|
int64_t all;
|
||||||
|
} int64p_t;
|
||||||
|
|
||||||
|
typedef union { /* Uint64 in parts */
|
||||||
|
#if HAVE_BIGENDIAN
|
||||||
|
struct {uint32_t ms, ls;} parts;
|
||||||
|
#else
|
||||||
|
struct {uint32_t ls, ms;} parts;
|
||||||
|
#endif
|
||||||
|
uint64_t all;
|
||||||
|
} uint64p_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dft_length, num_taps, post_peak;
|
||||||
|
void * dft_forward_setup, * dft_backward_setup;
|
||||||
|
real * coefs;
|
||||||
|
} dft_filter_t;
|
||||||
|
|
||||||
|
typedef struct { /* So generated filter coefs may be shared between channels */
|
||||||
|
real * poly_fir_coefs;
|
||||||
|
dft_filter_t dft_filter[2];
|
||||||
|
} rate_shared_t;
|
||||||
|
|
||||||
|
typedef double float_step_t; /* Or long double or __float128. */
|
||||||
|
|
||||||
|
typedef union { /* Fixed point arithmetic */
|
||||||
|
struct {uint64p_t ls; int64p_t ms;} fix; /* Hi-prec has ~96 bits. */
|
||||||
|
float_step_t flt;
|
||||||
|
} step_t;
|
||||||
|
|
||||||
|
#define integer fix.ms.parts.ms
|
||||||
|
#define fraction fix.ms.parts.ls
|
||||||
|
#define whole fix.ms.all
|
||||||
|
|
||||||
|
#define CORE_DBL 1
|
||||||
|
#define CORE_SIMD_POLY 2
|
||||||
|
#define CORE_SIMD_HALF 4
|
||||||
|
#define CORE_SIMD_DFT 8
|
||||||
|
#define LOG2_SIZEOF_REAL(core_flags) (2 + ((core_flags) & 1))
|
||||||
|
|
||||||
|
typedef int core_flags_t;
|
||||||
|
|
||||||
|
#if defined SOXR_LIB
|
||||||
|
#include "rdft_t.h"
|
||||||
|
#else
|
||||||
|
typedef void fn_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct stage {
|
||||||
|
int num;
|
||||||
|
|
||||||
|
/* Common to all stage types: */
|
||||||
|
core_flags_t core_flags;
|
||||||
|
stage_fn_t fn;
|
||||||
|
fifo_t fifo;
|
||||||
|
int pre; /* Number of past samples to store */
|
||||||
|
int pre_post; /* pre + number of future samples to store */
|
||||||
|
int preload; /* Number of zero samples to pre-load the fifo */
|
||||||
|
double out_in_ratio; /* For buffer management. */
|
||||||
|
int input_size;
|
||||||
|
bool is_input;
|
||||||
|
|
||||||
|
/* For a stage with variable (run-time generated) filter coefs: */
|
||||||
|
rdft_cb_table const * rdft_cb;
|
||||||
|
rate_shared_t * shared;
|
||||||
|
unsigned dft_filter_num; /* Which, if any, of the 2 DFT filters to use */
|
||||||
|
real * dft_scratch;
|
||||||
|
float * dft_out;
|
||||||
|
real const * coefs;
|
||||||
|
|
||||||
|
/* For a stage with variable L/M: */
|
||||||
|
step_t at, step;
|
||||||
|
bool use_hi_prec_clock;
|
||||||
|
int L, remM;
|
||||||
|
int n, phase_bits, block_len;
|
||||||
|
double mult, phase0;
|
||||||
|
} stage_t;
|
||||||
|
|
||||||
|
#define stage_occupancy(s) max(0, fifo_occupancy(&(s)->fifo) - (s)->pre_post)
|
||||||
|
#define stage_read_p(s) ((sample_t *)fifo_read_ptr(&(s)->fifo) + (s)->pre)
|
||||||
|
|
||||||
|
#define lq_bw0 (1385/2048.) /* ~.67625, FP exact. */
|
||||||
|
|
||||||
|
typedef enum {rolloff_small, rolloff_medium, rolloff_none} rolloff_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void * (* alloc)(size_t);
|
||||||
|
void * (* calloc)(size_t, size_t);
|
||||||
|
void (* free)(void *);
|
||||||
|
} alloc_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
alloc_t mem;
|
||||||
|
half_fir_info_t const * half_firs;
|
||||||
|
size_t half_firs_len;
|
||||||
|
half_fir_info_t const * doub_firs;
|
||||||
|
size_t doub_firs_len;
|
||||||
|
stage_fn_t cubic_stage_fn;
|
||||||
|
poly_fir_t const * poly_firs;
|
||||||
|
rdft_cb_table * rdft_cb;
|
||||||
|
} cr_core_t;
|
||||||
|
|
||||||
|
typedef struct rate rate_t;
|
||||||
|
struct rate {
|
||||||
|
cr_core_t const * core;
|
||||||
|
double io_ratio;
|
||||||
|
int64_t samples_in, samples_out;
|
||||||
|
int num_stages, flushing;
|
||||||
|
stage_t * stages;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined SOXR_LIB
|
||||||
|
|
||||||
|
#include "soxr.h"
|
||||||
|
|
||||||
|
char const * _soxr_init(
|
||||||
|
rate_t * const p, /* Per audio channel. */
|
||||||
|
rate_shared_t * const shared, /* Between channels (undergoing same rate change)*/
|
||||||
|
double const io_ratio, /* Input rate divided by output rate. */
|
||||||
|
soxr_quality_spec_t const * const q_spec,
|
||||||
|
soxr_runtime_spec_t const * const r_spec,
|
||||||
|
double multiplier, /* Linear gain to apply during conversion. 1 */
|
||||||
|
cr_core_t const * const core,
|
||||||
|
core_flags_t const);
|
||||||
|
|
||||||
|
void _soxr_process(void * p, size_t olen);
|
||||||
|
void * _soxr_input(void * p, void * samples, size_t n);
|
||||||
|
void const * _soxr_output(void * p, void * samples, size_t * n0);
|
||||||
|
void _soxr_flush(void * p);
|
||||||
|
void _soxr_close(void * p);
|
||||||
|
double _soxr_delay(void * p);
|
||||||
|
void _soxr_sizes(size_t * shared, size_t * channel);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#define RATE_CB _soxr_rate32_cb
|
||||||
|
#define CORE_STR "cr32"
|
||||||
|
|
||||||
|
#define CORE_TYPE 0
|
||||||
|
#include "cr-core.c"
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#define RATE_CB _soxr_rate32s_cb
|
||||||
|
#define CORE_STR "cr32s"
|
||||||
|
|
||||||
|
#define CORE_TYPE (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
|
||||||
|
#include "cr-core.c"
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#define RATE_CB _soxr_rate64_cb
|
||||||
|
#define CORE_STR "cr64"
|
||||||
|
|
||||||
|
#define CORE_TYPE CORE_DBL
|
||||||
|
#include "cr-core.c"
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#define RATE_CB _soxr_rate64s_cb
|
||||||
|
#define CORE_STR "cr64s"
|
||||||
|
|
||||||
|
#define CORE_TYPE (CORE_DBL|CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
|
||||||
|
#include "cr-core.c"
|
|
@ -1,4 +1,4 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -14,8 +14,8 @@
|
||||||
unsigned i; \
|
unsigned i; \
|
||||||
size_t j; \
|
size_t j; \
|
||||||
T const * src = *src0; \
|
T const * src = *src0; \
|
||||||
if (ch > 1) \
|
if (ch > 1) for (j = 0; j < n; ++j) \
|
||||||
for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = (DEINTERLEAVE_TO)*src++; \
|
for (i = 0; i < ch; ++i) dest[i][j] = (DEINTERLEAVE_TO)*src++; \
|
||||||
else if (flag) memcpy(dest[0], src, n * sizeof(T)), src = &src[n]; \
|
else if (flag) memcpy(dest[0], src, n * sizeof(T)), src = &src[n]; \
|
||||||
else for (j = 0; j < n; dest[0][j++] = (DEINTERLEAVE_TO)*src++); \
|
else for (j = 0; j < n; dest[0][j++] = (DEINTERLEAVE_TO)*src++); \
|
||||||
*src0 = src; \
|
*src0 = src; \
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_DOUBLE_PRECISION
|
#if WITH_CR64 || WITH_CR64S
|
||||||
void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */
|
void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */
|
||||||
soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch)
|
soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_SINGLE_PRECISION
|
#if WITH_CR32 || WITH_CR32S || WITH_VR32
|
||||||
void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch)
|
soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch)
|
||||||
{
|
{
|
||||||
|
@ -60,35 +60,6 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
|
|
||||||
#include "rint.h"
|
#include "rint.h"
|
||||||
|
|
||||||
#if HAVE_FENV_H
|
|
||||||
#include <fenv.h>
|
|
||||||
#define fe_test_invalid() fetestexcept(FE_INVALID)
|
|
||||||
#define fe_clear_invalid() feclearexcept(FE_INVALID)
|
|
||||||
#elif defined _MSC_VER
|
|
||||||
#define FE_INVALID 1
|
|
||||||
#if defined _WIN64
|
|
||||||
#include <float.h>
|
|
||||||
#define fe_test_invalid() (_statusfp() & _SW_INVALID)
|
|
||||||
#define fe_clear_invalid _clearfp /* FIXME clears all */
|
|
||||||
#else
|
|
||||||
static __inline int fe_test_invalid()
|
|
||||||
{
|
|
||||||
short status_word;
|
|
||||||
__asm fnstsw status_word
|
|
||||||
return status_word & FE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline int fe_clear_invalid()
|
|
||||||
{
|
|
||||||
int16_t status[14];
|
|
||||||
__asm fnstenv status
|
|
||||||
status[2] &= ~FE_INVALID;
|
|
||||||
__asm fldenv status
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__
|
#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__
|
||||||
|
@ -97,13 +68,13 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_DOUBLE_PRECISION
|
#if WITH_CR64 || WITH_CR64S
|
||||||
#define FLOATX double
|
#define FLOATX double
|
||||||
|
|
||||||
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2
|
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2
|
||||||
#define LSX_RINT_CLIP lsx_rint32_clip
|
#define LSX_RINT_CLIP lsx_rint32_clip
|
||||||
#define RINT_CLIP rint32_clip
|
#define RINT_CLIP rint32_clip
|
||||||
#define RINT rint32
|
#define RINT rint32D
|
||||||
#if defined FPU_RINT32
|
#if defined FPU_RINT32
|
||||||
#define FPU_RINT
|
#define FPU_RINT
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,7 +85,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2
|
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2
|
||||||
#define LSX_RINT_CLIP lsx_rint16_clip
|
#define LSX_RINT_CLIP lsx_rint16_clip
|
||||||
#define RINT_CLIP rint16_clip
|
#define RINT_CLIP rint16_clip
|
||||||
#define RINT rint16
|
#define RINT rint16D
|
||||||
#if defined FPU_RINT16
|
#if defined FPU_RINT16
|
||||||
#define FPU_RINT
|
#define FPU_RINT
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,7 +96,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither
|
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither
|
||||||
#define LSX_RINT_CLIP lsx_rint16_clip_dither
|
#define LSX_RINT_CLIP lsx_rint16_clip_dither
|
||||||
#define RINT_CLIP rint16_clip_dither
|
#define RINT_CLIP rint16_clip_dither
|
||||||
#define RINT rint16
|
#define RINT rint16D
|
||||||
#if defined FPU_RINT16
|
#if defined FPU_RINT16
|
||||||
#define FPU_RINT
|
#define FPU_RINT
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,13 +110,13 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_SINGLE_PRECISION
|
#if WITH_CR32 || WITH_CR32S || WITH_VR32
|
||||||
#define FLOATX float
|
#define FLOATX float
|
||||||
|
|
||||||
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2_f
|
#define LSX_RINT_CLIP_2 lsx_rint32_clip_2_f
|
||||||
#define LSX_RINT_CLIP lsx_rint32_clip_f
|
#define LSX_RINT_CLIP lsx_rint32_clip_f
|
||||||
#define RINT_CLIP rint32_clip_f
|
#define RINT_CLIP rint32_clip_f
|
||||||
#define RINT rint32
|
#define RINT rint32F
|
||||||
#if defined FPU_RINT32
|
#if defined FPU_RINT32
|
||||||
#define FPU_RINT
|
#define FPU_RINT
|
||||||
#endif
|
#endif
|
||||||
|
@ -156,7 +127,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_f
|
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_f
|
||||||
#define LSX_RINT_CLIP lsx_rint16_clip_f
|
#define LSX_RINT_CLIP lsx_rint16_clip_f
|
||||||
#define RINT_CLIP rint16_clip_f
|
#define RINT_CLIP rint16_clip_f
|
||||||
#define RINT rint16
|
#define RINT rint16F
|
||||||
#if defined FPU_RINT16
|
#if defined FPU_RINT16
|
||||||
#define FPU_RINT
|
#define FPU_RINT
|
||||||
#endif
|
#endif
|
||||||
|
@ -167,7 +138,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither_f
|
#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither_f
|
||||||
#define LSX_RINT_CLIP lsx_rint16_clip_dither_f
|
#define LSX_RINT_CLIP lsx_rint16_clip_dither_f
|
||||||
#define RINT_CLIP rint16_clip_dither_f
|
#define RINT_CLIP rint16_clip_dither_f
|
||||||
#define RINT rint16
|
#define RINT rint16D
|
||||||
#if defined FPU_RINT16
|
#if defined FPU_RINT16
|
||||||
#define FPU_RINT
|
#define FPU_RINT
|
||||||
#endif
|
#endif
|
||||||
|
@ -199,7 +170,7 @@ void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */
|
||||||
return 0; \
|
return 0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#if HAVE_DOUBLE_PRECISION
|
#if WITH_CR64 || WITH_CR64S
|
||||||
size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0,
|
size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0,
|
||||||
double const * const * src, size_t n, unsigned ch, unsigned long * seed)
|
double const * const * src, size_t n, unsigned ch, unsigned long * seed)
|
||||||
{
|
{
|
||||||
|
@ -225,7 +196,7 @@ size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_SINGLE_PRECISION
|
#if WITH_CR32 || WITH_CR32S || WITH_VR32
|
||||||
size_t /* clips */ _soxr_interleave_f(soxr_datatype_t data_type, void * * dest0,
|
size_t /* clips */ _soxr_interleave_f(soxr_datatype_t data_type, void * * dest0,
|
||||||
float const * const * src, size_t n, unsigned ch, unsigned long * seed)
|
float const * const * src, size_t n, unsigned ch, unsigned long * seed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if !defined soxr_dev32s_included
|
||||||
|
#define soxr_dev32s_included
|
||||||
|
|
||||||
|
#if defined __GNUC__
|
||||||
|
#define SIMD_INLINE(T) static __inline T __attribute__((always_inline))
|
||||||
|
#define vAlign __attribute__((aligned (16)))
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
#define SIMD_INLINE(T) static __forceinline T
|
||||||
|
#define vAlign __declspec(align(16))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86
|
||||||
|
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
#define vZero() _mm_setzero_ps()
|
||||||
|
#define vSet1(a) _mm_set_ss(a)
|
||||||
|
#define vMul(a,b) _mm_mul_ps(a,b)
|
||||||
|
#define vAdd(a,b) _mm_add_ps(a,b)
|
||||||
|
#define vMac(a,b,c) vAdd(vMul(a,b),c)
|
||||||
|
#define vLds(a) _mm_set1_ps(a)
|
||||||
|
#define vLd(a) _mm_load_ps(a)
|
||||||
|
#define vLdu(a) _mm_loadu_ps(a)
|
||||||
|
|
||||||
|
typedef __m128 v4_t;
|
||||||
|
|
||||||
|
SIMD_INLINE(void) vStorSum(float * a, v4_t b) {
|
||||||
|
v4_t t = vAdd(_mm_movehl_ps(b, b), b);
|
||||||
|
_mm_store_ss(a, vAdd(t, _mm_shuffle_ps(t,t,1)));}
|
||||||
|
|
||||||
|
#elif defined __arm__
|
||||||
|
|
||||||
|
#include <arm_neon.h>
|
||||||
|
|
||||||
|
#define vZero() vdupq_n_f32(0)
|
||||||
|
#define vMul(a,b) vmulq_f32(a,b)
|
||||||
|
#define vAdd(a,b) vaddq_f32(a,b)
|
||||||
|
#define vMac(a,b,c) vmlaq_f32(c,a,b)
|
||||||
|
#define vLds(a) vld1q_dup_f32(&(a))
|
||||||
|
#define vLd(a) vld1q_f32(a)
|
||||||
|
#define vLdu(a) vld1q_f32(a)
|
||||||
|
|
||||||
|
typedef float32x4_t v4_t;
|
||||||
|
|
||||||
|
SIMD_INLINE(void) vStorSum(float * a, v4_t b) {
|
||||||
|
float32x2_t t = vadd_f32(vget_high_f32(b), vget_low_f32(b));
|
||||||
|
*a = vget_lane_f32(vpadd_f32(t, t), 0);}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if !defined soxr_dev64s_included
|
||||||
|
#define soxr_dev64s_included
|
||||||
|
|
||||||
|
#if defined __GNUC__
|
||||||
|
#define SIMD_INLINE(T) static __inline T __attribute__((always_inline))
|
||||||
|
#define vAlign __attribute__((aligned (32)))
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
#define SIMD_INLINE(T) static __forceinline T
|
||||||
|
#define vAlign __declspec(align(32))
|
||||||
|
#else
|
||||||
|
#define SIMD_INLINE(T) static __inline T
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86
|
||||||
|
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
#if defined __AVX__
|
||||||
|
|
||||||
|
#define vZero() _mm256_setzero_pd()
|
||||||
|
#define vSet1(a) _mm256_set_pd(0,0,0,a)
|
||||||
|
#define vMul(a,b) _mm256_mul_pd(a,b)
|
||||||
|
#define vAdd(a,b) _mm256_add_pd(a,b)
|
||||||
|
#define vMac(a,b,c) vAdd(vMul(a,b),c) /* Note: gcc -mfma will `fuse' these */
|
||||||
|
#define vLds(a) _mm256_set1_pd(a)
|
||||||
|
#define vLd(a) _mm256_load_pd(a)
|
||||||
|
#define vLdu(a) _mm256_loadu_pd(a)
|
||||||
|
|
||||||
|
typedef __m256d v4_t;
|
||||||
|
|
||||||
|
SIMD_INLINE(void) vStorSum(double * a, v4_t b) {
|
||||||
|
b = _mm256_hadd_pd(b, _mm256_permute2f128_pd(b,b,1));
|
||||||
|
_mm_store_sd(a, _mm256_castpd256_pd128(_mm256_hadd_pd(b,b)));}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -282,22 +282,16 @@ Appendix :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <math.h>
|
#include "math-wrap.h"
|
||||||
#include "fft4g.h"
|
#include "fft4g.h"
|
||||||
|
|
||||||
#ifdef FFT4G_FLOAT
|
#ifdef FFT4G_FLOAT
|
||||||
#define double float
|
#define double float
|
||||||
#define one_half 0.5f
|
#define one_half 0.5f
|
||||||
|
|
||||||
#if defined _MSC_VER
|
#define sin(x) sinf(x)
|
||||||
#define sin (float)sin
|
#define cos(x) cosf(x)
|
||||||
#define cos (float)cos
|
#define atan(x) atanf(x)
|
||||||
#define atan (float)atan
|
|
||||||
#else
|
|
||||||
#define sin sinf
|
|
||||||
#define cos cosf
|
|
||||||
#define atan atanf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define cdft lsx_cdft_f
|
#define cdft lsx_cdft_f
|
||||||
#define rdft lsx_rdft_f
|
#define rdft lsx_rdft_f
|
||||||
|
@ -818,7 +812,7 @@ static void bitrv2(int n, int *ip0, double *a)
|
||||||
|
|
||||||
static void bitrv2conj(int n, int *ip0, double *a)
|
static void bitrv2conj(int n, int *ip0, double *a)
|
||||||
{
|
{
|
||||||
int j, j1, k, k1, l, m, m2, ip[256];
|
int j, j1, k, k1, l, m, m2, ip[512];
|
||||||
double xr, xi, yr, yi;
|
double xr, xi, yr, yi;
|
||||||
|
|
||||||
(void)ip0;
|
(void)ip0;
|
||||||
|
|
|
@ -1,27 +1,38 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#define FFT4G_FLOAT
|
#define FFT4G_FLOAT
|
||||||
#include "fft4g.c"
|
#include "fft4g.c"
|
||||||
|
#include "soxr-config.h"
|
||||||
|
|
||||||
static void * null(void) {return 0;}
|
#if WITH_CR32
|
||||||
static void forward (int length, void * setup, double * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;}
|
#include "rdft_t.h"
|
||||||
static void backward(int length, void * setup, double * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;}
|
static void * null(int u1) {(void)u1; return 0;}
|
||||||
|
static void forward (int length, void * setup, void * H, void * scratch) {lsx_safe_rdft_f(length, 1, H); (void)setup; (void)scratch;}
|
||||||
|
static void backward(int length, void * setup, void * H, void * scratch) {lsx_safe_rdft_f(length, -1, H); (void)setup; (void)scratch;}
|
||||||
static int multiplier(void) {return 2;}
|
static int multiplier(void) {return 2;}
|
||||||
static void nothing(void) {}
|
static void nothing(void *u1) {(void)u1;}
|
||||||
|
static void nothing2(int u1, void *u2, void *u3, void *u4) {(void)u1; (void)u2; (void)u3; (void)u4;}
|
||||||
|
static int flags(void) {return 0;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft32_cb = {
|
||||||
fn_t _soxr_rdft32_cb[] = {
|
null,
|
||||||
(fn_t)null,
|
null,
|
||||||
(fn_t)null,
|
nothing,
|
||||||
(fn_t)nothing,
|
forward,
|
||||||
(fn_t)forward,
|
forward,
|
||||||
(fn_t)forward,
|
backward,
|
||||||
(fn_t)backward,
|
backward,
|
||||||
(fn_t)backward,
|
_soxr_ordered_convolve_f,
|
||||||
(fn_t)_soxr_ordered_convolve_f,
|
_soxr_ordered_partial_convolve_f,
|
||||||
(fn_t)_soxr_ordered_partial_convolve_f,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
nothing2,
|
||||||
(fn_t)nothing,
|
malloc,
|
||||||
|
calloc,
|
||||||
|
free,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -2,25 +2,30 @@
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "simd.h"
|
#include "util32s.h"
|
||||||
|
#include "rdft_t.h"
|
||||||
|
|
||||||
static void * null(void) {return 0;}
|
static void * null(void) {return 0;}
|
||||||
static void nothing(void) {}
|
static void nothing(void) {}
|
||||||
static void forward (int length, void * setup, float * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;}
|
static void forward (int length, void * setup, float * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;}
|
||||||
static void backward(int length, void * setup, float * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;}
|
static void backward(int length, void * setup, float * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;}
|
||||||
static int multiplier(void) {return 2;}
|
static int multiplier(void) {return 2;}
|
||||||
|
static int flags(void) {return RDFT_IS_SIMD;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft32s_cb = {
|
||||||
fn_t _soxr_rdft32s_cb[] = {
|
null,
|
||||||
(fn_t)null,
|
null,
|
||||||
(fn_t)null,
|
nothing,
|
||||||
(fn_t)nothing,
|
forward,
|
||||||
(fn_t)forward,
|
forward,
|
||||||
(fn_t)forward,
|
backward,
|
||||||
(fn_t)backward,
|
backward,
|
||||||
(fn_t)backward,
|
ORDERED_CONVOLVE_SIMD,
|
||||||
(fn_t)_soxr_ordered_convolve_simd,
|
ORDERED_PARTIAL_CONVOLVE_SIMD,
|
||||||
(fn_t)_soxr_ordered_partial_convolve_simd,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
nothing,
|
||||||
(fn_t)nothing,
|
SIMD_ALIGNED_MALLOC,
|
||||||
|
SIMD_ALIGNED_CALLOC,
|
||||||
|
SIMD_ALIGNED_FREE,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,36 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "fft4g.c"
|
#include "fft4g.c"
|
||||||
#include "soxr-config.h"
|
#include "soxr-config.h"
|
||||||
|
|
||||||
#if HAVE_DOUBLE_PRECISION
|
#if WITH_CR64
|
||||||
static void * null(void) {return 0;}
|
#include "rdft_t.h"
|
||||||
static void nothing(void) {}
|
static void * null(int u1) {(void)u1; return 0;}
|
||||||
static void forward (int length, void * setup, double * H) {lsx_safe_rdft(length, 1, H); (void)setup;}
|
static void nothing(void *u1) {(void)u1;}
|
||||||
static void backward(int length, void * setup, double * H) {lsx_safe_rdft(length, -1, H); (void)setup;}
|
static void nothing2(int u1, void *u2, void *u3, void *u4) {(void)u1; (void)u2; (void)u3; (void)u4;}
|
||||||
|
static void forward (int length, void * setup, void * H, void * scratch) {lsx_safe_rdft(length, 1, H); (void)setup; (void)scratch;}
|
||||||
|
static void backward(int length, void * setup, void * H, void * scratch) {lsx_safe_rdft(length, -1, H); (void)setup; (void)scratch;}
|
||||||
static int multiplier(void) {return 2;}
|
static int multiplier(void) {return 2;}
|
||||||
|
static int flags(void) {return 0;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft64_cb = {
|
||||||
fn_t _soxr_rdft64_cb[] = {
|
null,
|
||||||
(fn_t)null,
|
null,
|
||||||
(fn_t)null,
|
nothing,
|
||||||
(fn_t)nothing,
|
forward,
|
||||||
(fn_t)forward,
|
forward,
|
||||||
(fn_t)forward,
|
backward,
|
||||||
(fn_t)backward,
|
backward,
|
||||||
(fn_t)backward,
|
_soxr_ordered_convolve,
|
||||||
(fn_t)_soxr_ordered_convolve,
|
_soxr_ordered_partial_convolve,
|
||||||
(fn_t)_soxr_ordered_partial_convolve,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
nothing2,
|
||||||
(fn_t)nothing,
|
malloc,
|
||||||
|
calloc,
|
||||||
|
free,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#ifndef fifo_included
|
#ifndef soxr_fifo_included
|
||||||
#define fifo_included
|
#define soxr_fifo_included
|
||||||
|
|
||||||
#if !defined FIFO_SIZE_T
|
#if !defined FIFO_SIZE_T
|
||||||
#define FIFO_SIZE_T size_t
|
#define FIFO_SIZE_T size_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined FIFO_REALLOC
|
#if !defined FIFO_REALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
#define FIFO_REALLOC(a,b,c) realloc(a,b)
|
#define FIFO_REALLOC(a,b,c) realloc(a,b)
|
||||||
#undef FIFO_FREE
|
#undef FIFO_FREE
|
||||||
#define FIFO_FREE free
|
#define FIFO_FREE free
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include "math-wrap.h"
|
||||||
#if !defined M_PI
|
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#endif
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -14,7 +11,7 @@
|
||||||
#include "fft4g.h"
|
#include "fft4g.h"
|
||||||
#include "ccrw2.h"
|
#include "ccrw2.h"
|
||||||
|
|
||||||
#if 1 || HAVE_DOUBLE_PRECISION /* Always need this, for lsx_fir_to_phase. */
|
#if 1 || WITH_CR64 || WITH_CR64S /* Always need this, for lsx_fir_to_phase. */
|
||||||
#define DFT_FLOAT double
|
#define DFT_FLOAT double
|
||||||
#define DONE_WITH_FFT_CACHE done_with_fft_cache
|
#define DONE_WITH_FFT_CACHE done_with_fft_cache
|
||||||
#define FFT_CACHE_CCRW fft_cache_ccrw
|
#define FFT_CACHE_CCRW fft_cache_ccrw
|
||||||
|
@ -31,7 +28,7 @@
|
||||||
#include "fft4g_cache.h"
|
#include "fft4g_cache.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_SINGLE_PRECISION && !HAVE_AVFFT
|
#if (WITH_CR32 && !AVCODEC_FOUND) || (WITH_CR32S && !AVCODEC_FOUND && !WITH_PFFFT)
|
||||||
#define DFT_FLOAT float
|
#define DFT_FLOAT float
|
||||||
#define DONE_WITH_FFT_CACHE done_with_fft_cache_f
|
#define DONE_WITH_FFT_CACHE done_with_fft_cache_f
|
||||||
#define FFT_CACHE_CCRW fft_cache_ccrw_f
|
#define FFT_CACHE_CCRW fft_cache_ccrw_f
|
||||||
|
@ -48,14 +45,14 @@
|
||||||
#include "fft4g_cache.h"
|
#include "fft4g_cache.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_DOUBLE_PRECISION || !SOXR_LIB
|
#if WITH_CR64 || WITH_CR64S || !SOXR_LIB
|
||||||
#define DFT_FLOAT double
|
#define DFT_FLOAT double
|
||||||
#define ORDERED_CONVOLVE lsx_ordered_convolve
|
#define ORDERED_CONVOLVE lsx_ordered_convolve
|
||||||
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve
|
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve
|
||||||
#include "rdft.h"
|
#include "rdft.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_SINGLE_PRECISION
|
#if WITH_CR32
|
||||||
#define DFT_FLOAT float
|
#define DFT_FLOAT float
|
||||||
#define ORDERED_CONVOLVE lsx_ordered_convolve_f
|
#define ORDERED_CONVOLVE lsx_ordered_convolve_f
|
||||||
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f
|
#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f
|
||||||
|
@ -96,12 +93,12 @@ double * lsx_make_lpf(
|
||||||
double * h = malloc((size_t)num_taps * sizeof(*h));
|
double * h = malloc((size_t)num_taps * sizeof(*h));
|
||||||
double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho);
|
double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho);
|
||||||
assert(Fc >= 0 && Fc <= 1);
|
assert(Fc >= 0 && Fc <= 1);
|
||||||
lsx_debug("make_lpf(n=%i Fc=%.7g β=%g ρ=%g scale=%g)",
|
lsx_debug("make_lpf(n=%i Fc=%.7g beta=%g rho=%g scale=%g)",
|
||||||
num_taps, Fc, beta, rho, scale);
|
num_taps, Fc, beta, rho, scale);
|
||||||
|
|
||||||
if (h) for (i = 0; i <= m / 2; ++i) {
|
if (h) for (i = 0; i <= m / 2; ++i) {
|
||||||
double z = i - .5 * m, x = z * M_PI, y = z * mult1;
|
double z = i - .5 * m, x = z * M_PI, y = z * mult1;
|
||||||
h[i] = x? sin(Fc * x) / x : Fc;
|
h[i] = x!=0? sin(Fc * x) / x : Fc;
|
||||||
h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult;
|
h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult;
|
||||||
if (m - i != i)
|
if (m - i != i)
|
||||||
h[m - i] = h[i];
|
h[m - i] = h[i];
|
||||||
|
@ -123,12 +120,15 @@ double * lsx_design_lpf(
|
||||||
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */
|
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */
|
||||||
double att, /* Stop-band attenuation in dB */
|
double att, /* Stop-band attenuation in dB */
|
||||||
int * num_taps, /* 0: value will be estimated */
|
int * num_taps, /* 0: value will be estimated */
|
||||||
int k, /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */
|
int k, /* >0: number of phases; <0: num_taps = 1 (mod -k) */
|
||||||
double beta) /* <0: value will be estimated */
|
double beta) /* <0: value will be estimated */
|
||||||
{
|
{
|
||||||
int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1);
|
int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1);
|
||||||
double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75;
|
double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75;
|
||||||
|
|
||||||
|
lsx_debug_more("./sinctest %-12.7g %-12.7g %g 0 %-5g %i %i 50 %g %g -4 >1",
|
||||||
|
Fp, Fs, Fn, att, *num_taps, k, beta, rho);
|
||||||
|
|
||||||
Fp /= fabs(Fn), Fs /= fabs(Fn); /* Normalise to Fn = 1 */
|
Fp /= fabs(Fn), Fs /= fabs(Fn); /* Normalise to Fn = 1 */
|
||||||
tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */
|
tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */
|
||||||
tr_bw /= phases, Fs /= phases;
|
tr_bw /= phases, Fs /= phases;
|
||||||
|
@ -145,7 +145,7 @@ double * lsx_design_lpf(
|
||||||
static double safe_log(double x)
|
static double safe_log(double x)
|
||||||
{
|
{
|
||||||
assert(x >= 0);
|
assert(x >= 0);
|
||||||
if (x)
|
if (x!=0)
|
||||||
return log(x);
|
return log(x);
|
||||||
lsx_debug("log(0)");
|
lsx_debug("log(0)");
|
||||||
return -26;
|
return -26;
|
||||||
|
@ -222,7 +222,7 @@ void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase)
|
||||||
while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0)
|
while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0)
|
||||||
--peak;
|
--peak;
|
||||||
|
|
||||||
if (!phase1)
|
if (phase1==0)
|
||||||
begin = 0;
|
begin = 0;
|
||||||
else if (phase1 == 1)
|
else if (phase1 == 1)
|
||||||
begin = peak - *len / 2;
|
begin = peak - *len / 2;
|
||||||
|
@ -243,3 +243,35 @@ void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase)
|
||||||
work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1));
|
work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1));
|
||||||
free(pi_wraps), free(work);
|
free(pi_wraps), free(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define F_x(F,expr) static double F(double x) {return expr;}
|
||||||
|
F_x(sinePhi, ((2.0517e-07*x-1.1303e-04)*x+.023154)*x+.55924 )
|
||||||
|
F_x(sinePsi, ((9.0667e-08*x-5.6114e-05)*x+.013658)*x+1.0977 )
|
||||||
|
F_x(sinePow, log(.5)/log(sin(x*.5)) )
|
||||||
|
#define dB_to_linear(x) exp((x) * (M_LN10 * 0.05))
|
||||||
|
|
||||||
|
double lsx_f_resp(double t, double a)
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
if (t > (a <= 160? .8 : .82)) {
|
||||||
|
double a1 = a+15;
|
||||||
|
double p = .00035*a+.375;
|
||||||
|
double w = 1/(1-.597)*asin(pow((a1-10.6)/a1,1/p));
|
||||||
|
double c = 1+asin(pow(1-a/a1,1/p))/w;
|
||||||
|
return a1*(pow(sin((c-t)*w),p)-1);
|
||||||
|
}
|
||||||
|
if (t > .5)
|
||||||
|
x = sinePsi(a), x = pow(sin((1-t) * x), sinePow(x));
|
||||||
|
else
|
||||||
|
x = sinePhi(a), x = 1 - pow(sin(t * x), sinePow(x));
|
||||||
|
return linear_to_dB(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
double lsx_inv_f_resp(double drop, double a)
|
||||||
|
{
|
||||||
|
double x = sinePhi(a), s;
|
||||||
|
drop = dB_to_linear(drop);
|
||||||
|
s = drop > .5 ? 1 - drop : drop;
|
||||||
|
x = asin(pow(s, 1/sinePow(x))) / x;
|
||||||
|
return drop > .5? x : 1 -x;
|
||||||
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ void lsx_safe_rdft(int len, int type, double * d);
|
||||||
void lsx_safe_cdft(int len, int type, double * d);
|
void lsx_safe_cdft(int len, int type, double * d);
|
||||||
void lsx_safe_rdft_f(int len, int type, float * d);
|
void lsx_safe_rdft_f(int len, int type, float * d);
|
||||||
void lsx_safe_cdft_f(int len, int type, float * d);
|
void lsx_safe_cdft_f(int len, int type, float * d);
|
||||||
void lsx_ordered_convolve(int n, void * not_used, double * a, const double * b);
|
void lsx_ordered_convolve(int n, void * not_used, void * a, const void * b);
|
||||||
void lsx_ordered_convolve_f(int n, void * not_used, float * a, const float * b);
|
void lsx_ordered_convolve_f(int n, void * not_used, void * a, const void * b);
|
||||||
void lsx_ordered_partial_convolve(int n, double * a, const double * b);
|
void lsx_ordered_partial_convolve(int n, void * a, const void * b);
|
||||||
void lsx_ordered_partial_convolve_f(int n, float * a, const float * b);
|
void lsx_ordered_partial_convolve_f(int n, void * a, const void * b);
|
||||||
|
|
||||||
double lsx_kaiser_beta(double att, double tr_bw);
|
double lsx_kaiser_beta(double att, double tr_bw);
|
||||||
double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho,
|
double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho,
|
||||||
|
@ -31,9 +31,14 @@ double * lsx_design_lpf(
|
||||||
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */
|
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */
|
||||||
double att, /* Stop-band attenuation in dB */
|
double att, /* Stop-band attenuation in dB */
|
||||||
int * num_taps, /* 0: value will be estimated */
|
int * num_taps, /* 0: value will be estimated */
|
||||||
int k, /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */
|
int k, /* >0: number of phases; <0: num_taps = 1 (mod -k) */
|
||||||
double beta); /* <0: value will be estimated */
|
double beta); /* <0: value will be estimated */
|
||||||
|
|
||||||
void lsx_fir_to_phase(double * * h, int * len,
|
void lsx_fir_to_phase(double * * h, int * len,
|
||||||
int * post_len, double phase0);
|
int * post_len, double phase0);
|
||||||
|
|
||||||
|
double lsx_f_resp(double t, double a);
|
||||||
|
double lsx_inv_f_resp(double drop, double a);
|
||||||
|
#define lsx_to_3dB(a) (1 - lsx_inv_f_resp(-3., a))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
|
||||||
|
|
||||||
#include "half_coefs.h"
|
|
||||||
|
|
||||||
#define FUNCTION h8
|
|
||||||
#define CONVOLVE _ _ _ _ _ _ _ _
|
|
||||||
#define h8_l 8
|
|
||||||
#define COEFS half_fir_coefs_8
|
|
||||||
#include "half-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION h9
|
|
||||||
#define CONVOLVE _ _ _ _ _ _ _ _ _
|
|
||||||
#define h9_l 9
|
|
||||||
#define COEFS half_fir_coefs_9
|
|
||||||
#include "half-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION h10
|
|
||||||
#define CONVOLVE _ _ _ _ _ _ _ _ _ _
|
|
||||||
#define h10_l 10
|
|
||||||
#define COEFS half_fir_coefs_10
|
|
||||||
#include "half-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION h11
|
|
||||||
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
#define h11_l 11
|
|
||||||
#define COEFS half_fir_coefs_11
|
|
||||||
#include "half-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION h12
|
|
||||||
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
#define h12_l 12
|
|
||||||
#define COEFS half_fir_coefs_12
|
|
||||||
#include "half-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION h13
|
|
||||||
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
#define h13_l 13
|
|
||||||
#define COEFS half_fir_coefs_13
|
|
||||||
#include "half-fir.h"
|
|
||||||
|
|
||||||
static struct {int num_coefs; stage_fn_t fn; float att;} const half_firs[] = {
|
|
||||||
{ 8, h8 , 136.51f},
|
|
||||||
{ 9, h9 , 152.32f},
|
|
||||||
{10, h10, 168.07f},
|
|
||||||
{11, h11, 183.78f},
|
|
||||||
{12, h12, 199.44f},
|
|
||||||
{13, h13, 212.75f},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define HI_PREC_CLOCK
|
|
||||||
|
|
||||||
#define VAR_LENGTH p->n
|
|
||||||
#define VAR_CONVOLVE while (j < FIR_LENGTH) _
|
|
||||||
#define VAR_POLY_PHASE_BITS p->phase_bits
|
|
||||||
|
|
||||||
#define FUNCTION vpoly0
|
|
||||||
#define FIR_LENGTH VAR_LENGTH
|
|
||||||
#define CONVOLVE VAR_CONVOLVE
|
|
||||||
#include "poly-fir0.h"
|
|
||||||
|
|
||||||
#define FUNCTION vpoly1
|
|
||||||
#define COEF_INTERP 1
|
|
||||||
#define PHASE_BITS VAR_POLY_PHASE_BITS
|
|
||||||
#define FIR_LENGTH VAR_LENGTH
|
|
||||||
#define CONVOLVE VAR_CONVOLVE
|
|
||||||
#include "poly-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION vpoly2
|
|
||||||
#define COEF_INTERP 2
|
|
||||||
#define PHASE_BITS VAR_POLY_PHASE_BITS
|
|
||||||
#define FIR_LENGTH VAR_LENGTH
|
|
||||||
#define CONVOLVE VAR_CONVOLVE
|
|
||||||
#include "poly-fir.h"
|
|
||||||
|
|
||||||
#define FUNCTION vpoly3
|
|
||||||
#define COEF_INTERP 3
|
|
||||||
#define PHASE_BITS VAR_POLY_PHASE_BITS
|
|
||||||
#define FIR_LENGTH VAR_LENGTH
|
|
||||||
#define CONVOLVE VAR_CONVOLVE
|
|
||||||
#include "poly-fir.h"
|
|
||||||
|
|
||||||
#undef HI_PREC_CLOCK
|
|
||||||
|
|
||||||
#define U100_l 42
|
|
||||||
#if RATE_SIMD_POLY
|
|
||||||
#define U100_l_EXTRA _ _
|
|
||||||
#define u100_l_EXTRA _
|
|
||||||
#define U100_l_EXTRA_LENGTH 2
|
|
||||||
#define u100_l_EXTRA_LENGTH 1
|
|
||||||
#else
|
|
||||||
#define U100_l_EXTRA
|
|
||||||
#define u100_l_EXTRA
|
|
||||||
#define U100_l_EXTRA_LENGTH 0
|
|
||||||
#define u100_l_EXTRA_LENGTH 0
|
|
||||||
#endif
|
|
||||||
#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ U100_l_EXTRA
|
|
||||||
#define FUNCTION U100_0
|
|
||||||
#define FIR_LENGTH (U100_l + U100_l_EXTRA_LENGTH)
|
|
||||||
#define CONVOLVE poly_fir_convolve_U100
|
|
||||||
#include "poly-fir0.h"
|
|
||||||
|
|
||||||
#define u100_l 11
|
|
||||||
#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _ u100_l_EXTRA
|
|
||||||
#define FUNCTION u100_0
|
|
||||||
#define FIR_LENGTH (u100_l + u100_l_EXTRA_LENGTH)
|
|
||||||
#define CONVOLVE poly_fir_convolve_u100
|
|
||||||
#include "poly-fir0.h"
|
|
||||||
|
|
||||||
#define FUNCTION u100_1
|
|
||||||
#define COEF_INTERP 1
|
|
||||||
#define PHASE_BITS 8
|
|
||||||
#define FIR_LENGTH (u100_l + u100_l_EXTRA_LENGTH)
|
|
||||||
#define CONVOLVE poly_fir_convolve_u100
|
|
||||||
#include "poly-fir.h"
|
|
||||||
#define u100_1_b 8
|
|
||||||
|
|
||||||
#define FUNCTION u100_2
|
|
||||||
#define COEF_INTERP 2
|
|
||||||
#define PHASE_BITS 6
|
|
||||||
#define FIR_LENGTH (u100_l + u100_l_EXTRA_LENGTH)
|
|
||||||
#define CONVOLVE poly_fir_convolve_u100
|
|
||||||
#include "poly-fir.h"
|
|
||||||
#define u100_2_b 6
|
|
||||||
|
|
||||||
typedef struct {float scalar; stage_fn_t fn;} poly_fir1_t;
|
|
||||||
typedef struct {float beta; poly_fir1_t interp[3];} poly_fir_t;
|
|
||||||
|
|
||||||
static poly_fir_t const poly_firs[] = {
|
|
||||||
{-1, {{0, vpoly0}, { 7.2f, vpoly1}, {5.0f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 9.4f, vpoly1}, {6.7f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, {12.4f, vpoly1}, {7.8f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, {13.6f, vpoly1}, {9.3f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, {10.5f, vpoly2}, {8.4f, vpoly3}}},
|
|
||||||
{-1, {{0, vpoly0}, {11.85f,vpoly2}, {9.0f, vpoly3}}},
|
|
||||||
|
|
||||||
{-1, {{0, vpoly0}, { 8.0f, vpoly1}, {5.3f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 8.6f, vpoly1}, {5.7f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, {10.6f, vpoly1}, {6.75f,vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, {12.6f, vpoly1}, {8.6f, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 9.6f, vpoly2}, {7.6f, vpoly3}}},
|
|
||||||
{-1, {{0, vpoly0}, {11.4f, vpoly2}, {8.65f,vpoly3}}},
|
|
||||||
|
|
||||||
{10.62f, {{U100_l, U100_0}, {0, 0}, {0, 0}}},
|
|
||||||
{11.28f, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}},
|
|
||||||
{-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}},
|
|
||||||
{-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}},
|
|
||||||
};
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if defined __GNUC__
|
||||||
|
#pragma GCC system_header
|
||||||
|
#elif defined __SUNPRO_C
|
||||||
|
#pragma disable_warn
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
#pragma warning(push, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_SIMD_HALF
|
||||||
|
#define VALIGN vAlign
|
||||||
|
#else
|
||||||
|
#define VALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(CORE_TYPE & CORE_SIMD_HALF)
|
||||||
|
static VALIGN const sample_t half_fir_coefs_7[] = {
|
||||||
|
3.1062656496657370e-01, -8.4998810699955796e-02, 3.4007044621123500e-02,
|
||||||
|
-1.2839903789829387e-02, 3.9899380181723145e-03, -8.9355202017945374e-04,
|
||||||
|
1.0918292424806546e-04,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static VALIGN const sample_t half_fir_coefs_8[] = {
|
||||||
|
3.1154652365332069e-01, -8.7344917685739543e-02, 3.6814458353637280e-02,
|
||||||
|
-1.5189204581464479e-02, 5.4540855610738801e-03, -1.5643862626630416e-03,
|
||||||
|
3.1816575906323303e-04, -3.4799449225005688e-05,
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALIGN const sample_t half_fir_coefs_9[] = {
|
||||||
|
3.1227034755311189e-01, -8.9221517147969526e-02, 3.9139704015071934e-02,
|
||||||
|
-1.7250558515852023e-02, 6.8589440230476112e-03, -2.3045049636430419e-03,
|
||||||
|
6.0963740543348963e-04, -1.1323803957431231e-04, 1.1197769991000046e-05,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CORE_TYPE & CORE_DBL
|
||||||
|
static VALIGN const sample_t half_fir_coefs_10[] = {
|
||||||
|
3.1285456012000523e-01, -9.0756740799292787e-02, 4.1096398104193160e-02,
|
||||||
|
-1.9066319572525220e-02, 8.1840569787684902e-03, -3.0766876176359834e-03,
|
||||||
|
9.6396524429277980e-04, -2.3585679989922018e-04, 4.0252189026627833e-05,
|
||||||
|
-3.6298196342497932e-06,
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALIGN const sample_t half_fir_coefs_11[] = {
|
||||||
|
3.1333588822574199e-01, -9.2035898673019811e-02, 4.2765169698406408e-02,
|
||||||
|
-2.0673580894964429e-02, 9.4225426824512421e-03, -3.8563379950013192e-03,
|
||||||
|
1.3634742159642453e-03, -3.9874150714431009e-04, 9.0586723632664806e-05,
|
||||||
|
-1.4285617244076783e-05, 1.1834642946400529e-06,
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALIGN const sample_t half_fir_coefs_12[] = {
|
||||||
|
3.1373928463345568e-01, -9.3118180335301962e-02, 4.4205005881659098e-02,
|
||||||
|
-2.2103860986973051e-02, 1.0574689371162864e-02, -4.6276428065385065e-03,
|
||||||
|
1.7936153397572132e-03, -5.9617527051353237e-04, 1.6314517495669067e-04,
|
||||||
|
-3.4555126770115446e-05, 5.0617615610782593e-06, -3.8768958592971409e-07,
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALIGN const sample_t half_fir_coefs_13[] = {
|
||||||
|
3.1408224847888910e-01, -9.4045836332667387e-02, 4.5459878763259978e-02,
|
||||||
|
-2.3383369012219993e-02, 1.1644273044890753e-02, -5.3806714579057013e-03,
|
||||||
|
2.2429072878264022e-03, -8.2204347506606424e-04, 2.5724946477840893e-04,
|
||||||
|
-6.6072709864248668e-05, 1.3099163296288644e-05, -1.7907147069136000e-06,
|
||||||
|
1.2750825595240592e-07,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef VALIGN
|
||||||
|
|
||||||
|
#if defined __SUNPRO_C
|
||||||
|
#pragma enable_warn
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
|
@ -1,25 +1,61 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
/* Down-sample by a factor of 2 using a FIR with odd length (LEN).*/
|
/* Decimate by 2 using a FIR with odd length (LEN). */
|
||||||
/* Input must be preceded and followed by LEN >> 1 samples. */
|
/* Input must be preceded and followed by LEN >> 1 samples. */
|
||||||
|
|
||||||
#define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j;
|
#define COEFS ((sample_t const *)p->coefs)
|
||||||
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
|
|
||||||
|
#if SIMD_SSE
|
||||||
|
#define BEGINNING v4_t sum, q1, q2, t
|
||||||
|
#define ____ \
|
||||||
|
q1 = _mm_shuffle_ps(t=vLdu(input+2*j),vLdu(input+2*j+4),_MM_SHUFFLE(3,1,3,1)); \
|
||||||
|
q2 = _mm_shuffle_ps(vLdu(input-2*j-4),vLdu(input-2*j-8),_MM_SHUFFLE(1,3,1,3)); \
|
||||||
|
sum = vAdd(j? sum : vMul(vSet1(.5), t), vMul(vAdd(q1, q2), vLd(COEFS+j))); \
|
||||||
|
j += 4;
|
||||||
|
#define __ \
|
||||||
|
q1 = _mm_shuffle_ps(vLdu(input+2*j), vLdu(input-2*j-4), _MM_SHUFFLE(1,3,3,1)); \
|
||||||
|
q2 = _mm_loadl_pi(q2, (__m64*)(COEFS+j)), q2 = _mm_movelh_ps(q2, q2); \
|
||||||
|
sum = vAdd(sum, vMul(q1, q2)); \
|
||||||
|
j += 2;
|
||||||
|
#define _ \
|
||||||
|
q1 = _mm_add_ss(_mm_load_ss(input+2*j+1), _mm_load_ss(input-2*j-1)); \
|
||||||
|
sum = _mm_add_ss(sum, _mm_mul_ss(q1, _mm_load_ss(COEFS+j))); \
|
||||||
|
++j;
|
||||||
|
#define END vStorSum(output+i, sum)
|
||||||
|
/* #elif SIMD_AVX; No good solution found. */
|
||||||
|
/* #elif SIMD_NEON; No need: gcc -O3 does a good job by itself. */
|
||||||
|
#else
|
||||||
|
#define BEGINNING sample_t sum = input[0] * .5f
|
||||||
|
#define ____ __ __
|
||||||
|
#define __ _ _
|
||||||
|
#define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j;
|
||||||
|
#define END output[i] = sum
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void FUNCTION_H(stage_t * p, fifo_t * output_fifo)
|
||||||
{
|
{
|
||||||
sample_t const * input = stage_read_p(p);
|
sample_t const * __restrict input = stage_read_p(p);
|
||||||
int i, num_out = (stage_occupancy(p) + 1) / 2;
|
int num_in = min(stage_occupancy(p), p->input_size);
|
||||||
sample_t * output = fifo_reserve(output_fifo, num_out);
|
int i, num_out = (num_in + 1) >> 1;
|
||||||
|
sample_t * __restrict output = fifo_reserve(output_fifo, num_out);
|
||||||
|
|
||||||
for (i = 0; i < num_out; ++i, input += 2) {
|
for (i = 0; i < num_out; ++i, input += 2) {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
sample_t sum = input[0] * .5f;
|
BEGINNING; CONVOLVE; END;
|
||||||
CONVOLVE
|
|
||||||
output[i] = sum;
|
|
||||||
}
|
}
|
||||||
fifo_read(&p->fifo, 2 * num_out, NULL);
|
fifo_read(&p->fifo, 2 * num_out, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef _
|
#undef _
|
||||||
|
#undef __
|
||||||
|
#undef ____
|
||||||
|
#undef BEGINNING
|
||||||
|
#undef END
|
||||||
#undef COEFS
|
#undef COEFS
|
||||||
#undef CONVOLVE
|
#undef CONVOLVE
|
||||||
#undef FUNCTION
|
#undef FUNCTION_H
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
|
||||||
|
|
||||||
#if defined __GNUC__
|
|
||||||
#pragma GCC system_header
|
|
||||||
#elif defined __SUNPRO_C
|
|
||||||
#pragma disable_warn
|
|
||||||
#elif defined _MSC_VER
|
|
||||||
#pragma warning(push, 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const sample_t half_fir_coefs_8[] = {
|
|
||||||
0.3115465451887802, -0.08734497241282892, 0.03681452335604365,
|
|
||||||
-0.01518925831569441, 0.005454118437408876, -0.001564400922162005,
|
|
||||||
0.0003181701445034203, -3.48001341225749e-5,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const sample_t half_fir_coefs_9[] = {
|
|
||||||
0.3122703613711853, -0.08922155288172305, 0.03913974805854332,
|
|
||||||
-0.01725059723447163, 0.006858970092378141, -0.002304518467568703,
|
|
||||||
0.0006096426006051062, -0.0001132393923815236, 1.119795386287666e-5,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const sample_t half_fir_coefs_10[] = {
|
|
||||||
0.3128545521327376, -0.09075671986104322, 0.04109637155154835,
|
|
||||||
-0.01906629512749895, 0.008184039342054333, -0.0030766775017262,
|
|
||||||
0.0009639607022414314, -0.0002358552746579827, 4.025184282444155e-5,
|
|
||||||
-3.629779111541012e-6,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const sample_t half_fir_coefs_11[] = {
|
|
||||||
0.3133358837508807, -0.09203588680609488, 0.04276515428384758,
|
|
||||||
-0.02067356614745591, 0.00942253142371517, -0.003856330993895144,
|
|
||||||
0.001363470684892284, -0.0003987400965541919, 9.058629923971627e-5,
|
|
||||||
-1.428553070915318e-5, 1.183455238783835e-6,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const sample_t half_fir_coefs_12[] = {
|
|
||||||
0.3137392991811407, -0.0931182192961332, 0.0442050575271454,
|
|
||||||
-0.02210391200618091, 0.01057473015666001, -0.00462766983973885,
|
|
||||||
0.001793630226239453, -0.0005961819959665878, 0.0001631475979359577,
|
|
||||||
-3.45557865639653e-5, 5.06188341942088e-6, -3.877010943315563e-7,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const sample_t half_fir_coefs_13[] = {
|
|
||||||
0.3140822554324578, -0.0940458550886253, 0.04545990399121566,
|
|
||||||
-0.02338339450796002, 0.01164429409071052, -0.005380686021429845,
|
|
||||||
0.002242915773871009, -0.000822047600000082, 0.0002572510962395222,
|
|
||||||
-6.607320708956279e-5, 1.309926399120154e-5, -1.790719575255006e-6,
|
|
||||||
1.27504961098836e-7,
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined __SUNPRO_C
|
|
||||||
#pragma enable_warn
|
|
||||||
#elif defined _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
|
@ -1,46 +1,84 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#if !defined soxr_internal_included
|
#if !defined soxr_internal_included
|
||||||
#define soxr_internal_included
|
#define soxr_internal_included
|
||||||
|
|
||||||
#include "soxr-config.h"
|
#include "std-types.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
#define min(a, b) ((a) <= (b) ? (a) : (b))
|
#define min(a, b) ((a) <= (b) ? (a) : (b))
|
||||||
#define max(a, b) ((a) >= (b) ? (a) : (b))
|
#define max(a, b) ((a) >= (b) ? (a) : (b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define range_limit(x, lower, upper) (min(max(x, lower), upper))
|
#define range_limit(x, lower, upper) (min(max(x, lower), upper))
|
||||||
#define linear_to_dB(x) (log10(x) * 20)
|
#define linear_to_dB(x) (log10(x) * 20)
|
||||||
#define array_length(a) (sizeof(a)/sizeof(a[0]))
|
#define array_length(a) (sizeof(a)/sizeof(a[0]))
|
||||||
|
#if !defined AL
|
||||||
#define AL(a) array_length(a)
|
#define AL(a) array_length(a)
|
||||||
|
#endif
|
||||||
#define iAL(a) (int)AL(a)
|
#define iAL(a) (int)AL(a)
|
||||||
#define sqr(a) ((a) * (a))
|
#define sqr(a) ((a) * (a))
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
|
#if defined __GNUC__
|
||||||
#define UNUSED __attribute__ ((unused))
|
#define UNUSED __attribute__ ((unused))
|
||||||
#else
|
#else
|
||||||
#define UNUSED
|
#define UNUSED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined NDEBUG || SOXR_SILENT
|
|
||||||
|
|
||||||
|
#if !WITH_DEV_TRACE
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
void lsx_dummy(char const *, ...);
|
void lsx_dummy(char const *, ...);
|
||||||
#else
|
#else
|
||||||
static __inline void lsx_dummy(char const * x, ...) {}
|
static __inline void lsx_dummy(char const * x, ...) {}
|
||||||
#endif
|
#endif
|
||||||
#define lsx_debug if(0) lsx_dummy
|
#define lsx_debug if(0) lsx_dummy
|
||||||
|
#define lsx_debug_more lsx_debug
|
||||||
#else
|
#else
|
||||||
#include <stdarg.h>
|
extern int _soxr_trace_level;
|
||||||
#include <stdio.h>
|
void _soxr_trace(char const * fmt, ...);
|
||||||
UNUSED static void lsx_debug(char const * fmt, ...)
|
#define lsx_debug if (_soxr_trace_level > 0) _soxr_trace
|
||||||
{
|
#define lsx_debug_more if (_soxr_trace_level > 1) _soxr_trace
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vfprintf(stderr, fmt, args);
|
|
||||||
fputc('\n', stderr);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* soxr_quality_spec_t.flags: */
|
||||||
|
|
||||||
|
#define SOXR_ROLLOFF_LSR2Q 3u /* Reserved for internal use. */
|
||||||
|
#define SOXR_ROLLOFF_MASK 3u /* For masking these bits. */
|
||||||
|
#define SOXR_MAINTAIN_3DB_PT 4u /* Reserved for internal use. */
|
||||||
|
#define SOXR_PROMOTE_TO_LQ 64u /* Reserved for internal use. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* soxr_runtime_spec_t.flags: */
|
||||||
|
|
||||||
|
#define SOXR_STRICT_BUFFERING 4u /* Reserved for future use. */
|
||||||
|
#define SOXR_NOSMALLINTOPT 8u /* For test purposes only. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* soxr_quality_spec recipe: */
|
||||||
|
|
||||||
|
#define SOXR_PRECISIONQ 11 /* Quality specified by the precision parameter. */
|
||||||
|
|
||||||
|
#define SOXR_PHASE_MASK 0x30 /* For masking these bits. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* soxr_quality_spec flags: */
|
||||||
|
|
||||||
|
#define RESET_ON_CLEAR (1u<<31)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
set(TARGET_HEADERS "@TARGET_HEADERS@")
|
|
||||||
set(TARGET_PCS "@TARGET_PCS@")
|
|
|
@ -1 +0,0 @@
|
||||||
set(TARGET_LIBS "@TARGET_LIBS@")
|
|
114
soxr/src/lsr.c
114
soxr/src/lsr.c
|
@ -1,114 +0,0 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
|
||||||
|
|
||||||
/* Wrapper mostly compatible with `libsamplerate'. */
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "soxr.h"
|
|
||||||
|
|
||||||
/* Runtime casts: */
|
|
||||||
typedef struct io_t {
|
|
||||||
float *in,*out; long ilen,olen,idone,odone; int eoi; double oi_ratio;} io_t;
|
|
||||||
#define SRC_DATA io_t
|
|
||||||
typedef struct soxr SRC_STATE;
|
|
||||||
#define src_callback_t soxr_input_fn_t
|
|
||||||
#define SRC_ERROR soxr_error_t
|
|
||||||
#define SRC_SRCTYPE unsigned
|
|
||||||
|
|
||||||
#include "soxr-lsr.h"
|
|
||||||
#include "rint.h"
|
|
||||||
|
|
||||||
soxr_error_t src_simple(io_t * p, unsigned id, int channels)
|
|
||||||
{
|
|
||||||
size_t idone, odone;
|
|
||||||
soxr_error_t error;
|
|
||||||
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + id, 0);
|
|
||||||
char const * e = getenv("SOXR_LSR_NUM_THREADS");
|
|
||||||
soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1));
|
|
||||||
assert (channels > 0);
|
|
||||||
assert (p->ilen >= 0);
|
|
||||||
assert (p->olen >= 0);
|
|
||||||
error = soxr_oneshot(1, p->oi_ratio, (unsigned)channels,
|
|
||||||
p->in, (size_t)p->ilen, &idone, p->out, (size_t)p->olen, &odone,
|
|
||||||
0, &q_spec, &r_spec);
|
|
||||||
p->idone = (long)idone, p->odone = (long)odone;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
soxr_t src_callback_new(soxr_input_fn_t fn, unsigned id, int channels, SRC_ERROR * error0, void * p)
|
|
||||||
{
|
|
||||||
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + id, 0);
|
|
||||||
char const * e = getenv("SOXR_LSR_NUM_THREADS");
|
|
||||||
soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1));
|
|
||||||
soxr_error_t error;
|
|
||||||
soxr_t soxr = 0;
|
|
||||||
assert (channels > 0);
|
|
||||||
/* To minimise latency e.g. for real-time playback:
|
|
||||||
if (id == 2)
|
|
||||||
r_spec.log2_large_dft_size = r_spec.log2_min_dft_size = 8;
|
|
||||||
*/
|
|
||||||
soxr = soxr_create(0, 0, (unsigned)channels, &error, 0, &q_spec, &r_spec);
|
|
||||||
if (soxr)
|
|
||||||
error = soxr_set_input_fn(soxr, fn, p, 0);
|
|
||||||
if (error0)
|
|
||||||
*(int *)error0 = (int)(ptrdiff_t)error;
|
|
||||||
return soxr;
|
|
||||||
}
|
|
||||||
|
|
||||||
soxr_error_t src_process(soxr_t p, io_t * io)
|
|
||||||
{
|
|
||||||
if (!p || !io) return "null pointer";
|
|
||||||
soxr_set_error(p, soxr_set_io_ratio(p, 1/io->oi_ratio, (size_t)io->olen));
|
|
||||||
|
|
||||||
{ size_t idone , odone;
|
|
||||||
soxr_process(p, io->in, (size_t)(io->eoi? ~io->ilen : io->ilen), /* hack */
|
|
||||||
&idone, io->out, (size_t)io->olen, &odone);
|
|
||||||
io->idone = (long)idone, io->odone = (long)odone;
|
|
||||||
return soxr_error(p); }
|
|
||||||
}
|
|
||||||
|
|
||||||
long src_callback_read(soxr_t p, double oi_ratio, long olen, float * obuf)
|
|
||||||
{
|
|
||||||
if (!p || olen < 0) return -1;
|
|
||||||
soxr_set_error(p, soxr_set_io_ratio(p, 1/oi_ratio, (size_t)olen));
|
|
||||||
return (long)soxr_output(p, obuf, (size_t)olen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void src_float_to_short_array(float const * src, short * dest, int len)
|
|
||||||
{
|
|
||||||
double d, N = 1. + SHRT_MAX;
|
|
||||||
assert (src && dest);
|
|
||||||
while (len--) d = src[len] * N, dest[len] = (short)(d > N - 1? (short)(N - 1) : d < -N? (short)-N : rint16(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
void src_short_to_float_array(short const * src, float * dest, int len)
|
|
||||||
{
|
|
||||||
assert (src && dest);
|
|
||||||
while (len--) dest[len] = (float)(src[len] * (1 / (1. + SHRT_MAX)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void src_float_to_int_array(float const * src, int * dest, int len)
|
|
||||||
{
|
|
||||||
double d, N = 32768. * 65536.; /* N.B. int32, not int! (Also next fn.) */
|
|
||||||
assert (src && dest);
|
|
||||||
while (len--) d = src[len] * N, dest[len] = d >= N - 1? (int)(N - 1) : d < -N? (int)(-N) : rint32(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
void src_int_to_float_array(int const * src, float * dest, int len)
|
|
||||||
{
|
|
||||||
assert (src && dest);
|
|
||||||
while (len--) dest[len] = (float)(src[len] * (1 / (32768. * 65536.)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static char const * const names[] = {"LSR best sinc", "LSR medium sinc", "LSR fastest sinc", "LSR ZOH", "LSR linear", "SoX VHQ"};
|
|
||||||
char const * src_get_name(unsigned n) {return n < 5u + !getenv("SOXR_LSR_STRICT")? names[n] : 0;}
|
|
||||||
char const * src_get_description(unsigned id) {return src_get_name(id);}
|
|
||||||
char const * src_get_version(void) {return soxr_version();}
|
|
||||||
char const * src_strerror(soxr_error_t error) {return error == (soxr_error_t)1? "Placeholder." : sizeof(int) >= sizeof(char *) || !error ? soxr_strerror(error) : "soxr error";}
|
|
||||||
int src_is_valid_ratio(double oi_ratio) {return getenv("SOXR_LSR_STRICT")? oi_ratio >= 1./256 && oi_ratio <= 256 : oi_ratio > 0;}
|
|
||||||
soxr_error_t src_error(soxr_t p) {return soxr_error(p);}
|
|
||||||
soxr_error_t src_reset(soxr_t p) {return soxr_clear(p);}
|
|
||||||
soxr_t src_delete(soxr_t p) {soxr_delete(p); return 0;}
|
|
||||||
soxr_error_t src_set_ratio(soxr_t p, double oi_ratio) {return soxr_set_io_ratio(p, 1/oi_ratio, 0);}
|
|
||||||
soxr_t src_new(unsigned id, int channels, SRC_ERROR * error) {return src_callback_new(0, id, channels, error, 0);}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if !defined soxr_math_wrap_included
|
||||||
|
#define soxr_math_wrap_included
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#if defined __STRICT_ANSI__
|
||||||
|
#define sinf(x) (float)sin ((double)(x))
|
||||||
|
#define cosf(x) (float)cos ((double)(x))
|
||||||
|
#define atanf(x) (float)atan((double)(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined M_PI
|
||||||
|
#define M_PI 3.141592653589793238462643383279502884
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined M_LN10
|
||||||
|
#define M_LN10 2.302585092994045684017991454684364208
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined M_SQRT2
|
||||||
|
#define M_SQRT2 1.414213562373095048801688724209698079
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined M_LN2
|
||||||
|
#define M_LN2 0.693147180559945309417232121458176568
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
/* AVX support macros */
|
||||||
|
|
||||||
|
#if !defined soxr_avx_included
|
||||||
|
#define soxr_avx_included
|
||||||
|
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
typedef __m256d v4sf;
|
||||||
|
#define VZERO() _mm256_setzero_pd()
|
||||||
|
#define VMUL(a,b) _mm256_mul_pd(a,b)
|
||||||
|
#define VADD(a,b) _mm256_add_pd(a,b)
|
||||||
|
#define VMADD(a,b,c) VADD(VMUL(a,b),c) /* Note: gcc -mfma will `fuse' these */
|
||||||
|
#define VSUB(a,b) _mm256_sub_pd(a,b)
|
||||||
|
#define LD_PS1(p) _mm256_set1_pd(p)
|
||||||
|
#define INTERLEAVE2(in1, in2, out1, out2) {v4sf \
|
||||||
|
t1 = _mm256_unpacklo_pd(in1, in2), \
|
||||||
|
t2 = _mm256_unpackhi_pd(in1, in2); \
|
||||||
|
out1 = _mm256_permute2f128_pd(t1,t2,0x20); \
|
||||||
|
out2 = _mm256_permute2f128_pd(t1,t2,0x31); }
|
||||||
|
#define UNINTERLEAVE2(in1, in2, out1, out2) {v4sf \
|
||||||
|
t1 = _mm256_permute2f128_pd(in1,in2,0x20), \
|
||||||
|
t2 = _mm256_permute2f128_pd(in1,in2,0x31); \
|
||||||
|
out1 = _mm256_unpacklo_pd(t1, t2); \
|
||||||
|
out2 = _mm256_unpackhi_pd(t1, t2);}
|
||||||
|
#define VTRANSPOSE4(x0,x1,x2,x3) {v4sf \
|
||||||
|
t0 = _mm256_shuffle_pd(x0,x1, 0x0), \
|
||||||
|
t2 = _mm256_shuffle_pd(x0,x1, 0xf), \
|
||||||
|
t1 = _mm256_shuffle_pd(x2,x3, 0x0), \
|
||||||
|
t3 = _mm256_shuffle_pd(x2,x3, 0xf); \
|
||||||
|
x0 = _mm256_permute2f128_pd(t0,t1, 0x20); \
|
||||||
|
x1 = _mm256_permute2f128_pd(t2,t3, 0x20); \
|
||||||
|
x2 = _mm256_permute2f128_pd(t0,t1, 0x31); \
|
||||||
|
x3 = _mm256_permute2f128_pd(t2,t3, 0x31);}
|
||||||
|
#define VSWAPHL(a,b) _mm256_permute2f128_pd(b, a, 0x30)
|
||||||
|
#define VALIGNED(ptr) ((((long)(ptr)) & 0x1F) == 0)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,110 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#if !defined PFFT_MACROS_ONLY
|
||||||
|
|
||||||
|
#include "math-wrap.h"
|
||||||
|
|
||||||
|
#if PFFFT_DOUBLE
|
||||||
|
#include "util64s.h"
|
||||||
|
#else
|
||||||
|
#include "util32s.h"
|
||||||
|
#define sin(x) sinf(x)
|
||||||
|
#define cos(x) cosf(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define pffft_aligned_free SIMD_ALIGNED_FREE
|
||||||
|
#define pffft_aligned_malloc SIMD_ALIGNED_MALLOC
|
||||||
|
#define pffft_aligned_calloc SIMD_ALIGNED_CALLOC
|
||||||
|
|
||||||
|
#undef inline
|
||||||
|
#define inline __inline
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "pffft.c"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined PFFT_MACROS_ONLY
|
||||||
|
|
||||||
|
#if !defined PFFFT_SIMD_DISABLE
|
||||||
|
|
||||||
|
static void pffft_zconvolve(PFFFT_Setup *s, const float *a, const float *b, float *ab) {
|
||||||
|
int i, Ncvec = s->Ncvec;
|
||||||
|
const v4sf * /*RESTRICT*/ va = (const v4sf*)a;
|
||||||
|
const v4sf * RESTRICT vb = (const v4sf*)b;
|
||||||
|
v4sf * /*RESTRICT*/ vab = (v4sf*)ab;
|
||||||
|
|
||||||
|
float ar, ai, br, bi;
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
__builtin_prefetch(va);
|
||||||
|
__builtin_prefetch(vb);
|
||||||
|
__builtin_prefetch(va+2);
|
||||||
|
__builtin_prefetch(vb+2);
|
||||||
|
__builtin_prefetch(va+4);
|
||||||
|
__builtin_prefetch(vb+4);
|
||||||
|
__builtin_prefetch(va+6);
|
||||||
|
__builtin_prefetch(vb+6);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(VALIGNED(a) && VALIGNED(b) && VALIGNED(ab));
|
||||||
|
ar = ((v4sf_union*)va)[0].f[0];
|
||||||
|
ai = ((v4sf_union*)va)[1].f[0];
|
||||||
|
br = ((v4sf_union*)vb)[0].f[0];
|
||||||
|
bi = ((v4sf_union*)vb)[1].f[0];
|
||||||
|
|
||||||
|
for (i=0; i < Ncvec; i += 2) {
|
||||||
|
v4sf ar, ai, br, bi;
|
||||||
|
ar = va[2*i+0]; ai = va[2*i+1];
|
||||||
|
br = vb[2*i+0]; bi = vb[2*i+1];
|
||||||
|
VCPLXMUL(ar, ai, br, bi);
|
||||||
|
vab[2*i+0] = ar;
|
||||||
|
vab[2*i+1] = ai;
|
||||||
|
ar = va[2*i+2]; ai = va[2*i+3];
|
||||||
|
br = vb[2*i+2]; bi = vb[2*i+3];
|
||||||
|
VCPLXMUL(ar, ai, br, bi);
|
||||||
|
vab[2*i+2] = ar;
|
||||||
|
vab[2*i+3] = ai;
|
||||||
|
}
|
||||||
|
if (s->transform == PFFFT_REAL) {
|
||||||
|
((v4sf_union*)vab)[0].f[0] = ar*br;
|
||||||
|
((v4sf_union*)vab)[1].f[0] = ai*bi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static void pffft_zconvolve(PFFFT_Setup *s, const float *a, const float *b, float *ab) {
|
||||||
|
int i, Ncvec = s->Ncvec;
|
||||||
|
|
||||||
|
if (s->transform == PFFFT_REAL) {
|
||||||
|
/* take care of the fftpack ordering */
|
||||||
|
ab[0] = a[0]*b[0];
|
||||||
|
ab[2*Ncvec-1] = a[2*Ncvec-1]*b[2*Ncvec-1];
|
||||||
|
++ab; ++a; ++b; --Ncvec;
|
||||||
|
}
|
||||||
|
for (i=0; i < Ncvec; ++i) {
|
||||||
|
float ar, ai, br, bi;
|
||||||
|
ar = a[2*i+0]; ai = a[2*i+1];
|
||||||
|
br = b[2*i+0]; bi = b[2*i+1];
|
||||||
|
VCPLXMUL(ar, ai, br, bi);
|
||||||
|
ab[2*i+0] = ar;
|
||||||
|
ab[2*i+1] = ai;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void pffft_reorder_back(int length, void * setup, float * data, float * work)
|
||||||
|
{
|
||||||
|
memcpy(work, data, (unsigned)length * sizeof(*work));
|
||||||
|
pffft_zreorder(setup, work, data, PFFFT_BACKWARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
637
soxr/src/pffft.c
637
soxr/src/pffft.c
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,9 @@
|
||||||
/* Copyright (c) 2011 Julien Pommier ( pommier@modartt.com )
|
/* https://bitbucket.org/jpommier/pffft/raw/483453d8f7661058e74aa4e7cf5c27bcd7887e7a/pffft.h
|
||||||
|
* with minor changes for libsoxr. */
|
||||||
|
|
||||||
|
#if !defined PFFT_MACROS_ONLY
|
||||||
|
|
||||||
|
/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com )
|
||||||
|
|
||||||
Based on original fortran 77 code from FFTPACKv4 from NETLIB,
|
Based on original fortran 77 code from FFTPACKv4 from NETLIB,
|
||||||
authored by Dr Paul Swarztrauber of NCAR, in 1985.
|
authored by Dr Paul Swarztrauber of NCAR, in 1985.
|
||||||
|
@ -60,8 +65,9 @@
|
||||||
- 1D transforms only, with 32-bit single precision.
|
- 1D transforms only, with 32-bit single precision.
|
||||||
|
|
||||||
- supports only transforms for inputs of length N of the form
|
- supports only transforms for inputs of length N of the form
|
||||||
N=(2^a)*(3^b), a >= 5 and b >=0 (32, 48, 64, 96, 128, 144 etc
|
N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128,
|
||||||
are all acceptable lengths). Performance is best for 128<=N<=8192.
|
144, 160, etc are all acceptable lengths). Performance is best for
|
||||||
|
128<=N<=8192.
|
||||||
|
|
||||||
- all (float*) pointers in the functions below are expected to
|
- all (float*) pointers in the functions below are expected to
|
||||||
have an "simd-compatible" alignment, that is 16 bytes on x86 and
|
have an "simd-compatible" alignment, that is 16 bytes on x86 and
|
||||||
|
@ -80,6 +86,10 @@
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PFFFT_DOUBLE
|
||||||
|
#define float double
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* opaque struct holding internal stuff (precomputed twiddle factors)
|
/* opaque struct holding internal stuff (precomputed twiddle factors)
|
||||||
|
@ -99,8 +109,10 @@ extern "C" {
|
||||||
PFFFT_Setup structure is read-only so it can safely be shared by
|
PFFFT_Setup structure is read-only so it can safely be shared by
|
||||||
multiple concurrent threads.
|
multiple concurrent threads.
|
||||||
*/
|
*/
|
||||||
static PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform);
|
static
|
||||||
static void pffft_destroy_setup(PFFFT_Setup *);
|
PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform);
|
||||||
|
static
|
||||||
|
void pffft_destroy_setup(PFFFT_Setup *);
|
||||||
/*
|
/*
|
||||||
Perform a Fourier transform , The z-domain data is stored in the
|
Perform a Fourier transform , The z-domain data is stored in the
|
||||||
most efficient order for transforming it back, or using it for
|
most efficient order for transforming it back, or using it for
|
||||||
|
@ -113,13 +125,14 @@ extern "C" {
|
||||||
Typically you will want to scale the backward transform by 1/N.
|
Typically you will want to scale the backward transform by 1/N.
|
||||||
|
|
||||||
The 'work' pointer should point to an area of N (2*N for complex
|
The 'work' pointer should point to an area of N (2*N for complex
|
||||||
fft) floats, properly aligned. [del]If 'work' is NULL, then stack will
|
fft) floats, properly aligned. If 'work' is NULL, then stack will
|
||||||
be used instead (this is probably the beest strategy for small
|
be used instead (this is probably the best strategy for small
|
||||||
FFTs, say for N < 16384).[/del]
|
FFTs, say for N < 16384).
|
||||||
|
|
||||||
input and output may alias.
|
input and output may alias.
|
||||||
*/
|
*/
|
||||||
static void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
|
static
|
||||||
|
void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Similar to pffft_transform, but makes sure that the output is
|
Similar to pffft_transform, but makes sure that the output is
|
||||||
|
@ -128,7 +141,8 @@ extern "C" {
|
||||||
|
|
||||||
input and output may alias.
|
input and output may alias.
|
||||||
*/
|
*/
|
||||||
static void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
|
static
|
||||||
|
void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(...,
|
call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(...,
|
||||||
|
@ -142,7 +156,8 @@ extern "C" {
|
||||||
|
|
||||||
input and output should not alias.
|
input and output should not alias.
|
||||||
*/
|
*/
|
||||||
static void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction);
|
static
|
||||||
|
void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Perform a multiplication of the frequency components of dft_a and
|
Perform a multiplication of the frequency components of dft_a and
|
||||||
|
@ -155,23 +170,28 @@ extern "C" {
|
||||||
the operation performed is: dft_ab += (dft_a * fdt_b)*scaling
|
the operation performed is: dft_ab += (dft_a * fdt_b)*scaling
|
||||||
|
|
||||||
The dft_a, dft_b and dft_ab pointers may alias.
|
The dft_a, dft_b and dft_ab pointers may alias.
|
||||||
void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling);
|
|
||||||
*/
|
*/
|
||||||
|
void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
the operation performed is: dft_ab = (dft_a * fdt_b)
|
the float buffers must have the correct alignment (16-byte boundary
|
||||||
|
on intel and powerpc). This function may be used to obtain such
|
||||||
The dft_a, dft_b and dft_ab pointers may alias.
|
correctly aligned buffers.
|
||||||
*/
|
*/
|
||||||
static void pffft_zconvolve(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab);
|
#if 0
|
||||||
|
void *pffft_aligned_malloc(size_t nb_bytes);
|
||||||
|
void pffft_aligned_free(void *);
|
||||||
|
|
||||||
/* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */
|
/* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */
|
||||||
int pffft_simd_size(void);
|
int pffft_simd_size();
|
||||||
|
#endif
|
||||||
|
|
||||||
static void pffft_reorder_back(int length, void * setup, float * data, float * work);
|
#undef float
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#define _soxr_simd_aligned_free free
|
#define SIMD_ALIGNED_FREE free
|
||||||
#define _soxr_simd_aligned_malloc malloc
|
#define SIMD_ALIGNED_MALLOC malloc
|
||||||
#define PFFFT_SIMD_DISABLE
|
#define PFFFT_SIMD_DISABLE
|
||||||
#include "pffft.c"
|
#define PFFFT_DOUBLE 0
|
||||||
|
#include "pffft-wrap.c"
|
||||||
|
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "rdft_t.h"
|
||||||
|
|
||||||
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
|
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
|
||||||
static void delete_setup(void * setup) {pffft_destroy_setup(setup);}
|
static void delete_setup(void * setup) {pffft_destroy_setup(setup);}
|
||||||
|
@ -15,18 +18,22 @@ static void backward (int length, void * setup, float * H, float * scratch) {pff
|
||||||
static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
||||||
static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;}
|
static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;}
|
||||||
static int multiplier(void) {return 1;}
|
static int multiplier(void) {return 1;}
|
||||||
|
static int flags(void) {return RDFT_NEEDS_SCRATCH;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft32_cb = {
|
||||||
fn_t _soxr_rdft32_cb[] = {
|
setup,
|
||||||
(fn_t)setup,
|
setup,
|
||||||
(fn_t)setup,
|
delete_setup,
|
||||||
(fn_t)delete_setup,
|
forward,
|
||||||
(fn_t)forward,
|
oforward,
|
||||||
(fn_t)oforward,
|
backward,
|
||||||
(fn_t)backward,
|
obackward,
|
||||||
(fn_t)obackward,
|
convolve,
|
||||||
(fn_t)convolve,
|
_soxr_ordered_partial_convolve_f,
|
||||||
(fn_t)_soxr_ordered_partial_convolve_f,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
pffft_reorder_back,
|
||||||
(fn_t)pffft_reorder_back,
|
malloc,
|
||||||
|
calloc,
|
||||||
|
free,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,27 +1,34 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
#include "pffft.c"
|
#define PFFFT_DOUBLE 0
|
||||||
|
#include "pffft-wrap.c"
|
||||||
|
|
||||||
|
#include "rdft_t.h"
|
||||||
|
|
||||||
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
|
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
|
||||||
static void forward (int length, void * setup, float * h, float * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
|
static void forward (int length, void * setup, float * h, float * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
|
||||||
static void oforward (int length, void * setup, float * h, float * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
|
static void oforward (int length, void * setup, float * h, float * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
|
||||||
static void backward (int length, void * setup, float * H, float * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
static void backward (int length, void * setup, float * H, float * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
||||||
static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
||||||
static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;}
|
static void convolve(int length, void * setup, float * H, float const * with) {pffft_zconvolve(setup, H, with, H); (void)length;}
|
||||||
static int multiplier(void) {return 1;}
|
static int multiplier(void) {return 1;}
|
||||||
|
static int flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;}
|
||||||
|
|
||||||
typedef void (* fn_t)(void);
|
rdft_cb_table _soxr_rdft32s_cb = {
|
||||||
fn_t _soxr_rdft32s_cb[] = {
|
setup,
|
||||||
(fn_t)setup,
|
setup,
|
||||||
(fn_t)setup,
|
pffft_destroy_setup,
|
||||||
(fn_t)pffft_destroy_setup,
|
forward,
|
||||||
(fn_t)forward,
|
oforward,
|
||||||
(fn_t)oforward,
|
backward,
|
||||||
(fn_t)backward,
|
obackward,
|
||||||
(fn_t)obackward,
|
convolve,
|
||||||
(fn_t)convolve,
|
ORDERED_PARTIAL_CONVOLVE_SIMD,
|
||||||
(fn_t)_soxr_ordered_partial_convolve_simd,
|
multiplier,
|
||||||
(fn_t)multiplier,
|
pffft_reorder_back,
|
||||||
(fn_t)pffft_reorder_back,
|
SIMD_ALIGNED_MALLOC,
|
||||||
|
SIMD_ALIGNED_CALLOC,
|
||||||
|
SIMD_ALIGNED_FREE,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
|
#define PFFFT_DOUBLE 1
|
||||||
|
#include "pffft-wrap.c"
|
||||||
|
|
||||||
|
#include "rdft_t.h"
|
||||||
|
|
||||||
|
static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);}
|
||||||
|
static void forward (int length, void * setup, double * h, double * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
|
||||||
|
static void oforward (int length, void * setup, double * h, double * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;}
|
||||||
|
static void backward (int length, void * setup, double * H, double * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
||||||
|
static void obackward(int length, void * setup, double * H, double * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;}
|
||||||
|
static void convolve(int length, void * setup, double * H, double const * with) {pffft_zconvolve(setup, H, with, H); (void)length;}
|
||||||
|
static int multiplier(void) {return 1;}
|
||||||
|
static int flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;}
|
||||||
|
|
||||||
|
rdft_cb_table _soxr_rdft64s_cb = {
|
||||||
|
setup,
|
||||||
|
setup,
|
||||||
|
pffft_destroy_setup,
|
||||||
|
forward,
|
||||||
|
oforward,
|
||||||
|
backward,
|
||||||
|
obackward,
|
||||||
|
convolve,
|
||||||
|
ORDERED_PARTIAL_CONVOLVE_SIMD,
|
||||||
|
multiplier,
|
||||||
|
pffft_reorder_back,
|
||||||
|
SIMD_ALIGNED_MALLOC,
|
||||||
|
SIMD_ALIGNED_CALLOC,
|
||||||
|
SIMD_ALIGNED_FREE,
|
||||||
|
flags,
|
||||||
|
};
|
|
@ -1,97 +1,149 @@
|
||||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||||
|
|
||||||
/* Resample using an interpolated poly-phase FIR with length LEN.*/
|
/* Resample using an interpolated poly-phase FIR with length LEN. */
|
||||||
/* Input must be followed by LEN-1 samples. */
|
/* Input must be followed by FIR_LENGTH-1 samples. */
|
||||||
|
|
||||||
#define a (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 0,j))
|
#if COEF_INTERP != 1 && COEF_INTERP != 2 && COEF_INTERP != 3
|
||||||
#define b (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 1,j))
|
|
||||||
#define c (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 2,j))
|
|
||||||
#define d (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 3,j))
|
|
||||||
#if COEF_INTERP == 0
|
|
||||||
#define _ sum += a *in[j], ++j;
|
|
||||||
#elif COEF_INTERP == 1
|
|
||||||
#define _ sum += (b *x + a)*in[j], ++j;
|
|
||||||
#elif COEF_INTERP == 2
|
|
||||||
#define _ sum += ((c *x + b)*x + a)*in[j], ++j;
|
|
||||||
#elif COEF_INTERP == 3
|
|
||||||
#define _ sum += (((d*x + c)*x + b)*x + a)*in[j], ++j;
|
|
||||||
#else
|
|
||||||
#error COEF_INTERP
|
#error COEF_INTERP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SIMD_AVX || SIMD_SSE || SIMD_NEON
|
||||||
|
#define N (FIR_LENGTH>>2)
|
||||||
|
|
||||||
|
#if COEF_INTERP == 1
|
||||||
|
#define _ sum=vMac(vMac(b,X,a),vLdu(in+j*4),sum), ++j;
|
||||||
|
#elif COEF_INTERP == 2
|
||||||
|
#define _ sum=vMac(vMac(vMac(c,X,b),X,a),vLdu(in+j*4),sum), ++j;
|
||||||
|
#else
|
||||||
|
#define _ sum=vMac(vMac(vMac(vMac(d,X,c),X,b),X,a),vLdu(in+j*4),sum), ++j;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define a coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-0)]
|
||||||
|
#define b coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-1)]
|
||||||
|
#define c coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-2)]
|
||||||
|
#define d coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-3)]
|
||||||
|
|
||||||
|
#define BEGINNING v4_t X = vLds(x), sum = vZero(); \
|
||||||
|
v4_t const * const __restrict coefs = (v4_t *)COEFS
|
||||||
|
#define END vStorSum(output+i, sum)
|
||||||
|
#define cc(n) case n: core(n); break
|
||||||
|
#define CORE(n) switch (n) {cc(2); cc(3); cc(4); cc(5); cc(6); default: core(n);}
|
||||||
|
#else
|
||||||
|
#define N FIR_LENGTH
|
||||||
|
|
||||||
|
#if COEF_INTERP == 1
|
||||||
|
#define _ sum += (b*x + a)*in[j], ++j;
|
||||||
|
#elif COEF_INTERP == 2
|
||||||
|
#define _ sum += ((c*x + b)*x + a)*in[j], ++j;
|
||||||
|
#else
|
||||||
|
#define _ sum += (((d*x + c)*x + b)*x + a)*in[j], ++j;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define a (coef(COEFS, COEF_INTERP, N, phase, 0,j))
|
||||||
|
#define b (coef(COEFS, COEF_INTERP, N, phase, 1,j))
|
||||||
|
#define c (coef(COEFS, COEF_INTERP, N, phase, 2,j))
|
||||||
|
#define d (coef(COEFS, COEF_INTERP, N, phase, 3,j))
|
||||||
|
|
||||||
|
#define BEGINNING sample_t sum = 0
|
||||||
|
#define END output[i] = sum
|
||||||
|
#define CORE(n) core(n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define floatPrecCore(n) { \
|
||||||
|
float_step_t at = p->at.flt; \
|
||||||
|
for (i = 0; (int)at < num_in; ++i, at += p->step.flt) { \
|
||||||
|
sample_t const * const __restrict in = input + (int)at; \
|
||||||
|
float_step_t frac = at - (int)at; \
|
||||||
|
int phase = (int)(frac * (1 << PHASE_BITS)); \
|
||||||
|
sample_t x = (sample_t)(frac * (1 << PHASE_BITS) - phase); \
|
||||||
|
int j = 0; \
|
||||||
|
BEGINNING; CONVOLVE(n); END; \
|
||||||
|
} \
|
||||||
|
fifo_read(&p->fifo, (int)at, NULL); \
|
||||||
|
p->at.flt = at - (int)at; } /* Could round to 1 in some cirmcumstances. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define highPrecCore(n) { \
|
||||||
|
step_t at; at.fix = p->at.fix; \
|
||||||
|
for (i = 0; at.integer < num_in; ++i, \
|
||||||
|
at.fix.ls.all += p->step.fix.ls.all, \
|
||||||
|
at.whole += p->step.whole + (at.fix.ls.all < p->step.fix.ls.all)) { \
|
||||||
|
sample_t const * const __restrict in = input + at.integer; \
|
||||||
|
uint32_t frac = at.fraction; \
|
||||||
|
int phase = (int)(frac >> (32 - PHASE_BITS)); /* High-order bits */ \
|
||||||
|
/* Low-order bits, scaled to [0,1): */ \
|
||||||
|
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32)); \
|
||||||
|
int j = 0; \
|
||||||
|
BEGINNING; CONVOLVE(n); END; \
|
||||||
|
} \
|
||||||
|
fifo_read(&p->fifo, at.integer, NULL); \
|
||||||
|
p->at.whole = at.fraction; \
|
||||||
|
p->at.fix.ls = at.fix.ls; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define stdPrecCore(n) { \
|
||||||
|
int64p_t at; at.all = p->at.whole; \
|
||||||
|
for (i = 0; at.parts.ms < num_in; ++i, at.all += p->step.whole) { \
|
||||||
|
sample_t const * const __restrict in = input + at.parts.ms; \
|
||||||
|
uint32_t const frac = at.parts.ls; \
|
||||||
|
int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */ \
|
||||||
|
/* Low-order bits, scaled to [0,1): */ \
|
||||||
|
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32)); \
|
||||||
|
int j = 0; \
|
||||||
|
BEGINNING; CONVOLVE(n); END; \
|
||||||
|
} \
|
||||||
|
fifo_read(&p->fifo, at.parts.ms, NULL); \
|
||||||
|
p->at.whole = at.parts.ls; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_FLOAT_STD_PREC_CLOCK
|
||||||
|
#define SPCORE floatPrecCore
|
||||||
|
#else
|
||||||
|
#define SPCORE stdPrecCore
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_HI_PREC_CLOCK
|
||||||
|
#define core(n) if (p->use_hi_prec_clock) highPrecCore(n) else SPCORE(n)
|
||||||
|
#else
|
||||||
|
#define core(n) SPCORE(n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
|
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
|
||||||
{
|
{
|
||||||
sample_t const * input = stage_read_p(p);
|
sample_t const * input = stage_read_p(p);
|
||||||
int i, num_in = stage_occupancy(p), max_num_out = 1 + (int)(num_in*p->out_in_ratio);
|
int num_in = min(stage_occupancy(p), p->input_size);
|
||||||
sample_t * output = fifo_reserve(output_fifo, max_num_out);
|
int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio);
|
||||||
|
sample_t * const __restrict output = fifo_reserve(output_fifo, max_num_out);
|
||||||
|
|
||||||
#if defined HI_PREC_CLOCK
|
CORE(N);
|
||||||
#if FLOAT_HI_PREC_CLOCK
|
|
||||||
if (p->use_hi_prec_clock) {
|
|
||||||
float_step_t at = p->at.flt;
|
|
||||||
for (i = 0; (int)at < num_in; ++i, at += p->step.flt) {
|
|
||||||
sample_t const * in = input + (int)at;
|
|
||||||
float_step_t frac = at - (int)at;
|
|
||||||
int phase = (int)(frac * (1 << PHASE_BITS));
|
|
||||||
#if COEF_INTERP > 0
|
|
||||||
sample_t x = (sample_t)(frac * (1 << PHASE_BITS) - phase);
|
|
||||||
#endif
|
|
||||||
sample_t sum = 0;
|
|
||||||
int j = 0;
|
|
||||||
CONVOLVE
|
|
||||||
output[i] = sum;
|
|
||||||
}
|
|
||||||
fifo_read(&p->fifo, (int)at, NULL);
|
|
||||||
p->at.flt = at - (int)at;
|
|
||||||
} else
|
|
||||||
#else
|
|
||||||
if (p->use_hi_prec_clock) {
|
|
||||||
for (i = 0; p->at.integer < num_in; ++i,
|
|
||||||
p->at.fix.ls.all += p->step.fix.ls.all,
|
|
||||||
p->at.whole += p->step.whole + (p->at.fix.ls.all < p->step.fix.ls.all)) {
|
|
||||||
sample_t const * in = input + p->at.integer;
|
|
||||||
uint32_t frac = p->at.fraction;
|
|
||||||
int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */
|
|
||||||
#if COEF_INTERP > 0 /* low-order bits, scaled to [0,1) */
|
|
||||||
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32));
|
|
||||||
#endif
|
|
||||||
sample_t sum = 0;
|
|
||||||
int j = 0;
|
|
||||||
CONVOLVE
|
|
||||||
output[i] = sum;
|
|
||||||
}
|
|
||||||
fifo_read(&p->fifo, p->at.integer, NULL);
|
|
||||||
p->at.integer = 0;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
for (i = 0; p->at.integer < num_in; ++i, p->at.whole += p->step.whole) {
|
|
||||||
sample_t const * in = input + p->at.integer;
|
|
||||||
uint32_t frac = p->at.fraction;
|
|
||||||
int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */
|
|
||||||
#if COEF_INTERP > 0 /* low-order bits, scaled to [0,1) */
|
|
||||||
sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32));
|
|
||||||
#endif
|
|
||||||
sample_t sum = 0;
|
|
||||||
int j = 0;
|
|
||||||
CONVOLVE
|
|
||||||
output[i] = sum;
|
|
||||||
}
|
|
||||||
fifo_read(&p->fifo, p->at.integer, NULL);
|
|
||||||
p->at.integer = 0;
|
|
||||||
}
|
|
||||||
assert(max_num_out - i >= 0);
|
assert(max_num_out - i >= 0);
|
||||||
fifo_trim_by(output_fifo, max_num_out - i);
|
fifo_trim_by(output_fifo, max_num_out - i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef _
|
#undef _
|
||||||
#undef a
|
#undef a
|
||||||
#undef b
|
#undef b
|
||||||
#undef c
|
#undef c
|
||||||
#undef d
|
#undef d
|
||||||
|
#undef CORE
|
||||||
|
#undef cc
|
||||||
|
#undef core
|
||||||
#undef COEF_INTERP
|
#undef COEF_INTERP
|
||||||
|
#undef N
|
||||||
|
#undef BEGINNING
|
||||||
|
#undef END
|
||||||
#undef CONVOLVE
|
#undef CONVOLVE
|
||||||
#undef FIR_LENGTH
|
#undef FIR_LENGTH
|
||||||
#undef FUNCTION
|
#undef FUNCTION
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue