parent
							
								
									55429fa623
								
							
						
					
					
						commit
						fbebc52511
					
				@ -0,0 +1,11 @@ | 
				
			||||
# Copyright 2023 jacqueline <me@jacqueline.id.au> | 
				
			||||
# | 
				
			||||
# SPDX-License-Identifier: GPL-3.0-only | 
				
			||||
idf_component_register() | 
				
			||||
 | 
				
			||||
set(LIBSAMPLERATE_EXAMPLES false) | 
				
			||||
set(LIBSAMPLERATE_INSTALL false) | 
				
			||||
set(BUILD_TESTING false) | 
				
			||||
 | 
				
			||||
add_subdirectory(libsamplerate-0.2.2) | 
				
			||||
target_link_libraries(${COMPONENT_LIB} INTERFACE samplerate) | 
				
			||||
@ -0,0 +1,13 @@ | 
				
			||||
Original author: | 
				
			||||
 | 
				
			||||
Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
 | 
				
			||||
Current maintainers: | 
				
			||||
 | 
				
			||||
After the release of version 0.1.9, @erikd transferred the project to | 
				
			||||
[the libsndfile team](https://github.com/libsndfile) consisting of: | 
				
			||||
 | 
				
			||||
* Erik de Castro Lopo aka @erikd | 
				
			||||
* David Seifert aka @SoapGentoo | 
				
			||||
* Arthur Taylor aka @arthurt | 
				
			||||
* @evpobr | 
				
			||||
@ -0,0 +1,150 @@ | 
				
			||||
cmake_minimum_required(VERSION 3.1..3.18) | 
				
			||||
 | 
				
			||||
# Policies | 
				
			||||
 | 
				
			||||
# Include file check macros honor CMAKE_REQUIRED_LIBRARIES, CMake >= 3.12 | 
				
			||||
if(POLICY CMP0075) | 
				
			||||
  cmake_policy(SET CMP0075 NEW) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
# MSVC runtime library flags are selected by an abstraction, CMake >= 3.15 | 
				
			||||
# This policy still need to be set even with cmake_minimum_required() command above. | 
				
			||||
if(POLICY CMP0091) | 
				
			||||
  cmake_policy(SET CMP0091 NEW) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
project(libsamplerate VERSION 0.2.2 LANGUAGES C) | 
				
			||||
 | 
				
			||||
# Configuration | 
				
			||||
 | 
				
			||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) | 
				
			||||
  set(IS_ROOT_PROJECT ON) | 
				
			||||
else() | 
				
			||||
  set(IS_ROOT_PROJECT OFF) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
option(LIBSAMPLERATE_EXAMPLES "Enable to generate examples" ${IS_ROOT_PROJECT}) | 
				
			||||
option(LIBSAMPLERATE_INSTALL "Enable to add install directives" ${IS_ROOT_PROJECT}) | 
				
			||||
 | 
				
			||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) | 
				
			||||
 | 
				
			||||
set(CMAKE_C_STANDARD 99) | 
				
			||||
set(CMAKE_C_STANDARD_REQUIRED TRUE) | 
				
			||||
 | 
				
			||||
include(TestBigEndian) | 
				
			||||
include(CheckFunctionExists) | 
				
			||||
include(CheckIncludeFile) | 
				
			||||
include(CheckLibraryExists) | 
				
			||||
include(CheckSymbolExists) | 
				
			||||
include(GNUInstallDirs) | 
				
			||||
 | 
				
			||||
include(CTest) | 
				
			||||
 | 
				
			||||
if(DEFINED LIBSAMPLERATE_TESTS) | 
				
			||||
  message(DEPRECATION "LIBSAMPLERATE_TESTS option deprecated, use BUILD_TESTING option instead.") | 
				
			||||
  set(BUILD_TESTING ${LIBSAMPLERATE_TESTS}) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
add_definitions(-DHAVE_CONFIG_H) | 
				
			||||
include_directories(${PROJECT_BINARY_DIR}) | 
				
			||||
if(MSVC) | 
				
			||||
  add_definitions(-D_CRT_SECURE_NO_WARNINGS) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
if(NOT (WIN32 OR APPLE OR CYGWIN OR HAIKU OR BEOS)) | 
				
			||||
  find_library(MATH_LIBRARY m) | 
				
			||||
  if(MATH_LIBRARY) | 
				
			||||
    set(LIBM_REQUIRED 1) | 
				
			||||
    if(LIBM_REQUIRED) | 
				
			||||
      list(APPEND CMAKE_REQUIRED_LIBRARIES m) | 
				
			||||
      if(LIBM_REQUIRED) | 
				
			||||
        link_libraries(${MATH_LIBRARY}) | 
				
			||||
      endif() | 
				
			||||
    endif() | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
option(LIBSAMPLERATE_SSE2_LRINT "Implement lrintf using SSE2 on x86 CPUs if possible" OFF) | 
				
			||||
if(LIBSAMPLERATE_SSE2_LRINT) | 
				
			||||
  add_definitions(-DENABLE_SSE2_LRINT) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") | 
				
			||||
  option(LIBSAMPLERATE_ENABLE_SANITIZERS "Enable ASAN and UBSAN" OFF) | 
				
			||||
 | 
				
			||||
  if(LIBSAMPLERATE_ENABLE_SANITIZERS) | 
				
			||||
    # Use ASAN and UBSAN, make it fail on any error, improve stack traces | 
				
			||||
    set(sanitizer_flags -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer) | 
				
			||||
 | 
				
			||||
    add_compile_options(${sanitizer_flags}) | 
				
			||||
    string(REPLACE ";" " " sanitizer_flags "${sanitizer_flags}") | 
				
			||||
    string(APPEND CMAKE_EXE_LINKER_FLAGS " ${sanitizer_flags}") | 
				
			||||
    string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${sanitizer_flags}") | 
				
			||||
    string(APPEND CMAKE_SHARED_LINKER_FLAGS " ${sanitizer_flags}") | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
test_big_endian(CPU_IS_BIG_ENDIAN) | 
				
			||||
if(CPU_IS_BIG_ENDIAN) | 
				
			||||
  set(CPU_IS_LITTLE_ENDIAN 0) | 
				
			||||
else() | 
				
			||||
  set(CPU_IS_LITTLE_ENDIAN 1) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
check_include_file(stdbool.h HAVE_STDBOOL_H) | 
				
			||||
check_include_file(unistd.h HAVE_UNISTD_H) | 
				
			||||
check_include_file(immintrin.h HAVE_IMMINTRIN_H) | 
				
			||||
 | 
				
			||||
# For examples and tests | 
				
			||||
 | 
				
			||||
find_package(PkgConfig) | 
				
			||||
 | 
				
			||||
if(LIBSAMPLERATE_EXAMPLES OR BUILD_TESTING) | 
				
			||||
  if((NOT VCPKG_TOOLCHAIN) AND PKG_CONFIG_FOUND AND (NOT CMAKE_VERSION VERSION_LESS 3.6)) | 
				
			||||
    pkg_check_modules(SndFile sndfile IMPORTED_TARGET) | 
				
			||||
    if(SndFile_FOUND) | 
				
			||||
      set(SNDFILE_TARGET PkgConfig::SndFile) | 
				
			||||
    endif() | 
				
			||||
  else() | 
				
			||||
    find_package(SndFile) | 
				
			||||
    if(SndFile_FOUND) | 
				
			||||
      set(SNDFILE_TARGET SndFile::sndfile) | 
				
			||||
    endif() | 
				
			||||
  endif() | 
				
			||||
 | 
				
			||||
  set(HAVE_SNDFILE ${SndFile_FOUND}) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
# SampleRate library | 
				
			||||
 | 
				
			||||
add_subdirectory(src) | 
				
			||||
 | 
				
			||||
# Tests | 
				
			||||
 | 
				
			||||
# BUILD_TESTING is declared by CTest module and is ON by default | 
				
			||||
if(BUILD_TESTING) | 
				
			||||
  add_subdirectory(tests) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
# Examples | 
				
			||||
 | 
				
			||||
if(LIBSAMPLERATE_EXAMPLES) | 
				
			||||
  add_subdirectory(examples) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
configure_file(config.h.cmake config.h) | 
				
			||||
 | 
				
			||||
if(LIBSAMPLERATE_INSTALL) | 
				
			||||
  add_subdirectory(docs) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
# Packaging support | 
				
			||||
 | 
				
			||||
# See https://cmake.org/cmake/help/v3.12/release/3.12.html#cpack | 
				
			||||
if(CMAKE_VERSION VERSION_LESS 3.12) | 
				
			||||
  set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) | 
				
			||||
  set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) | 
				
			||||
  set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
include(CPack) | 
				
			||||
@ -0,0 +1,25 @@ | 
				
			||||
Copyright (c) 2012-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
All rights reserved. | 
				
			||||
 | 
				
			||||
Redistribution and use in source and binary forms, with or without | 
				
			||||
modification, are permitted provided that the following conditions are | 
				
			||||
met: | 
				
			||||
 | 
				
			||||
1. Redistributions of source code must retain the above copyright | 
				
			||||
   notice, this list of conditions and the following disclaimer. | 
				
			||||
 | 
				
			||||
2. 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. | 
				
			||||
 | 
				
			||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT | 
				
			||||
HOLDER 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. | 
				
			||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						@ -0,0 +1,106 @@ | 
				
			||||
Install Instructions for libsamplerate | 
				
			||||
====================================== | 
				
			||||
 | 
				
			||||
The following instructions explain how to install libsamplerate under | 
				
			||||
Linux and other Unix-like systems, including macOS. (For Windows, | 
				
			||||
see http://libsndfile.github.io/libsamplerate/win32.html). | 
				
			||||
 | 
				
			||||
Preliminaries | 
				
			||||
------------- | 
				
			||||
1) Included with libsamplerate are example programs which use libsndfile: | 
				
			||||
 | 
				
			||||
        http://libsndfile.github.io/libsndfile/ | 
				
			||||
 | 
				
			||||
   for file I/O. If you want to build them, you need to | 
				
			||||
   ensure that libsndfile is correctly installed first. If it is, the | 
				
			||||
   command "pkg-config --cflags --libs sndfile" should print out | 
				
			||||
   something like this: | 
				
			||||
 | 
				
			||||
     -lsndfile | 
				
			||||
 | 
				
			||||
   If pkg-config doesn't exist, you will need need to install it. If | 
				
			||||
   pkg-config cannot find libsndfile, you may need to install it. If you | 
				
			||||
   install from from a Linux distribution package, make sure you also | 
				
			||||
   install the libsndfile-devel package which contains the header files. | 
				
			||||
 | 
				
			||||
   If libsndfile is installed, you may need to set the PKG_CONFIG_PATH | 
				
			||||
   environment variable. If libsndfile is installed in /usr/local/lib, | 
				
			||||
   you will need to set PKG_CONFIG_PATH using: | 
				
			||||
 | 
				
			||||
       export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig | 
				
			||||
 | 
				
			||||
2) The included tests suite for libsamplerate needs libfftw3 which is | 
				
			||||
   available here: | 
				
			||||
 | 
				
			||||
       http://www.fftw.org/ | 
				
			||||
 | 
				
			||||
   If FFTW3 is not available, libsamplerate should still compile and | 
				
			||||
   install without problems, but the test suite will not be as | 
				
			||||
   comprehensive as it normally is. | 
				
			||||
 | 
				
			||||
Building | 
				
			||||
-------- | 
				
			||||
Building and verifying libsamplerate is a four or five step process. | 
				
			||||
 | 
				
			||||
1) The first step is to run configure | 
				
			||||
 | 
				
			||||
        ./configure | 
				
			||||
 | 
				
			||||
   which should print out something like the following: | 
				
			||||
 | 
				
			||||
       checking build system type... | 
				
			||||
       ... | 
				
			||||
       ... | 
				
			||||
       -=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=- | 
				
			||||
 | 
				
			||||
         Configuration summary : | 
				
			||||
 | 
				
			||||
           Version : ..................... X.Y.Z | 
				
			||||
           Enable debugging : ............ no | 
				
			||||
 | 
				
			||||
         Tools : | 
				
			||||
 | 
				
			||||
           Compiler is GCC : ............. yes | 
				
			||||
           GCC major version : ........... 3 | 
				
			||||
 | 
				
			||||
         Extra tools required for testing and examples : | 
				
			||||
 | 
				
			||||
           Use FFTW : .................... yes | 
				
			||||
           Have libsndfile : ............. yes | 
				
			||||
 | 
				
			||||
         Installation directories : | 
				
			||||
 | 
				
			||||
           Library directory : ........... /usr/local/lib | 
				
			||||
           Program directory : ........... /usr/local/bin | 
				
			||||
           Pkgconfig directory : ......... /usr/local/lib/pkgconfig | 
				
			||||
 | 
				
			||||
       Compiling some other packages against libsamplerate may require | 
				
			||||
       the addition of "/usr/local/lib/pkgconfig" to the | 
				
			||||
       PKG_CONFIG_PATH environment variable. | 
				
			||||
 | 
				
			||||
   There are a number of configure options. See the output of | 
				
			||||
   configure when run with the --help command line option. | 
				
			||||
 | 
				
			||||
2) If all goes well with the above then compiling the library can be | 
				
			||||
   done with | 
				
			||||
 | 
				
			||||
       make | 
				
			||||
 | 
				
			||||
3) When that has finished, the test suite can be run using: | 
				
			||||
 | 
				
			||||
       make check | 
				
			||||
 | 
				
			||||
4) The final step is to install the library. This step needs to be | 
				
			||||
   carried out as the root user (or with sudo): | 
				
			||||
 | 
				
			||||
       make install | 
				
			||||
 | 
				
			||||
   This command will by default install the library in the directory | 
				
			||||
   /usr/local/lib. It can be installed in other locations by using the | 
				
			||||
   --prefix option in step 1). | 
				
			||||
 | 
				
			||||
5) On Linux, one more step is required, the registering of the library | 
				
			||||
   with the system. This is done by running the following command | 
				
			||||
   (also as the root user): | 
				
			||||
 | 
				
			||||
        ldconfig -v | 
				
			||||
@ -0,0 +1,158 @@ | 
				
			||||
## Process this file with automake to produce Makefile.in
 | 
				
			||||
 | 
				
			||||
DISTCHECK_CONFIGURE_FLAGS = --enable-werror
 | 
				
			||||
 | 
				
			||||
AM_CPPFLAGS = -I$(top_srcdir)/include
 | 
				
			||||
 | 
				
			||||
EXTRA_DIST = README.md autogen.sh libsamplerate.spec.in samplerate.pc.in  \
 | 
				
			||||
    Octave/generate_filter.m Octave/make_filter.m Octave/measure_filter.m \
 | 
				
			||||
    Octave/Readme.md Win32/libsamplerate-0.def
 | 
				
			||||
 | 
				
			||||
pkgconfig_DATA = samplerate.pc
 | 
				
			||||
 | 
				
			||||
# Some people prefer "make test" to "make check".
 | 
				
			||||
test: | 
				
			||||
	$(MAKE) check
 | 
				
			||||
 | 
				
			||||
########
 | 
				
			||||
# src/ #
 | 
				
			||||
########
 | 
				
			||||
 | 
				
			||||
lib_LTLIBRARIES = src/libsamplerate.la
 | 
				
			||||
include_HEADERS = include/samplerate.h
 | 
				
			||||
 | 
				
			||||
EXTRA_DIST += cmake CMakeLists.txt config.h.cmake docs/CMakeLists.txt   \
 | 
				
			||||
	examples/CMakeLists.txt src/CMakeLists.txt tests/CMakeLists.txt \
 | 
				
			||||
	src/config.h.in src/Version_script.in src/check_asm.sh \
 | 
				
			||||
	tests/streaming_test.c
 | 
				
			||||
CLEANFILES = src/src_sinc.s
 | 
				
			||||
 | 
				
			||||
# MinGW requires -no-undefined if a DLL is to be built.
 | 
				
			||||
src_libsamplerate_la_LDFLAGS = -no-undefined -version-info $(SHARED_VERSION_INFO) $(SHLIB_VERSION_ARG)
 | 
				
			||||
src_libsamplerate_la_SOURCES = src/samplerate.c src/src_sinc.c src/src_zoh.c src/src_linear.c \
 | 
				
			||||
	src/common.h src/fastest_coeffs.h src/mid_qual_coeffs.h src/high_qual_coeffs.h
 | 
				
			||||
 | 
				
			||||
#-------------------------------------------------------------------------------
 | 
				
			||||
# An extra check for bad asm.
 | 
				
			||||
 | 
				
			||||
check-asm: src/check_asm.sh src/src_sinc.s src/src_linear.s src/src_zoh.s | 
				
			||||
	@echo
 | 
				
			||||
	@echo
 | 
				
			||||
	$(top_srcdir)/src/check_asm.sh src/src_sinc.s
 | 
				
			||||
	$(top_srcdir)/src/check_asm.sh src/src_linear.s
 | 
				
			||||
	$(top_srcdir)/src/check_asm.sh src/src_zoh.s
 | 
				
			||||
	@echo
 | 
				
			||||
	@echo
 | 
				
			||||
 | 
				
			||||
.c.s: | 
				
			||||
	$(CC) -S $(CFLAGS) $(CPPFLAGS) $(DEFAULT_INCLUDES) $< -o $@
 | 
				
			||||
 | 
				
			||||
# Disable autoheader.
 | 
				
			||||
AUTOHEADER=echo
 | 
				
			||||
 | 
				
			||||
########
 | 
				
			||||
# docs/ #
 | 
				
			||||
########
 | 
				
			||||
 | 
				
			||||
dist_doc_DATA = docs/SRC.png docs/SRC.css docs/index.md docs/license.md docs/history.md \
 | 
				
			||||
	docs/download.md docs/lists.md docs/quality.md docs/win32.md docs/faq.md docs/api.md \
 | 
				
			||||
	docs/api_simple.md docs/api_callback.md docs/api_full.md docs/api_misc.md docs/bugs.md
 | 
				
			||||
 | 
				
			||||
#############
 | 
				
			||||
# examples/ #
 | 
				
			||||
#############
 | 
				
			||||
 | 
				
			||||
if HAVE_LIBSNDFILE | 
				
			||||
noinst_PROGRAMS = examples/varispeed-play examples/timewarp-file
 | 
				
			||||
 | 
				
			||||
examples_varispeed_play_SOURCES = examples/varispeed-play.c examples/audio_out.c examples/audio_out.h
 | 
				
			||||
examples_varispeed_play_CFLAGS = $(SNDFILE_CFLAGS) $(AUDIO_CFLAGS)
 | 
				
			||||
examples_varispeed_play_LDADD = src/libsamplerate.la $(SNDFILE_LIBS) $(AUDIO_LIBS)
 | 
				
			||||
 | 
				
			||||
examples_timewarp_file_SOURCES = examples/timewarp-file.c
 | 
				
			||||
examples_timewarp_file_CFLAGS = $(SNDFILE_CFLAGS)
 | 
				
			||||
examples_timewarp_file_LDADD = src/libsamplerate.la $(SNDFILE_LIBS)
 | 
				
			||||
endif | 
				
			||||
 | 
				
			||||
##########
 | 
				
			||||
# tests/ #
 | 
				
			||||
##########
 | 
				
			||||
 | 
				
			||||
TESTS = \
 | 
				
			||||
	tests/callback_hang_test \
 | 
				
			||||
	tests/callback_test \
 | 
				
			||||
	tests/clone_test \
 | 
				
			||||
	tests/downsample_test \
 | 
				
			||||
	tests/float_short_test \
 | 
				
			||||
	tests/misc_test \
 | 
				
			||||
	tests/multi_channel_test \
 | 
				
			||||
	tests/nullptr_test \
 | 
				
			||||
	tests/reset_test \
 | 
				
			||||
	tests/simple_test \
 | 
				
			||||
	tests/snr_bw_test \
 | 
				
			||||
	tests/termination_test \
 | 
				
			||||
	tests/throughput_test \
 | 
				
			||||
	tests/varispeed_test
 | 
				
			||||
 | 
				
			||||
check_PROGRAMS = \
 | 
				
			||||
	$(TESTS) \
 | 
				
			||||
	tests/multichan_throughput_test \
 | 
				
			||||
	tests/src-evaluate
 | 
				
			||||
 | 
				
			||||
#===============================================================================
 | 
				
			||||
 | 
				
			||||
tests_misc_test_SOURCES = tests/misc_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_misc_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_termination_test_SOURCES = tests/termination_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_termination_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_callback_hang_test_SOURCES = tests/callback_hang_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_callback_hang_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_simple_test_SOURCES = tests/simple_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_simple_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_reset_test_SOURCES = tests/reset_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_reset_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_multi_channel_test_SOURCES = tests/multi_channel_test.c tests/util.c tests/calc_snr.c
 | 
				
			||||
tests_multi_channel_test_CFLAGS = $(FFTW3_CFLAGS)
 | 
				
			||||
tests_multi_channel_test_LDADD = src/libsamplerate.la $(FFTW3_LIBS)
 | 
				
			||||
 | 
				
			||||
tests_snr_bw_test_SOURCES = tests/snr_bw_test.c tests/calc_snr.c tests/util.c tests/util.h
 | 
				
			||||
tests_snr_bw_test_CFLAGS = $(FFTW3_CFLAGS)
 | 
				
			||||
tests_snr_bw_test_LDADD = src/libsamplerate.la $(FFTW3_LIBS)
 | 
				
			||||
 | 
				
			||||
tests_callback_test_SOURCES = tests/callback_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_callback_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_float_short_test_SOURCES = tests/float_short_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_float_short_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_downsample_test_SOURCES = tests/downsample_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_downsample_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_varispeed_test_SOURCES = tests/varispeed_test.c tests/util.c tests/util.h tests/calc_snr.c
 | 
				
			||||
tests_varispeed_test_CFLAGS = $(FFTW3_CFLAGS)
 | 
				
			||||
tests_varispeed_test_LDADD = src/libsamplerate.la $(FFTW3_LIBS)
 | 
				
			||||
 | 
				
			||||
tests_clone_test_SOURCES = tests/clone_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_clone_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
tests_nullptr_test_SOURCES = tests/nullptr_test.c tests/util.c tests/util.h
 | 
				
			||||
tests_nullptr_test_LDADD = src/libsamplerate.la
 | 
				
			||||
 | 
				
			||||
# This program is for evaluating other sample rate converters.
 | 
				
			||||
 | 
				
			||||
tests_throughput_test_SOURCES = tests/throughput_test.c tests/util.c tests/calc_snr.c
 | 
				
			||||
tests_throughput_test_CFLAGS = $(FFTW3_CFLAGS)
 | 
				
			||||
tests_throughput_test_LDADD = src/libsamplerate.la $(FFTW3_LIBS)
 | 
				
			||||
 | 
				
			||||
tests_multichan_throughput_test_SOURCES = tests/multichan_throughput_test.c tests/util.c tests/calc_snr.c
 | 
				
			||||
tests_multichan_throughput_test_CFLAGS = $(FFTW3_CFLAGS)
 | 
				
			||||
tests_multichan_throughput_test_LDADD = src/libsamplerate.la $(FFTW3_LIBS)
 | 
				
			||||
 | 
				
			||||
tests_src_evaluate_SOURCES = tests/src-evaluate.c tests/calc_snr.c tests/util.c
 | 
				
			||||
tests_src_evaluate_CFLAGS = $(SNDFILE_CFLAGS) $(FFTW3_CFLAGS)
 | 
				
			||||
tests_src_evaluate_LDADD = $(SNDFILE_LIBS) $(FFTW3_LIBS)
 | 
				
			||||
@ -0,0 +1,81 @@ | 
				
			||||
Version 0.2.2 (2021-09-05) | 
				
			||||
  * Fix CMake overlinking for examples (#146) | 
				
			||||
  * Switch to GCC's visibility for hiding more implementation details | 
				
			||||
  * Check GNU ld instead of gcc for exported symbols control logic in | 
				
			||||
    configure.ac | 
				
			||||
  * Disable static builds using Autotools by default. If you want static | 
				
			||||
    libraries, pass --enable-static to ./configure | 
				
			||||
  * ABI version incompatibility between Autotools and CMake build on Apple | 
				
			||||
    platforms. | 
				
			||||
  * Fixes and improvements for CMake build system. | 
				
			||||
  * Fixes and improvements for Autotools build system. | 
				
			||||
  * Switch to .xz over .bz2 for release tarballs. | 
				
			||||
  * Minor bug fixes and updates. | 
				
			||||
 | 
				
			||||
Version 0.2.1 (2021-01-23) | 
				
			||||
  * Fix incorrect passing of -version-info to libtool, causing a | 
				
			||||
    regression on versioned file name of the shared library (#140). | 
				
			||||
  * Fix time resolution on GNU/Hurd for throughput_test | 
				
			||||
  * Update AUTHORS and release manager details | 
				
			||||
 | 
				
			||||
Version 0.2.0 (2021-01-21) | 
				
			||||
  * API: | 
				
			||||
    * Add `src_clone()` function to clone a SRC_STATE* handle | 
				
			||||
  * Cleanup Autotools build system. | 
				
			||||
  * Require C99 compiler | 
				
			||||
  * Move `sndfile-resample` to sndfile-tools package | 
				
			||||
  * Add missing `src_get_channels`() export to windows def file | 
				
			||||
  * Fix macOS compile errors and modernize audio api on that platform | 
				
			||||
  * Add Octave scripts to generate filter coefficients | 
				
			||||
  * Fix two potential undefined behaviours | 
				
			||||
  * Fix a buffer out-of-bounds read error in src/src_sinc.c | 
				
			||||
  * Improve multichan_throughput_test | 
				
			||||
  * Replace buggy implementationg of Duffs device by regular loop | 
				
			||||
  * CMake: | 
				
			||||
    * Fix CMake generated shared library ABI compliance with Autotools build  | 
				
			||||
  * Documentation: | 
				
			||||
    * Move site to new URL: http://libsndfile.github.io/libsamplerate/ | 
				
			||||
    * Convert documentation pages from HTML to Markdown | 
				
			||||
    * Use GitHub's Jekyll static site generator to generate static HTML pages | 
				
			||||
      for site | 
				
			||||
 | 
				
			||||
Version 0.1.9 (2016-09-23) | 
				
			||||
  * Relicense under 2 clause BSD license. | 
				
			||||
  * Minor bug fixes and upates. | 
				
			||||
 | 
				
			||||
Version 0.1.8 (2011-08-15) | 
				
			||||
  * Minor bug fixes and upates. | 
				
			||||
 | 
				
			||||
Version 0.1.7 (2009-02-14) | 
				
			||||
  * Fix a segfault which occurs when memcpy is passed a bad length parameter. | 
				
			||||
  * Fix compilation under MSVC. | 
				
			||||
 | 
				
			||||
Version 0.1.6 (2009-01-27) | 
				
			||||
  * Minor bug fix in test suite (account for rounding error on x86_64). | 
				
			||||
 | 
				
			||||
Version 0.1.5 (2009-01-11) | 
				
			||||
  * Optimisation resulting dramatic throughput improvements. | 
				
			||||
 | 
				
			||||
Version 0.1.4 (2008-07-02) | 
				
			||||
  * Fix bug which causes a segfault with extremely low conversion ratios. | 
				
			||||
 | 
				
			||||
Version 0.1.3 (2008-03-23) | 
				
			||||
  * Huge improvement to the quality of conversion with the | 
				
			||||
    SRC_SINC_MEDIUM_QUALITY and SRC_SINC_BEST_QUALITY converters. | 
				
			||||
  * Minor bug fixes. | 
				
			||||
 | 
				
			||||
Version 0.1.2 (2004-09-12) | 
				
			||||
  * Fixed where callback based API wasn't being reset properly. | 
				
			||||
  * Minor bug fixes. | 
				
			||||
 | 
				
			||||
Version 0.1.1 (2004-07-17) | 
				
			||||
  * Fixed bug in callback based API. | 
				
			||||
  * Fixed a bug brought to light by aggressive optimisations of gcc-3.4. | 
				
			||||
  * Minor bug fixes. | 
				
			||||
 | 
				
			||||
Version 0.1.0 (2004-03-14) | 
				
			||||
  * Added callback based API. | 
				
			||||
  * Added a pair of functions for doing short to float and float to short | 
				
			||||
    conversions on an arrays of data. | 
				
			||||
  * Many minor bug fixes. | 
				
			||||
 | 
				
			||||
@ -0,0 +1,27 @@ | 
				
			||||
# Generating Filter Coefficients | 
				
			||||
 | 
				
			||||
The scripts below are used in [GNU Octave][GNU Octave] which should be available | 
				
			||||
on most platforms including Linux, Mac and Windows. | 
				
			||||
 | 
				
			||||
On Debian and other Debian derived Linux distributions, Octave can be installed | 
				
			||||
using: `sudo apt install octave octave-signal`. | 
				
			||||
 | 
				
			||||
Filter coefficients can be generated as follows by running the `octave` command | 
				
			||||
in the same directory as the scripts and this Readme file: | 
				
			||||
 | 
				
			||||
``` | 
				
			||||
octave:1> pkg load signal | 
				
			||||
octave:2> f = make_filter (8, 128, 100.3) ; | 
				
			||||
# f = make_fip_filter (8, 128, 100.3) ; | 
				
			||||
#   Coeff. count     : 4922 | 
				
			||||
#   Fudge factor     : 1.2018769 | 
				
			||||
#   Pass band width  : 0.0039062499 (should be 0.0039062500) | 
				
			||||
#   Stop band atten. : 100.71 dB | 
				
			||||
#   -3dB band Width  : 0.490 | 
				
			||||
#   half length      : 2464 | 
				
			||||
#   increment        : 128 | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The parameters above generate the coefficient set used in `src/fastest_coeffs.h`. | 
				
			||||
 | 
				
			||||
[GNU Octave]: https://www.gnu.org/software/octave/ | 
				
			||||
@ -0,0 +1,35 @@ | 
				
			||||
function f = generate_filter (cycles, fudge_factor, increment, atten) | 
				
			||||
 | 
				
			||||
if nargin != 4, | 
				
			||||
	error ("Need four args.") ; | 
				
			||||
	endif | 
				
			||||
 | 
				
			||||
# Calclate N and make sure it is even. | 
				
			||||
N = fix (4 * cycles * fudge_factor * increment) ; | 
				
			||||
 | 
				
			||||
if rem (N, 2) != 0, | 
				
			||||
	N = N - 1 ; | 
				
			||||
	endif | 
				
			||||
 | 
				
			||||
# Generate the Sinc function. | 
				
			||||
 | 
				
			||||
m = -((N-1)/2):((N-1)/2) ; | 
				
			||||
f = sinc (m / fudge_factor / increment) ; | 
				
			||||
 | 
				
			||||
# Genertate the window function and apply it. | 
				
			||||
 | 
				
			||||
w = kaiser (N, (atten + 0.5) / 10) ; | 
				
			||||
w = w' ; | 
				
			||||
 | 
				
			||||
f = f .* w ; | 
				
			||||
 | 
				
			||||
f = f / sum (f) ; | 
				
			||||
 | 
				
			||||
endfunction | 
				
			||||
 | 
				
			||||
# Do not edit or modify anything in this comment block. | 
				
			||||
# The arch-tag line is a file identity tag for the GNU Arch  | 
				
			||||
# revision control system. | 
				
			||||
# | 
				
			||||
# arch-tag: 7e57a3cb-3f5c-4346-bfcd-4da1e758e2a7 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,134 @@ | 
				
			||||
function f = make_filter (cycles, increment, atten, filename) | 
				
			||||
 | 
				
			||||
# This works : | 
				
			||||
#  | 
				
			||||
# f = make_filter (67, 128, 100.3) ; | 
				
			||||
# f = make_filter (13, 128, 100.5) ; | 
				
			||||
# f = make_filter (185, 4, 157.0) ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
#======================================================================= | 
				
			||||
 | 
				
			||||
if nargin < 3, | 
				
			||||
	error ('Try make_filter (12, 32, 88, "output.txt")') ; | 
				
			||||
	endif | 
				
			||||
 | 
				
			||||
if nargin < 4, | 
				
			||||
	filename = 0 ; | 
				
			||||
elseif (isstr (filename) == 0), | 
				
			||||
	error ("Fourth parameter must be a file name.") ; | 
				
			||||
	endif | 
				
			||||
 | 
				
			||||
fudge_factor1 = 1.0 ; | 
				
			||||
f1 = generate_filter (cycles, fudge_factor1, increment, atten) ; | 
				
			||||
[stop_atten stop_band_start1 minus_3db] = measure_filter (f1, atten) ; | 
				
			||||
printf ("    fudge_factor : %15.13f   stop_band_start : %15.13f   1\n", fudge_factor1, stop_band_start1) ; | 
				
			||||
 | 
				
			||||
fudge_factor2 = 1.25 ; | 
				
			||||
f2 = generate_filter (cycles, fudge_factor2, increment, atten) ; | 
				
			||||
[stop_atten stop_band_start2 minus_3db] = measure_filter (f2, atten) ; | 
				
			||||
printf ("    fudge_factor : %15.13f   stop_band_start : %15.13f   2\n", fudge_factor2, stop_band_start2) ; | 
				
			||||
 | 
				
			||||
f = f1 ; | 
				
			||||
fudge_factor = fudge_factor1 ; | 
				
			||||
stop_band_start = stop_band_start1 ; | 
				
			||||
 | 
				
			||||
while ((stop_band_start1 - stop_band_start2) > 0.0000000001) | 
				
			||||
	if (stop_band_start1 < stop_band_start2) | 
				
			||||
		printf ("stop_band_start1 < stop_band_start2\n") ; | 
				
			||||
		break ; | 
				
			||||
		endif | 
				
			||||
 | 
				
			||||
	fudge_factor = fudge_factor1 + (fudge_factor2 - fudge_factor1) / 2 ; | 
				
			||||
	f = generate_filter (cycles, fudge_factor, increment, atten) ; | 
				
			||||
	[stop_atten stop_band_start minus_3db] = measure_filter (f, atten) ; | 
				
			||||
	 | 
				
			||||
	if (stop_band_start > 1.0) | 
				
			||||
		printf ("A %10.8f   %10.8f   %10.8f\n", fudge_factor1, fudge_factor, fudge_factor2) ; | 
				
			||||
		continue ; | 
				
			||||
		endif | 
				
			||||
 | 
				
			||||
	if (stop_band_start < 0.5 / increment) | 
				
			||||
		f2 = f ; | 
				
			||||
		stop_band_start2 = stop_band_start ; | 
				
			||||
		fudge_factor2 = fudge_factor ; | 
				
			||||
		choice = 2 ; | 
				
			||||
	else | 
				
			||||
		f1 = f ; | 
				
			||||
		stop_band_start1 = stop_band_start ; | 
				
			||||
		fudge_factor1 = fudge_factor ; | 
				
			||||
		choice = 1 ; | 
				
			||||
		endif | 
				
			||||
 | 
				
			||||
	printf ("    fudge_factor : %15.13f   stop_band_start : %15.13f   %d\n", fudge_factor, stop_band_start, choice) ; | 
				
			||||
	endwhile | 
				
			||||
 | 
				
			||||
printf ("\n") ; | 
				
			||||
 | 
				
			||||
#------------------------------------------------------------------------------- | 
				
			||||
# Grab only half the coefficients. | 
				
			||||
 | 
				
			||||
N = length (f) ; | 
				
			||||
 | 
				
			||||
f = increment * f' ; | 
				
			||||
 | 
				
			||||
if rem (length (f), 2) == 0, | 
				
			||||
	index = find (f == max (f)) ; | 
				
			||||
	index = min (index) - 1 ; | 
				
			||||
	half_f = f (index:length (f)) ; | 
				
			||||
else | 
				
			||||
	error ("Length should be even.") ; | 
				
			||||
	endif | 
				
			||||
 | 
				
			||||
trailing_zeros = 4 - rem (length (half_f), 4) ; | 
				
			||||
 | 
				
			||||
#------------------------------------------------------------------------------- | 
				
			||||
# Print analysis. | 
				
			||||
 | 
				
			||||
printf ("# f = make_filter (%d, %d, %4.1f) ;\n", cycles, increment, atten) ; | 
				
			||||
printf ("#   Coeff. count     : %d\n", N) ; | 
				
			||||
printf ("#   Fudge factor     : %9.7f\n", fudge_factor) ; | 
				
			||||
printf ("#   Pass band width  : %12.10f (should be %12.10f)\n", stop_band_start, 0.5 / increment) ; | 
				
			||||
printf ("#   Stop band atten. : %5.2f dB\n", abs (stop_atten)) ; | 
				
			||||
printf ("#   -3dB band Width  : %5.3f\n", 0.5 / increment / minus_3db) ; | 
				
			||||
printf ("#   half length      : %d\n", length (half_f) + trailing_zeros) ; | 
				
			||||
printf ("#   increment        : %d\n", increment) ; | 
				
			||||
 | 
				
			||||
if filename, | 
				
			||||
	file = fopen (filename, "w") ; | 
				
			||||
	if file == 0, | 
				
			||||
		str = sprintf ("Error, not able to open '%s'", filename) | 
				
			||||
		error (str) ; | 
				
			||||
		endif | 
				
			||||
 | 
				
			||||
	fprintf (file, "/*\n") ; | 
				
			||||
	fprintf (file, "**  f = make_filter (%d, %d, %4.1f) ;\n", cycles, increment, atten) ; | 
				
			||||
	fprintf (file, "**  Pass band width  : %9.7f (should be %9.7f)\n", stop_band_start, 0.5 / increment) ; | 
				
			||||
	fprintf (file, "**  Stop band atten. : %5.2f dB\n", abs (stop_atten)) ; | 
				
			||||
	fprintf (file, "**  -3dB band width  : %5.3f\n", 0.5 / increment / minus_3db) ; | 
				
			||||
	fprintf (file, "**  half length      : %d\n", length (half_f)) ; | 
				
			||||
	fprintf (file, "**  increment        : %d\n", increment) ; | 
				
			||||
	fprintf (file, "*/\n\n") ; | 
				
			||||
 | 
				
			||||
	for val = half_f, | 
				
			||||
		fprintf (file, "% 24.20e,\n", val) ; | 
				
			||||
		endfor | 
				
			||||
 | 
				
			||||
	if trailing_zeros > 0, | 
				
			||||
		for val = 2:trailing_zeros, | 
				
			||||
			fprintf (file, " 0,\n") ; | 
				
			||||
			endfor | 
				
			||||
		fprintf (file, " 0\n") ; | 
				
			||||
		endif | 
				
			||||
 | 
				
			||||
	fclose (file) ; | 
				
			||||
	endif | 
				
			||||
 | 
				
			||||
endfunction | 
				
			||||
 | 
				
			||||
# Do not edit or modify anything in this comment block. | 
				
			||||
# The arch-tag line is a file identity tag for the GNU Arch  | 
				
			||||
# revision control system. | 
				
			||||
# | 
				
			||||
# arch-tag: 2f1ff4fa-ea6a-4e54-a5f8-dad55def9834 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,70 @@ | 
				
			||||
function [stop_atten stop_band_start minus_3db] = measure_filter (f, atten) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
spec_len = 400000 ; | 
				
			||||
 | 
				
			||||
# Calculate the spectrum. | 
				
			||||
 | 
				
			||||
spec = 20 * log10 (abs (fft ([f zeros(1, spec_len - length (f))]))) ; | 
				
			||||
 | 
				
			||||
spec = spec (1:spec_len/2) ; | 
				
			||||
 | 
				
			||||
#------------------------------------------------------------------------------- | 
				
			||||
# Find the first null which starts off the stop band. | 
				
			||||
 | 
				
			||||
first_null = 0 ; | 
				
			||||
for k = 2:length (spec) - 1, | 
				
			||||
	if spec (k) < -0.8 * atten && spec (k-1) > spec (k) && spec (k) < spec (k + 1), | 
				
			||||
		first_null = k ; | 
				
			||||
		break | 
				
			||||
		endif | 
				
			||||
	endfor | 
				
			||||
 | 
				
			||||
#------------------------------------------------------------------------------- | 
				
			||||
# Find the stop band minimum attenuation. | 
				
			||||
 | 
				
			||||
stop_atten = max (spec (first_null:length (spec))) ; | 
				
			||||
 | 
				
			||||
#------------------------------------------------------------------------------- | 
				
			||||
# Find the x position on the transition band which has the same attenuation. | 
				
			||||
 | 
				
			||||
atten_start = 0 ; | 
				
			||||
for k = 1:first_null, | 
				
			||||
	if spec (k) > stop_atten && spec (k + 1) < stop_atten, | 
				
			||||
		atten_start = k ; | 
				
			||||
		break ; | 
				
			||||
		endif | 
				
			||||
	endfor | 
				
			||||
	 | 
				
			||||
atten_start = atten_start - 1 ;		# Arrays are 1 based so subtract 1. | 
				
			||||
	 | 
				
			||||
stop_band_start = atten_start + (stop_atten - spec (atten_start)) / (spec (atten_start+1) - spec (atten_start)) ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
stop_band_start = stop_band_start / spec_len ; | 
				
			||||
 | 
				
			||||
#------------------------------------------------------------------------------- | 
				
			||||
# Find -3db point. | 
				
			||||
 | 
				
			||||
minus_3db = 0 ; | 
				
			||||
for k = 1:first_null, | 
				
			||||
	if spec (k) > -3.0 && spec (k + 1) < -3.0, | 
				
			||||
		minus_3db = k ; | 
				
			||||
		break ; | 
				
			||||
		endif | 
				
			||||
	endfor | 
				
			||||
	 | 
				
			||||
minus_3db = minus_3db - 1 ; 		# Arrays are 1 based so subtract 1. | 
				
			||||
	 | 
				
			||||
minus_3db = minus_3db + (stop_atten - spec (minus_3db)) / (spec (minus_3db+1) - spec (minus_3db)) ; | 
				
			||||
 | 
				
			||||
minus_3db = minus_3db / spec_len ; | 
				
			||||
 | 
				
			||||
endfunction | 
				
			||||
 | 
				
			||||
# Do not edit or modify anything in this comment block. | 
				
			||||
# The arch-tag line is a file identity tag for the GNU Arch  | 
				
			||||
# revision control system. | 
				
			||||
# | 
				
			||||
# arch-tag: cc2bc9a2-d387-4fed-aa0a-570e91f17c99 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,62 @@ | 
				
			||||
 | 
				
			||||
 | 
				
			||||
This is libsamplerate, `0.2.2`. | 
				
			||||
 | 
				
			||||
libsamplerate (also known as Secret Rabbit Code) is a library for performing sample rate conversion of audio data. | 
				
			||||
 | 
				
			||||
* The [`src/`](https://github.com/libsndfile/libsamplerate/tree/master/src) directory contains the source code for library itself. | 
				
			||||
* The [`docs/`](https://github.com/libsndfile/libsamplerate/tree/master/docs) directory contains the libsamplerate documentation. | 
				
			||||
* The [`examples/`](https://github.com/libsndfile/libsamplerate/tree/master/examples) directory contains examples of how to write code using libsamplerate. | 
				
			||||
* The [`tests/`](https://github.com/libsndfile/libsamplerate/tree/master/tests) directory contains programs which link against libsamplerate and test its functionality. | 
				
			||||
* The [`Win32/`](https://github.com/libsndfile/libsamplerate/tree/master/Win32) directory contains files to allow libsamplerate to compile under Win32 with the Microsoft Visual C++ compiler. | 
				
			||||
 | 
				
			||||
Additional references: | 
				
			||||
 | 
				
			||||
* [Official website](http://libsndfile.github.io/libsamplerate//) | 
				
			||||
* [GitHub](https://github.com/libsndfile/libsamplerate) | 
				
			||||
 | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
## Build Status | 
				
			||||
 | 
				
			||||
| Branch         | Status                                                                                                            | | 
				
			||||
|----------------|-------------------------------------------------------------------------------------------------------------------| | 
				
			||||
| `master`       |        | | 
				
			||||
 | 
				
			||||
Branches [actively built](https://github.com/libsndfile/libsamplerate/actions) by GitHub Actions. | 
				
			||||
 | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
## Win32 | 
				
			||||
 | 
				
			||||
There are detailed instructions for building libsamplerate on Win32 in the file [`docs/win32.md`](https://github.com/libsndfile/libsamplerate/tree/master/docs/win32.md). | 
				
			||||
 | 
				
			||||
## macOS | 
				
			||||
 | 
				
			||||
Building on macOS should be the same as building it on any other Unix platform. | 
				
			||||
 | 
				
			||||
## Other Platforms | 
				
			||||
 | 
				
			||||
To compile libsamplerate on platforms which have a Bourne compatible shell, an ANSI C compiler and a make utility should require no more that the following three commands: | 
				
			||||
```bash | 
				
			||||
./configure | 
				
			||||
make | 
				
			||||
make install | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
## CMake | 
				
			||||
 | 
				
			||||
There is a new [CMake](https://cmake.org/download/)-based build system available: | 
				
			||||
```bash | 
				
			||||
mkdir build | 
				
			||||
cd build | 
				
			||||
cmake .. | 
				
			||||
make | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
* Use `cmake -DCMAKE_BUILD_TYPE=Release ..` to make a release build. | 
				
			||||
* Use `cmake -DBUILD_SHARED_LIBS=ON ..` to build a shared library. | 
				
			||||
 | 
				
			||||
## Contacts | 
				
			||||
 | 
				
			||||
libsamplerate was written by [Erik de Castro Lopo](mailto:erikd@mega-nerd.com). | 
				
			||||
@ -0,0 +1,30 @@ | 
				
			||||
EXPORTS | 
				
			||||
 | 
				
			||||
src_new 				@1 | 
				
			||||
src_delete				@2 | 
				
			||||
 | 
				
			||||
src_get_name			@10 | 
				
			||||
src_get_description		@11 | 
				
			||||
src_get_version			@12 | 
				
			||||
 | 
				
			||||
src_process				@20 | 
				
			||||
src_reset				@21 | 
				
			||||
src_set_ratio			@22 | 
				
			||||
src_clone				@23 | 
				
			||||
 | 
				
			||||
src_error				@30 | 
				
			||||
src_strerror			@31 | 
				
			||||
 | 
				
			||||
src_simple				@40 | 
				
			||||
 | 
				
			||||
src_is_valid_ratio		@50 | 
				
			||||
 | 
				
			||||
src_callback_new		@60 | 
				
			||||
src_callback_read		@61 | 
				
			||||
 | 
				
			||||
src_short_to_float_array	@70 | 
				
			||||
src_float_to_short_array	@71 | 
				
			||||
src_int_to_float_array		@80 | 
				
			||||
src_float_to_int_array		@81 | 
				
			||||
 | 
				
			||||
src_get_channels		@90 | 
				
			||||
@ -0,0 +1,119 @@ | 
				
			||||
#!/bin/sh | 
				
			||||
# Run this to set up the build system: configure, makefiles, etc. | 
				
			||||
# (based on the version in enlightenment's cvs) | 
				
			||||
 | 
				
			||||
package="libsamplerate" | 
				
			||||
 | 
				
			||||
olddir=`pwd` | 
				
			||||
srcdir=`dirname $0` | 
				
			||||
test -z "$srcdir" && srcdir=. | 
				
			||||
 | 
				
			||||
cd "$srcdir" | 
				
			||||
DIE=0 | 
				
			||||
 | 
				
			||||
echo "checking for autoconf... " | 
				
			||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || { | 
				
			||||
        echo | 
				
			||||
        echo "You must have autoconf installed to compile $package." | 
				
			||||
        echo "Download the appropriate package for your distribution," | 
				
			||||
        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" | 
				
			||||
        DIE=1 | 
				
			||||
} | 
				
			||||
 | 
				
			||||
VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/" | 
				
			||||
VERSIONMKMAJ="sed -e s/\([0-9][0-9]*\)[^0-9].*/\\1/" | 
				
			||||
VERSIONMKMIN="sed -e s/.*[0-9][0-9]*\.//" | 
				
			||||
 | 
				
			||||
# do we need automake? | 
				
			||||
if test -r Makefile.am; then | 
				
			||||
  AM_OPTIONS=`fgrep AUTOMAKE_OPTIONS Makefile.am` | 
				
			||||
  AM_NEEDED=`echo $AM_OPTIONS | $VERSIONGREP` | 
				
			||||
  if test x"$AM_NEEDED" = "x$AM_OPTIONS"; then | 
				
			||||
    AM_NEEDED="" | 
				
			||||
  fi | 
				
			||||
  if test -z $AM_NEEDED; then | 
				
			||||
    echo -n "checking for automake... " | 
				
			||||
    AUTOMAKE=automake | 
				
			||||
    ACLOCAL=aclocal | 
				
			||||
    if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then | 
				
			||||
      echo "yes" | 
				
			||||
    else | 
				
			||||
      echo "no" | 
				
			||||
      AUTOMAKE= | 
				
			||||
    fi | 
				
			||||
  else | 
				
			||||
    echo -n "checking for automake $AM_NEEDED or later... " | 
				
			||||
    majneeded=`echo $AM_NEEDED | $VERSIONMKMAJ` | 
				
			||||
    minneeded=`echo $AM_NEEDED | $VERSIONMKMIN` | 
				
			||||
    for am in automake-$AM_NEEDED automake$AM_NEEDED \ | 
				
			||||
	automake automake-1.7 automake-1.8 automake-1.9 automake-1.10; do | 
				
			||||
      ($am --version < /dev/null > /dev/null 2>&1) || continue | 
				
			||||
      ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP` | 
				
			||||
      maj=`echo $ver | $VERSIONMKMAJ` | 
				
			||||
      min=`echo $ver | $VERSIONMKMIN` | 
				
			||||
      if test $maj -eq $majneeded -a $min -ge $minneeded; then | 
				
			||||
        AUTOMAKE=$am | 
				
			||||
        echo $AUTOMAKE | 
				
			||||
        break | 
				
			||||
      fi | 
				
			||||
    done | 
				
			||||
    test -z $AUTOMAKE &&  echo "no" | 
				
			||||
    echo -n "checking for aclocal $AM_NEEDED or later... " | 
				
			||||
    for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED \ | 
				
			||||
	aclocal aclocal-1.7 aclocal-1.8 aclocal-1.9 aclocal-1.10; do | 
				
			||||
      ($ac --version < /dev/null > /dev/null 2>&1) || continue | 
				
			||||
      ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP` | 
				
			||||
      maj=`echo $ver | $VERSIONMKMAJ` | 
				
			||||
      min=`echo $ver | $VERSIONMKMIN` | 
				
			||||
      if test $maj -eq $majneeded -a $min -ge $minneeded; then | 
				
			||||
        ACLOCAL=$ac | 
				
			||||
        echo $ACLOCAL | 
				
			||||
        break | 
				
			||||
      fi | 
				
			||||
    done | 
				
			||||
    test -z $ACLOCAL && echo "no" | 
				
			||||
  fi | 
				
			||||
  test -z $AUTOMAKE || test -z $ACLOCAL && { | 
				
			||||
        echo | 
				
			||||
        echo "You must have automake installed to compile $package." | 
				
			||||
        echo "Download the appropriate package for your distribution," | 
				
			||||
        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" | 
				
			||||
        exit 1 | 
				
			||||
  } | 
				
			||||
fi | 
				
			||||
 | 
				
			||||
echo -n "checking for libtool... " | 
				
			||||
for LIBTOOLIZE in libtoolize glibtoolize nope; do | 
				
			||||
  ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break | 
				
			||||
done | 
				
			||||
if test x$LIBTOOLIZE = xnope; then | 
				
			||||
  echo "nope." | 
				
			||||
  LIBTOOLIZE=libtoolize | 
				
			||||
else | 
				
			||||
  echo $LIBTOOLIZE | 
				
			||||
fi | 
				
			||||
($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || { | 
				
			||||
	echo | 
				
			||||
	echo "You must have libtool installed to compile $package." | 
				
			||||
	echo "Download the appropriate package for your system," | 
				
			||||
	echo "or get the source from one of the GNU ftp sites" | 
				
			||||
	echo "listed in http://www.gnu.org/order/ftp.html" | 
				
			||||
	DIE=1 | 
				
			||||
} | 
				
			||||
 | 
				
			||||
if test "$DIE" -eq 1; then | 
				
			||||
        exit 1 | 
				
			||||
fi | 
				
			||||
 | 
				
			||||
echo "Generating configuration files for $package, please wait...." | 
				
			||||
 | 
				
			||||
echo "  $ACLOCAL $ACLOCAL_FLAGS" | 
				
			||||
$ACLOCAL $ACLOCAL_FLAGS || exit 1 | 
				
			||||
echo "  $LIBTOOLIZE --automake" | 
				
			||||
$LIBTOOLIZE --automake || exit 1 | 
				
			||||
echo "  autoheader" | 
				
			||||
autoheader || exit 1 | 
				
			||||
echo "  $AUTOMAKE --add-missing $AUTOMAKE_FLAGS" | 
				
			||||
$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1 | 
				
			||||
echo "  autoconf" | 
				
			||||
autoconf || exit 1 | 
				
			||||
@ -0,0 +1,81 @@ | 
				
			||||
macro(CLIP_MODE) | 
				
			||||
 | 
				
			||||
  set(CLIP_MODE_POSITIVE_MESSAGE "Target processor clips on positive float to int conversion") | 
				
			||||
  set(CLIP_MODE_NEGATIVE_MESSAGE "Target processor clips on negative float to int conversion") | 
				
			||||
 | 
				
			||||
  message(STATUS "Checking processor clipping capabilities...") | 
				
			||||
 | 
				
			||||
  if(CMAKE_CROSSCOMPILING) | 
				
			||||
 | 
				
			||||
    set(CLIP_MSG "disabled") | 
				
			||||
    set(CPU_CLIPS_POSITIVE FALSE CACHE BOOL ${CLIP_MODE_POSITIVE_MESSAGE}) | 
				
			||||
    set(CPU_CLIPS_NEGATIVE FALSE CACHE BOOL ${CLIP_MODE_NEGATIVE_MESSAGE}) | 
				
			||||
 | 
				
			||||
  else() | 
				
			||||
      include(CheckCSourceRuns) | 
				
			||||
      include(CMakePushCheckState) | 
				
			||||
      cmake_push_check_state(RESET) | 
				
			||||
 | 
				
			||||
      if(MATH_LIBRARY) | 
				
			||||
        list(APPEND CMAKE_REQUIRED_LIBRARIES ${MATH_LIBRARY}) | 
				
			||||
      endif() | 
				
			||||
 | 
				
			||||
      check_c_source_runs( | 
				
			||||
      " | 
				
			||||
      #include <math.h> | 
				
			||||
      int main (void) | 
				
			||||
      {   double  fval ; | 
				
			||||
          int k, ival ; | 
				
			||||
 | 
				
			||||
          fval = 1.0 * 0x7FFFFFFF ; | 
				
			||||
          for (k = 0 ; k < 100 ; k++) | 
				
			||||
          {   ival = (lrint (fval)) >> 24 ; | 
				
			||||
              if (ival != 127) | 
				
			||||
                  return 1 ; | 
				
			||||
 | 
				
			||||
              fval *= 1.2499999 ; | 
				
			||||
              } ; | 
				
			||||
 | 
				
			||||
              return 0 ; | 
				
			||||
          } | 
				
			||||
      " | 
				
			||||
      CPU_CLIPS_POSITIVE) | 
				
			||||
 | 
				
			||||
      check_c_source_runs( | 
				
			||||
        " | 
				
			||||
        #include <math.h> | 
				
			||||
        int main (void) | 
				
			||||
        {   double  fval ; | 
				
			||||
            int k, ival ; | 
				
			||||
 | 
				
			||||
            fval = -8.0 * 0x10000000 ; | 
				
			||||
            for (k = 0 ; k < 100 ; k++) | 
				
			||||
            {   ival = (lrint (fval)) >> 24 ; | 
				
			||||
                if (ival != -128) | 
				
			||||
                    return 1 ; | 
				
			||||
 | 
				
			||||
                fval *= 1.2499999 ; | 
				
			||||
                } ; | 
				
			||||
 | 
				
			||||
                return 0 ; | 
				
			||||
            } | 
				
			||||
        " | 
				
			||||
        CPU_CLIPS_NEGATIVE) | 
				
			||||
 | 
				
			||||
      cmake_pop_check_state() | 
				
			||||
 | 
				
			||||
      if(CPU_CLIPS_POSITIVE AND CPU_CLIPS_NEGATIVE) | 
				
			||||
          set(CLIP_MSG "both") | 
				
			||||
      elseif(CPU_CLIPS_POSITIVE) | 
				
			||||
          set(CLIP_MSG "positive") | 
				
			||||
      elseif(CPU_CLIPS_NEGATIVE) | 
				
			||||
          set(CLIP_MSG "negative") | 
				
			||||
      else() | 
				
			||||
          set(CLIP_MSG "none") | 
				
			||||
      endif() | 
				
			||||
 | 
				
			||||
  endif() | 
				
			||||
 | 
				
			||||
  message(STATUS "Checking processor clipping capabilities... ${CLIP_MSG}") | 
				
			||||
 | 
				
			||||
endmacro() | 
				
			||||
@ -0,0 +1,88 @@ | 
				
			||||
# Adapted from: https://github.com/wjakob/layerlab/blob/master/cmake/FindFFTW.cmake | 
				
			||||
 | 
				
			||||
# Copyright (c) 2015, Wenzel Jakob | 
				
			||||
# All rights reserved. | 
				
			||||
# | 
				
			||||
# 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. | 
				
			||||
# | 
				
			||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. | 
				
			||||
 | 
				
			||||
# - Find FFTW3 | 
				
			||||
# Find the native FFTW3 includes and library | 
				
			||||
# | 
				
			||||
#  Cache variables: | 
				
			||||
# | 
				
			||||
#  FFTW3_INCLUDE_DIR  - where to find fftw3.h | 
				
			||||
#  FFTW3_LIBRARY      - Path to FFTW3 libray. | 
				
			||||
#  FFTW3_ROOT         - Root of FFTW3 installation. | 
				
			||||
# | 
				
			||||
#  User variables: | 
				
			||||
# | 
				
			||||
#  FFTW3_INCLUDE_DIRS - where to find fftw3.h | 
				
			||||
#  FFTW3_LIBRARIES    - List of libraries when using FFTW3. | 
				
			||||
#  FFTW3_FOUND        - True if FFTW3 found. | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if(FFTW3_INCLUDE_DIR) | 
				
			||||
  # Already in cache, be silent | 
				
			||||
  set(FFTW3_FIND_QUIETLY TRUE) | 
				
			||||
endif(FFTW3_INCLUDE_DIR) | 
				
			||||
 | 
				
			||||
find_package(PkgConfig QUIET) | 
				
			||||
pkg_check_modules(PC_FFTW3 QUIET fftw3) | 
				
			||||
 | 
				
			||||
set(FFTW3_VERSION ${PC_FFTW3_VERSION}) | 
				
			||||
 | 
				
			||||
find_path(FFTW3_INCLUDE_DIR fftw3.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_FFTW3_INCLUDEDIR} | 
				
			||||
    ${PC_FFTW3_INCLUDE_DIRS} | 
				
			||||
    ${FFTW3_ROOT}) | 
				
			||||
 | 
				
			||||
find_library(FFTW3_LIBRARY NAMES fftw3 | 
				
			||||
  HINTS | 
				
			||||
    ${PC_FFTW3_LIBDIR} | 
				
			||||
    ${PC_FFTW3_LIBRARY_DIRS} | 
				
			||||
    ${FFTW3_ROOT}) | 
				
			||||
 | 
				
			||||
# handle the QUIETLY and REQUIRED arguments and set FFTW3_FOUND to TRUE if | 
				
			||||
# all listed variables are TRUE | 
				
			||||
include(FindPackageHandleStandardArgs) | 
				
			||||
find_package_handle_standard_args(FFTW3 | 
				
			||||
  REQUIRED_VARS | 
				
			||||
    FFTW3_LIBRARY | 
				
			||||
    FFTW3_INCLUDE_DIR | 
				
			||||
  VERSION_VAR | 
				
			||||
    FFTW3_VERSION) | 
				
			||||
 | 
				
			||||
if(FFTW3_FOUND) | 
				
			||||
	set(FFTW3_LIBRARIES ${FFTW3_LIBRARY}) | 
				
			||||
	set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR}) | 
				
			||||
	 | 
				
			||||
	if(NOT TARGET FFTW3::fftw3) | 
				
			||||
	  add_library(FFTW3::fftw3 UNKNOWN IMPORTED) | 
				
			||||
		set_target_properties(FFTW3::fftw3 PROPERTIES | 
				
			||||
			INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR}" | 
				
			||||
			IMPORTED_LOCATION "${FFTW3_LIBRARY}" | 
				
			||||
		) | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
mark_as_advanced(FFTW3_LIBRARY FFTW3_INCLUDE_DIR) | 
				
			||||
@ -0,0 +1,63 @@ | 
				
			||||
# - Find FLAC | 
				
			||||
# Find the native FLAC includes and libraries | 
				
			||||
# | 
				
			||||
#  FLAC_INCLUDE_DIRS - where to find FLAC headers. | 
				
			||||
#  FLAC_LIBRARIES    - List of libraries when using libFLAC. | 
				
			||||
#  FLAC_FOUND        - True if libFLAC found. | 
				
			||||
#  FLAC_DEFINITIONS  - FLAC compile definitons  | 
				
			||||
 | 
				
			||||
if(FLAC_INCLUDE_DIR) | 
				
			||||
  # Already in cache, be silent | 
				
			||||
  set(FLAC_FIND_QUIETLY TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
find_package(Ogg QUIET) | 
				
			||||
 | 
				
			||||
find_package(PkgConfig QUIET) | 
				
			||||
pkg_check_modules(PC_FLAC QUIET flac) | 
				
			||||
 | 
				
			||||
set(FLAC_VERSION ${PC_FLAC_VERSION}) | 
				
			||||
 | 
				
			||||
find_path(FLAC_INCLUDE_DIR FLAC/stream_decoder.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_FLAC_INCLUDEDIR} | 
				
			||||
    ${PC_FLAC_INCLUDE_DIRS} | 
				
			||||
    ${FLAC_ROOT}) | 
				
			||||
 | 
				
			||||
# MSVC built libraries can name them *_static, which is good as it | 
				
			||||
# distinguishes import libraries from static libraries with the same extension. | 
				
			||||
find_library(FLAC_LIBRARY | 
				
			||||
  NAMES | 
				
			||||
    FLAC | 
				
			||||
    libFLAC | 
				
			||||
    libFLAC_dynamic | 
				
			||||
    libFLAC_static | 
				
			||||
  HINTS | 
				
			||||
    ${PC_FLAC_LIBDIR} | 
				
			||||
    ${PC_FLAC_LIBRARY_DIRS} | 
				
			||||
    ${FLAC_ROOT}) | 
				
			||||
 | 
				
			||||
# Handle the QUIETLY and REQUIRED arguments and set FLAC_FOUND to TRUE if | 
				
			||||
# all listed variables are TRUE. | 
				
			||||
include(FindPackageHandleStandardArgs) | 
				
			||||
find_package_handle_standard_args(FLAC | 
				
			||||
  REQUIRED_VARS | 
				
			||||
    FLAC_LIBRARY | 
				
			||||
    FLAC_INCLUDE_DIR | 
				
			||||
    Ogg_FOUND | 
				
			||||
  VERSION_VAR | 
				
			||||
        FLAC_VERSION) | 
				
			||||
 | 
				
			||||
if(FLAC_FOUND) | 
				
			||||
  set(FLAC_INCLUDE_DIRS ${FLAC_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS}) | 
				
			||||
  set(FLAC_LIBRARIES ${FLAC_LIBRARY} ${Ogg_LIBRARIES}) | 
				
			||||
    if(NOT TARGET FLAC::FLAC) | 
				
			||||
    add_library(FLAC::FLAC UNKNOWN IMPORTED) | 
				
			||||
    set_target_properties(FLAC::FLAC PROPERTIES | 
				
			||||
      INTERFACE_INCLUDE_DIRECTORIES "${FLAC_INCLUDE_DIR}" | 
				
			||||
      IMPORTED_LOCATION "${FLAC_LIBRARY}" | 
				
			||||
      INTERFACE_LINK_LIBRARIES Ogg::ogg) | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
mark_as_advanced(FLAC_INCLUDE_DIR FLAC_LIBRARY) | 
				
			||||
@ -0,0 +1,57 @@ | 
				
			||||
# - Find ogg | 
				
			||||
# Find the native ogg includes and libraries | 
				
			||||
# | 
				
			||||
#  Ogg_INCLUDE_DIRS - where to find ogg.h, etc. | 
				
			||||
#  Ogg_LIBRARIES    - List of libraries when using ogg. | 
				
			||||
#  Ogg_FOUND        - True if ogg found. | 
				
			||||
 | 
				
			||||
if(Ogg_INCLUDE_DIR) | 
				
			||||
  # Already in cache, be silent | 
				
			||||
  set(Ogg_FIND_QUIETLY TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
find_package(PkgConfig QUIET) | 
				
			||||
pkg_check_modules(PC_Ogg QUIET ogg) | 
				
			||||
 | 
				
			||||
set(Ogg_VERSION ${PC_Ogg_VERSION}) | 
				
			||||
 | 
				
			||||
find_path(Ogg_INCLUDE_DIR ogg/ogg.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Ogg_INCLUDEDIR} | 
				
			||||
    ${PC_Ogg_INCLUDE_DIRS} | 
				
			||||
    ${Ogg_ROOT}) | 
				
			||||
# MSVC built ogg may be named ogg_static. | 
				
			||||
# The provided project files name the library with the lib prefix. | 
				
			||||
find_library(Ogg_LIBRARY | 
				
			||||
  NAMES | 
				
			||||
    ogg | 
				
			||||
    ogg_static | 
				
			||||
    libogg | 
				
			||||
    libogg_static | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Ogg_LIBDIR} | 
				
			||||
    ${PC_Ogg_LIBRARY_DIRS} | 
				
			||||
    ${Ogg_ROOT}) | 
				
			||||
# Handle the QUIETLY and REQUIRED arguments and set Ogg_FOUND | 
				
			||||
# to TRUE if all listed variables are TRUE. | 
				
			||||
include(FindPackageHandleStandardArgs) | 
				
			||||
find_package_handle_standard_args(Ogg | 
				
			||||
  REQUIRED_VARS | 
				
			||||
    Ogg_LIBRARY | 
				
			||||
    Ogg_INCLUDE_DIR | 
				
			||||
  VERSION_VAR | 
				
			||||
    Ogg_VERSION) | 
				
			||||
 | 
				
			||||
if(Ogg_FOUND) | 
				
			||||
  set(Ogg_LIBRARIES ${Ogg_LIBRARY}) | 
				
			||||
  set(Ogg_INCLUDE_DIRS ${Ogg_INCLUDE_DIR}) | 
				
			||||
   | 
				
			||||
  if(NOT TARGET Ogg::ogg) | 
				
			||||
  add_library(Ogg::ogg UNKNOWN IMPORTED) | 
				
			||||
    set_target_properties(Ogg::ogg PROPERTIES | 
				
			||||
      INTERFACE_INCLUDE_DIRECTORIES "${Ogg_INCLUDE_DIR}" | 
				
			||||
      IMPORTED_LOCATION "${Ogg_LIBRARY}") | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
mark_as_advanced(Ogg_INCLUDE_DIR Ogg_LIBRARY) | 
				
			||||
@ -0,0 +1,64 @@ | 
				
			||||
# - Find opus | 
				
			||||
# Find the native opus includes and libraries | 
				
			||||
# | 
				
			||||
#  OPUS_INCLUDE_DIRS - where to find opus.h, etc. | 
				
			||||
#  OPUS_LIBRARIES    - List of libraries when using opus. | 
				
			||||
#  OPUS_FOUND        - True if Opus found. | 
				
			||||
 | 
				
			||||
if(OPUS_INCLUDE_DIR) | 
				
			||||
  # Already in cache, be silent | 
				
			||||
  set(OPUS_FIND_QUIETLY TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
find_package(Ogg QUIET) | 
				
			||||
 | 
				
			||||
find_package(PkgConfig QUIET) | 
				
			||||
pkg_check_modules(PC_OPUS QUIET opus) | 
				
			||||
 | 
				
			||||
set(OPUS_VERSION ${PC_OPUS_VERSION}) | 
				
			||||
 | 
				
			||||
find_path(OPUS_INCLUDE_DIR opus/opus.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_OPUS_INCLUDEDIR} | 
				
			||||
    ${PC_OPUS_INCLUDE_DIRS} | 
				
			||||
    ${OPUS_ROOT}) | 
				
			||||
 | 
				
			||||
# MSVC built opus may be named opus_static. | 
				
			||||
# The provided project files name the library with the lib prefix. | 
				
			||||
 | 
				
			||||
find_library(OPUS_LIBRARY | 
				
			||||
  NAMES | 
				
			||||
    opus | 
				
			||||
    opus_static | 
				
			||||
    libopus | 
				
			||||
    libopus_static | 
				
			||||
  HINTS | 
				
			||||
    ${PC_OPUS_LIBDIR} | 
				
			||||
    ${PC_OPUS_LIBRARY_DIRS} | 
				
			||||
    ${OPUS_ROOT}) | 
				
			||||
 | 
				
			||||
# Handle the QUIETLY and REQUIRED arguments and set OPUS_FOUND | 
				
			||||
# to TRUE if all listed variables are TRUE. | 
				
			||||
include(FindPackageHandleStandardArgs) | 
				
			||||
find_package_handle_standard_args(Opus | 
				
			||||
  REQUIRED_VARS | 
				
			||||
    OPUS_LIBRARY | 
				
			||||
    OPUS_INCLUDE_DIR | 
				
			||||
    Ogg_FOUND | 
				
			||||
  VERSION_VAR | 
				
			||||
    OPUS_VERSION) | 
				
			||||
 | 
				
			||||
if(OPUS_FOUND) | 
				
			||||
  set(OPUS_LIBRARIES ${OPUS_LIBRARY}) | 
				
			||||
  set(OPUS_INCLUDE_DIRS ${OPUS_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS}) | 
				
			||||
 | 
				
			||||
  if(NOT TARGET Opus::opus) | 
				
			||||
    add_library(Opus::opus UNKNOWN IMPORTED) | 
				
			||||
    set_target_properties(Opus::opus PROPERTIES | 
				
			||||
      INTERFACE_INCLUDE_DIRECTORIES "${OPUS_INCLUDE_DIR}" | 
				
			||||
      IMPORTED_LOCATION "${OPUS_LIBRARY}" | 
				
			||||
      INTERFACE_LINK_LIBRARIES Ogg::ogg) | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
mark_as_advanced(OPUS_INCLUDE_DIR OPUS_LIBRARY) | 
				
			||||
@ -0,0 +1,57 @@ | 
				
			||||
# Variables defined: | 
				
			||||
#  SNDFILE_FOUND | 
				
			||||
#  SNDFILE_INCLUDE_DIR | 
				
			||||
#  SNDFILE_LIBRARY | 
				
			||||
# | 
				
			||||
# Environment variables used: | 
				
			||||
#  SNDFILE_ROOT | 
				
			||||
 | 
				
			||||
if(SndFile_INCLUDE_DIR) | 
				
			||||
  # Already in cache, be silent | 
				
			||||
  set(SndFile_FIND_QUIETLY TRUE) | 
				
			||||
endif(SndFile_INCLUDE_DIR) | 
				
			||||
 | 
				
			||||
find_package(PkgConfig QUIET) | 
				
			||||
pkg_check_modules(PC_SndFile QUIET sndfile) | 
				
			||||
 | 
				
			||||
set(SndFile_VERSION ${PC_SndFile_VERSION}) | 
				
			||||
 | 
				
			||||
find_package(Vorbis COMPONENTS Enc QUIET) | 
				
			||||
find_package(FLAC QUIET) | 
				
			||||
find_package(Opus QUIET) | 
				
			||||
 | 
				
			||||
find_path(SndFile_INCLUDE_DIR sndfile.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_SndFile_INCLUDEDIR} | 
				
			||||
    ${PC_SndFile_INCLUDE_DIRS} | 
				
			||||
    ${SndFile_ROOT}) | 
				
			||||
 | 
				
			||||
find_library(SndFile_LIBRARY NAMES sndfile | 
				
			||||
  HINTS | 
				
			||||
    ${PC_SndFile_LIBDIR} | 
				
			||||
    ${PC_SndFile_LIBRARY_DIRS} | 
				
			||||
    ${SndFile_ROOT}) | 
				
			||||
 | 
				
			||||
include(FindPackageHandleStandardArgs) | 
				
			||||
find_package_handle_standard_args(SndFile | 
				
			||||
  REQUIRED_VARS | 
				
			||||
    SndFile_LIBRARY | 
				
			||||
    SndFile_INCLUDE_DIR | 
				
			||||
  VERSION_VAR | 
				
			||||
    SndFile_VERSION) | 
				
			||||
 | 
				
			||||
if(SndFile_FOUND) | 
				
			||||
 | 
				
			||||
  set(SndFile_LIBRARIES ${SndFile_LIBRARY} ${Vorbis_Enc_LIBRARIES} ${FLAC_LIBRARIES} ${OPUS_LIBRARIES}) | 
				
			||||
  set(SndFile_INCLUDE_DIRS ${SndFile_INCLUDE_DIR} ${Vorbis_Enc_INCLUDE_DIRS} ${FLAC_INCLUDE_DIRS} ${OPUS_INCLUDE_DIRS}) | 
				
			||||
   | 
				
			||||
  if(NOT TARGET SndFile::sndfile) | 
				
			||||
    add_library(SndFile::sndfile UNKNOWN IMPORTED) | 
				
			||||
    set_target_properties(SndFile::sndfile PROPERTIES | 
				
			||||
      INTERFACE_INCLUDE_DIRECTORIES "${SndFile_INCLUDE_DIR}" | 
				
			||||
      IMPORTED_LOCATION "${SndFile_LIBRARY}" | 
				
			||||
      INTERFACE_LINK_LIBRARIES "Vorbis::vorbisenc;Opus::opus;FLAC::FLAC") | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
mark_as_advanced(SndFile_LIBRARY SndFile_INCLUDE_DIR) | 
				
			||||
@ -0,0 +1,204 @@ | 
				
			||||
#[=======================================================================[.rst: | 
				
			||||
FindVorbis | 
				
			||||
---------- | 
				
			||||
 | 
				
			||||
Finds the native vorbis, vorbisenc amd vorbisfile includes and libraries. | 
				
			||||
 | 
				
			||||
Imported Targets | 
				
			||||
^^^^^^^^^^^^^^^^ | 
				
			||||
 | 
				
			||||
This module provides the following imported targets, if found: | 
				
			||||
 | 
				
			||||
``Vorbis::vorbis`` | 
				
			||||
  The Vorbis library | 
				
			||||
``Vorbis::vorbisenc`` | 
				
			||||
  The VorbisEnc library | 
				
			||||
``Vorbis::vorbisfile`` | 
				
			||||
  The VorbisFile library | 
				
			||||
 | 
				
			||||
Result Variables | 
				
			||||
^^^^^^^^^^^^^^^^ | 
				
			||||
 | 
				
			||||
This will define the following variables: | 
				
			||||
 | 
				
			||||
``Vorbis_Vorbis_INCLUDE_DIRS`` | 
				
			||||
  List of include directories when using vorbis. | 
				
			||||
``Vorbis_Enc_INCLUDE_DIRS`` | 
				
			||||
  List of include directories when using vorbisenc. | 
				
			||||
``Vorbis_File_INCLUDE_DIRS`` | 
				
			||||
  List of include directories when using vorbisfile. | 
				
			||||
``Vorbis_Vorbis_LIBRARIES`` | 
				
			||||
  List of libraries when using vorbis. | 
				
			||||
``Vorbis_Enc_LIBRARIES`` | 
				
			||||
  List of libraries when using vorbisenc. | 
				
			||||
``Vorbis_File_LIBRARIES`` | 
				
			||||
  List of libraries when using vorbisfile. | 
				
			||||
``Vorbis_FOUND`` | 
				
			||||
  True if vorbis and requested components found. | 
				
			||||
``Vorbis_Vorbis_FOUND`` | 
				
			||||
  True if vorbis found. | 
				
			||||
``Vorbis_Enc_FOUND`` | 
				
			||||
  True if vorbisenc found. | 
				
			||||
``Vorbis_Enc_FOUND`` | 
				
			||||
  True if vorbisfile found. | 
				
			||||
 | 
				
			||||
Cache variables | 
				
			||||
^^^^^^^^^^^^^^^ | 
				
			||||
 | 
				
			||||
The following cache variables may also be set: | 
				
			||||
 | 
				
			||||
``Vorbis_Vorbis_INCLUDE_DIR`` | 
				
			||||
  The directory containing ``vorbis/vorbis.h``. | 
				
			||||
``Vorbis_Enc_INCLUDE_DIR`` | 
				
			||||
  The directory containing ``vorbis/vorbisenc.h``. | 
				
			||||
``Vorbis_File_INCLUDE_DIR`` | 
				
			||||
  The directory containing ``vorbis/vorbisenc.h``. | 
				
			||||
``Vorbis_Vorbis_LIBRARY`` | 
				
			||||
  The path to the vorbis library. | 
				
			||||
``Vorbis_Enc_LIBRARY`` | 
				
			||||
  The path to the vorbisenc library. | 
				
			||||
``Vorbis_File_LIBRARY`` | 
				
			||||
  The path to the vorbisfile library. | 
				
			||||
 | 
				
			||||
Hints | 
				
			||||
^^^^^ | 
				
			||||
 | 
				
			||||
A user may set ``Vorbis_ROOT`` to a vorbis installation root to tell this module where to look. | 
				
			||||
 | 
				
			||||
#]=======================================================================] | 
				
			||||
 | 
				
			||||
if(Vorbis_Vorbis_INCLUDE_DIR) | 
				
			||||
  # Already in cache, be silent | 
				
			||||
  set(Vorbis_FIND_QUIETLY TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
set(Vorbis_Vorbis_FIND_QUIETLY TRUE) | 
				
			||||
set(Vorbis_Enc_FIND_QUIETLY TRUE) | 
				
			||||
set(Vorbis_File_FIND_QUIETLY TRUE) | 
				
			||||
 | 
				
			||||
find_package(Ogg QUIET) | 
				
			||||
 | 
				
			||||
find_package(PkgConfig QUIET) | 
				
			||||
pkg_check_modules(PC_Vorbis_Vorbis QUIET vorbis) | 
				
			||||
pkg_check_modules(PC_Vorbis_Enc QUIET vorbisenc) | 
				
			||||
pkg_check_modules(PC_Vorbis_File QUIET vorbisfile) | 
				
			||||
 | 
				
			||||
set(Vorbis_VERSION ${PC_Vorbis_Vorbis_VERSION}) | 
				
			||||
 | 
				
			||||
find_path(Vorbis_Vorbis_INCLUDE_DIR vorbis/codec.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Vorbis_Vorbis_INCLUDEDIR} | 
				
			||||
    ${PC_Vorbis_Vorbis_INCLUDE_DIRS} | 
				
			||||
    ${Vorbis_ROOT}) | 
				
			||||
 | 
				
			||||
find_path(Vorbis_Enc_INCLUDE_DIR vorbis/vorbisenc.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Vorbis_Enc_INCLUDEDIR} | 
				
			||||
    ${PC_Vorbis_Enc_INCLUDE_DIRS} | 
				
			||||
    ${Vorbis_ROOT}) | 
				
			||||
 | 
				
			||||
find_path(Vorbis_File_INCLUDE_DIR vorbis/vorbisfile.h | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Vorbis_File_INCLUDEDIR} | 
				
			||||
    ${PC_Vorbis_File_INCLUDE_DIRS} | 
				
			||||
    ${Vorbis_ROOT}) | 
				
			||||
 | 
				
			||||
find_library(Vorbis_Vorbis_LIBRARY | 
				
			||||
  NAMES | 
				
			||||
    vorbis | 
				
			||||
    vorbis_static | 
				
			||||
    libvorbis | 
				
			||||
    libvorbis_static | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Vorbis_Vorbis_LIBDIR} | 
				
			||||
    ${PC_Vorbis_Vorbis_LIBRARY_DIRS} | 
				
			||||
    ${Vorbis_ROOT}) | 
				
			||||
 | 
				
			||||
find_library(Vorbis_Enc_LIBRARY | 
				
			||||
  NAMES | 
				
			||||
    vorbisenc | 
				
			||||
    vorbisenc_static | 
				
			||||
    libvorbisenc | 
				
			||||
    libvorbisenc_static | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Vorbis_Enc_LIBDIR} | 
				
			||||
    ${PC_Vorbis_Enc_LIBRARY_DIRS} | 
				
			||||
    ${Vorbis_ROOT}) | 
				
			||||
 | 
				
			||||
find_library(Vorbis_File_LIBRARY | 
				
			||||
  NAMES | 
				
			||||
    vorbisfile | 
				
			||||
    vorbisfile_static | 
				
			||||
    libvorbisfile | 
				
			||||
    libvorbisfile_static | 
				
			||||
  HINTS | 
				
			||||
    ${PC_Vorbis_File_LIBDIR} | 
				
			||||
    ${PC_Vorbis_File_LIBRARY_DIRS} | 
				
			||||
    ${Vorbis_ROOT}) | 
				
			||||
 | 
				
			||||
include(FindPackageHandleStandardArgs) | 
				
			||||
 | 
				
			||||
if(Vorbis_Vorbis_LIBRARY AND Vorbis_Vorbis_INCLUDE_DIR AND Ogg_FOUND) | 
				
			||||
  set(Vorbis_Vorbis_FOUND TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
if(Vorbis_Enc_LIBRARY AND Vorbis_Enc_INCLUDE_DIR AND Vorbis_Vorbis_FOUND) | 
				
			||||
  set(Vorbis_Enc_FOUND TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
if(Vorbis_Vorbis_FOUND AND Vorbis_File_LIBRARY AND Vorbis_File_INCLUDE_DIR) | 
				
			||||
  set(Vorbis_File_FOUND TRUE) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
find_package_handle_standard_args(Vorbis | 
				
			||||
  REQUIRED_VARS | 
				
			||||
    Vorbis_Vorbis_LIBRARY | 
				
			||||
    Vorbis_Vorbis_INCLUDE_DIR | 
				
			||||
    Ogg_FOUND | 
				
			||||
  HANDLE_COMPONENTS | 
				
			||||
  VERSION_VAR Vorbis_VERSION) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if(Vorbis_Vorbis_FOUND) | 
				
			||||
  set(Vorbis_Vorbis_INCLUDE_DIRS ${Vorbis_Vorbis_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS}) | 
				
			||||
  set(Vorbis_Vorbis_LIBRARIES ${Vorbis_Vorbis_LIBRARY} ${Ogg_LIBRARIES}) | 
				
			||||
  if(NOT TARGET Vorbis::vorbis) | 
				
			||||
    add_library(Vorbis::vorbis UNKNOWN IMPORTED) | 
				
			||||
    set_target_properties(Vorbis::vorbis PROPERTIES | 
				
			||||
      INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Vorbis_INCLUDE_DIR}" | 
				
			||||
      IMPORTED_LOCATION "${Vorbis_Vorbis_LIBRARY}" | 
				
			||||
      INTERFACE_LINK_LIBRARIES Ogg::ogg | 
				
			||||
    ) | 
				
			||||
  endif() | 
				
			||||
 | 
				
			||||
  if(Vorbis_Enc_FOUND) | 
				
			||||
    set(Vorbis_Enc_INCLUDE_DIRS ${Vorbis_Enc_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS}) | 
				
			||||
    set(Vorbis_Enc_LIBRARIES ${Vorbis_Enc_LIBRARY} ${Vorbis_Vorbis_LIBRARIES}) | 
				
			||||
    if(NOT TARGET Vorbis::vorbisenc) | 
				
			||||
      add_library(Vorbis::vorbisenc UNKNOWN IMPORTED) | 
				
			||||
      set_target_properties(Vorbis::vorbisenc PROPERTIES | 
				
			||||
        INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Enc_INCLUDE_DIR}" | 
				
			||||
        IMPORTED_LOCATION "${Vorbis_Enc_LIBRARY}" | 
				
			||||
        INTERFACE_LINK_LIBRARIES Vorbis::vorbis | 
				
			||||
      ) | 
				
			||||
    endif() | 
				
			||||
  endif() | 
				
			||||
 | 
				
			||||
  if(Vorbis_File_FOUND) | 
				
			||||
    set(Vorbis_File_INCLUDE_DIRS ${Vorbis_File_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS}) | 
				
			||||
    set(Vorbis_File_LIBRARIES ${Vorbis_File_LIBRARY} ${Vorbis_Vorbis_LIBRARIES}) | 
				
			||||
    if(NOT TARGET Vorbis::vorbisfile) | 
				
			||||
      add_library(Vorbis::vorbisfile UNKNOWN IMPORTED) | 
				
			||||
      set_target_properties(Vorbis::vorbisfile PROPERTIES | 
				
			||||
        INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_File_INCLUDE_DIR}" | 
				
			||||
        IMPORTED_LOCATION "${Vorbis_File_LIBRARY}" | 
				
			||||
        INTERFACE_LINK_LIBRARIES Vorbis::vorbis | 
				
			||||
      ) | 
				
			||||
    endif() | 
				
			||||
  endif() | 
				
			||||
 | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
mark_as_advanced(Vorbis_Vorbis_INCLUDE_DIR Vorbis_Vorbis_LIBRARY) | 
				
			||||
mark_as_advanced(Vorbis_Enc_INCLUDE_DIR Vorbis_Enc_LIBRARY) | 
				
			||||
mark_as_advanced(Vorbis_File_INCLUDE_DIR Vorbis_File_LIBRARY) | 
				
			||||
@ -0,0 +1 @@ | 
				
			||||
include(${CMAKE_CURRENT_LIST_DIR}/SampleRateTargets.cmake) | 
				
			||||
@ -0,0 +1,76 @@ | 
				
			||||
/* config.h - generated by CMake. */ | 
				
			||||
 | 
				
			||||
/* Name of package */ | 
				
			||||
#define PACKAGE "${PROJECT_NAME}" | 
				
			||||
 | 
				
			||||
/* Version number of package */ | 
				
			||||
#define VERSION "${PROJECT_VERSION}" | 
				
			||||
 | 
				
			||||
/* Target processor clips on negative float to int conversion. */ | 
				
			||||
#cmakedefine01 CPU_CLIPS_NEGATIVE | 
				
			||||
 | 
				
			||||
/* Target processor clips on positive float to int conversion. */ | 
				
			||||
#cmakedefine01 CPU_CLIPS_POSITIVE | 
				
			||||
 | 
				
			||||
/* Target processor is big endian. */ | 
				
			||||
#cmakedefine01 CPU_IS_BIG_ENDIAN | 
				
			||||
 | 
				
			||||
/* Target processor is little endian. */ | 
				
			||||
#cmakedefine01 CPU_IS_LITTLE_ENDIAN | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the `alarm' function. */ | 
				
			||||
#cmakedefine01 HAVE_ALARM | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the <alsa/asoundlib.h> header file. */ | 
				
			||||
#cmakedefine01 HAVE_ALSA | 
				
			||||
 | 
				
			||||
/* Set to 1 if you have libfftw3. */ | 
				
			||||
#cmakedefine01 HAVE_FFTW3 | 
				
			||||
 | 
				
			||||
/* Define if you have C99's lrint function. */ | 
				
			||||
#cmakedefine01 HAVE_LRINT | 
				
			||||
 | 
				
			||||
/* Define if you have C99's lrintf function. */ | 
				
			||||
#cmakedefine01 HAVE_LRINTF | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the <immintrin.h> header file. */ | 
				
			||||
#cmakedefine HAVE_IMMINTRIN_H | 
				
			||||
 | 
				
			||||
/* Define if you have signal SIGALRM. */ | 
				
			||||
#cmakedefine01 HAVE_SIGALRM | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the `signal' function. */ | 
				
			||||
#cmakedefine01 HAVE_SIGNAL | 
				
			||||
 | 
				
			||||
/* Set to 1 if you have libsndfile. */ | 
				
			||||
#cmakedefine01 HAVE_SNDFILE | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the <stdbool.h> header file. */ | 
				
			||||
#cmakedefine HAVE_STDBOOL_H | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the <stdint.h> header file. */ | 
				
			||||
#cmakedefine01 HAVE_STDINT_H | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the <sys/times.h> header file. */ | 
				
			||||
#cmakedefine01 HAVE_SYS_TIMES_H | 
				
			||||
 | 
				
			||||
/* Define to 1 if you have the <unistd.h> header file. */ | 
				
			||||
#cmakedefine HAVE_UNISTD_H | 
				
			||||
 | 
				
			||||
/* Define to 1 if the compiler supports simple visibility declarations. */ | 
				
			||||
#cmakedefine HAVE_VISIBILITY | 
				
			||||
 | 
				
			||||
/* define fast samplerate convertor */ | 
				
			||||
#cmakedefine ENABLE_SINC_FAST_CONVERTER | 
				
			||||
 | 
				
			||||
/* define balanced samplerate convertor */ | 
				
			||||
#cmakedefine ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
 | 
				
			||||
/* define best samplerate convertor */ | 
				
			||||
#cmakedefine ENABLE_SINC_BEST_CONVERTER | 
				
			||||
 | 
				
			||||
/* The size of `int', as computed by sizeof. */ | 
				
			||||
#define SIZEOF_INT ${SIZEOF_INT} | 
				
			||||
 | 
				
			||||
/* The size of `long', as computed by sizeof. */ | 
				
			||||
#define SIZEOF_LONG ${SIZEOF_LONG} | 
				
			||||
@ -0,0 +1,400 @@ | 
				
			||||
# Copyright (C) 2002-2021 Erik de Castro Lopo (erikd AT mega-nerd DOT com). | 
				
			||||
 | 
				
			||||
dnl Require autoconf version >= 2.69) | 
				
			||||
AC_PREREQ([2.69]) | 
				
			||||
 | 
				
			||||
AC_INIT([libsamplerate],[0.2.2],[erikd@mega-nerd.com], | 
				
			||||
		[libsamplerate],[https://github.com/libsndfile/libsamplerate/]) | 
				
			||||
 | 
				
			||||
dnl Check whether we want to set defaults for CFLAGS, CPPFLAGS and LDFLAGS | 
				
			||||
AC_MSG_CHECKING([whether configure should try to set CFLAGS/CPPFLAGS/LDFLAGS]) | 
				
			||||
AS_IF([test "x${CFLAGS+set}" = "xset" || test "x${CPPFLAGS+set}" = "xset" || test "x${LDFLAGS+set}" = "xset"], [ | 
				
			||||
		enable_flags_setting=no | 
				
			||||
		: ${CFLAGS=""} | 
				
			||||
	], [ | 
				
			||||
		enable_flags_setting=yes | 
				
			||||
		dnl Set to empty flags so AC_PROG_CC does not add -g -O2 | 
				
			||||
		CFLAGS="" | 
				
			||||
	]) | 
				
			||||
AC_MSG_RESULT([${enable_flags_setting}]) | 
				
			||||
 | 
				
			||||
dnl Put config stuff in 'build-aux'. | 
				
			||||
AC_CONFIG_AUX_DIR([build-aux]) | 
				
			||||
 | 
				
			||||
AC_CONFIG_SRCDIR([src/samplerate.c]) | 
				
			||||
AC_CANONICAL_HOST | 
				
			||||
 | 
				
			||||
AC_CONFIG_MACRO_DIR([m4]) | 
				
			||||
AC_CONFIG_HEADERS([src/config.h]) | 
				
			||||
 | 
				
			||||
AM_INIT_AUTOMAKE([1.14 foreign dist-xz no-dist-gzip subdir-objects serial-tests]) | 
				
			||||
AM_SILENT_RULES([yes]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
 | 
				
			||||
AC_PROG_CC | 
				
			||||
AC_PROG_CC_C99 | 
				
			||||
 | 
				
			||||
AS_IF([test "x$ac_cv_prog_cc_c99" = "xno"], [ | 
				
			||||
		AC_MSG_ERROR([libsamplerate requires a C99 capable compiler!]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AC_LANG([C]) | 
				
			||||
AX_COMPILER_VENDOR | 
				
			||||
AX_COMPILER_VERSION | 
				
			||||
 | 
				
			||||
AC_PROG_SED | 
				
			||||
AC_PROG_INSTALL | 
				
			||||
AC_PROG_LN_S | 
				
			||||
AC_PROG_MAKE_SET | 
				
			||||
AC_PROG_MKDIR_P | 
				
			||||
 | 
				
			||||
PKG_PROG_PKG_CONFIG | 
				
			||||
dnl Catch ancient versions of pkg-config below 0.27 | 
				
			||||
AX_REQUIRE_DEFINED([PKG_INSTALLDIR]) | 
				
			||||
PKG_INSTALLDIR | 
				
			||||
 | 
				
			||||
LT_INIT([disable-static]) | 
				
			||||
LT_PROG_RC | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Rules for library version information: | 
				
			||||
dnl | 
				
			||||
dnl   1. Start with version information of `0:0:0' for each libtool library. | 
				
			||||
dnl   2. Update the version information only immediately before a public release of | 
				
			||||
dnl      your software. More frequent updates are unnecessary, and only guarantee | 
				
			||||
dnl      that the current interface number gets larger faster. | 
				
			||||
dnl   3. If the library source code has changed at all since the last update, then | 
				
			||||
dnl      increment revision (`c:r:a' becomes `c:r+1:a'). | 
				
			||||
dnl   4. If any interfaces have been added, removed, or changed since the last update, | 
				
			||||
dnl      increment current, and set revision to 0. | 
				
			||||
dnl   5. If any interfaces have been added since the last public release, then increment | 
				
			||||
dnl      age. | 
				
			||||
dnl   6. If any interfaces have been removed since the last public release, then set age | 
				
			||||
dnl      to 0. | 
				
			||||
 | 
				
			||||
dnl   This is libtool version of library, we add it to `--version-info` property. | 
				
			||||
 | 
				
			||||
m4_define([lt_current], [2]) | 
				
			||||
m4_define([lt_revision], [2]) | 
				
			||||
m4_define([lt_age], [2]) | 
				
			||||
 | 
				
			||||
dnl This is ABI version for linker scripts, CMake uses the same format for | 
				
			||||
dnl VERSION property of shared library. | 
				
			||||
dnl The formula is: c:r:a -> c-a:a:r | 
				
			||||
 | 
				
			||||
m4_define([abi_version_major], [m4_eval(lt_current - lt_age)]) | 
				
			||||
m4_define([abi_version_minor], [lt_age]) | 
				
			||||
m4_define([abi_version_patch], [lt_revision]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
 | 
				
			||||
AC_CHECK_HEADERS([stdbool.h stdint.h sys/times.h unistd.h immintrin.h]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Couple of initializations here. Fill in real values later. | 
				
			||||
 | 
				
			||||
SHLIB_VERSION_ARG="" | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Finished checking, handle options. | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([werror], | 
				
			||||
	[AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([cpu-clip], | 
				
			||||
	[AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([sse2-lrint], | 
				
			||||
	[AS_HELP_STRING([--enable-sse2-lrint], [implement lrintf using SSE2 on x86 CPUs if possible])]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([sndfile], | 
				
			||||
	[AS_HELP_STRING([--disable-sndfile], [disable support for sndfile (default=autodetect)])], [], [enable_sndfile=auto]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([alsa], | 
				
			||||
	[AS_HELP_STRING([--disable-alsa], [disable ALSA support in the varispeed-play example program (default=autodetect)])], [], [enable_alsa=auto]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([fftw], | 
				
			||||
	[AS_HELP_STRING([--disable-fftw], [disable usage of FFTW (default=autodetect)])], [], [enable_fftw=auto]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([sinc_fast], | 
				
			||||
	[AS_HELP_STRING([--disable-sinc-fast], [disable sinc fast converter support (default=autodetect)])], [], [enable_sinc_fast=yes]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([sinc_medium], | 
				
			||||
	[AS_HELP_STRING([--disable-sinc-medium], [disable sinc balanced converter support (default=autodetect)])], [], [enable_sinc_medium=yes]) | 
				
			||||
 | 
				
			||||
AC_ARG_ENABLE([sinc_best], | 
				
			||||
	[AS_HELP_STRING([--disable-sinc-best], [disable sinc best converter support (default=autodetect)])], [], [enable_sinc_best=yes]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Check types and their sizes. | 
				
			||||
 | 
				
			||||
AC_CHECK_SIZEOF(int,0) | 
				
			||||
AC_CHECK_SIZEOF(long,0) | 
				
			||||
AC_CHECK_SIZEOF(float,4) | 
				
			||||
AC_CHECK_SIZEOF(double,8) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Determine endian-ness of host processor. | 
				
			||||
 | 
				
			||||
AC_C_BIGENDIAN([ | 
				
			||||
		dnl big-endian | 
				
			||||
		ac_cv_c_big_endian=1 | 
				
			||||
		ac_cv_c_little_endian=0 | 
				
			||||
	], [ | 
				
			||||
		dnl little-endian | 
				
			||||
		ac_cv_c_big_endian=0 | 
				
			||||
		ac_cv_c_little_endian=1 | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AC_DEFINE_UNQUOTED([CPU_IS_BIG_ENDIAN], [${ac_cv_c_big_endian}], [Host processor is big endian.]) | 
				
			||||
AC_DEFINE_UNQUOTED([CPU_IS_LITTLE_ENDIAN], [${ac_cv_c_little_endian}], [Host processor is little endian.]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Check for functions. | 
				
			||||
 | 
				
			||||
AC_CHECK_FUNCS([malloc calloc free memcpy memmove alarm signal]) | 
				
			||||
 | 
				
			||||
AS_CASE([${host_os}], | 
				
			||||
	dnl These system don't have libm, or don't need it | 
				
			||||
	dnl The list is from LT_LIB_M of libtool-2.4.6 with mingw added to it. | 
				
			||||
	[darwin*|mingw*|cygwin*|haiku*|beos*|cegcc*|pw32*],[], | 
				
			||||
	[*], [ | 
				
			||||
		AC_SEARCH_LIBS([floor], [m], [], [ | 
				
			||||
			AC_MSG_ERROR([unable to find the floor() function!]) | 
				
			||||
		]) | 
				
			||||
	]) | 
				
			||||
AC_CHECK_FUNCS([floor ceil fmod lrint lrintf]) | 
				
			||||
 | 
				
			||||
AC_CHECK_SIGNAL(SIGALRM) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Determine if the processor can do clipping on float to int conversions. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_cpu_clip" != "xno"], [ | 
				
			||||
		AC_C_CLIP_MODE | 
				
			||||
	], [ | 
				
			||||
		AS_ECHO(["checking processor clipping capabilities... disabled"]) | 
				
			||||
		ac_cv_c_clip_positive=0 | 
				
			||||
		ac_cv_c_clip_negative=0 | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AC_DEFINE_UNQUOTED([CPU_CLIPS_POSITIVE], [${ac_cv_c_clip_positive}], [Host processor clips on positive float to int conversion.]) | 
				
			||||
AC_DEFINE_UNQUOTED([CPU_CLIPS_NEGATIVE], [${ac_cv_c_clip_negative}], [Host processor clips on negative float to int conversion.]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Determine if the user enabled lrint implementations using SSE2. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_sse2_lrint" = "xyes"], [ | 
				
			||||
		CFLAGS="$CFLAGS -DENABLE_SSE2_LRINT" | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Check for libsndfile which is required for the test and example programs. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_sndfile" != "xno"], [ | 
				
			||||
		PKG_CHECK_MODULES([SNDFILE], [sndfile >= 1.0.6], [ | 
				
			||||
				AC_DEFINE([HAVE_SNDFILE], [1], [Set to 1 if you have libsndfile]) | 
				
			||||
				enable_sndfile="yes" | 
				
			||||
			], [ | 
				
			||||
				AS_IF([test "x$enable_sndfile" = "xyes"], [ | 
				
			||||
						dnl explicitly passed --enable-sndfile, hence error out loud and clearly | 
				
			||||
						AC_MSG_ERROR([You explicitly requested libsndfile support, but libsndfile could not be found!]) | 
				
			||||
					], [ | 
				
			||||
						dnl did not explicitly pass --enable-sndfile, relying on default automagic on | 
				
			||||
						enable_sndfile="no (auto)" | 
				
			||||
					]) | 
				
			||||
			]) | 
				
			||||
	]) | 
				
			||||
AM_CONDITIONAL([HAVE_LIBSNDFILE], [test "x$enable_sndfile" = "xyes"]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Check for ALSA. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_alsa" != "xno"], [ | 
				
			||||
		PKG_CHECK_MODULES([ALSA], [alsa], [ | 
				
			||||
				AC_DEFINE([HAVE_ALSA], [1], [Set to 1 if you have alsa]) | 
				
			||||
				enable_alsa="yes" | 
				
			||||
			], [ | 
				
			||||
				AS_IF([test "x$enable_alsa" = "xyes"], [ | 
				
			||||
						dnl explicitly passed --enable-alsa, hence error out loud and clearly | 
				
			||||
						AC_MSG_ERROR([You explicitly requested alsa support, but alsa could not be found!]) | 
				
			||||
					], [ | 
				
			||||
						dnl did not explicitly pass --enable-alsa, relying on default automagic on | 
				
			||||
						enable_alsa="no (auto)" | 
				
			||||
					]) | 
				
			||||
			]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Check for libfftw3 which is required for the test and example programs. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_fftw" != "xno"], [ | 
				
			||||
		PKG_CHECK_MODULES([FFTW3], [fftw3 >= 3.0.0], [ | 
				
			||||
				AC_DEFINE([HAVE_FFTW3], [1], [Set to 1 if you have fftw3]) | 
				
			||||
				enable_fftw="yes" | 
				
			||||
			], [ | 
				
			||||
				AS_IF([test "x$enable_fftw" = "xyes"], [ | 
				
			||||
						dnl explicitly passed --enable-fftw, hence error out loud and clearly | 
				
			||||
						AC_MSG_ERROR([You explicitly requested FFTW3 support, but FFTW3 could not be found!]) | 
				
			||||
					], [ | 
				
			||||
						dnl did not explicitly pass --enable-fftw, relying on default automagic on | 
				
			||||
						enable_fftw="no (auto)" | 
				
			||||
					]) | 
				
			||||
			]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Set Sinc Quality. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_sinc_fast" != "xno"], [ | 
				
			||||
		AC_DEFINE_UNQUOTED([ENABLE_SINC_FAST_CONVERTER], [${enable_sinc_fast}], [Enable sinc fast converter.]) | 
				
			||||
	], [ | 
				
			||||
		enable_sinc_fast="no" | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_sinc_medium" != "xno"], [ | 
				
			||||
		AC_DEFINE_UNQUOTED([ENABLE_SINC_MEDIUM_CONVERTER], [${enable_sinc_medium}], [Enable sinc balanced converter.]) | 
				
			||||
	], [ | 
				
			||||
		enable_sinc_medium="no" | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_sinc_best" != "xno"], [ | 
				
			||||
		AC_DEFINE_UNQUOTED([ENABLE_SINC_BEST_CONVERTER], [${enable_sinc_best}], [Enable sinc best converter.]) | 
				
			||||
	], [ | 
				
			||||
		enable_sinc_best="no" | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Compiler stuff. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_flags_setting" = "xyes"], [ | 
				
			||||
		AX_APPEND_COMPILE_FLAGS([-DHAVE_CONFIG_H -O2 -pipe -DNDEBUG], [CFLAGS]) | 
				
			||||
 | 
				
			||||
		AS_CASE([${host_os}], | 
				
			||||
			[darwin*], [ | 
				
			||||
				ldflags_test="-Wl,-dead_strip_dylibs"], | 
				
			||||
			[linux*], [ | 
				
			||||
				ldflags_test="-Wl,-O1 -Wl,--as-needed -Wl,--no-undefined -Wl,--gc-sections"] | 
				
			||||
			) | 
				
			||||
		AX_APPEND_LINK_FLAGS([${ldflags_test}], [LDFLAGS]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Exported symbols control. | 
				
			||||
 | 
				
			||||
saved_CFLAGS="$CFLAGS" | 
				
			||||
CFLAGS="$CFLAGS -fvisibility=hidden -Werror" | 
				
			||||
AC_MSG_CHECKING([if compiler supports visibility attributes]) | 
				
			||||
AC_LANG_PUSH([C]) | 
				
			||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ | 
				
			||||
		__attribute__((visibility("default"))) int foo(void); | 
				
			||||
		__attribute__((visibility("hidden")))  int bar(void); | 
				
			||||
		int foo(void) { return 0; } | 
				
			||||
		int bar(void) { return 1; }]], [])], | 
				
			||||
	[have_visibility=yes],[have_visibility=no]) | 
				
			||||
AC_LANG_POP([C]) | 
				
			||||
AC_MSG_RESULT([$have_visibility]) | 
				
			||||
CFLAGS="$saved_CFLAGS" | 
				
			||||
AS_IF([test "x$have_visibility" = "xyes"], [ | 
				
			||||
		AC_DEFINE([HAVE_VISIBILITY], [1], [Define to 1 if the compiler supports simple visibility declarations.]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AS_IF([test "x$lt_cv_prog_gnu_ld" = "xyes"], [ | 
				
			||||
		AS_CASE([${host_os}], | 
				
			||||
			[mingw*|cygwin*], [ | 
				
			||||
				SHLIB_VERSION_ARG="-export-symbols \$(top_srcdir)/Win32/libsamplerate-0.def"], | 
				
			||||
			[*], [ | 
				
			||||
				SHLIB_VERSION_ARG="-Wl,--version-script=\$(top_builddir)/src/Version_script" | 
				
			||||
			]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Warning flags. | 
				
			||||
 | 
				
			||||
AS_IF([test "x$enable_werror" = "xyes"], [ | 
				
			||||
		AX_APPEND_COMPILE_FLAGS([-Werror], [CFLAGS]) | 
				
			||||
	]) | 
				
			||||
 | 
				
			||||
AX_APPEND_COMPILE_FLAGS([-W -Wstrict-prototypes -Wmissing-prototypes -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wpointer-arith], [CFLAGS]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Set OS-specific audio-out flags. | 
				
			||||
 | 
				
			||||
AUDIO_CFLAGS="" | 
				
			||||
AUDIO_LIBS="" | 
				
			||||
 | 
				
			||||
AS_CASE([${host_os}], | 
				
			||||
	[darwin*], [dnl this requires 10.5+ | 
				
			||||
		AUDIO_LIBS="-framework CoreAudio"], | 
				
			||||
	[mingw32*], [ | 
				
			||||
		AUDIO_LIBS="-lwinmm"], | 
				
			||||
	[linux*], [dnl have OSS as fallback if no ALSA | 
				
			||||
		AS_IF([test "x$enable_alsa" = "xyes"], [ | 
				
			||||
			AUDIO_LIBS="$ALSA_LIBS" | 
				
			||||
			AUDIO_CFLAGS="$ALSA_CFLAGS"])], | 
				
			||||
	[]) | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
dnl  Now use the information from the checking stage. | 
				
			||||
 | 
				
			||||
AC_SUBST(SHLIB_VERSION_ARG) | 
				
			||||
AC_SUBST([SHARED_VERSION_INFO], [lt_current:lt_revision:lt_age]) | 
				
			||||
AC_SUBST(AUDIO_CFLAGS) | 
				
			||||
AC_SUBST(AUDIO_LIBS) | 
				
			||||
 | 
				
			||||
AC_CONFIG_FILES([ | 
				
			||||
		Makefile | 
				
			||||
		src/Version_script | 
				
			||||
		libsamplerate.spec | 
				
			||||
		samplerate.pc | 
				
			||||
	]) | 
				
			||||
AC_OUTPUT | 
				
			||||
 | 
				
			||||
dnl ==================================================================================== | 
				
			||||
 | 
				
			||||
AX_RECURSIVE_EVAL([$libdir], [full_absolute_libdir]) | 
				
			||||
AX_RECURSIVE_EVAL([$bindir], [full_absolute_bindir]) | 
				
			||||
AX_RECURSIVE_EVAL([$pkgconfigdir], [full_absolute_pkgconfigdir]) | 
				
			||||
AX_RECURSIVE_EVAL([$htmldir], [full_absolute_htmldir]) | 
				
			||||
AC_MSG_RESULT([ | 
				
			||||
-=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-=- | 
				
			||||
 | 
				
			||||
  Configuration summary : | 
				
			||||
 | 
				
			||||
    libsamplerate version : ............... ${VERSION} | 
				
			||||
 | 
				
			||||
    Host CPU : ............................ ${host_cpu} | 
				
			||||
    Host Vendor : ......................... ${host_vendor} | 
				
			||||
    Host OS : ............................. ${host_os} | 
				
			||||
 | 
				
			||||
    CFLAGS : .............................. ${CFLAGS} | 
				
			||||
    CPPFLAGS : ............................ ${CPPFLAGS} | 
				
			||||
    LDFLAGS : ............................. ${LDFLAGS} | 
				
			||||
 | 
				
			||||
  Tools : | 
				
			||||
 | 
				
			||||
    C Compiler Vendor is : ................ ${ax_cv_c_compiler_vendor} (${ax_cv_c_compiler_version}) | 
				
			||||
 | 
				
			||||
  Extra tools required for testing and examples : | 
				
			||||
 | 
				
			||||
    Have libsndfile : ..................... ${enable_sndfile} | 
				
			||||
    Have ALSA : ........................... ${enable_alsa} | 
				
			||||
    Have FFTW : ........................... ${enable_fftw} | 
				
			||||
 | 
				
			||||
  Converter configuration : | 
				
			||||
    Sinc fast : ........................... ${enable_sinc_fast} | 
				
			||||
    Sinc balanced : ....................... ${enable_sinc_medium} | 
				
			||||
    Sinc best : ........................... ${enable_sinc_best} | 
				
			||||
 | 
				
			||||
  Installation directories : | 
				
			||||
 | 
				
			||||
    Library directory : ................... ${full_absolute_libdir} | 
				
			||||
    Program directory : ................... ${full_absolute_bindir} | 
				
			||||
    Pkgconfig directory : ................. ${full_absolute_pkgconfigdir} | 
				
			||||
    HTML docs directory : ................. ${full_absolute_htmldir} | 
				
			||||
 | 
				
			||||
Compiling some other packages against libsamplerate may require | 
				
			||||
the addition of '$full_absolute_pkgconfigdir' to the | 
				
			||||
PKG_CONFIG_PATH environment variable. | 
				
			||||
]) | 
				
			||||
@ -0,0 +1,19 @@ | 
				
			||||
install( | 
				
			||||
  FILES  | 
				
			||||
    api.md | 
				
			||||
    api_callback.md | 
				
			||||
    api_full.md | 
				
			||||
    api_misc.md | 
				
			||||
    api_simple.md | 
				
			||||
    bugs.md | 
				
			||||
    download.md | 
				
			||||
    faq.md | 
				
			||||
    history.md | 
				
			||||
    index.md | 
				
			||||
    license.md | 
				
			||||
    lists.md | 
				
			||||
    quality.md | 
				
			||||
    win32.md | 
				
			||||
    SRC.png | 
				
			||||
  DESTINATION | 
				
			||||
    ${CMAKE_INSTALL_DOCDIR}) | 
				
			||||
@ -0,0 +1,56 @@ | 
				
			||||
a:link { | 
				
			||||
  color: #FB1465; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
a:active, a:visited { | 
				
			||||
  color: #FB1465; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
body { | 
				
			||||
  background: black; | 
				
			||||
  color: white; | 
				
			||||
  font-family: arial, helvetica, sans-serif; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
h1, h2, h3, h4, h5, h6 { | 
				
			||||
  color: #FB1465; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
code, kbd, samp, var { | 
				
			||||
  font-family: courier, monospace; | 
				
			||||
  font-size: 1em; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
main { | 
				
			||||
  padding-left: 3%; | 
				
			||||
  padding-right: 3%; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
pre { | 
				
			||||
  font-family: courier, monospace; | 
				
			||||
  font-size: 1em; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
.image-logo { | 
				
			||||
  display: block; | 
				
			||||
  margin-left: auto; | 
				
			||||
  margin-right: auto; | 
				
			||||
  margin-bottom: 1em; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
.indent_block { | 
				
			||||
  margin-left: 10%; | 
				
			||||
  margin-right: 10%; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
.nf { | 
				
			||||
  font-weight: bold; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
.container { | 
				
			||||
  display: flex; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
.content { | 
				
			||||
  flex: 1; | 
				
			||||
} | 
				
			||||
| 
		 After Width: | Height: | Size: 22 KiB  | 
@ -0,0 +1,8 @@ | 
				
			||||
--- | 
				
			||||
author: Erik de Castro Lopo, erikd@mega-nerd.com | 
				
			||||
description: An audio Sample Rate Conversion library | 
				
			||||
keywords: libsamplerate, sound, resample, audio, dsp, Linux | 
				
			||||
version: 0.2.1 | 
				
			||||
 | 
				
			||||
markdown: kramdown | 
				
			||||
--- | 
				
			||||
@ -0,0 +1,49 @@ | 
				
			||||
<!DOCTYPE html"> | 
				
			||||
<html lang="en"> | 
				
			||||
 | 
				
			||||
<head> | 
				
			||||
  <meta charset="utf-8"> | 
				
			||||
  <meta name="viewport" content="width=device-width, initial-scale=1.0"> | 
				
			||||
  <meta name="description" content="{{ site.description | page.description }}"> | 
				
			||||
  <meta name="keywords" content="{{ site.keywords | page.keywords }}"> | 
				
			||||
  <title>{{ page.title }}</title> | 
				
			||||
  <link rel="stylesheet" href="SRC.css" type="text/css" media="all"> | 
				
			||||
</HEAD> | 
				
			||||
 | 
				
			||||
<body> | 
				
			||||
  <footer> | 
				
			||||
    <img src="SRC.png" class="image-logo" height=100 width=760 alt="SRC.png"> | 
				
			||||
  </footer> | 
				
			||||
  <div class="container"> | 
				
			||||
    <div class="navbar"> | 
				
			||||
      <nav> | 
				
			||||
        <a href="index.html">Home</a><br> | 
				
			||||
        <a href="license.html">License</a><br> | 
				
			||||
        <a href="history.html">History</a><br> | 
				
			||||
        <a href="download.html">Download</a><br> | 
				
			||||
        <a href="quality.html">Quality</a><br> | 
				
			||||
        <a href="api.html">API</a><br> | 
				
			||||
        <a href="bugs.html">Bug Reporting</a><br> | 
				
			||||
        <a href="win32.html">On Win32</a><br> | 
				
			||||
        <a href="faq.html">FAQ</a><br> | 
				
			||||
        <a href="lists.html">Mailing Lists</a><br> | 
				
			||||
        <a href="https://github.com/libsndfile/libsamplerate/blob/master/ChangeLog">ChangeLog</a><br> | 
				
			||||
      </nav> | 
				
			||||
      <div class="block"> | 
				
			||||
        <p>Author:<br> Erik de Castro Lopo</p> | 
				
			||||
      </div> | 
				
			||||
    </div> | 
				
			||||
    <div class="content"> | 
				
			||||
      <main> | 
				
			||||
        <article> | 
				
			||||
 | 
				
			||||
          {{ content }} | 
				
			||||
 | 
				
			||||
        </article> | 
				
			||||
      </main> | 
				
			||||
    </div> | 
				
			||||
  </div> | 
				
			||||
 | 
				
			||||
</body> | 
				
			||||
 | 
				
			||||
</html> | 
				
			||||
@ -0,0 +1,46 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Applications Programming Interface | 
				
			||||
 | 
				
			||||
The publically callable functions of libsamplerate are all listed in the | 
				
			||||
**\<samplerate.h\>** header file. In order to use any of the functionality of | 
				
			||||
libsamplerate, you need to add | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
#include <samplerate.h> | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
to the top of any function that call any of the following functions. You will | 
				
			||||
also need to link you binary with the libsamplerate library. | 
				
			||||
 | 
				
			||||
The API allows three methods for accessing the capabilities of the library: | 
				
			||||
 | 
				
			||||
- A [simple interface](api_simple.md) which can sample rate convert a single | 
				
			||||
  block of samples (one or more channels) in one go. The simple API is less | 
				
			||||
  capable than the full API. | 
				
			||||
- A [more fully featured interface](api_full.md) which allows time varying | 
				
			||||
  sample rate conversion on streaming data (again one or more channels). | 
				
			||||
- A [callback interface](api_callback.md) which has the same functionality as | 
				
			||||
  the interface above but allows the details of input and output to be | 
				
			||||
  separated. The output is generated by call a read function and the library | 
				
			||||
  calls a user supplied callback function to obtain its input. This interface is | 
				
			||||
  particularly well suited to applications where the output sample rate is | 
				
			||||
  varied with time. | 
				
			||||
 | 
				
			||||
**NB :** All three access methods are able to process multi channel interleaved | 
				
			||||
data. | 
				
			||||
 | 
				
			||||
The parts of the API which are common to all three interfaces are: | 
				
			||||
 | 
				
			||||
- The [error reporting](api_misc.md#error-reporting) mechanisim. | 
				
			||||
- The available [converter](api_misc.md#converters) types. | 
				
			||||
- The [SRC_DATA](api_misc.md#src_data) struct. | 
				
			||||
 | 
				
			||||
All three versions of the API are restricted to operating on buffers of ISO C | 
				
			||||
Standard **float** data. However, there are two [auxiliary functions](api_misc.md#auxiliary-functions) | 
				
			||||
for converting arrays of float data to and from short data. | 
				
			||||
 | 
				
			||||
**Note:** The **tests/** and **examples/** directories of the source code | 
				
			||||
distribution contain numerous example programs showing the use of the library. | 
				
			||||
@ -0,0 +1,88 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Callback API | 
				
			||||
 | 
				
			||||
The callback API consists of the following functions : | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
typedef long (*src_callback_t) (void *cb_data, float **data) ; | 
				
			||||
 | 
				
			||||
SRC_STATE* src_callback_new (src_callback_t func, | 
				
			||||
                    int converter_type, int channels, | 
				
			||||
                    int *error, void* cb_data) ; | 
				
			||||
 | 
				
			||||
SRC_STATE* src_delete (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
long src_callback_read (SRC_STATE *state, double src_ratio, | 
				
			||||
                    long frames, float *data) ; | 
				
			||||
 | 
				
			||||
int src_reset (SRC_STATE *state) ; | 
				
			||||
int src_set_ratio (SRC_STATE *state, double new_ratio) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
Like the [simple API](api_simple.md) and the [full API](api_full.md), the | 
				
			||||
callback based API is able to operate on interleaved multi channel data. | 
				
			||||
 | 
				
			||||
An example of the use of the callback based API can be found in the | 
				
			||||
**varispeed-play** program in the **examples/** directory of the source code | 
				
			||||
tarball. | 
				
			||||
 | 
				
			||||
## Initialisation | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
SRC_STATE* src_callback_new (src_callback_t func, | 
				
			||||
                    int converter_type, int channels, | 
				
			||||
                    int *error, void* cb_data) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src_callback_new** function returns an anonymous pointer to a sample rate | 
				
			||||
converter callback object, src_state. This is the same type of object as that | 
				
			||||
returned by [src\_new](api_full.md#initialisation), but with different internal | 
				
			||||
state. Although these are the same object type, they cannot be used | 
				
			||||
interchangeably. If an error occurs the function returns a NULL pointer and | 
				
			||||
fills in the error value pointed to by the **error** pointer supplied by the | 
				
			||||
caller. | 
				
			||||
 | 
				
			||||
The caller then passes the SRC_STATE object to the **src_callback_read** | 
				
			||||
function to pull data out of the converter. When the caller is finished with the | 
				
			||||
converter they should pass it to the clean up function [src_delete](api_full.md#cleanup). | 
				
			||||
 | 
				
			||||
The **func** parameter is a user supplied function which must match the | 
				
			||||
**src_callback_t** type signature while **cb_data** is a pointer to data which | 
				
			||||
be passed as the first parameter to the user supplied callback function. This | 
				
			||||
function is called by the converter whenever it needs input data as a result of | 
				
			||||
being calls to **src_callback_read**. | 
				
			||||
 | 
				
			||||
If the converter was initialised to work with more than one channel, the | 
				
			||||
callback function must work with mutiple channels of interleaved data. The | 
				
			||||
callback function should return the number of frames it supplying to the | 
				
			||||
converter. For multi channel files, this return value should be the number of | 
				
			||||
floats divided by the number of channels. | 
				
			||||
 | 
				
			||||
The converter must be one of the supplied converter types documented [here](api_misc.md#converters). | 
				
			||||
 | 
				
			||||
The caller then passes the SRC_STATE pointer to the **src_callback_read** | 
				
			||||
function to pull data out of the converter. | 
				
			||||
 | 
				
			||||
## Callback Read | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
long src_callback_read (SRC_STATE *state, double src_ratio, | 
				
			||||
                    long frames, float *data) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src_callback_read** function is passed the [**SRC_STATE**](api_misc.md#src_data) | 
				
			||||
pointer returned by **src_callback_new**, the coversion ratio | 
				
			||||
(output_sample_rate / input_sample_rate), the maximum number of output frames to | 
				
			||||
generate and a pointer to a buffer in which to place the output data. For multi | 
				
			||||
channel files, the data int the output buffer is stored in interleaved format. | 
				
			||||
 | 
				
			||||
The **src_callback_read** function returns the number of frames generated or | 
				
			||||
zero if an error occurs or it runs out of input (ie the user supplied callback | 
				
			||||
function returns zero and there is no more data buffered internally). If an | 
				
			||||
error has occurred, the function [src_error](api_misc.md#error-reporting) | 
				
			||||
will return non-zero. | 
				
			||||
 | 
				
			||||
See also : [**src_set_ratio**](api_full.md#set-ratio) | 
				
			||||
@ -0,0 +1,146 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Full API | 
				
			||||
 | 
				
			||||
The full API consists of the following functions : | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
SRC_STATE* src_new (int converter_type, int channels, int *error) ; | 
				
			||||
SRC_STATE* src_delete (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
int src_process (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
int src_reset (SRC_STATE *state) ; | 
				
			||||
int src_set_ratio (SRC_STATE *state, double new_ratio) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
## Initialisation | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
SRC_STATE* src_new (int converter_type, int channels, int *error) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src\_new** function returns an anonymous pointer to a sample rate | 
				
			||||
converter object, src\_state. If an error occurs the function returns a | 
				
			||||
NULL pointer and fills in the error value pointed to by the **error** | 
				
			||||
pointer supplied by the caller. The converter must be one of the | 
				
			||||
supplied converter types documented [here](api_misc.md#converters). | 
				
			||||
 | 
				
			||||
## Cleanup | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
SRC_STATE* src_delete (SRC_STATE *state) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src\_delete** function frees up all memory allocated for the given | 
				
			||||
sample rate converter object and returns a NULL pointer. The caller is | 
				
			||||
responsible for freeing any memory passed to the sample rate converter | 
				
			||||
via the pointer to the **SRC\_DATA** struct. | 
				
			||||
 | 
				
			||||
## Process | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
int src_process (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src\_process** function processes the data provided by the caller | 
				
			||||
in an **SRC\_DATA** struct using the sample rate converter object | 
				
			||||
specified by the **SRC\_STATE** pointer. When operating on streaming | 
				
			||||
data, this function can be called over and over again, with each new | 
				
			||||
call providing new input data and returning new output data. | 
				
			||||
 | 
				
			||||
The **SRC\_DATA** struct passed as the second parameter to the | 
				
			||||
**src\_process** function has the following fields: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
typedef struct | 
				
			||||
{   const float  *data_in; | 
				
			||||
    float *data_out; | 
				
			||||
 | 
				
			||||
    long   input_frames, output_frames ; | 
				
			||||
    long   input_frames_used, output_frames_gen ; | 
				
			||||
 | 
				
			||||
    int    end_of_input ; | 
				
			||||
 | 
				
			||||
    double src_ratio ; | 
				
			||||
} SRC_DATA ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The fields of this struct which must be filled in by the caller are: | 
				
			||||
 | 
				
			||||
data_in | 
				
			||||
: A pointer to the input data samples. | 
				
			||||
 | 
				
			||||
input_frames | 
				
			||||
: The number of frames of data pointed to by data_in. | 
				
			||||
 | 
				
			||||
data_out | 
				
			||||
: A pointer to the output data samples. | 
				
			||||
 | 
				
			||||
output_frames | 
				
			||||
: Maximum number of frames pointer to by data_out. | 
				
			||||
 | 
				
			||||
src_ratio | 
				
			||||
: Equal to output_sample_rate / input_sample_rate. | 
				
			||||
 | 
				
			||||
end_of_input | 
				
			||||
: Equal to 0 if more input data is available and 1 otherwise. | 
				
			||||
 | 
				
			||||
Note that the data\_in and data\_out arrays may not overlap. If they do, | 
				
			||||
the library will return an error code. | 
				
			||||
 | 
				
			||||
When the **src\_process** function returns **output\_frames\_gen** will | 
				
			||||
be set to the number of output frames generated and | 
				
			||||
**input\_frames\_used** will be set to the number of input frames | 
				
			||||
consumed to generate the provided number of output frames. | 
				
			||||
 | 
				
			||||
The **src\_process** function returns non-zero if an error occurs. The | 
				
			||||
non-zero error return value can be decoded into a text string using the | 
				
			||||
function documented [here](api_misc.md#error-reporting). | 
				
			||||
 | 
				
			||||
## Reset | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
int src_reset (SRC_STATE *state) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src\_reset** function resets the internal state of the sample rate | 
				
			||||
converter object to the same state it had immediately after its creation | 
				
			||||
using **src\_new**. This should be called whenever a sample rate | 
				
			||||
converter is to be used on two separate, unrelated pieces of audio. | 
				
			||||
 | 
				
			||||
## Clone | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
SRC_STATE* src_clone (SRC_STATE *state, int *error) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **src_clone** function creates a copy of the internal state of the sample | 
				
			||||
rate converter object. The output of the next call to **src\_process** will be | 
				
			||||
identical for both the original and cloned state (given the same **SRC_DATA** | 
				
			||||
input). This could be used to later resume sample rate conversion at a specific | 
				
			||||
location in a stream with the same state, which may be useful in real-time | 
				
			||||
applications. | 
				
			||||
 | 
				
			||||
If an error occurs the function returns a NULL pointer and fills in the | 
				
			||||
error value pointed to by the **error** pointer supplied by the caller. | 
				
			||||
 | 
				
			||||
## Set Ratio | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
int src_set_ratio (SRC_STATE *state, double new_ratio) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
When using the **src_process** or **src_callback_process** APIs and updating the | 
				
			||||
**src_ratio** field of the **SRC_STATE** struct, the library will try to | 
				
			||||
smoothly transition between the conversion ratio of the last call and the | 
				
			||||
conversion ratio of the current call. | 
				
			||||
 | 
				
			||||
If the user wants to bypass this smooth transition and achieve a step response in | 
				
			||||
the conversion ratio, the **src_set_ratio** function can be used to set the | 
				
			||||
starting conversion ratio of the next call to **src_process** or | 
				
			||||
**src_callback_process**. | 
				
			||||
 | 
				
			||||
This function returns non-zero on error and the error return value can be | 
				
			||||
decoded into a text string using the function documented [here](api_misc.md#error-reporting). | 
				
			||||
@ -0,0 +1,145 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Miscellaneous API Documentation | 
				
			||||
 | 
				
			||||
## Error Reporting | 
				
			||||
 | 
				
			||||
Most of the API functions either return an integer error (ie **src_simple** and | 
				
			||||
**src_process**) or return an integer error value via an int pointer parameter | 
				
			||||
(**src_new**). These integer error values can be converted into human-readable | 
				
			||||
text strings by calling the function: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
const char* src_strerror (int error) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
which will return an error string for valid error numbers, the string | 
				
			||||
\"No Error\" for an error value of zero or a NULL pointer if no error message | 
				
			||||
has been defined for that error value. | 
				
			||||
 | 
				
			||||
## Converters | 
				
			||||
 | 
				
			||||
Secret Rabbit Code has a number of different converters which can be selected | 
				
			||||
using the **converter_type** parameter when calling **src_simple** or | 
				
			||||
**src_new**. Currently, the five converters available are: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
enum | 
				
			||||
{ | 
				
			||||
    SRC_SINC_BEST_QUALITY       = 0, | 
				
			||||
    SRC_SINC_MEDIUM_QUALITY     = 1, | 
				
			||||
    SRC_SINC_FASTEST            = 2, | 
				
			||||
    SRC_ZERO_ORDER_HOLD         = 3, | 
				
			||||
    SRC_LINEAR                  = 4 | 
				
			||||
} ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
As new converters are added, they will be given a number corresponding to the next | 
				
			||||
integer. | 
				
			||||
 | 
				
			||||
The details of these converters are as follows: | 
				
			||||
 | 
				
			||||
- **SRC_SINC_BEST_QUALITY** - This is a bandlimited interpolator derived from | 
				
			||||
  the mathematical **sinc** function and this is the highest quality sinc based | 
				
			||||
  converter, providing a worst case Signal-to-Noise Ratio (SNR) of 97 decibels | 
				
			||||
  (dB) at a bandwidth of 97%. All three SRC_SINC_* converters are based on the | 
				
			||||
  techniques of [Julius O. Smith](http://ccrma.stanford.edu/~jos/resample/) | 
				
			||||
  although this code was developed independently. | 
				
			||||
- **SRC_SINC_MEDIUM_QUALITY** - This is another bandlimited interpolator much | 
				
			||||
  like the previous one. It has an SNR of 97dB and a bandwidth of 90%. The speed | 
				
			||||
  of the conversion is much faster than the previous one. | 
				
			||||
- **SRC_SINC_FASTEST** - This is the fastest bandlimited interpolator and has an | 
				
			||||
  SNR of 97dB and a bandwidth of 80%. | 
				
			||||
- **SRC_ZERO_ORDER_HOLD** - A Zero Order Hold converter (interpolated value is | 
				
			||||
  equal to the last value). The quality is poor but the conversion speed is | 
				
			||||
  blindlingly fast. Be aware that this interpolator is not bandlimited, and the  | 
				
			||||
  user is responsible for adding anti-aliasing filtering.  | 
				
			||||
- **SRC_LINEAR** - A linear converter. Again the quality is poor, but the | 
				
			||||
  conversion speed is blindingly fast. This interpolator is also not bandlimited,  | 
				
			||||
  and the user is responsible for adding anti-aliasing filtering. | 
				
			||||
 | 
				
			||||
There are two functions that give either a (text string) name or description for | 
				
			||||
each converter: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
const char *src_get_name (int converter_type) ; | 
				
			||||
const char *src_get_description (int converter_type) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The name will typically be a short string for use in a dialog box, while the | 
				
			||||
description string is longer. | 
				
			||||
 | 
				
			||||
Both of these functions return a NULL pointer if there is no converter for the | 
				
			||||
given **converter_type** value. Since the converters have consecutive | 
				
			||||
**converter_type** values, the caller is easily able to figure out the number of | 
				
			||||
converters at run time. This enables a binary dynamically linked against an old | 
				
			||||
version of the library to know about converters from later versions of the | 
				
			||||
library as they become available. | 
				
			||||
 | 
				
			||||
## SRC_DATA | 
				
			||||
 | 
				
			||||
Both the simple and the full featured versions of the API use the **SRC_DATA** | 
				
			||||
struct to pass audio and control data into the sample rate converter. This | 
				
			||||
struct is defined as: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
typedef struct | 
				
			||||
{   const float  *data_in; | 
				
			||||
    float *data_out ; | 
				
			||||
 | 
				
			||||
    long   input_frames, output_frames ; | 
				
			||||
    long   input_frames_used, output_frames_gen ; | 
				
			||||
 | 
				
			||||
    int    end_of_input ; | 
				
			||||
 | 
				
			||||
    double src_ratio ; | 
				
			||||
} SRC_DATA ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The **data_in** pointer is used to pass audio data into the converter while the | 
				
			||||
**data_out** pointer supplies the converter with an array to hold the | 
				
			||||
converter's output. For a converter which has been configured for multichannel | 
				
			||||
operation, these pointers need to point to a single array of interleaved data. | 
				
			||||
 | 
				
			||||
The **input_frames** and **output_frames** fields supply the converter with the | 
				
			||||
lengths of the arrays (in frames) pointed to by the **data_in** and **data_out** | 
				
			||||
pointers respectively. For monophonic data, these values would indicate the | 
				
			||||
length of the arrays while for multi channel data these values would be equal to | 
				
			||||
the length of the array divided by the number of channels. | 
				
			||||
 | 
				
			||||
The **end_of_input** field is only used when the sample rate converter is used | 
				
			||||
by calling the **src_process** function. In this case it should be set to zero | 
				
			||||
if more buffers are to be passed to the converter and 1 if the current buffer is | 
				
			||||
the last. | 
				
			||||
 | 
				
			||||
Finally, the **src_ratio** field specifies the conversion ratio defined as the | 
				
			||||
output sample rate divided by the input sample rate. For a connected set of | 
				
			||||
buffers, this value can vary on each call to **src_process** resulting in a | 
				
			||||
time varying sample rate conversion process. For time varying sample rate | 
				
			||||
conversions, the ratio will be linearly interpolated between the **src_ratio** | 
				
			||||
value of the previous call to **src_process** and the value for the current | 
				
			||||
call. | 
				
			||||
 | 
				
			||||
The **input_frames_used** and **output_frames_gen** fields are set by the | 
				
			||||
converter to inform the caller of the number of frames consumed from the | 
				
			||||
**data_in** array and the number of frames generated in the **data_out** array | 
				
			||||
respectively. These values are for the current call to **src_process** only. | 
				
			||||
 | 
				
			||||
## Auxiliary Functions | 
				
			||||
 | 
				
			||||
There are four auxiliary functions for converting arrays of float data to and | 
				
			||||
from short or int data. These functions are defined as: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
void src_short_to_float_array (const short *in, float *out, int len) ; | 
				
			||||
void src_float_to_short_array (const float *in, short *out, int len) ; | 
				
			||||
void src_int_to_float_array (const int *in, float *out, int len) ; | 
				
			||||
void src_float_to_int_array (const float *in, int *out, int len) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The float data is assumed to be in the range [-1.0, 1.0] and it is automatically | 
				
			||||
scaled on the conversion to and from float. On the float to short/int conversion | 
				
			||||
path, any data values which would overflow the range of short/int data are | 
				
			||||
clipped. | 
				
			||||
@ -0,0 +1,71 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Simple API | 
				
			||||
 | 
				
			||||
**Important Note:** The simple API is not designed to work on small chunks of a | 
				
			||||
larger piece of audio. If you attempt to use it this way you are doing it wrong | 
				
			||||
and will not get the results you want. For processing audio data in chunks you | 
				
			||||
**must** use the [full api](api_full.md) or the [callback based api](api_callback.md). | 
				
			||||
 | 
				
			||||
The simple API consists of a single function: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
int src_simple (SRC_DATA *data, int converter_type, int channels) ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The use of this function rather than the more fully featured API requires the | 
				
			||||
caller to know the total length of the input data before hand and that all input | 
				
			||||
and output data can be held in the system's memory at once. It also assumes that | 
				
			||||
there is a single constant ratio between input and output sample rates. | 
				
			||||
 | 
				
			||||
Dealing with the easy stuff first, the **converter_type** parameter should be | 
				
			||||
one of the values defined in **samplerate.h** and documented [here](api_misc.md#converters) | 
				
			||||
while the **channels** parameter specifies the number of interleaved channels | 
				
			||||
that the sample rate converter is being asked to process (number of input | 
				
			||||
channels and output channels is always equal). There is no hard upper limit on | 
				
			||||
the number of channels; it is limited purely by the amount of memory available. | 
				
			||||
 | 
				
			||||
The first parameter to **src_simple** is a pointer to an **SRC_DATA** struct | 
				
			||||
(more info [here](api_misc.md#src_data)) defined as follows: | 
				
			||||
 | 
				
			||||
```c | 
				
			||||
typedef struct | 
				
			||||
{   const float  *data_in; | 
				
			||||
    float *data_out ; | 
				
			||||
 | 
				
			||||
    long   input_frames, output_frames ; | 
				
			||||
    long   input_frames_used, output_frames_gen ; | 
				
			||||
 | 
				
			||||
    int    end_of_input ; | 
				
			||||
 | 
				
			||||
    double src_ratio ; | 
				
			||||
} SRC_DATA ; | 
				
			||||
``` | 
				
			||||
 | 
				
			||||
The fields of this struct which must be filled in by the caller are: | 
				
			||||
 | 
				
			||||
data_in | 
				
			||||
: A pointer to the input data samples. | 
				
			||||
 | 
				
			||||
input_frames | 
				
			||||
: The number of frames of data pointed to by data_in. | 
				
			||||
 | 
				
			||||
data_out | 
				
			||||
: A pointer to the output data samples. | 
				
			||||
 | 
				
			||||
output_frames | 
				
			||||
: Maximum number of frames pointer to by data_out. | 
				
			||||
 | 
				
			||||
src_ratio | 
				
			||||
: Equal to output_sample_rate / input_sample_rate. | 
				
			||||
 | 
				
			||||
When the **src_simple** function returns **output_frames_gen** will be set to | 
				
			||||
the number of output frames generated and **input_frames_used** will be set to | 
				
			||||
the number of input frames used to generate the provided number of output | 
				
			||||
frames. | 
				
			||||
 | 
				
			||||
The **src_simple** function returns a non-zero value when an error occurs. See | 
				
			||||
[here](api_misc.md#error-reporting) for how to convert the error value into a | 
				
			||||
text string. | 
				
			||||
@ -0,0 +1,37 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Bug Reporting | 
				
			||||
 | 
				
			||||
If you are a user and have a problem using libsamplerate with another piece of | 
				
			||||
software, you should contact the author of that other software and get them to | 
				
			||||
explore their use of this library and possibly submit a bug report. If you are a | 
				
			||||
coder and think you have found a bug in libsamplerate then read on. | 
				
			||||
 | 
				
			||||
Secret Rabbit Code is an extremely complex piece of code but I do think that it | 
				
			||||
is relatively bug free. In addition, the source code distribution includes a | 
				
			||||
comprehensive test suite for regression testing. This means it is extremely | 
				
			||||
unlikely that new bugs creep in when modifications are made to the code. | 
				
			||||
 | 
				
			||||
SRC is also not the most simple library to use which means that I do get a | 
				
			||||
number of bug reports which turn out to be bugs in the user's program rather | 
				
			||||
than bugs in SRC. Up until now, I have investigated each bug report as | 
				
			||||
thoroughly as possible. Unfortunately, this chews up a lot of my time which | 
				
			||||
could otherwise be spent improving SRC, working on other Free Software or | 
				
			||||
spending time with my family. | 
				
			||||
 | 
				
			||||
I have therefore decided, that I cannot investigate any bug report unless the | 
				
			||||
person reporting the problem can supply me with a short self contained test | 
				
			||||
program or a modification to one of the existing test programs in the tests/ | 
				
			||||
directory of the source code distribution. The test program should meet the | 
				
			||||
following criteria: | 
				
			||||
 | 
				
			||||
- Written in C or C++. | 
				
			||||
- Does not use any libraries or header files other than the ones which are | 
				
			||||
  standard for the relevant languages. (Of course libsamplerate can be used :-)). | 
				
			||||
- It is the minimal program which can adequately display the problem. | 
				
			||||
- It clearly displays the criteria for pass or fail. | 
				
			||||
 | 
				
			||||
Supplying a good test program will maximize the speed with which your bug report | 
				
			||||
gets dealt with. | 
				
			||||
@ -0,0 +1,15 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Download | 
				
			||||
 | 
				
			||||
The latest version of Secret Rabbit Code is {{ site.version }}. | 
				
			||||
 | 
				
			||||
Download it on [GitHub releases page](https://github.com/libsndfile/libsamplerate/releases/latest). | 
				
			||||
 | 
				
			||||
Compiling libsamplerate is relatively easy. The INSTALL file in the top level | 
				
			||||
directory gives instructions on compiling and installing libsamplerate on | 
				
			||||
Unix-like systems (including MacOSX). For Win32 there are instructions in the | 
				
			||||
docs/ directory of the tarball. These instructions are mirrored | 
				
			||||
[here](win32.md). | 
				
			||||
@ -0,0 +1,193 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Frequently Asked Questions | 
				
			||||
 | 
				
			||||
1. [Q1 : Is it normal for the output of libsamplerate to be louder than its input?](#Q001) | 
				
			||||
2. [Q2 : On Unix/Linux/MacOSX, what is the best way of detecting the presence and location of libsamplerate and its header file using autoconf?](#Q002) | 
				
			||||
3. [Q3 : If I upsample and downsample to the original rate, for example 44.1-\>96-\>44.1, do I get an identical signal as the one before the up/down resampling?](#Q003) | 
				
			||||
4. [Q4 : If I ran src\_simple (libsamplerate) on small chunks (160 frames) would that sound bad?](#Q004) | 
				
			||||
5. [Q5 : I\'m using libsamplerate but the high quality settings sound worse than the SRC\_LINEAR converter. Why?](#Q005) | 
				
			||||
6. [Q6 : I\'m use the SRC\_SINC\_\* converters and up-sampling by a ratio of 2. I reset the converter and put in 1000 samples and I expect to get 2000 samples out, but I\'m getting less than that. Why?](#Q006) | 
				
			||||
7. [Q7 : I have input and output sample rates that are integer values, but the API wants me to divide one by the other and put the result in a floating point number. Won\'t this case problems for long running conversions?](#Q007) | 
				
			||||
 | 
				
			||||
## Q1 : Is it normal for the output of libsamplerate to be louder than its input? {#Q001} | 
				
			||||
 | 
				
			||||
The output of libsamplerate will be roughly the same volume as the input. | 
				
			||||
However, even if the input is strictly in the range (-1.0, 1.0), it is still | 
				
			||||
possible for the output to contain peak values outside this range. | 
				
			||||
 | 
				
			||||
Consider four consecutive samples of [0.5 0.999 0.999 0.5]. If we are up | 
				
			||||
sampling by a factor of two we need to insert samples between each of the | 
				
			||||
existing samples. Its pretty obvious then, that the sample between the two 0.999 | 
				
			||||
values should and will be bigger than 0.999. | 
				
			||||
 | 
				
			||||
This means that anyone using libsamplerate should normalize its output before | 
				
			||||
doing things like saving the audio to a 16 bit WAV file. | 
				
			||||
 | 
				
			||||
## Q2 : On Unix/Linux/MacOSX, what is the best way of detecting the presence and location of libsamplerate and its header file using autoconf? {#Q002} | 
				
			||||
 | 
				
			||||
libsamplerate uses the pkg-config (man pkg-config) method of registering itself | 
				
			||||
with the host system. The best way of detecting its presence is using something | 
				
			||||
like this in configure.ac (or configure.in): | 
				
			||||
 | 
				
			||||
    PKG_CHECK_MODULES(SAMPLERATE, samplerate >= 0.1.3, | 
				
			||||
            ac_cv_samplerate=1, ac_cv_samplerate=0) | 
				
			||||
 | 
				
			||||
    AC_DEFINE_UNQUOTED([HAVE_SAMPLERATE],${ac_cv_samplerate}, | 
				
			||||
            [Set to 1 if you have libsamplerate.]) | 
				
			||||
 | 
				
			||||
    AC_SUBST(SAMPLERATE_CFLAGS) | 
				
			||||
    AC_SUBST(SAMPLERATE_LIBS) | 
				
			||||
 | 
				
			||||
This will automatically set the **SAMPLERATE_CFLAGS** and **SAMPLERATE_LIBS** | 
				
			||||
variables which can be used in Makefile.am or Makefile.in like this: | 
				
			||||
 | 
				
			||||
    SAMPLERATE_CFLAGS = @SAMPLERATE_CFLAGS@ | 
				
			||||
    SAMPLERATE_LIBS = @SAMPLERATE_LIBS@ | 
				
			||||
 | 
				
			||||
If you install libsamplerate from source, you will probably need to set the | 
				
			||||
**PKG_CONFIG_PATH** environment variable's suggested at the end of the | 
				
			||||
libsamplerate configure process. For instance on my system I get this: | 
				
			||||
 | 
				
			||||
    -=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-=- | 
				
			||||
 | 
				
			||||
        Configuration summary : | 
				
			||||
 | 
				
			||||
        Version : ..................... 0.1.3 | 
				
			||||
        Enable debugging : ............ no | 
				
			||||
 | 
				
			||||
        Tools : | 
				
			||||
 | 
				
			||||
        Compiler is GCC : ............. yes | 
				
			||||
        GCC major version : ........... 3 | 
				
			||||
 | 
				
			||||
        Extra tools required for testing and examples : | 
				
			||||
 | 
				
			||||
        Have FFTW : ................... yes | 
				
			||||
        Have libsndfile : ............. yes | 
				
			||||
        Have libefence : .............. no | 
				
			||||
 | 
				
			||||
        Installation directories : | 
				
			||||
 | 
				
			||||
        Library directory : ........... /usr/local/lib | 
				
			||||
        Program directory : ........... /usr/local/bin | 
				
			||||
        Pkgconfig directory : ......... /usr/local/lib/pkgconfig | 
				
			||||
 | 
				
			||||
## Q3 : If I upsample and downsample to the original rate, for example 44.1->96->44.1, do I get an identical signal as the one before the up/down resampling? {#Q003} | 
				
			||||
 | 
				
			||||
The short answer is that for the general case, no, you don't. The long answer is | 
				
			||||
that for some signals, with some converters, you will get very, very close. | 
				
			||||
 | 
				
			||||
In order to resample correctly (ie using the **SRC_SINC_*** converters), | 
				
			||||
filtering needs to be applied, regardless of whether its upsampling or | 
				
			||||
downsampling. This filter needs to attenuate all frequencies above 0.5 times the | 
				
			||||
minimum of the source and destination sample rate (call this fshmin). Since the | 
				
			||||
filter needed to achieve full attenuation at this point, it has to start rolling | 
				
			||||
off a some frequency below this point. It is this rolloff of the very highest | 
				
			||||
frequencies which causes some of the loss. | 
				
			||||
 | 
				
			||||
The other factor is that the filter itself can introduce transient artifacts | 
				
			||||
which causes the output to be different to the input. | 
				
			||||
 | 
				
			||||
## Q4 : If I ran src_simple on small chunks (say 160 frames) would that sound bad? {#Q004} | 
				
			||||
 | 
				
			||||
Well if you are after odd sound effects, it might sound OK. If you are after | 
				
			||||
high quality sample rate conversion you will be disappointed. | 
				
			||||
 | 
				
			||||
The src_simple() was designed to provide a simple to use interface for people | 
				
			||||
who wanted to do sample rate conversion on say, a whole file all at once. | 
				
			||||
 | 
				
			||||
## Q5 : I'm using libsamplerate but the high quality settings sound worse than the SRC_LINEAR converter. Why? {#Q005} | 
				
			||||
 | 
				
			||||
There are two possible problems. Firstly, if you are using the src_simple() | 
				
			||||
function on successive blocks of a stream of samples, you will get bad results. | 
				
			||||
The src_simple() function is designed for use on a whole sound file, all at | 
				
			||||
once, not on contiguous segments of the same sound file. To fix the problem, you | 
				
			||||
need to move to the src_process() API or the callback based API. | 
				
			||||
 | 
				
			||||
If you are already using the src_process() API or the callback based API and the | 
				
			||||
high quality settings sound worse than SRC_LINEAR, then you have other problems. | 
				
			||||
Read on for more debugging hints. | 
				
			||||
 | 
				
			||||
All of the higher quality converters need to keep state while doing conversions | 
				
			||||
on segments of a large chunk of audio. This state information is kept inside the | 
				
			||||
private data pointed to by the SRC_STATE pointer returned by the src_new() | 
				
			||||
function. This means, that when you want to start doing sample rate conversion | 
				
			||||
on a stream of data, you should call src_new() to get a new SRC_STATE pointer | 
				
			||||
(or alternatively, call src_reset() on an existing SRC_STATE pointer). You | 
				
			||||
should then pass this SRC_STATE pointer to the src_process() function with each | 
				
			||||
new block of audio data. When you have completed the conversion, you can then | 
				
			||||
call src_delete() on the SRC_STATE pointer. | 
				
			||||
 | 
				
			||||
If you are doing all of the above correctly, you need to examine your usage of | 
				
			||||
the values passed to src\_process() in the [SRC_DATA](api_misc.md#src_data) | 
				
			||||
struct. Specifically: | 
				
			||||
 | 
				
			||||
- Check that input_frames and output_frames fields are being set in terms of | 
				
			||||
  frames (number of sample values times channels) instead of just the number of | 
				
			||||
  samples. | 
				
			||||
- Check that you are using the return values input_frames_used and | 
				
			||||
  output_frames_gen to update your source and destination pointers correctly. | 
				
			||||
- Check that you are updating the data_in and data_out pointers correctly for | 
				
			||||
  each successive call. | 
				
			||||
 | 
				
			||||
While doing the above, it is probably useful to compare what you are doing to | 
				
			||||
what is done in the example programs in the examples/ directory of the source | 
				
			||||
code tarball. | 
				
			||||
 | 
				
			||||
If you have done all of the above and are still having problems then its | 
				
			||||
probably time to email the author with the smallest chunk of code that | 
				
			||||
adequately demonstrates your problem. This chunk should not need to be any more | 
				
			||||
than 100 lines of code. | 
				
			||||
 | 
				
			||||
## Q6 : I'm use the SRC_SINC_* converters and up-sampling by a ratio of 2. I reset the converter and put in 1000 samples and I expect to get 2000 samples out, but I'm getting less than that. Why? {#Q006} | 
				
			||||
 | 
				
			||||
The short answer is that there is a transport delay inside the converter itself. | 
				
			||||
Long answer follows. | 
				
			||||
 | 
				
			||||
By way of example, the first time you call src_process() you might only get 1900 | 
				
			||||
samples out. However, after that first call all subsequent calls will probably | 
				
			||||
get you about 2000 samples out for every 1000 samples you put in. | 
				
			||||
 | 
				
			||||
The main problems people have with this transport delay is that they need to | 
				
			||||
read out an exact number of samples and the transport delay scews this up. The | 
				
			||||
best way to overcome this problem is to always supply more samples on the input | 
				
			||||
than is actually needed to create the required number of output samples. With | 
				
			||||
reference to the example above, if you always supply 1500 samples at the input, | 
				
			||||
you will always get 2000 samples at the output. You will always need to keep | 
				
			||||
track of the number of input frames used on each call to src_process() and deal | 
				
			||||
with these values appropriately. | 
				
			||||
 | 
				
			||||
## Q7 : I have input and output sample rates that are integer values, but the API wants me to divide one by the other and put the result in a floating point number. Won't this case problems for long running conversions? {#Q007} | 
				
			||||
 | 
				
			||||
The short answer is no, the precision of the ratio is many orders of magnitude | 
				
			||||
more than is really needed. | 
				
			||||
 | 
				
			||||
For the long answer, lets do come calculations. Firstly, the `src_ratio` field | 
				
			||||
is double precision floating point number which has [53 bits of precision](http://en.wikipedia.org/wiki/Double_precision). | 
				
			||||
 | 
				
			||||
That means that the maximum error in your ratio converted to a double is one bit | 
				
			||||
in 2^53 which means the double float value would be wrong by one sample | 
				
			||||
after 9007199254740992 samples have passed or wrong by more than half a sample | 
				
			||||
wrong after half that many (4503599627370496 samples) have passed. | 
				
			||||
 | 
				
			||||
Now if for example our output sample rate is 96kHz then | 
				
			||||
 | 
				
			||||
    4503599627370496 samples at 96kHz is 46912496118 seconds | 
				
			||||
    46912496118 seconds is 781874935 minutes | 
				
			||||
    781874935 minutes is 13031248 hours | 
				
			||||
    13031248 hours is 542968 days | 
				
			||||
    542968 days is 1486 years | 
				
			||||
 | 
				
			||||
So, after 1486 years, the input will be wrong by more than half of one sampling | 
				
			||||
period. | 
				
			||||
 | 
				
			||||
All this assumes that the crystal oscillators uses to sample the audio stream is | 
				
			||||
perfect. This is not the case. According to [this web site](http://www.ieee-uffc.org/freqcontrol/quartz/vig/vigcomp.htm), | 
				
			||||
the accuracy of standard crystal oscillators (XO, TCXO, OCXO) is at best 1 in | 
				
			||||
100 million. The `src_ratio` is therefore 45035996 times more accurate than the | 
				
			||||
crystal clock source used to sample the original audio signal and any potential | 
				
			||||
problem with the `src_ratio` being a floating point number will be completely | 
				
			||||
swamped by sampling inaccuracies. | 
				
			||||
| 
		 After Width: | Height: | Size: 8.6 KiB  | 
@ -0,0 +1,38 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# History | 
				
			||||
 | 
				
			||||
- Version 0.0.0 (Oct 06 2002) First alpha release (friends and family only). | 
				
			||||
- Version 0.0.2 (Oct 10 2002) Second alpha release (fools rush in ....). | 
				
			||||
- ... | 
				
			||||
- Version 0.0.7 (Nov 17 2002) The last mono only version. | 
				
			||||
- Version 0.0.9 (Nov 21 2002) Full multi channel support. First pass at | 
				
			||||
  documentation. Still not ready for release. | 
				
			||||
- Version 0.0.11 (Nov 26 2002) Incorporated some suggestions from Conrad Parker. | 
				
			||||
- Version 0.0.12 (Nov 28 2002) First public release. | 
				
			||||
- Version 0.0.13 (Dec 03 2002) Fixes for MacOSX and Solaris. | 
				
			||||
- Version 0.0.14 (Jan 13 2003) Now compiles on Win32. Major code speedup. Minor | 
				
			||||
  bug fixes. | 
				
			||||
- Version 0.0.15 (May 02 2003) Minor bug fixes. | 
				
			||||
- Version 0.1.0 (Mar 14 2004) Add callback API, functions for short to float and | 
				
			||||
  float to short conversion. Minor bug fixes. | 
				
			||||
- Version 0.1.1 (Jul 17 2004) Callback API bug fix. Bugfix for aggressive | 
				
			||||
  gcc-3.4 optimisations. | 
				
			||||
- Version 0.1.2 (Sep 12 2004) Callback API reset bug fix. | 
				
			||||
- Version 0.1.3 (Mar 23 2008) Huge quality improvements to two best SINC based | 
				
			||||
  converters. | 
				
			||||
- Version 0.1.4 (Jul 02 2008) Fix segfault when using extremely low conversion | 
				
			||||
  ratios. | 
				
			||||
- Version 0.1.5 (Jan 11 2009) Optimisation resulting in dramatic throughput | 
				
			||||
  improvements ([See here.](http://www.mega-nerd.com/erikd/Blog/CodeHacking/SecretRabbitCode/rel_0_1_5.html)). | 
				
			||||
- Version 0.1.6 (Jan 27 2009) Minor bug fix in test suite (account for rounding | 
				
			||||
  error on x86_64). | 
				
			||||
- Version 0.1.7 (Feb 14 2009) Fix a segfault bug. Fix compilation under MSVC. | 
				
			||||
- Version 0.1.8 (Aug 15 2011) Minor bug fixes and updates. | 
				
			||||
- Version 0.1.9 (Sep 19 2016) Fix for a segfault. Relicense under BSD license. | 
				
			||||
- Version 0.2.0 (Jan 21 2021) Cleaned up build system. | 
				
			||||
- Version 0.2.1 (Jan 23 2021) Fix libtool ABI versioning. | 
				
			||||
- Version 0.2.2 (Sep 05 2021) Fix ABI version incompatibility between Autotools | 
				
			||||
  and CMake build on Apple platforms. Minor bug fixes and updates. | 
				
			||||
@ -0,0 +1,160 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
title: Libsamplerate home page | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
{: .indent_block} | 
				
			||||
*"Choosing a sample rate coverter wasn't easy. We ran numerous tests with Secret | 
				
			||||
Rabbit Code and other sample rate converters, then compared them all. In the | 
				
			||||
end, SRC outperformed the others, including some extremely well known and | 
				
			||||
popular software. We had one issue with SRC, but after emailing Erik, he got | 
				
			||||
back to us immediately with an answer. Choosing SRC was a no brainer."*   | 
				
			||||
Ryan Smith, International Marketing Manager,   | 
				
			||||
[Emersys Corp.](http://emersys.co.kr/), South Korea.   | 
				
			||||
Product : [Maven3D](http://maven3d.com) | 
				
			||||
 | 
				
			||||
**S**ecret **R**abbit **C**ode (aka libsamplerate) is a **S**ample **R**ate | 
				
			||||
**C**onverter for audio. One example of where such a thing would be useful is | 
				
			||||
converting audio from the CD sample rate of 44.1kHz to the 48kHz sample rate | 
				
			||||
used by DAT players. | 
				
			||||
 | 
				
			||||
**SRC** is capable of arbitrary and time varying conversions, from downsampling | 
				
			||||
by a factor of 256 to upsampling by the same factor. Arbitrary in this case | 
				
			||||
means that the ratio of input and output sample rates can be an irrational | 
				
			||||
number. The conversion ratio can also vary with time for speeding up and slowing | 
				
			||||
down effects. | 
				
			||||
 | 
				
			||||
**SRC** provides a small set of converters to allow quality to be traded off | 
				
			||||
against computation cost. The current best converter provides a signal-to-noise | 
				
			||||
ratio of 145dB with -3dB passband extending from DC to 96% of the theoretical | 
				
			||||
best bandwidth for a given pair of input and output sample rates. | 
				
			||||
 | 
				
			||||
Since the library has few dependencies beyond that provided by the standard C | 
				
			||||
library, it should compile and work on just about any operating system. It is | 
				
			||||
known to work on Linux, MacOSX, [Win32](win32.md) and Solaris. With some | 
				
			||||
relatively minor hacking it should also be relatively easy to port it to | 
				
			||||
embedded systems and digital signal processors. | 
				
			||||
 | 
				
			||||
In addition, the library comes with a comprehensive test suite which can | 
				
			||||
validate the performance of the library on new platforms. | 
				
			||||
 | 
				
			||||
## Download | 
				
			||||
 | 
				
			||||
Check latest version on | 
				
			||||
[GitHub Releases page](https://github.com/libsndfile/libsamplerate/releases). | 
				
			||||
 | 
				
			||||
Binaries and source packages are signed by current release manager David Seifert aka | 
				
			||||
@SoapGentoo. You can verify signatures with his public GPG key (`0xA47620E801E47E95`): | 
				
			||||
 | 
				
			||||
``` | 
				
			||||
-----BEGIN PGP PUBLIC KEY BLOCK----- | 
				
			||||
Version: GnuPG v2 | 
				
			||||
 | 
				
			||||
mQINBFppABgBEAC42ZiNvV7BTIgR6TQy0YnF54fx3mVRP1u8Mq00UZa7reAsNKh7 | 
				
			||||
1H60j0W4s6+4pVVIKGfpVGxLwUdJe+KVCYw1Cd3YW6uMf5zZrC/ZWqnJiH/n6S6o | 
				
			||||
1l4INII2o6YbGBnzIWBPRo7PlOL+mvgKTLpBSJPnhD8XDGN5wRiV8rL2+6Dptg0F | 
				
			||||
nJt7oxECGF3OD3gk6HMel0o82CVkIqMtNaX1L/bhcdF7K0Rp2MXPZMmpn1izW5sI | 
				
			||||
asN1G9+w+Zwj7kMJzq1Aw3ac+rsX4SEYdvXjS2QhDHQUIr6LXri3D2WbcEqIZj2R | 
				
			||||
JVoVwblsrG11dYXFDBbgrq4NhgTBsxHYDlkr/qF2W+kbPC/nhSqTVZeCYvTBZbOQ | 
				
			||||
+RqyN/I0izukglnWmV1jGijFA8snyP8efx732hw/24zRYmtXOtnEITUpw8WOeZCq | 
				
			||||
6uiHaQ+eopnY2ojBg9BI7WZm0AFn58xxT9soMsyFOUFgXTqaWFZWlJ3fhZE8/0v8 | 
				
			||||
JEu/kPGE5aJReT3b34B+Bojkj74XR+h2u7iJJBHMTE8RwGoUOZHer/XsL9xlcdks | 
				
			||||
I+7TCjiq++ShaSSt2XsJmw2BhREohrjW/2KkwmvT3b44RMpKPB4WTH+++aqJQNeM | 
				
			||||
IqmswOMoZvzEZezInj7WVY/r0WEei1Y6wt1tBrJ/cFf1oQBM1UmphxcrfQARAQAB | 
				
			||||
tB9EYXZpZCBTZWlmZXJ0IDxzb2FwQGdlbnRvby5vcmc+iQJUBBMBCgA+BQsJCAcD | 
				
			||||
BRUKCQgLBRYCAwEAAh4BAheAAhsBFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/V | 
				
			||||
CvoFCQkuceIACgkQpHYg6AHkfpXYxA//aiJW1NwunpmzEc62id8lRMnoLHWVjISZ | 
				
			||||
b+xSlm+hk4LYq+ZbthJDzKcT86/3DJOSE1zQw9wLuCao9IW2UfFJQBtR+TAfbagG | 
				
			||||
0Yyk/kMcLoFJxnG1ywdJWypCAauuIhia52Z7PmmjsBbFwr6LygDwSQmZAyACMAs7 | 
				
			||||
TLQe+yERc2RNDsIEsquLSxxRF0Spk9gagWtKgrPc2XBjuNtQDwW7JgsOUoEeHyxC | 
				
			||||
29fRUjC3o/pG2I6iAZp17OROZI5yl4TSORrSBDGIi2sayxyxP0x+IPKtrCUcBGNx | 
				
			||||
wGp+56bP/V0hA6sgCPh/iwvqLoeibso6l/Kd4ltVAEQnHTd6fr8g+wLEUXfbJVTR | 
				
			||||
7aeFUoaFmWjSPlQrNr6HlxSLV/kRx9kVJp1Pn16vkfVBF7fG7iDLiqphwEeQg5ND | 
				
			||||
nmGeKAbRRNxFHyBHf0XRsaYiFZQckguO+71XSRtVx8/YP5nyNbtl9y1h/4JlT6Gy | 
				
			||||
t7hb5twYFQyQrKss83E/Bo1sRdHpj0ibtqb4ZbYANbh482E6yFhAkuo8YjVTJipI | 
				
			||||
1Ve8EBKnX3R+pDt147uyysNvtPVXML+sWpGSMVSm4NA8uT3F5nqxVwj+SeXy3Wq/ | 
				
			||||
CHQ2VBKGBC655G+wFD5C6O7cTx2MwH+2H8tzhWm+gFlI3MFKEXa/PC+YUC/diYcb | 
				
			||||
BrApavriTRa5Ag0EWmkAZgEQAPXMD3mZI+ChvBysXZWksC88/uSEwFeb3XkcRm7v | 
				
			||||
04GN7hcz+bfrmnUTB3tuE/ZQgv+u7ZjetvH1aEKieznn/GjnWoOBoJusOYvfAQeF | 
				
			||||
0mQVi118QiOZRCnEZpkz+RY9TiXVgrZJg+AGqHZ3Ol4GkInEV2NWgH37Xal+HkFl | 
				
			||||
rwI2U7mL0kZRG+LAVCQHKzqU0R0HE1XyJ4qf0awtG5Qi/TZvgXBdZPDXgr8i9Vlf | 
				
			||||
UUu10c2XnXM0Av/YAlZmBFjVYrSOUCFenqSVqL+s9sTCVdWlJrGjrr3Ja4uT3kl2 | 
				
			||||
rLva0AR4oSQoxt8adKohmFz0vzOkQtCoRzhrCwoo3JvNjKdSNoOP1nSsxlO5ji8r | 
				
			||||
ih5d+ajPgi580XyHLnrvG7vobR48qqscv1hizKuCgTacOTe6Db2Gqc8xF6v8HhJa | 
				
			||||
KwWJtmFllIfN/tIvZ6BbbgHQn0IGf4CYnWf0SksPZqpBmTRpD2jfBxcj2UEg+AR3 | 
				
			||||
LARjuyUVpFJScyu6ExQG+6O+ByLL31iWP5MgUrza1rIpriPa3NT3rZ3DG2pvQrS3 | 
				
			||||
ySsrPzH7VRX8L1ThSMSzjwF96aMsd14s7XzR4EzNuWwZDukfs0yavZk6l4o1M0mb | 
				
			||||
tbJi7hE4cz13KRHYvIkKMdZGYUnzRzZUDlsj2imakk3BR6GXnxZ1ST6062g+QxiL | 
				
			||||
AJFLABEBAAGJBHIEGAEKACYCGwIWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9UL | 
				
			||||
DQUJCS5xpwJAwXQgBBkBCgAdFiEEuNUxXaAAcsCoYIifzjbhFyAuOEIFAlppAGYA | 
				
			||||
CgkQzjbhFyAuOELmrQ/9H9wrWsWa21STZdxUmyU2sh9VXAWEHl1Ey0fVTznDM0Fl | 
				
			||||
zx5YSR/TmmnE36rpaz31Ttkx8SP914oV+mMgseecdya9Bf6uZL9Cv7V3KEsJBRL/ | 
				
			||||
ncrOWQBHP/Xy1X+mLD6A19xq7H4RihSLj0LeK2YVjrJzJ7wMf4mKXuBayQeAHImU | 
				
			||||
WRCRTbmK3umh2nB5V0iPd/XZEIiYtiTPe+7E/va6+0bBvOumF3a+Z0iui7eU4hFC | 
				
			||||
7Jk71D0dcg09SlIaNoMOrw7cMC3j2pMdKtsj8+0I6WBv14PhhqPAsnjdf7I/4NfK | 
				
			||||
L7Jav8T/gDS01uA2Jxm72d+wr+eSjOBXa6x8CEbTqfkjAGxsWENThCp6zDkaXSDd | 
				
			||||
JsV0va47vjzG8+wTDAvPy5IxIM/KZZdl4uWM+mF5K+q+eSTOHe7aLF2OdcussoBA | 
				
			||||
A18zm994dAkG1COX/qpxanxx2bv/2IvCGPg+x6JtAN8ji2kncWu3dWGQdE5XbVjc | 
				
			||||
fDwgsUPpp04G27Mr/x+HpEbgZ5SdA0dAqJktlNvCcHALhlblCWrsh/1QNjT/2iG8 | 
				
			||||
wsjcpEy/s4tWAuV4PTa4xvZ1JPS7Z7Eo5aBy9ZGOWG9SrHEiHnhkUsiswbHBOEjd | 
				
			||||
pBSkmNElDcv9fRUahVCTPfvWBATFDrQyMjJBSm+cV8c/iFQM7isVSu8W7E0eetsJ | 
				
			||||
EKR2IOgB5H6Vv9sP/1dxTvH0N0UoEoxIG/hnirEkbRpljdvqy4/uikYBKyQgSbo8 | 
				
			||||
VITTjea7gIhDztil9WZYt35jbOmoaGM2Z6TP2LEDOWgljYUNq9pl9Sc2GS8cNtEO | 
				
			||||
WxExzGOc1Flo730dX3A85Ks3+0WPXZjLDcRRcPVkFd5WLQQDV1YVYopWkuQBC+Br | 
				
			||||
4q3uv+sk+bw6gDa9+zFBbDuegdsYuTXrFHoxHz2GRv9Yb7ULCMgpFeNKDgtQq91u | 
				
			||||
RqewoTwQp9tlp91LH/hh7R0Q4DRgeFDkLnVRXwSKjVvCrT5cBgImGwtFTGS4egoy | 
				
			||||
MDKd/KKjZllp1ahRCln1XfmFQyQVMVvuF/JTtt31n6KwXwK2yxIlXB01xvRH+Ees | 
				
			||||
AWeRYWKWXydaAY/9Ve0/PLFlgsr/XUGvt0GoEKe7odD3nZgg6015+/8JTroKw19L | 
				
			||||
NZkhdfFMl11Zi0j5k3UbyzjYVpFSd8K2o0VoOG1LFsPp8tlRxNoVzpId0CX1au/p | 
				
			||||
y1H7Wy/39mzriRG3rw+mJAQbBjN09putCltXFXpOEWk08n/N3vufCVQUoSu/2Bqw | 
				
			||||
2HYj8VtToQp+O5dG3XxvDHINtInP1yr2Wcw2plna0KoXLwv/lZgDm3LN+eCWpG6d | 
				
			||||
N/xk25DTSqTHArUQIEkhcHYK6GnyxUcvoKtG88hXtqEPYXiK08FZYAUPTnDYuQIN | 
				
			||||
BFppAIkBEADDjvQZUs1NoqJpxkD2QDBudU1DBCaeI1D6CancMtb5FebPUxgFlDMd | 
				
			||||
CBGOun48dY5i87gDhT/qS3gP/Mv9rjKJmcG9JHfhpXdW73owxrcsQ96nxxVJNEVl | 
				
			||||
UHJw00z8C9eGWqr0SzSoE33K/PkzSkgtsaotF6+3uCerWulweulmGa5dpVfV0mbS | 
				
			||||
aVw8VmrhZ5NmCeodyy/lR85rPik5pb32NT6v7xBkgkfS0VYtPB2E5gW1pXX/jEOi | 
				
			||||
Mfq9idOEP9lxrNXV9j49Lr0JQCwAcrYbQ2+VPe6eacJEjzJ/6HiUqhPrYdnvydmb | 
				
			||||
hU+xmv2NjGp2UnDZDEhzQfwm6fMx+8Nx2uPzCnXQGoyRBwiC/KcdW0F1ZPKdSXqH | 
				
			||||
NKoOF62pLvIMSmfI3ZVOrTohArfr1kFEYVDv9Nl7oY+qg2rZEc2srOF74a9Z46bR | 
				
			||||
TDPsEQzE2UMCvu3+rofhSD7aRotlKeDCvbe2s0yE4Man457Xc3LXh8Gva8CzCOLE | 
				
			||||
2eMhNTsHIZk68WgXp3/uvE4Xy42myrk1AV8XXDdlWgx0Kc/I6tE59O5NVPSfuGvH | 
				
			||||
1a15KKx0F6euEnYDKKpQ5PDR6dSn61po0tfbt96m044G/xQFjrfhHei4jji9Ogd9 | 
				
			||||
vlXVAi2vn3+NCSHFP5l3igLByBHy9iLIdmz7yQuus/1nwRmxOHOf2QARAQABiQI8 | 
				
			||||
BBgBCgAmAhsMFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/VCxkFCQkucZAACgkQ | 
				
			||||
pHYg6AHkfpVPSRAAmheYkYJmtDbkzPBBnj5mbCIQN1/G5PI9eixc/TXWFOXtcjU1 | 
				
			||||
mJlJpSidHJyLRrx7r0c+N+s8vnY/JuUBsNoMJMER+Mv/CFW4iFi59V534SyAb2S0 | 
				
			||||
7NINJnFNkXBY62CDz9KsMuv/MdSv2yLhPH2Tfrm/eDRQesj1PanE4U1cgjWyJRc/ | 
				
			||||
IOlaRHvTasWDLgwbQi8ykt+4xUWzL/YKHzB+KyyzBK7vPBXqySX8ka4BOw7SDwG5 | 
				
			||||
lX2gtmhk4AGBwVChLXKflqVx1WXj4DPOt0kmOKVnKFyvUijK58M0A2FMgFMXDTIS | 
				
			||||
DRtoZPdx/rkODXxgS+W+27NcYAnxJiM0cQqizEnQh7PQ1KzgdChPejYXMKe9lwdn | 
				
			||||
ssMUxrBpbuAuagEf+pebNjD2eaNR4p8kfaDdGn53q55ysDvoyxKvnVQGSk1FAR9Q | 
				
			||||
s4N5a4f02U7dzlyEhEfIcuUlRCfnlpn4n725YIhHheDig5zKWoEZCkNIfiRcGzDl | 
				
			||||
8Drj+tlZiUR+gDkIoWSBaCkKbIQlc8qCYy6Hm7oZBaol6xKlUnTMK2rjK8fR4i8r | 
				
			||||
bVDWBAaWj3jcDHJ0Jg3fS/qBpeya/JXMp89TR8NK5Ys7PZpWbor+puXBYyXDAVx3 | 
				
			||||
rXQ7JBA5klHPxrgjso1S/LqwscKLENtrVjdjhryLBmPifrmofJRnrpiHIEa5Ag0E | 
				
			||||
WmkAswEQAL0hKwsRybQzkNGpJP+ElLSwFHd7XQhr+qIwLllpumWtnIK/DHmv8SpW | 
				
			||||
FqAYajmRTXipFcBHH25x2jIIliZidn0a9826l+sMzrFadMC6/W4pitP71TeqZzwn | 
				
			||||
pAuHs14YL7Wiy0aJQnfbCpRzPq3kYyOXmhmY7lPWO0WdUpR6W8wUbleK5XOVDDRx | 
				
			||||
aIC/M3hhDOxZOMzQ+pdn4BaOFQQ0ygsRkqOudbuc0R1giYRt1i6gMeT8gfzL9jlw | 
				
			||||
HcJ+aVnxdUQQ4uC47oKo/+lg7qh7LsiW79pQC1Bcdm8lhRmqtxe6ub60ecjax3XU | 
				
			||||
1ILIEfIFCv6M7LRUAwz0bqk35spgkJqrGGKkdeWEKAFHg2QWR2F0zy+HdlPLfKxO | 
				
			||||
uhaccpwc9EJtf744GS0SXa2AXr32j56n7CFcEjFcIQPBC6OJn6eA3hOVUYGZ7SrT | 
				
			||||
4fsmZiFAdGEkvLKFuNhju1Hj2EJQUY1pm4GSBco7BR8x+QqoYrt5clU3WxRMNfTR | 
				
			||||
0Rtuzsh4xskXNVMMgvKOahAtxENv2M2Cx6zJPVL5dmaysP7d6QRVeOQA5PwkcZ5Q | 
				
			||||
qK6JtDZj2jpaKQH4Za715kiIcdqMDSkwxa6avc0kARHvfFcBR4hwDm1GAlaKG7eH | 
				
			||||
8TOGGQIk8x2F3s4l8mTJVLWTP/uJYnkYBdqANYo5t1NIQLvwLFV3ABEBAAGJAjwE | 
				
			||||
GAEKACYCGyAWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9ULIwUJCS5xcAAKCRCk | 
				
			||||
diDoAeR+leekD/sF7aHH0W35ckWrXZlfSp0qHPWrBUaLBI9OAUHenRhgs4SbK0D4 | 
				
			||||
wqEiu0C5iDQojpXAeALQ8g/1pUsZ1yuFqYbGYWrHkA0Pm+P3tAGB4LMZ41YfvROP | 
				
			||||
uaiW/+IMJbWllgRtaDt8/NtCgs30WI9I+az5M29HcGfvEwEUykrBx3dE9T+1ui3O | 
				
			||||
capdd+GMvdAAsX5PyVkjWgZ7GrZeH8mG7UysYfT4qthxEtQfZ/u8ceSduKA46ugh | 
				
			||||
C2eafIDNvluqn7BU4oKxME61u6C8BN2yHLI6LV0Tr4z5H8joVbM4BSFMwLVGlsXf | 
				
			||||
HhB8kLiErN6bXolxsjARlmYiD9S9H2AcYidr6RYXf2EVFSpBG59xn1WTDN+DsHQf | 
				
			||||
7btNPEPl/OPxa3OQjG+xn8USddiP0N0B4xsyzMNCCKDgvXXcIhX55KG9eh3Tc98S | 
				
			||||
fEyhxu8ybZBIGmTJysPKxijfvSgQF+RPNTsz9lvXqkoK7RTgeYMschpjJEznCLbt | 
				
			||||
M6eTDb5z0G5uLXh6+dYxtDOlPogI5OHd+G51LwCjvrQ+AtIUCgafuemwA9mpFT2b | 
				
			||||
svb/qcxSVUb44bVaNHn1JHebX2YbokGtBOm1x2PI5fT8n6YIIYz3jKYOZAYdUT7x | 
				
			||||
6qURyNjOfG4aPJIATwuh4GSNuxUG40+yuT+XfQF24mu1esS1J3wzRloJ7w== | 
				
			||||
=K3x+ | 
				
			||||
-----END PGP PUBLIC KEY BLOCK----- | 
				
			||||
``` | 
				
			||||
@ -0,0 +1,12 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# License | 
				
			||||
 | 
				
			||||
From its first release in 2002, Secret Rabbit Code was under a dual licensing | 
				
			||||
scheme where people could chose to use it under the terms of the GNU General | 
				
			||||
Public License or pay for a commercial use license. | 
				
			||||
 | 
				
			||||
In 2016, thanks to a generous offer from Epic Games International, Secret Rabbit | 
				
			||||
Code was relicensed under the 2-clause BSD license. | 
				
			||||
| 
		 After Width: | Height: | Size: 770 B  | 
@ -0,0 +1,84 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# SRC Quality | 
				
			||||
 | 
				
			||||
**This document not yet complete.** | 
				
			||||
 | 
				
			||||
When measuring the performance of a Sample Rate Converter, there are three | 
				
			||||
factors to consider: | 
				
			||||
 | 
				
			||||
- **Signal-to-Noise Ratio** - a measure of how much noise the sample rate | 
				
			||||
  conversion process adds to the signal. This is measured in decibels (dB) and | 
				
			||||
  the higher this value the better. For most sample rate converters, the SNR | 
				
			||||
  will vary depending on the input signal and the ratio between input and output | 
				
			||||
  sample rates. The only valid comparison of SNR is between the worst case for | 
				
			||||
  each converter. | 
				
			||||
- **Bandwidth** - most sample rate converters attenuate high frequencies as part | 
				
			||||
  of their operation. Bandwidth can be measured by finding the frequency where | 
				
			||||
  the attenuation is 3dB and expressing that as a percentage of the full | 
				
			||||
  bandwidth at that sampling rate. | 
				
			||||
- **Speed** - the faster the better **:-)**. | 
				
			||||
 | 
				
			||||
There are a number of sample rate converters available for downloading but I | 
				
			||||
will limit the comparison of Secret Rabbit Code to the following: | 
				
			||||
 | 
				
			||||
- [sndfile-resample](http://libsndfile.github.io/libsamplerate/download.html) | 
				
			||||
  which is a program (which uses libsamplerate) from the **examples/** directory | 
				
			||||
  of the Secret Rabbit Code source code distribution. | 
				
			||||
- [Resample](https://ccrma.stanford.edu/~jos/resample/) by Julius O Smiths which | 
				
			||||
  seems to have been the first high quality converter available as source code. | 
				
			||||
- [ResampAudio](http://www.tsp.ece.mcgill.ca/MMSP/Documents/Software/AFsp/ResampAudio.html) | 
				
			||||
  which is part of [Audio File Programs and Routines](http://www.tsp.ece.mcgill.ca/MMSP/Documents/Software/AFsp/AFsp.html) | 
				
			||||
  by Peter Kabal. | 
				
			||||
- [SoX](http://home.sprynet.com/~cbagwell/sox.html) which is maintained by Chris | 
				
			||||
  Bagwell. SoX is also able to perform some low quality sample rate conversions | 
				
			||||
  but these will not be investigated. | 
				
			||||
- [Shibatch](http://shibatch.sourceforge.net/) which seems to be a frequency | 
				
			||||
  domain sample rate converter. Unfortunately, this converter does not handle | 
				
			||||
  arbitrary conversion ratios and hence could not be properly compared to the | 
				
			||||
  other converters. | 
				
			||||
- [sr-convert](http://sr-convert.sourceforge.net/) is another converter which | 
				
			||||
  does not handle arbitrary conversion ratios. | 
				
			||||
 | 
				
			||||
It should be noted that the first three converters above are based on the | 
				
			||||
algorithm by [Julius O. Smith](http://www-ccrma.stanford.edu/~jos/resample/) | 
				
			||||
which emulates the conversion of the digital signal to an analogue one and then | 
				
			||||
samples the analogue signal at the new sample rate. | 
				
			||||
 | 
				
			||||
## Methodology | 
				
			||||
 | 
				
			||||
Measuring the SNR of a converter is relatively straightforward. Generate an | 
				
			||||
input signal consisting of a windowed sine wave, sample rate convert it and | 
				
			||||
measure the signal-to-noise ratio of the output signal. A typical length for the | 
				
			||||
original file is 30000 samples. | 
				
			||||
 | 
				
			||||
The bandwidth of a sample rate converter is a little more difficult to measure. | 
				
			||||
Currently this is done by generating two short files containing a windowed sine | 
				
			||||
wave. The frequencies of the sine waves are 0.35 and 0.495 of the sample rate. | 
				
			||||
These files are then upsampled by a factor of 2 using the converter under test. | 
				
			||||
If the attenuation of the lower frequency is less than 3dB and higher frequency | 
				
			||||
is more than 3dB, it is then possible to iteratively increase the lower | 
				
			||||
frequency and decrease the upper frequency keeping the -3dB point bracketed. | 
				
			||||
When the distance between the upper and lower frequency is sufficiently small, | 
				
			||||
it is possible to obtain a very accurate estimate of the -3dB frequency. | 
				
			||||
 | 
				
			||||
The speed of a sample rate converter is easy to measure; simply perform a | 
				
			||||
conversion on a large file or a number of smaller files and time the conversion | 
				
			||||
process. | 
				
			||||
 | 
				
			||||
The above measurement techniques are built into a test program which is | 
				
			||||
delivered with the Secret Rabbit Code source code distribution. This program is | 
				
			||||
able to test the first four of the above converters. | 
				
			||||
 | 
				
			||||
## SoX | 
				
			||||
 | 
				
			||||
SoX provides three methods of resampling; a linear interpolator, a polyphase | 
				
			||||
resampler and the Julius O. Smith simulated analogue filter method. | 
				
			||||
 | 
				
			||||
## Shibatch | 
				
			||||
 | 
				
			||||
Shibach | 
				
			||||
 | 
				
			||||
**More Coming Soon.** | 
				
			||||
@ -0,0 +1,15 @@ | 
				
			||||
--- | 
				
			||||
layout: default | 
				
			||||
--- | 
				
			||||
 | 
				
			||||
# Compiling on Win32 | 
				
			||||
 | 
				
			||||
You can use [CMake](https://cmake.org/) to generate Visual Studio project. The | 
				
			||||
configuration process is described [here](https://cmake.org/runningcmake/). | 
				
			||||
 | 
				
			||||
The libsamplerate library itself does not require any dependencies, but if you | 
				
			||||
want to build examples and tests, you will need the [libsndfile](https://github.com/libsndfile/libsndfile) | 
				
			||||
and [FFTW](http://www.fftw.org/) libraries. The easiest way to install them is | 
				
			||||
to use a package manager, such as [Vcpkg](https://github.com/microsoft/vcpkg). Their README.md contains detailed | 
				
			||||
installation instructions for supported platforms. Libsamplerate requires the | 
				
			||||
`libsndfile` and `fftw3` packages. | 
				
			||||
@ -0,0 +1,31 @@ | 
				
			||||
find_package(ALSA) | 
				
			||||
set(HAVE_ALSA ${ALSA_FOUND} PARENT_SCOPE) | 
				
			||||
# ALSA::ALSA target is exported since CMake >= 3.12, create it for | 
				
			||||
# old CMake versions | 
				
			||||
if(ALSA_FOUND) | 
				
			||||
  if(NOT TARGET ALSA::ALSA) | 
				
			||||
    add_library(ALSA::ALSA UNKNOWN IMPORTED) | 
				
			||||
    set_target_properties(ALSA::ALSA PROPERTIES | 
				
			||||
    INTERFACE_INCLUDE_DIRECTORIES "${ALSA_INCLUDE_DIRS}" | 
				
			||||
    IMPORTED_LOCATION "${ALSA_LIBRARIES}") | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
add_executable(timewarp-file timewarp-file.c) | 
				
			||||
target_link_libraries(timewarp-file | 
				
			||||
  PRIVATE | 
				
			||||
    samplerate | 
				
			||||
    $<$<BOOL:${SndFile_FOUND}>:${SNDFILE_TARGET}>) | 
				
			||||
 | 
				
			||||
add_executable(varispeed-play varispeed-play.c audio_out.c audio_out.h) | 
				
			||||
target_link_libraries(varispeed-play | 
				
			||||
  PRIVATE | 
				
			||||
    samplerate | 
				
			||||
    $<$<BOOL:${SndFile_FOUND}>:${SNDFILE_TARGET}>) | 
				
			||||
if(WIN32) | 
				
			||||
  target_link_libraries(varispeed-play PRIVATE winmm) | 
				
			||||
elseif(APPLE) | 
				
			||||
  target_link_libraries(varispeed-play PRIVATE "-framework CoreAudio") | 
				
			||||
elseif(ALSA_FOUND) | 
				
			||||
  target_link_libraries(varispeed-play PRIVATE ALSA::ALSA) | 
				
			||||
endif() | 
				
			||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						@ -0,0 +1,25 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 1999-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
typedef	struct AUDIO_OUT AUDIO_OUT ; | 
				
			||||
 | 
				
			||||
typedef int (*get_audio_callback_t) (void *callback_data, float *samples, int frames) ; | 
				
			||||
 | 
				
			||||
/* A general audio output function (Linux/ALSA, Linux/OSS, Win32, MacOSX,
 | 
				
			||||
** Solaris) which retrieves data using the callback function in the above | 
				
			||||
** struct. | 
				
			||||
** | 
				
			||||
** audio_open - opens the device and returns an anonymous pointer to its | 
				
			||||
**              own private data. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
AUDIO_OUT *audio_open (int channels, int samplerate) ; | 
				
			||||
 | 
				
			||||
void audio_play (get_audio_callback_t callback, AUDIO_OUT *audio_out, void *callback_data) ; | 
				
			||||
 | 
				
			||||
void audio_close (AUDIO_OUT *audio_data) ; | 
				
			||||
@ -0,0 +1,234 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2005-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#ifdef HAVE_UNISTD_H | 
				
			||||
#include <unistd.h> | 
				
			||||
#endif | 
				
			||||
#include <string.h> | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#if (HAVE_SNDFILE) | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
#include <sndfile.h> | 
				
			||||
 | 
				
			||||
#define ARRAY_LEN(x)	((int) (sizeof (x) / sizeof ((x) [0]))) | 
				
			||||
 | 
				
			||||
#define DEFAULT_CONVERTER 	SRC_SINC_MEDIUM_QUALITY | 
				
			||||
 | 
				
			||||
#define	BUFFER_LEN			1024 | 
				
			||||
#define	INPUT_STEP_SIZE		8 | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	sf_count_t	index ; | 
				
			||||
	double		ratio ; | 
				
			||||
} TIMEWARP_FACTOR ; | 
				
			||||
 | 
				
			||||
static void usage_exit (const char *progname) ; | 
				
			||||
static sf_count_t timewarp_convert (SNDFILE *infile, SNDFILE *outfile, int converter, int channels) ; | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (int argc, char *argv []) | 
				
			||||
{	SNDFILE	*infile, *outfile ; | 
				
			||||
	SF_INFO sfinfo ; | 
				
			||||
	sf_count_t	count ; | 
				
			||||
 | 
				
			||||
	if (argc != 3) | 
				
			||||
		usage_exit (argv [0]) ; | 
				
			||||
 | 
				
			||||
	putchar ('\n') ; | 
				
			||||
	printf ("Input File    : %s\n", argv [argc - 2]) ; | 
				
			||||
	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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (INPUT_STEP_SIZE * sfinfo.channels > BUFFER_LEN) | 
				
			||||
	{	printf ("\n\nError : INPUT_STEP_SIZE * sfinfo.channels > BUFFER_LEN\n\n") ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
	/* Delete the output file length to zero if already exists. */ | 
				
			||||
	remove (argv [argc - 1]) ; | 
				
			||||
 | 
				
			||||
	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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ; | 
				
			||||
 | 
				
			||||
	printf ("Output file   : %s\n", argv [argc - 1]) ; | 
				
			||||
	printf ("Converter     : %s\n", src_get_name (DEFAULT_CONVERTER)) ; | 
				
			||||
 | 
				
			||||
	count = timewarp_convert (infile, outfile, DEFAULT_CONVERTER, sfinfo.channels) ; | 
				
			||||
 | 
				
			||||
	printf ("Output Frames : %ld\n\n", (long) count) ; | 
				
			||||
 | 
				
			||||
	sf_close (infile) ; | 
				
			||||
	sf_close (outfile) ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static TIMEWARP_FACTOR warp [] = | 
				
			||||
{	{	0		, 1.00000001 }, | 
				
			||||
	{	20000	, 1.01000000 }, | 
				
			||||
	{	20200	, 1.00000001 }, | 
				
			||||
	{	40000	, 1.20000000 }, | 
				
			||||
	{	40300	, 1.00000001 }, | 
				
			||||
	{	60000	, 1.10000000 }, | 
				
			||||
	{	60400	, 1.00000001 }, | 
				
			||||
	{	80000	, 1.50000000 }, | 
				
			||||
	{	81000	, 1.00000001 }, | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
static sf_count_t | 
				
			||||
timewarp_convert (SNDFILE *infile, SNDFILE *outfile, int converter, int channels) | 
				
			||||
{	static float input [BUFFER_LEN] ; | 
				
			||||
	static float output [BUFFER_LEN] ; | 
				
			||||
 | 
				
			||||
	SRC_STATE	*src_state ; | 
				
			||||
	SRC_DATA	src_data ; | 
				
			||||
	int			error, warp_index = 0 ; | 
				
			||||
	sf_count_t	input_count = 0, 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 ; | 
				
			||||
 | 
				
			||||
	if (warp [0].index > 0) | 
				
			||||
		src_data.src_ratio = 1.0 ; | 
				
			||||
	else | 
				
			||||
	{	src_data.src_ratio = warp [0].ratio ; | 
				
			||||
		warp_index ++ ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	src_data.data_out = output ; | 
				
			||||
	src_data.output_frames = BUFFER_LEN /channels ; | 
				
			||||
 | 
				
			||||
	while (1) | 
				
			||||
	{ | 
				
			||||
		if (warp_index < ARRAY_LEN (warp) - 1 && input_count >= warp [warp_index].index) | 
				
			||||
		{	src_data.src_ratio = warp [warp_index].ratio ; | 
				
			||||
			warp_index ++ ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/* If the input buffer is empty, refill it. */ | 
				
			||||
		if (src_data.input_frames == 0) | 
				
			||||
		{	src_data.input_frames = (long) sf_readf_float (infile, input, INPUT_STEP_SIZE) ; | 
				
			||||
			input_count += src_data.input_frames ; | 
				
			||||
			src_data.data_in = input ; | 
				
			||||
 | 
				
			||||
			/* The last read will not be a full buffer, so snd_of_input. */ | 
				
			||||
			if (src_data.input_frames < INPUT_STEP_SIZE) | 
				
			||||
				src_data.end_of_input = SF_TRUE ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/* Process current block. */ | 
				
			||||
		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 ; | 
				
			||||
 | 
				
			||||
		/* 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_delete (src_state) ; | 
				
			||||
 | 
				
			||||
	return output_count ; | 
				
			||||
} /* timewarp_convert */ | 
				
			||||
 | 
				
			||||
/*------------------------------------------------------------------------------
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
usage_exit (const char *progname) | 
				
			||||
{	const char	*cptr ; | 
				
			||||
 | 
				
			||||
	if ((cptr = strrchr (progname, '/')) != NULL) | 
				
			||||
		progname = cptr + 1 ; | 
				
			||||
 | 
				
			||||
	if ((cptr = strrchr (progname, '\\')) != NULL) | 
				
			||||
		progname = cptr + 1 ; | 
				
			||||
 | 
				
			||||
	printf ("\n" | 
				
			||||
		"  A program demonstrating the time warping capabilities of libsamplerate." | 
				
			||||
		"  It uses libsndfile for file I/O and Secret Rabbit Code (aka libsamplerate)" | 
				
			||||
		"  for performing the warping.\n" | 
				
			||||
		"  It works on any file format supported by libsndfile with any \n" | 
				
			||||
		"  number of channels (limited only by host memory).\n" | 
				
			||||
		"\n" | 
				
			||||
		"  The warping is dependant on a table hard code into the source code.\n" | 
				
			||||
		"\n" | 
				
			||||
		"  libsamplerate version : %s\n" | 
				
			||||
		"\n" | 
				
			||||
		"  Usage : \n" | 
				
			||||
		"       %s <input file> <output file>\n" | 
				
			||||
		"\n", src_get_version (), progname) ; | 
				
			||||
 | 
				
			||||
	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" | 
				
			||||
		"  (https://github.com/libsndfile/libsndfile/).\n" | 
				
			||||
		"  It is therefore completely broken and non-functional.\n" | 
				
			||||
		"****************************************************************\n" | 
				
			||||
		"\n" | 
				
			||||
		) ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
@ -0,0 +1,246 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#ifdef HAVE_UNISTD_H | 
				
			||||
#include <unistd.h> | 
				
			||||
#endif | 
				
			||||
#include <string.h> | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#if (HAVE_SNDFILE) | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
#include <sndfile.h> | 
				
			||||
 | 
				
			||||
#include "audio_out.h" | 
				
			||||
 | 
				
			||||
#define ARRAY_LEN(x)	((int) (sizeof (x) / sizeof ((x) [0]))) | 
				
			||||
 | 
				
			||||
#define	BUFFER_LEN			4096 | 
				
			||||
#define	VARISPEED_BLOCK_LEN	64 | 
				
			||||
 | 
				
			||||
#define	MIN(a,b)		((a) < (b) ? (a) : (b)) | 
				
			||||
 | 
				
			||||
#define	SRC_MAGIC		((int) ('S' << 16) + ('R' << 8) + ('C')) | 
				
			||||
#define	SNDFILE_MAGIC	((int) ('s' << 24) + ('n' << 20) + ('d' << 16) + ('f' << 12) + ('i' << 8) + ('l' << 4) + 'e') | 
				
			||||
 | 
				
			||||
#ifndef	M_PI | 
				
			||||
#define	M_PI			3.14159265358979323846264338 | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	int			magic ; | 
				
			||||
	SNDFILE 	*sndfile ; | 
				
			||||
	SF_INFO 	sfinfo ; | 
				
			||||
 | 
				
			||||
	float		buffer	[BUFFER_LEN] ; | 
				
			||||
} SNDFILE_CB_DATA ; | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	int			magic ; | 
				
			||||
 | 
				
			||||
	SNDFILE_CB_DATA	sf ; | 
				
			||||
 | 
				
			||||
	int			freq_point ; | 
				
			||||
 | 
				
			||||
	SRC_STATE	*src_state ; | 
				
			||||
 | 
				
			||||
} SRC_CB_DATA ; | 
				
			||||
 | 
				
			||||
static int varispeed_get_data (SRC_CB_DATA *data, float *samples, int frames) ; | 
				
			||||
static void varispeed_play (const char *filename, int converter) ; | 
				
			||||
 | 
				
			||||
static long src_input_callback (void *cb_data, float **data) ; | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (int argc, char *argv []) | 
				
			||||
{	const char	*cptr, *progname, *filename ; | 
				
			||||
	int			k, converter ; | 
				
			||||
 | 
				
			||||
	converter = SRC_SINC_FASTEST ; | 
				
			||||
 | 
				
			||||
	progname = argv [0] ; | 
				
			||||
 | 
				
			||||
	if ((cptr = strrchr (progname, '/')) != NULL) | 
				
			||||
		progname = cptr + 1 ; | 
				
			||||
 | 
				
			||||
	if ((cptr = strrchr (progname, '\\')) != NULL) | 
				
			||||
		progname = cptr + 1 ; | 
				
			||||
 | 
				
			||||
	printf ("\n" | 
				
			||||
		"  %s\n" | 
				
			||||
		"\n" | 
				
			||||
		"  This is a demo program which plays the given file at a slowly \n" | 
				
			||||
		"  varying speed. Lots of fun with drum loops and full mixes.\n" | 
				
			||||
		"\n" | 
				
			||||
		"  It uses Secret Rabbit Code (aka libsamplerate) to perform the \n" | 
				
			||||
		"  vari-speeding and libsndfile for file I/O.\n" | 
				
			||||
		"\n", progname) ; | 
				
			||||
 | 
				
			||||
	if (argc == 2) | 
				
			||||
		filename = argv [1] ; | 
				
			||||
	else if (argc == 4 && strcmp (argv [1], "-c") == 0) | 
				
			||||
	{	filename = argv [3] ; | 
				
			||||
		converter = atoi (argv [2]) ; | 
				
			||||
		} | 
				
			||||
	else | 
				
			||||
	{	printf ("  Usage :\n\n       %s [-c <number>] <input file>\n\n", 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\n", k, cptr) ; | 
				
			||||
 | 
				
			||||
		puts ("") ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	varispeed_play (filename, converter) ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
varispeed_play (const char *filename, int converter) | 
				
			||||
{	SRC_CB_DATA		data ; | 
				
			||||
	AUDIO_OUT		*audio_out ; | 
				
			||||
	int				error ; | 
				
			||||
 | 
				
			||||
	memset (&data, 0, sizeof (data)) ; | 
				
			||||
 | 
				
			||||
	data.magic = SRC_MAGIC ; | 
				
			||||
	data.sf.magic = SNDFILE_MAGIC ; | 
				
			||||
 | 
				
			||||
	if ((data.sf.sndfile = sf_open (filename, SFM_READ, &data.sf.sfinfo)) == NULL) | 
				
			||||
	{	puts (sf_strerror (NULL)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Initialize the sample rate converter. */ | 
				
			||||
	if ((data.src_state = src_callback_new (src_input_callback, converter, data.sf.sfinfo.channels, &error, &data.sf)) == NULL) | 
				
			||||
	{	printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	printf ( | 
				
			||||
 | 
				
			||||
		"  Playing   : %s\n" | 
				
			||||
		"  Converter : %s\n" | 
				
			||||
		"\n" | 
				
			||||
		"  Press <control-c> to exit.\n" | 
				
			||||
		"\n", | 
				
			||||
		filename, src_get_name (converter)) ; | 
				
			||||
 | 
				
			||||
	if ((audio_out = audio_open (data.sf.sfinfo.channels, data.sf.sfinfo.samplerate)) == NULL) | 
				
			||||
	{	printf ("\n\nError : audio_open () failed.\n") ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Pass the data and the callbacl function to audio_play */ | 
				
			||||
	audio_play ((get_audio_callback_t) varispeed_get_data, audio_out, &data) ; | 
				
			||||
 | 
				
			||||
	/* Cleanup */ | 
				
			||||
	audio_close (audio_out) ; | 
				
			||||
	sf_close (data.sf.sndfile) ; | 
				
			||||
	src_delete (data.src_state) ; | 
				
			||||
 | 
				
			||||
} /* varispeed_play */ | 
				
			||||
 | 
				
			||||
static long | 
				
			||||
src_input_callback (void *cb_data, float **audio) | 
				
			||||
{	SNDFILE_CB_DATA * data = (SNDFILE_CB_DATA *) cb_data ; | 
				
			||||
	const int input_frames = ARRAY_LEN (data->buffer) / data->sfinfo.channels ; | 
				
			||||
	int		read_frames ; | 
				
			||||
 | 
				
			||||
	if (data->magic != SNDFILE_MAGIC) | 
				
			||||
	{	printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	for (read_frames = 0 ; read_frames < input_frames ; ) | 
				
			||||
	{	sf_count_t position ; | 
				
			||||
 | 
				
			||||
		read_frames += (int) sf_readf_float (data->sndfile, data->buffer + read_frames * data->sfinfo.channels, input_frames - read_frames) ; | 
				
			||||
 | 
				
			||||
		position = sf_seek (data->sndfile, 0, SEEK_CUR) ; | 
				
			||||
 | 
				
			||||
		if (position < 0 || position == data->sfinfo.frames) | 
				
			||||
			sf_seek (data->sndfile, 0, SEEK_SET) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	*audio = & (data->buffer [0]) ; | 
				
			||||
 | 
				
			||||
	return input_frames ; | 
				
			||||
} /* src_input_callback */ | 
				
			||||
 | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static int | 
				
			||||
varispeed_get_data (SRC_CB_DATA *data, float *samples, int out_frames) | 
				
			||||
{	float	*output ; | 
				
			||||
	int		rc, out_frame_count ; | 
				
			||||
 | 
				
			||||
	if (data->magic != SRC_MAGIC) | 
				
			||||
	{	printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	for (out_frame_count = 0 ; out_frame_count < out_frames ; out_frame_count += VARISPEED_BLOCK_LEN) | 
				
			||||
	{	double	src_ratio = 1.0 - 0.5 * sin (data->freq_point * 2 * M_PI / 20000) ; | 
				
			||||
 | 
				
			||||
		data->freq_point ++ ; | 
				
			||||
 | 
				
			||||
		output = samples + out_frame_count * data->sf.sfinfo.channels ; | 
				
			||||
 | 
				
			||||
		if ((rc = src_callback_read (data->src_state, src_ratio, VARISPEED_BLOCK_LEN, output)) < VARISPEED_BLOCK_LEN) | 
				
			||||
		{	printf ("\nError : src_callback_read short output (%d instead of %d)\n\n", rc, VARISPEED_BLOCK_LEN) ; | 
				
			||||
			exit (1) ; | 
				
			||||
			} ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return out_frames ; | 
				
			||||
} /* varispeed_get_data */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#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.zip.com.au/~erikd/libsndfile/).\n" | 
				
			||||
		" It is therefore completely broken and non-functional.\n" | 
				
			||||
		"****************************************************************\n" | 
				
			||||
		"\n" | 
				
			||||
		) ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
#endif | 
				
			||||
@ -0,0 +1,189 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** API documentation is available here: | 
				
			||||
**     http://libsndfile.github.io/libsamplerate/api.html
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifndef SAMPLERATE_H | 
				
			||||
#define SAMPLERATE_H | 
				
			||||
 | 
				
			||||
#ifdef __cplusplus | 
				
			||||
extern "C" { | 
				
			||||
#endif	/* __cplusplus */ | 
				
			||||
 | 
				
			||||
 | 
				
			||||
/* Opaque data type SRC_STATE. */ | 
				
			||||
typedef struct SRC_STATE_tag SRC_STATE ; | 
				
			||||
 | 
				
			||||
/* SRC_DATA is used to pass data to src_simple() and src_process(). */ | 
				
			||||
typedef struct | 
				
			||||
{	const float	*data_in ; | 
				
			||||
	float	*data_out ; | 
				
			||||
 | 
				
			||||
	long	input_frames, output_frames ; | 
				
			||||
	long	input_frames_used, output_frames_gen ; | 
				
			||||
 | 
				
			||||
	int		end_of_input ; | 
				
			||||
 | 
				
			||||
	double	src_ratio ; | 
				
			||||
} SRC_DATA ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** User supplied callback function type for use with src_callback_new() | 
				
			||||
** and src_callback_read(). First parameter is the same pointer that was | 
				
			||||
** passed into src_callback_new(). Second parameter is pointer to a | 
				
			||||
** pointer. The user supplied callback function must modify *data to | 
				
			||||
** point to the start of the user supplied float array. The user supplied | 
				
			||||
** function must return the number of frames that **data points to. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
typedef long (*src_callback_t) (void *cb_data, float **data) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Standard initialisation function : return an anonymous pointer to the | 
				
			||||
**	internal state of the converter. Choose a converter from the enums below. | 
				
			||||
**	Error returned in *error. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
SRC_STATE* src_new (int converter_type, int channels, int *error) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** Clone a handle : return an anonymous pointer to a new converter | 
				
			||||
** containing the same internal state as orig. Error returned in *error. | 
				
			||||
*/ | 
				
			||||
SRC_STATE* src_clone (SRC_STATE* orig, int *error) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Initilisation for callback based API : return an anonymous pointer to the | 
				
			||||
**	internal state of the converter. Choose a converter from the enums below. | 
				
			||||
**	The cb_data pointer can point to any data or be set to NULL. Whatever the | 
				
			||||
**	value, when processing, user supplied function "func" gets called with | 
				
			||||
**	cb_data as first parameter. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels, | 
				
			||||
				int *error, void* cb_data) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Cleanup all internal allocations. | 
				
			||||
**	Always returns NULL. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
SRC_STATE* src_delete (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Standard processing function. | 
				
			||||
**	Returns non zero on error. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_process (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Callback based processing function. Read up to frames worth of data from | 
				
			||||
**	the converter int *data and return frames read or -1 on error. | 
				
			||||
*/ | 
				
			||||
long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Simple interface for performing a single conversion from input buffer to | 
				
			||||
**	output buffer at a fixed conversion ratio. | 
				
			||||
**	Simple interface does not require initialisation as it can only operate on | 
				
			||||
**	a single buffer worth of audio. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_simple (SRC_DATA *data, int converter_type, int channels) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** This library contains a number of different sample rate converters, | 
				
			||||
** numbered 0 through N. | 
				
			||||
** | 
				
			||||
** Return a string giving either a name or a more full description of each | 
				
			||||
** sample rate converter or NULL if no sample rate converter exists for | 
				
			||||
** the given value. The converters are sequentially numbered from 0 to N. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
const char *src_get_name (int converter_type) ; | 
				
			||||
const char *src_get_description (int converter_type) ; | 
				
			||||
const char *src_get_version (void) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Set a new SRC ratio. This allows step responses | 
				
			||||
**	in the conversion ratio. | 
				
			||||
**	Returns non zero on error. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_set_ratio (SRC_STATE *state, double new_ratio) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Get the current channel count. | 
				
			||||
**	Returns negative on error, positive channel count otherwise | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_get_channels (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Reset the internal SRC state. | 
				
			||||
**	Does not modify the quality settings. | 
				
			||||
**	Does not free any memory allocations. | 
				
			||||
**	Returns non zero on error. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_reset (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** Return TRUE if ratio is a valid conversion ratio, FALSE | 
				
			||||
** otherwise. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_is_valid_ratio (double ratio) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Return an error number. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int src_error (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
**	Convert the error number into a string. | 
				
			||||
*/ | 
				
			||||
const char* src_strerror (int error) ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** The following enums can be used to set the interpolator type | 
				
			||||
** using the function src_set_converter(). | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
enum | 
				
			||||
{ | 
				
			||||
	SRC_SINC_BEST_QUALITY		= 0, | 
				
			||||
	SRC_SINC_MEDIUM_QUALITY		= 1, | 
				
			||||
	SRC_SINC_FASTEST			= 2, | 
				
			||||
	SRC_ZERO_ORDER_HOLD			= 3, | 
				
			||||
	SRC_LINEAR					= 4, | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** Extra helper functions for converting from short to float and | 
				
			||||
** back again. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
void src_short_to_float_array (const short *in, float *out, int len) ; | 
				
			||||
void src_float_to_short_array (const float *in, short *out, int len) ; | 
				
			||||
 | 
				
			||||
void src_int_to_float_array (const int *in, float *out, int len) ; | 
				
			||||
void src_float_to_int_array (const float *in, int *out, int len) ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
#ifdef __cplusplus | 
				
			||||
}		/* extern "C" */ | 
				
			||||
#endif	/* __cplusplus */ | 
				
			||||
 | 
				
			||||
#endif	/* SAMPLERATE_H */ | 
				
			||||
 | 
				
			||||
@ -0,0 +1,58 @@ | 
				
			||||
 | 
				
			||||
%define name    @PACKAGE@ | 
				
			||||
%define version @VERSION@ | 
				
			||||
%define release 1 | 
				
			||||
%define prefix  /usr | 
				
			||||
 | 
				
			||||
Summary: A library to do sample rate conversion for audio. | 
				
			||||
Name: %{name} | 
				
			||||
Version: %{version} | 
				
			||||
Release: %{release} | 
				
			||||
Prefix: %{prefix} | 
				
			||||
Copyright: BSD | 
				
			||||
Group: Libraries/Sound | 
				
			||||
Source: http://www.mega-nerd.com/SRC/libsamplerate-%{version}.tar.gz | 
				
			||||
URL: https://github.com/libsndfile/libsamplerate/ | 
				
			||||
BuildRoot: /var/tmp/%{name}-%{version} | 
				
			||||
 | 
				
			||||
%description | 
				
			||||
libsamplerate is a C library capable of arbitrary and time varying | 
				
			||||
conversions; from downsampling by a factor of 12 to upsampling by the | 
				
			||||
same factor. The conversion ratio can also vary with time for speeding | 
				
			||||
up and slowing down effects. | 
				
			||||
 | 
				
			||||
%package devel | 
				
			||||
Summary: Libraries, includes, etc to develop libsamplerate applications | 
				
			||||
Group: Libraries | 
				
			||||
 | 
				
			||||
%description devel | 
				
			||||
Libraries, include files, etc you can use to develop libsamplerate applications. | 
				
			||||
 | 
				
			||||
%prep | 
				
			||||
%setup | 
				
			||||
 | 
				
			||||
%build | 
				
			||||
./configure --prefix=%{prefix} | 
				
			||||
make | 
				
			||||
 | 
				
			||||
%install | 
				
			||||
if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi | 
				
			||||
mkdir -p $RPM_BUILD_ROOT | 
				
			||||
make prefix=$RPM_BUILD_ROOT%{prefix} install | 
				
			||||
 | 
				
			||||
%clean | 
				
			||||
if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi | 
				
			||||
 | 
				
			||||
%files | 
				
			||||
%defattr(-,root,root) | 
				
			||||
%doc AUTHORS COPYING ChangeLog INSTALL NEWS README doc | 
				
			||||
%prefix/lib/libsamplerate.so.* | 
				
			||||
 | 
				
			||||
%files devel | 
				
			||||
%defattr(-,root,root) | 
				
			||||
%{prefix}/lib/libsamplerate.a | 
				
			||||
%{prefix}/lib/libsamplerate.la | 
				
			||||
%{prefix}/lib/libsamplerate.so | 
				
			||||
%{prefix}/include/samplerate.h | 
				
			||||
%{prefix}/lib/pkgconfig/samplerate.pc | 
				
			||||
 | 
				
			||||
@ -0,0 +1,67 @@ | 
				
			||||
# ============================================================================ | 
				
			||||
#  https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html | 
				
			||||
# ============================================================================ | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   For every FLAG1, FLAG2 it is checked whether the compiler works with the | 
				
			||||
#   flag.  If it does, the flag is added FLAGS-VARIABLE | 
				
			||||
# | 
				
			||||
#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g. | 
				
			||||
#   CFLAGS) is used.  During the check the flag is always added to the | 
				
			||||
#   current language's flags. | 
				
			||||
# | 
				
			||||
#   If EXTRA-FLAGS is defined, it is added to the current language's default | 
				
			||||
#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with | 
				
			||||
#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to | 
				
			||||
#   force the compiler to issue an error when a bad flag is given. | 
				
			||||
# | 
				
			||||
#   INPUT gives an alternative input source to AC_COMPILE_IFELSE. | 
				
			||||
# | 
				
			||||
#   NOTE: This macro depends on the AX_APPEND_FLAG and | 
				
			||||
#   AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with | 
				
			||||
#   AX_APPEND_LINK_FLAGS. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.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 3 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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 6 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_APPEND_COMPILE_FLAGS], | 
				
			||||
[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) | 
				
			||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) | 
				
			||||
for flag in $1; do | 
				
			||||
  AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) | 
				
			||||
done | 
				
			||||
])dnl AX_APPEND_COMPILE_FLAGS | 
				
			||||
@ -0,0 +1,71 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#      https://www.gnu.org/software/autoconf-archive/ax_append_flag.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   FLAG is appended to the FLAGS-VARIABLE shell variable, with a space | 
				
			||||
#   added in between. | 
				
			||||
# | 
				
			||||
#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g. | 
				
			||||
#   CFLAGS) is used.  FLAGS-VARIABLE is not changed if it already contains | 
				
			||||
#   FLAG.  If FLAGS-VARIABLE is unset in the shell, it is set to exactly | 
				
			||||
#   FLAG. | 
				
			||||
# | 
				
			||||
#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> | 
				
			||||
#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.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 3 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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 7 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_APPEND_FLAG], | 
				
			||||
[dnl | 
				
			||||
AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF | 
				
			||||
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) | 
				
			||||
AS_VAR_SET_IF(FLAGS,[ | 
				
			||||
  AS_CASE([" AS_VAR_GET(FLAGS) "], | 
				
			||||
    [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], | 
				
			||||
    [ | 
				
			||||
     AS_VAR_APPEND(FLAGS,[" $1"]) | 
				
			||||
     AC_RUN_LOG([: FLAGS="$FLAGS"]) | 
				
			||||
    ]) | 
				
			||||
  ], | 
				
			||||
  [ | 
				
			||||
  AS_VAR_SET(FLAGS,[$1]) | 
				
			||||
  AC_RUN_LOG([: FLAGS="$FLAGS"]) | 
				
			||||
  ]) | 
				
			||||
AS_VAR_POPDEF([FLAGS])dnl | 
				
			||||
])dnl AX_APPEND_FLAG | 
				
			||||
@ -0,0 +1,65 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#   https://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   For every FLAG1, FLAG2 it is checked whether the linker works with the | 
				
			||||
#   flag.  If it does, the flag is added FLAGS-VARIABLE | 
				
			||||
# | 
				
			||||
#   If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is | 
				
			||||
#   used. During the check the flag is always added to the linker's flags. | 
				
			||||
# | 
				
			||||
#   If EXTRA-FLAGS is defined, it is added to the linker's default flags | 
				
			||||
#   when the check is done.  The check is thus made with the flags: "LDFLAGS | 
				
			||||
#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to | 
				
			||||
#   issue an error when a bad flag is given. | 
				
			||||
# | 
				
			||||
#   INPUT gives an alternative input source to AC_COMPILE_IFELSE. | 
				
			||||
# | 
				
			||||
#   NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG. | 
				
			||||
#   Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.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 3 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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 6 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_APPEND_LINK_FLAGS], | 
				
			||||
[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) | 
				
			||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) | 
				
			||||
for flag in $1; do | 
				
			||||
  AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4]) | 
				
			||||
done | 
				
			||||
])dnl AX_APPEND_LINK_FLAGS | 
				
			||||
@ -0,0 +1,74 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#  https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   Check whether the given FLAG works with the current language's compiler | 
				
			||||
#   or gives an error.  (Warnings, however, are ignored) | 
				
			||||
# | 
				
			||||
#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on | 
				
			||||
#   success/failure. | 
				
			||||
# | 
				
			||||
#   If EXTRA-FLAGS is defined, it is added to the current language's default | 
				
			||||
#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with | 
				
			||||
#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to | 
				
			||||
#   force the compiler to issue an error when a bad flag is given. | 
				
			||||
# | 
				
			||||
#   INPUT gives an alternative input source to AC_COMPILE_IFELSE. | 
				
			||||
# | 
				
			||||
#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this | 
				
			||||
#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> | 
				
			||||
#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.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 3 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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 5 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG], | 
				
			||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF | 
				
			||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl | 
				
			||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ | 
				
			||||
  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS | 
				
			||||
  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" | 
				
			||||
  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], | 
				
			||||
    [AS_VAR_SET(CACHEVAR,[yes])], | 
				
			||||
    [AS_VAR_SET(CACHEVAR,[no])]) | 
				
			||||
  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) | 
				
			||||
AS_VAR_IF(CACHEVAR,yes, | 
				
			||||
  [m4_default([$2], :)], | 
				
			||||
  [m4_default([$3], :)]) | 
				
			||||
AS_VAR_POPDEF([CACHEVAR])dnl | 
				
			||||
])dnl AX_CHECK_COMPILE_FLAGS | 
				
			||||
@ -0,0 +1,74 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#    https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   Check whether the given FLAG works with the linker or gives an error. | 
				
			||||
#   (Warnings, however, are ignored) | 
				
			||||
# | 
				
			||||
#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on | 
				
			||||
#   success/failure. | 
				
			||||
# | 
				
			||||
#   If EXTRA-FLAGS is defined, it is added to the linker's default flags | 
				
			||||
#   when the check is done.  The check is thus made with the flags: "LDFLAGS | 
				
			||||
#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to | 
				
			||||
#   issue an error when a bad flag is given. | 
				
			||||
# | 
				
			||||
#   INPUT gives an alternative input source to AC_LINK_IFELSE. | 
				
			||||
# | 
				
			||||
#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this | 
				
			||||
#   macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> | 
				
			||||
#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.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 3 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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 5 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_CHECK_LINK_FLAG], | 
				
			||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF | 
				
			||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl | 
				
			||||
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ | 
				
			||||
  ax_check_save_flags=$LDFLAGS | 
				
			||||
  LDFLAGS="$LDFLAGS $4 $1" | 
				
			||||
  AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], | 
				
			||||
    [AS_VAR_SET(CACHEVAR,[yes])], | 
				
			||||
    [AS_VAR_SET(CACHEVAR,[no])]) | 
				
			||||
  LDFLAGS=$ax_check_save_flags]) | 
				
			||||
AS_VAR_IF(CACHEVAR,yes, | 
				
			||||
  [m4_default([$2], :)], | 
				
			||||
  [m4_default([$3], :)]) | 
				
			||||
AS_VAR_POPDEF([CACHEVAR])dnl | 
				
			||||
])dnl AX_CHECK_LINK_FLAGS | 
				
			||||
@ -0,0 +1,87 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#    https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_COMPILER_VENDOR | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, | 
				
			||||
#   hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, | 
				
			||||
#   watcom, etc. The vendor is returned in the cache variable | 
				
			||||
#   $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu> | 
				
			||||
#   Copyright (c) 2008 Matteo Frigo | 
				
			||||
# | 
				
			||||
#   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 3 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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 16 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_COMPILER_VENDOR], | 
				
			||||
[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, | 
				
			||||
  dnl Please add if possible support to ax_compiler_version.m4 | 
				
			||||
  [# note: don't check for gcc first since some other compilers define __GNUC__ | 
				
			||||
  vendors="intel:     __ICC,__ECC,__INTEL_COMPILER | 
				
			||||
           ibm:       __xlc__,__xlC__,__IBMC__,__IBMCPP__ | 
				
			||||
           pathscale: __PATHCC__,__PATHSCALE__ | 
				
			||||
           clang:     __clang__ | 
				
			||||
           cray:      _CRAYC | 
				
			||||
           fujitsu:   __FUJITSU | 
				
			||||
           gnu:       __GNUC__ | 
				
			||||
           sun:       __SUNPRO_C,__SUNPRO_CC | 
				
			||||
           hp:        __HP_cc,__HP_aCC | 
				
			||||
           dec:       __DECC,__DECCXX,__DECC_VER,__DECCXX_VER | 
				
			||||
           borland:   __BORLANDC__,__CODEGEARC__,__TURBOC__ | 
				
			||||
           comeau:    __COMO__ | 
				
			||||
           kai:       __KCC | 
				
			||||
           lcc:       __LCC__ | 
				
			||||
           sgi:       __sgi,sgi | 
				
			||||
           microsoft: _MSC_VER | 
				
			||||
           metrowerks: __MWERKS__ | 
				
			||||
           watcom:    __WATCOMC__ | 
				
			||||
           portland:  __PGI | 
				
			||||
	   tcc:       __TINYC__ | 
				
			||||
           unknown:   UNKNOWN" | 
				
			||||
  for ventest in $vendors; do | 
				
			||||
    case $ventest in | 
				
			||||
      *:) vendor=$ventest; continue ;; | 
				
			||||
      *)  vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; | 
				
			||||
    esac | 
				
			||||
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ | 
				
			||||
      #if !($vencpp) | 
				
			||||
        thisisanerror; | 
				
			||||
      #endif | 
				
			||||
    ])], [break]) | 
				
			||||
  done | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` | 
				
			||||
 ]) | 
				
			||||
]) | 
				
			||||
@ -0,0 +1,492 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#   https://www.gnu.org/software/autoconf-archive/ax_compiler_version.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_COMPILER_VERSION | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   This macro retrieves the compiler version and returns it in the cache | 
				
			||||
#   variable $ax_cv_c_compiler_version for C and $ax_cv_cxx_compiler_version | 
				
			||||
#   for C++. | 
				
			||||
# | 
				
			||||
#   Version is returned as epoch:major.minor.patchversion | 
				
			||||
# | 
				
			||||
#   Epoch is used in order to have an increasing version number in case of | 
				
			||||
#   marketing change. | 
				
			||||
# | 
				
			||||
#   Epoch use: * borland compiler use chronologically 0turboc for turboc | 
				
			||||
#   era, | 
				
			||||
# | 
				
			||||
#     1borlanc BORLANDC++ before 5, 2cppbuilder for cppbuilder era, | 
				
			||||
#     3borlancpp for return of BORLANDC++ (after version 5.5), | 
				
			||||
#     4cppbuilder for cppbuilder with year version, | 
				
			||||
#     and 5xe for XE era. | 
				
			||||
# | 
				
			||||
#   An empty string is returned otherwise. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2014 Bastien ROUCARIES <roucaries.bastien+autoconf@gmail.com> | 
				
			||||
# | 
				
			||||
#   Copying and distribution of this file, with or without modification, are | 
				
			||||
#   permitted in any medium without royalty provided the copyright notice | 
				
			||||
#   and this notice are preserved. This file is offered as-is, without any | 
				
			||||
#   warranty. | 
				
			||||
 | 
				
			||||
#serial 9 | 
				
			||||
 | 
				
			||||
# for intel | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_INTEL], | 
				
			||||
  [ dnl | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    [__INTEL_COMPILER/100],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown intel compiler version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    [(__INTEL_COMPILER%100)/10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown intel compiler version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [(__INTEL_COMPILER%10)],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown intel compiler version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for IBM | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_IBM], | 
				
			||||
  [ dnl | 
				
			||||
  dnl check between z/OS C/C++  and XL C/C++ | 
				
			||||
  AC_COMPILE_IFELSE([ | 
				
			||||
    AC_LANG_PROGRAM([], | 
				
			||||
      [ | 
				
			||||
        #if defined(__COMPILER_VER__) | 
				
			||||
        choke me; | 
				
			||||
        #endif | 
				
			||||
      ])], | 
				
			||||
    [ | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
        [__xlC__/100],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler major version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
        [__xlC__%100],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler minor version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
        [__xlC_ver__/0x100],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler patch version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_build, | 
				
			||||
        [__xlC_ver__%0x100],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler build version])) | 
				
			||||
      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_build" | 
				
			||||
    ], | 
				
			||||
    [ | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
        [__xlC__%1000],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler patch version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
        [(__xlC__/10000)%10],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler minor version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
        [(__xlC__/100000)%10],, | 
				
			||||
      	AC_MSG_FAILURE([[[$0]] unknown IBM compiler major version])) | 
				
			||||
      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
    ]) | 
				
			||||
]) | 
				
			||||
 | 
				
			||||
# for pathscale | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_PATHSCALE],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    __PATHCC__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown pathscale major])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    __PATHCC_MINOR__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown pathscale minor])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [__PATHCC_PATCHLEVEL__],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown pathscale patch level])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for clang | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_CLANG],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    __clang_major__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown clang major])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    __clang_minor__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown clang minor])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [__clang_patchlevel__],,0) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for crayc | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_CRAY],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    _RELEASE,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown crayc release])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    _RELEASE_MINOR,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown crayc minor])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for fujitsu | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_FUJITSU],[ | 
				
			||||
  AC_COMPUTE_INT(ax_cv_[]_AC_LANG_ABBREV[]_compiler_version, | 
				
			||||
                 __FCC_VERSION,, | 
				
			||||
		 AC_MSG_FAILURE([[[$0]]unknown fujitsu release])) | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for GNU | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_GNU],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    __GNUC__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown gcc major])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    __GNUC_MINOR__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown gcc minor])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [__GNUC_PATCHLEVEL__],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown gcc patch level])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# For sun | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_SUN],[ | 
				
			||||
  m4_define([_AX_COMPILER_VERSION_SUN_NUMBER], | 
				
			||||
            [ | 
				
			||||
	     #if defined(__SUNPRO_CC) | 
				
			||||
	     __SUNPRO_CC | 
				
			||||
	     #else | 
				
			||||
	     __SUNPRO_C | 
				
			||||
	     #endif | 
				
			||||
	    ]) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_until59, | 
				
			||||
    !!(_AX_COMPILER_VERSION_SUN_NUMBER < 0x1000),, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown sun release version])) | 
				
			||||
  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_until59" = X1], | 
				
			||||
    [dnl | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
        _AX_COMPILER_VERSION_SUN_NUMBER % 0x10,, | 
				
			||||
	AC_MSG_FAILURE([[[$0]] unknown sun patch version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x10) % 0x10,, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown sun minor version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x100),, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown sun major version])) | 
				
			||||
    ], | 
				
			||||
    [dnl | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
        _AX_COMPILER_VERSION_SUN_NUMBER % 0x10,, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown sun patch version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x100) % 0x100,, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown sun minor version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x1000),, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown sun major version])) | 
				
			||||
    ]) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
]) | 
				
			||||
 | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_HP],[ | 
				
			||||
  m4_define([_AX_COMPILER_VERSION_HP_NUMBER], | 
				
			||||
            [ | 
				
			||||
	     #if defined(__HP_cc) | 
				
			||||
	     __HP_cc | 
				
			||||
	     #else | 
				
			||||
	     __HP_aCC | 
				
			||||
	     #endif | 
				
			||||
	    ]) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_untilA0121, | 
				
			||||
    !!(_AX_COMPILER_VERSION_HP_NUMBER <= 1),, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown hp release version])) | 
				
			||||
  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_untilA0121" = X1], | 
				
			||||
    [dnl By default output last version with this behavior. | 
				
			||||
     dnl it is so old | 
				
			||||
      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="01.21.00" | 
				
			||||
    ], | 
				
			||||
    [dnl | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
        (_AX_COMPILER_VERSION_HP_NUMBER % 100),, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown hp release version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
        ((_AX_COMPILER_VERSION_HP_NUMBER / 100)%100),, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown hp minor version])) | 
				
			||||
      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
        ((_AX_COMPILER_VERSION_HP_NUMBER / 10000)%100),, | 
				
			||||
        AC_MSG_FAILURE([[[$0]] unknown hp major version])) | 
				
			||||
      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
    ]) | 
				
			||||
]) | 
				
			||||
 | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_DEC],[dnl | 
				
			||||
  m4_define([_AX_COMPILER_VERSION_DEC_NUMBER], | 
				
			||||
            [ | 
				
			||||
	     #if defined(__DECC_VER) | 
				
			||||
	     __DECC_VER | 
				
			||||
	     #else | 
				
			||||
	     __DECCXX_VER | 
				
			||||
	     #endif | 
				
			||||
	    ]) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    (_AX_COMPILER_VERSION_DEC_NUMBER % 10000),, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown dec release version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    ((_AX_COMPILER_VERSION_DEC_NUMBER / 100000UL)%100),, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown dec minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    ((_AX_COMPILER_VERSION_DEC_NUMBER / 10000000UL)%100),, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown dec major version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# borland | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_BORLAND],[dnl | 
				
			||||
  m4_define([_AX_COMPILER_VERSION_TURBOC_NUMBER], | 
				
			||||
            [ | 
				
			||||
	     #if defined(__TURBOC__) | 
				
			||||
	     __TURBOC__ | 
				
			||||
	     #else | 
				
			||||
	     choke me | 
				
			||||
	     #endif | 
				
			||||
	    ]) | 
				
			||||
  m4_define([_AX_COMPILER_VERSION_BORLANDC_NUMBER], | 
				
			||||
            [ | 
				
			||||
	     #if defined(__BORLANDC__) | 
				
			||||
	     __BORLANDC__ | 
				
			||||
	     #else | 
				
			||||
	     __CODEGEARC__ | 
				
			||||
	     #endif | 
				
			||||
	    ]) | 
				
			||||
 AC_COMPILE_IFELSE( | 
				
			||||
   [AC_LANG_PROGRAM(, | 
				
			||||
     _AX_COMPILER_VERSION_TURBOC_NUMBER)], | 
				
			||||
   [dnl TURBOC | 
				
			||||
     AC_COMPUTE_INT( | 
				
			||||
       _ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw, | 
				
			||||
       _AX_COMPILER_VERSION_TURBOC_NUMBER,, | 
				
			||||
       AC_MSG_FAILURE([[[$0]] unknown turboc version])) | 
				
			||||
     AS_IF( | 
				
			||||
       [test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw -lt 661 || test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw -gt 1023], | 
				
			||||
       [dnl compute normal version | 
				
			||||
        AC_COMPUTE_INT( | 
				
			||||
	  _ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
	  _AX_COMPILER_VERSION_TURBOC_NUMBER % 0x100,, | 
				
			||||
	  AC_MSG_FAILURE([[[$0]] unknown turboc minor version])) | 
				
			||||
	AC_COMPUTE_INT( | 
				
			||||
	  _ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
	  (_AX_COMPILER_VERSION_TURBOC_NUMBER/0x100)%0x100,, | 
				
			||||
	  AC_MSG_FAILURE([[[$0]] unknown turboc major version])) | 
				
			||||
	ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor"], | 
				
			||||
      [dnl special version | 
				
			||||
       AS_CASE([$_ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw], | 
				
			||||
         [661],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:1.00"], | 
				
			||||
	 [662],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:1.01"], | 
				
			||||
         [663],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:2.00"], | 
				
			||||
	 [ | 
				
			||||
	 AC_MSG_WARN([[[$0]] unknown turboc version between 0x295 and 0x400 please report bug]) | 
				
			||||
	 ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="" | 
				
			||||
	 ]) | 
				
			||||
      ]) | 
				
			||||
    ], | 
				
			||||
    # borlandc | 
				
			||||
    [ | 
				
			||||
    AC_COMPUTE_INT( | 
				
			||||
      _ax_[]_AC_LANG_ABBREV[]_compiler_version_borlandc_raw, | 
				
			||||
      _AX_COMPILER_VERSION_BORLANDC_NUMBER,, | 
				
			||||
      AC_MSG_FAILURE([[[$0]] unknown borlandc version])) | 
				
			||||
    AS_CASE([$_ax_[]_AC_LANG_ABBREV[]_compiler_version_borlandc_raw], | 
				
			||||
      dnl BORLANDC++ before 5.5 | 
				
			||||
      [512] ,[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:2.00"], | 
				
			||||
      [1024],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:3.00"], | 
				
			||||
      [1024],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:3.00"], | 
				
			||||
      [1040],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:3.1"], | 
				
			||||
      [1106],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:4.0"], | 
				
			||||
      [1280],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:5.0"], | 
				
			||||
      [1312],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:5.02"], | 
				
			||||
      dnl C++ Builder era | 
				
			||||
      [1328],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="2cppbuilder:3.0"], | 
				
			||||
      [1344],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="2cppbuilder:4.0"], | 
				
			||||
      dnl BORLANDC++ after 5.5 | 
				
			||||
      [1360],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="3borlancpp:5.5"], | 
				
			||||
      [1361],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="3borlancpp:5.51"], | 
				
			||||
      [1378],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="3borlancpp:5.6.4"], | 
				
			||||
      dnl C++ Builder with year number | 
				
			||||
      [1392],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2006"], | 
				
			||||
      [1424],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2007"], | 
				
			||||
      [1555],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2009"], | 
				
			||||
      [1569],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2010"], | 
				
			||||
      dnl XE version | 
				
			||||
      [1584],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe"], | 
				
			||||
      [1600],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe:2"], | 
				
			||||
      [1616],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe:3"], | 
				
			||||
      [1632],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe:4"], | 
				
			||||
      [ | 
				
			||||
      AC_MSG_WARN([[[$0]] Unknown borlandc compiler version $_ax_[]_AC_LANG_ABBREV[]_compiler_version_borlandc_raw please report bug]) | 
				
			||||
      ]) | 
				
			||||
    ]) | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# COMO | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_COMEAU], | 
				
			||||
  [ dnl | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    [__COMO_VERSION__%100],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown comeau compiler minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    [(__COMO_VERSION__/100)%10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown comeau compiler major version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# KAI | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_KAI],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [__KCC_VERSION%100],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown kay compiler patch version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    [(__KCC_VERSION/100)%10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown kay compiler minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    [(__KCC_VERSION/1000)%10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown kay compiler major version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
dnl LCC | 
				
			||||
dnl LCC does not output version... | 
				
			||||
 | 
				
			||||
# SGI | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_SGI],[ | 
				
			||||
   m4_define([_AX_COMPILER_VERSION_SGI_NUMBER], | 
				
			||||
            [ | 
				
			||||
	     #if defined(_COMPILER_VERSION) | 
				
			||||
	     _COMPILER_VERSION | 
				
			||||
	     #else | 
				
			||||
	     _SGI_COMPILER_VERSION | 
				
			||||
	     #endif | 
				
			||||
	    ]) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [_AX_COMPILER_VERSION_SGI_NUMBER%10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown SGI compiler patch version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    [(_AX_COMPILER_VERSION_SGI_NUMBER/10)%10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown SGI compiler minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    [(_AX_COMPILER_VERSION_SGI_NUMBER/100)%10],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown SGI compiler major version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# microsoft | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_MICROSOFT],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    _MSC_VER%100,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown microsoft compiler minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    (_MSC_VER/100)%100,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown microsoft compiler major version])) | 
				
			||||
  dnl could be overridden | 
				
			||||
  _ax_[]_AC_LANG_ABBREV[]_compiler_version_patch=0 | 
				
			||||
  _ax_[]_AC_LANG_ABBREV[]_compiler_version_build=0 | 
				
			||||
  # special case for version 6 | 
				
			||||
  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major" = "X12"], | 
				
			||||
    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
       _MSC_FULL_VER%1000,, | 
				
			||||
       _ax_[]_AC_LANG_ABBREV[]_compiler_version_patch=0)]) | 
				
			||||
  # for version 7 | 
				
			||||
  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major" = "X13"], | 
				
			||||
    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
       _MSC_FULL_VER%1000,, | 
				
			||||
       AC_MSG_FAILURE([[[$0]] unknown microsoft compiler patch version])) | 
				
			||||
    ]) | 
				
			||||
  # for version > 8 | 
				
			||||
 AS_IF([test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_major -ge 14], | 
				
			||||
    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
       _MSC_FULL_VER%10000,, | 
				
			||||
       AC_MSG_FAILURE([[[$0]] unknown microsoft compiler patch version])) | 
				
			||||
    ]) | 
				
			||||
 AS_IF([test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_major -ge 15], | 
				
			||||
    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_build, | 
				
			||||
       _MSC_BUILD,, | 
				
			||||
       AC_MSG_FAILURE([[[$0]] unknown microsoft compiler build version])) | 
				
			||||
    ]) | 
				
			||||
 ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_build" | 
				
			||||
 ]) | 
				
			||||
 | 
				
			||||
# for metrowerks | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_METROWERKS],[dnl | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    __MWERKS__%0x100,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown metrowerks compiler patch version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    (__MWERKS__/0x100)%0x10,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown metrowerks compiler minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    (__MWERKS__/0x1000)%0x10,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown metrowerks compiler major version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for watcom | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_WATCOM],[dnl | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    __WATCOMC__%100,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown watcom compiler minor version])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    (__WATCOMC__/100)%100,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown watcom compiler major version])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# for PGI | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_PORTLAND],[ | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major, | 
				
			||||
    __PGIC__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown pgi major])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor, | 
				
			||||
    __PGIC_MINOR__,, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown pgi minor])) | 
				
			||||
  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch, | 
				
			||||
    [__PGIC_PATCHLEVEL__],, | 
				
			||||
    AC_MSG_FAILURE([[[$0]] unknown pgi patch level])) | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch" | 
				
			||||
  ]) | 
				
			||||
 | 
				
			||||
# tcc | 
				
			||||
AC_DEFUN([_AX_COMPILER_VERSION_TCC],[ | 
				
			||||
  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version=[`tcc -v | $SED 's/^[ ]*tcc[ ]\+version[ ]\+\([0-9.]\+\).*/\1/g'`] | 
				
			||||
  ]) | 
				
			||||
# main entry point | 
				
			||||
AC_DEFUN([AX_COMPILER_VERSION],[dnl | 
				
			||||
  AC_REQUIRE([AX_COMPILER_VENDOR]) | 
				
			||||
  AC_REQUIRE([AC_PROG_SED]) | 
				
			||||
  AC_CACHE_CHECK([for _AC_LANG compiler version], | 
				
			||||
    ax_cv_[]_AC_LANG_ABBREV[]_compiler_version, | 
				
			||||
    [ dnl | 
				
			||||
      AS_CASE([$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor], | 
				
			||||
        [intel],[_AX_COMPILER_VERSION_INTEL], | 
				
			||||
	[ibm],[_AX_COMPILER_VERSION_IBM], | 
				
			||||
	[pathscale],[_AX_COMPILER_VERSION_PATHSCALE], | 
				
			||||
	[clang],[_AX_COMPILER_VERSION_CLANG], | 
				
			||||
	[cray],[_AX_COMPILER_VERSION_CRAY], | 
				
			||||
	[fujitsu],[_AX_COMPILER_VERSION_FUJITSU], | 
				
			||||
        [gnu],[_AX_COMPILER_VERSION_GNU], | 
				
			||||
	[sun],[_AX_COMPILER_VERSION_SUN], | 
				
			||||
	[hp],[_AX_COMPILER_VERSION_HP], | 
				
			||||
	[dec],[_AX_COMPILER_VERSION_DEC], | 
				
			||||
	[borland],[_AX_COMPILER_VERSION_BORLAND], | 
				
			||||
	[comeau],[_AX_COMPILER_VERSION_COMEAU], | 
				
			||||
	[kai],[_AX_COMPILER_VERSION_KAI], | 
				
			||||
	[sgi],[_AX_COMPILER_VERSION_SGI], | 
				
			||||
	[microsoft],[_AX_COMPILER_VERSION_MICROSOFT], | 
				
			||||
	[metrowerks],[_AX_COMPILER_VERSION_METROWERKS], | 
				
			||||
	[watcom],[_AX_COMPILER_VERSION_WATCOM], | 
				
			||||
	[portland],[_AX_COMPILER_VERSION_PORTLAND], | 
				
			||||
	[tcc],[_AX_COMPILER_VERSION_TCC], | 
				
			||||
  	[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version=""]) | 
				
			||||
    ]) | 
				
			||||
]) | 
				
			||||
@ -0,0 +1,56 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#    https://www.gnu.org/software/autoconf-archive/ax_recursive_eval.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_RECURSIVE_EVAL(VALUE, RESULT) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   Interpolate the VALUE in loop until it doesn't change, and set the | 
				
			||||
#   result to $RESULT. WARNING: It's easy to get an infinite loop with some | 
				
			||||
#   unsane input. | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2008 Alexandre Duret-Lutz <adl@gnu.org> | 
				
			||||
# | 
				
			||||
#   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, see <https://www.gnu.org/licenses/>. | 
				
			||||
# | 
				
			||||
#   As a special exception, the respective Autoconf Macro's copyright owner | 
				
			||||
#   gives unlimited permission to copy, distribute and modify the configure | 
				
			||||
#   scripts that are the output of Autoconf when processing the Macro. You | 
				
			||||
#   need not follow the terms of the GNU General Public License when using | 
				
			||||
#   or distributing such scripts, even though portions of the text of the | 
				
			||||
#   Macro appear in them. The GNU General Public License (GPL) does govern | 
				
			||||
#   all other use of the material that constitutes the Autoconf Macro. | 
				
			||||
# | 
				
			||||
#   This special exception to the GPL applies to versions of the Autoconf | 
				
			||||
#   Macro released by the Autoconf Archive. When you make and distribute a | 
				
			||||
#   modified version of the Autoconf Macro, you may extend this special | 
				
			||||
#   exception to the GPL to apply to your modified version as well. | 
				
			||||
 | 
				
			||||
#serial 1 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_RECURSIVE_EVAL], | 
				
			||||
[_lcl_receval="$1" | 
				
			||||
$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" | 
				
			||||
     test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" | 
				
			||||
     _lcl_receval_old='' | 
				
			||||
     while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do | 
				
			||||
       _lcl_receval_old="[$]_lcl_receval" | 
				
			||||
       eval _lcl_receval="\"[$]_lcl_receval\"" | 
				
			||||
     done | 
				
			||||
     echo "[$]_lcl_receval")`]) | 
				
			||||
@ -0,0 +1,37 @@ | 
				
			||||
# =========================================================================== | 
				
			||||
#    https://www.gnu.org/software/autoconf-archive/ax_require_defined.html | 
				
			||||
# =========================================================================== | 
				
			||||
# | 
				
			||||
# SYNOPSIS | 
				
			||||
# | 
				
			||||
#   AX_REQUIRE_DEFINED(MACRO) | 
				
			||||
# | 
				
			||||
# DESCRIPTION | 
				
			||||
# | 
				
			||||
#   AX_REQUIRE_DEFINED is a simple helper for making sure other macros have | 
				
			||||
#   been defined and thus are available for use.  This avoids random issues | 
				
			||||
#   where a macro isn't expanded.  Instead the configure script emits a | 
				
			||||
#   non-fatal: | 
				
			||||
# | 
				
			||||
#     ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found | 
				
			||||
# | 
				
			||||
#   It's like AC_REQUIRE except it doesn't expand the required macro. | 
				
			||||
# | 
				
			||||
#   Here's an example: | 
				
			||||
# | 
				
			||||
#     AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) | 
				
			||||
# | 
				
			||||
# LICENSE | 
				
			||||
# | 
				
			||||
#   Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org> | 
				
			||||
# | 
				
			||||
#   Copying and distribution of this file, with or without modification, are | 
				
			||||
#   permitted in any medium without royalty provided the copyright notice | 
				
			||||
#   and this notice are preserved. This file is offered as-is, without any | 
				
			||||
#   warranty. | 
				
			||||
 | 
				
			||||
#serial 2 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl | 
				
			||||
  m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) | 
				
			||||
])dnl AX_REQUIRE_DEFINED | 
				
			||||
@ -0,0 +1,26 @@ | 
				
			||||
dnl @synopsis AC_CHECK_SIGNAL(SIGNAME) | 
				
			||||
dnl | 
				
			||||
dnl | 
				
			||||
dnl @category C | 
				
			||||
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com> | 
				
			||||
dnl @version 1.0	Jul 07 2007 | 
				
			||||
 | 
				
			||||
AC_DEFUN([AC_CHECK_SIGNAL], | 
				
			||||
[AC_CACHE_CHECK(for $1, | 
				
			||||
  ac_cv_signal_$1, | 
				
			||||
[ | 
				
			||||
AC_TRY_LINK([ | 
				
			||||
#include <signal.h> | 
				
			||||
 | 
				
			||||
], signal($1, SIG_DFL) ;, ac_cv_signal_$1=yes, ac_cv_signal_$1=no) | 
				
			||||
 | 
				
			||||
]) | 
				
			||||
 | 
				
			||||
if test "$ac_cv_signal_$1" = yes; then | 
				
			||||
  AC_DEFINE(HAVE_$1, 1, | 
				
			||||
            [Define if you have signal $1.]) | 
				
			||||
fi | 
				
			||||
])# AC_CHECK_SIGNAL | 
				
			||||
 | 
				
			||||
 | 
				
			||||
## AC_CHECK_SIGNALS | 
				
			||||
@ -0,0 +1,124 @@ | 
				
			||||
dnl @synopsis AC_C_CLIP_MODE | 
				
			||||
dnl | 
				
			||||
dnl Determine the clipping mode when converting float to int. | 
				
			||||
dnl @version 1.0	May 17 2003 | 
				
			||||
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com> | 
				
			||||
dnl | 
				
			||||
dnl Permission to use, copy, modify, distribute, and sell this file for any  | 
				
			||||
dnl purpose is hereby granted without fee, provided that the above copyright  | 
				
			||||
dnl and this permission notice appear in all copies.  No representations are | 
				
			||||
dnl made about the suitability of this software for any purpose.  It is  | 
				
			||||
dnl provided "as is" without express or implied warranty. | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
dnl Find the clipping mode in the following way: | 
				
			||||
dnl    1) If we are not cross compiling test it. | 
				
			||||
dnl    2) IF we are cross compiling, assume that clipping isn't done correctly. | 
				
			||||
 | 
				
			||||
AC_DEFUN([AC_C_CLIP_MODE], | 
				
			||||
[AC_CACHE_CHECK(processor clipping capabilities,  | 
				
			||||
	ac_cv_c_clip_type, | 
				
			||||
 | 
				
			||||
# Initialize to unknown | 
				
			||||
ac_cv_c_clip_positive=unknown | 
				
			||||
ac_cv_c_clip_negative=unknown | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if test $ac_cv_c_clip_positive = unknown ; then | 
				
			||||
	AC_TRY_RUN( | 
				
			||||
	[[ | 
				
			||||
	#define	_ISOC9X_SOURCE	1 | 
				
			||||
	#define _ISOC99_SOURCE	1 | 
				
			||||
	#define	__USE_ISOC99	1 | 
				
			||||
	#define __USE_ISOC9X	1 | 
				
			||||
	#include <math.h> | 
				
			||||
	int main (void) | 
				
			||||
	{	double	fval ; | 
				
			||||
		int k, ival ; | 
				
			||||
 | 
				
			||||
		fval = 1.0 * 0x7FFFFFFF ; | 
				
			||||
		for (k = 0 ; k < 100 ; k++) | 
				
			||||
		{	ival = (lrint (fval)) >> 24 ; | 
				
			||||
			if (ival != 127) | 
				
			||||
				return 1 ; | 
				
			||||
		 | 
				
			||||
			fval *= 1.2499999 ; | 
				
			||||
			} ; | 
				
			||||
		 | 
				
			||||
			return 0 ; | 
				
			||||
		} | 
				
			||||
		]], | 
				
			||||
		ac_cv_c_clip_positive=yes, | 
				
			||||
		ac_cv_c_clip_positive=no, | 
				
			||||
		ac_cv_c_clip_positive=unknown | 
				
			||||
		) | 
				
			||||
 | 
				
			||||
	AC_TRY_RUN( | 
				
			||||
	[[ | 
				
			||||
	#define	_ISOC9X_SOURCE	1 | 
				
			||||
	#define _ISOC99_SOURCE	1 | 
				
			||||
	#define	__USE_ISOC99	1 | 
				
			||||
	#define __USE_ISOC9X	1 | 
				
			||||
	#include <math.h> | 
				
			||||
	int main (void) | 
				
			||||
	{	double	fval ; | 
				
			||||
		int k, ival ; | 
				
			||||
 | 
				
			||||
		fval = -8.0 * 0x10000000 ; | 
				
			||||
		for (k = 0 ; k < 100 ; k++) | 
				
			||||
		{	ival = (lrint (fval)) >> 24 ; | 
				
			||||
			if (ival != -128) | 
				
			||||
				return 1 ; | 
				
			||||
		 | 
				
			||||
			fval *= 1.2499999 ; | 
				
			||||
			} ; | 
				
			||||
		 | 
				
			||||
			return 0 ; | 
				
			||||
		} | 
				
			||||
		]], | 
				
			||||
		ac_cv_c_clip_negative=yes, | 
				
			||||
		ac_cv_c_clip_negative=no, | 
				
			||||
		ac_cv_c_clip_negative=unknown | 
				
			||||
		) | 
				
			||||
	fi | 
				
			||||
 | 
				
			||||
if test $ac_cv_c_clip_positive = yes ; then | 
				
			||||
	ac_cv_c_clip_positive=1 | 
				
			||||
else | 
				
			||||
	ac_cv_c_clip_positive=0 | 
				
			||||
	fi | 
				
			||||
 | 
				
			||||
if test $ac_cv_c_clip_negative = yes ; then | 
				
			||||
	ac_cv_c_clip_negative=1 | 
				
			||||
else | 
				
			||||
	ac_cv_c_clip_negative=0 | 
				
			||||
	fi | 
				
			||||
 | 
				
			||||
[[ | 
				
			||||
case "$ac_cv_c_clip_positive$ac_cv_c_clip_negative" in | 
				
			||||
	"00") | 
				
			||||
		ac_cv_c_clip_type="none" | 
				
			||||
		;; | 
				
			||||
	"10") | 
				
			||||
		ac_cv_c_clip_type="positive" | 
				
			||||
		;; | 
				
			||||
	"01") | 
				
			||||
		ac_cv_c_clip_type="negative" | 
				
			||||
		;; | 
				
			||||
	"11") | 
				
			||||
		ac_cv_c_clip_type="both" | 
				
			||||
		;; | 
				
			||||
	esac | 
				
			||||
	]] | 
				
			||||
 | 
				
			||||
) | 
				
			||||
] | 
				
			||||
 | 
				
			||||
)# AC_C_CLIP_MODE | 
				
			||||
 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,12 @@ | 
				
			||||
prefix=@prefix@ | 
				
			||||
exec_prefix=@exec_prefix@ | 
				
			||||
libdir=@libdir@ | 
				
			||||
includedir=@includedir@ | 
				
			||||
 | 
				
			||||
Name: samplerate | 
				
			||||
Description: An audio Sample Rate Conversion library | 
				
			||||
Requires:  | 
				
			||||
Version: @VERSION@ | 
				
			||||
Libs: -L${libdir} -lsamplerate | 
				
			||||
Libs.private: @LIBS@ | 
				
			||||
Cflags: -I${includedir}  | 
				
			||||
@ -0,0 +1,169 @@ | 
				
			||||
option(LIBSAMPLERATE_COMPATIBLE_NAME "Use old dll name on Windows platform" OFF) | 
				
			||||
 | 
				
			||||
option(LIBSAMPLERATE_ENABLE_SINC_FAST_CONVERTER "Enable Fastest Sinc Interpolator converter" ON) | 
				
			||||
option(LIBSAMPLERATE_ENABLE_SINC_MEDIUM_CONVERTER "Enable Medium Sinc Interpolator converter" ON) | 
				
			||||
option(LIBSAMPLERATE_ENABLE_SINC_BEST_CONVERTER "Enable Best Sinc Interpolator converter" ON) | 
				
			||||
 | 
				
			||||
option(LIBSAMPLERATE_INSTALL_PKGCONFIG_MODULE "Install samplerate.pc PkgConfig module." ON) | 
				
			||||
 | 
				
			||||
set(ENABLE_SINC_FAST_CONVERTER ${LIBSAMPLERATE_ENABLE_SINC_FAST_CONVERTER} PARENT_SCOPE) | 
				
			||||
set(ENABLE_SINC_MEDIUM_CONVERTER ${LIBSAMPLERATE_ENABLE_SINC_MEDIUM_CONVERTER} PARENT_SCOPE) | 
				
			||||
set(ENABLE_SINC_BEST_CONVERTER ${LIBSAMPLERATE_ENABLE_SINC_BEST_CONVERTER} PARENT_SCOPE) | 
				
			||||
 | 
				
			||||
include(CMakePushCheckState) | 
				
			||||
include(CheckCSourceCompiles) | 
				
			||||
include(ClipMode) | 
				
			||||
include(CMakePackageConfigHelpers) | 
				
			||||
 | 
				
			||||
# This will set CPU_CLIPS_NEGATIVE and CPU_CLIPS_POSITIVE | 
				
			||||
clip_mode() | 
				
			||||
 | 
				
			||||
# check for symbol visibility attributes support | 
				
			||||
cmake_push_check_state() | 
				
			||||
set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden -Werror") | 
				
			||||
check_c_source_compiles("__attribute__((visibility(\"default\"))) int foo(void); | 
				
			||||
                         __attribute__((visibility(\"hidden\")))  int bar(void); | 
				
			||||
                         int foo (void) {return 0;} | 
				
			||||
                         int bar (void) {return 1;} | 
				
			||||
                         int main(void) {return 0;}" HAVE_VISIBILITY) | 
				
			||||
cmake_pop_check_state() | 
				
			||||
 | 
				
			||||
add_library(samplerate | 
				
			||||
  common.h | 
				
			||||
  fastest_coeffs.h | 
				
			||||
  high_qual_coeffs.h | 
				
			||||
  mid_qual_coeffs.h | 
				
			||||
  samplerate.c | 
				
			||||
  ${PROJECT_SOURCE_DIR}/include/samplerate.h | 
				
			||||
  src_linear.c | 
				
			||||
  src_sinc.c | 
				
			||||
  src_zoh.c | 
				
			||||
  $<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:../Win32/libsamplerate-0.def>) | 
				
			||||
 | 
				
			||||
# ALIAS to use if libsamplerate is included from other project with add_subdirectory() | 
				
			||||
add_library(SampleRate::samplerate ALIAS samplerate) | 
				
			||||
 | 
				
			||||
# CMake generates wrong DLL names for MinGW and Cygwin, fix it | 
				
			||||
if(BUILD_SHARED_LIBS AND WIN32) | 
				
			||||
  if(LIBSAMPLERATE_COMPATIBLE_NAME) | 
				
			||||
    if(MSVC) | 
				
			||||
      set_target_properties(samplerate PROPERTIES OUTPUT_NAME "libsamplerate-${libsamplerate_VERSION_MAJOR}") | 
				
			||||
    else() | 
				
			||||
      set_target_properties(samplerate PROPERTIES OUTPUT_NAME "samplerate-${libsamplerate_VERSION_MAJOR}") | 
				
			||||
    endif() | 
				
			||||
  else() | 
				
			||||
    if(MINGW OR CYGWIN) | 
				
			||||
      set_target_properties(samplerate PROPERTIES RUNTIME_OUTPUT_NAME "samplerate-${libsamplerate_VERSION_MAJOR}") | 
				
			||||
    endif() | 
				
			||||
  endif() | 
				
			||||
  if(OS2) | 
				
			||||
    # OS/2 doesn't support a DLL name longer than 8 characters. | 
				
			||||
    set_target_properties(samplerate PROPERTIES OUTPUT_NAME "SAMPRATE") | 
				
			||||
    set_target_properties(samplerate PROPERTIES PREFIX "") | 
				
			||||
  endif() | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
target_include_directories(samplerate | 
				
			||||
  PUBLIC | 
				
			||||
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> | 
				
			||||
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) | 
				
			||||
 | 
				
			||||
if(LIBM_REQUIRED) | 
				
			||||
    target_link_libraries(samplerate PRIVATE m) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
# Set public header | 
				
			||||
set_property(TARGET samplerate PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/samplerate.h) | 
				
			||||
 | 
				
			||||
if(BUILD_SHARED_LIBS) | 
				
			||||
  # Set ABI version. This is critical for Unix-like OSes | 
				
			||||
  set_target_properties(samplerate PROPERTIES | 
				
			||||
    VERSION ${libsamplerate_VERSION} | 
				
			||||
    SOVERSION ${libsamplerate_VERSION_MAJOR}) | 
				
			||||
 | 
				
			||||
    # Use Version_script to export ABI set | 
				
			||||
    if(UNIX AND (NOT APPLE)) | 
				
			||||
      if((CMAKE_C_COMPILER_ID STREQUAL "GNU") OR | 
				
			||||
         (CMAKE_C_COMPILER_ID STREQUAL "Clang") OR | 
				
			||||
         (CMAKE_C_COMPILER_ID STREQUAL "Intel")) | 
				
			||||
 | 
				
			||||
        set(PACKAGE ${PROJECT_NAME}) | 
				
			||||
        configure_file(Version_script.in Version_script) | 
				
			||||
        unset(PACKAGE) | 
				
			||||
 | 
				
			||||
        if(CMAKE_VERSION VERSION_LESS 3.13) | 
				
			||||
          # This works  | 
				
			||||
          set_property(TARGET samplerate APPEND_STRING PROPERTY | 
				
			||||
            LINK_FLAGS "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/Version_script") | 
				
			||||
        else() | 
				
			||||
          # This works even better, e.g. for Clang it uses `-Xlinker` option, | 
				
			||||
          # but requires CMake >= 3.13. | 
				
			||||
          target_link_options(samplerate | 
				
			||||
            PRIVATE | 
				
			||||
              "LINKER:--version-script,${CMAKE_CURRENT_BINARY_DIR}/Version_script") | 
				
			||||
        endif() | 
				
			||||
 | 
				
			||||
      endif() | 
				
			||||
    endif() | 
				
			||||
 | 
				
			||||
  # keep in sync with configure.ac | 
				
			||||
  set (LIBSAMPLERATE_ABI_VERSION_CURRENT 2) | 
				
			||||
  set (LIBSAMPLERATE_ABI_VERSION_REVISION 2) | 
				
			||||
  set (LIBSAMPLERATE_ABI_VERSION_AGE 2) | 
				
			||||
  math (EXPR LIBSAMPLERATE_MACHO_COMPATIBILITY_VERSION "${LIBSAMPLERATE_ABI_VERSION_CURRENT} + 1") | 
				
			||||
  set (LIBSAMPLERATE_MACHO_CURRENT_VERSION "${LIBSAMPLERATE_MACHO_COMPATIBILITY_VERSION}.${LIBSAMPLERATE_ABI_VERSION_REVISION}.0") | 
				
			||||
  if (APPLE) | 
				
			||||
    if (NOT (CMAKE_VERSION VERSION_LESS 3.17)) | 
				
			||||
      set_target_properties (samplerate PROPERTIES | 
				
			||||
        MACHO_CURRENT_VERSION ${LIBSAMPLERATE_MACHO_CURRENT_VERSION} | 
				
			||||
        MACHO_COMPATIBILITY_VERSION ${LIBSAMPLERATE_MACHO_COMPATIBILITY_VERSION} | 
				
			||||
        ) | 
				
			||||
    else () | 
				
			||||
      message (FATAL_ERROR "Apple platform requires cmake >= 3.17 to build dylib.") | 
				
			||||
    endif () | 
				
			||||
  endif () | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
# Istallation | 
				
			||||
 | 
				
			||||
if(LIBSAMPLERATE_INSTALL) | 
				
			||||
 | 
				
			||||
  install(TARGETS samplerate EXPORT SampleRateTargets | 
				
			||||
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | 
				
			||||
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | 
				
			||||
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | 
				
			||||
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) | 
				
			||||
 | 
				
			||||
  # pkg-config module | 
				
			||||
 | 
				
			||||
  if(LIBSAMPLERATE_INSTALL_PKGCONFIG_MODULE) | 
				
			||||
    set(prefix ${CMAKE_INSTALL_PREFIX}) | 
				
			||||
    set(exec_prefix "\${prefix}") | 
				
			||||
    set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") | 
				
			||||
    set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") | 
				
			||||
    set(VERSION "${PROJECT_VERSION}") | 
				
			||||
    if(LIBM_REQUIRED) | 
				
			||||
      set(LIBS "-lm") | 
				
			||||
    endif() | 
				
			||||
    configure_file(../samplerate.pc.in samplerate.pc @ONLY) | 
				
			||||
    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/samplerate.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) | 
				
			||||
  endif() | 
				
			||||
 | 
				
			||||
  set(CMAKE_INSTALL_PACKAGEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/SampleRate") | 
				
			||||
 | 
				
			||||
  configure_package_config_file(../cmake/SampleRateConfig.cmake.in SampleRateConfig.cmake | 
				
			||||
    INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}) | 
				
			||||
 | 
				
			||||
  write_basic_package_version_file(SampleRateConfigVersion.cmake COMPATIBILITY SameMajorVersion) | 
				
			||||
  install( | 
				
			||||
    FILES | 
				
			||||
      ${CMAKE_CURRENT_BINARY_DIR}/SampleRateConfig.cmake | 
				
			||||
      ${CMAKE_CURRENT_BINARY_DIR}/SampleRateConfigVersion.cmake | 
				
			||||
    DESTINATION | 
				
			||||
      ${CMAKE_INSTALL_PACKAGEDIR}) | 
				
			||||
 | 
				
			||||
  install(EXPORT SampleRateTargets | 
				
			||||
    NAMESPACE SampleRate:: | 
				
			||||
    DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}) | 
				
			||||
 | 
				
			||||
endif() | 
				
			||||
@ -0,0 +1,45 @@ | 
				
			||||
# | 
				
			||||
# Export file for libsamplerate | 
				
			||||
# | 
				
			||||
# Only the symbols listed in the global section will be callable from | 
				
			||||
# applications linking to libsamplerate. | 
				
			||||
# | 
				
			||||
 | 
				
			||||
@PACKAGE@.so.0.0 | 
				
			||||
{ | 
				
			||||
	global: | 
				
			||||
		src_new ; | 
				
			||||
		src_delete ; | 
				
			||||
		src_get_name ; | 
				
			||||
		src_get_description ; | 
				
			||||
		src_get_version ; | 
				
			||||
		src_process ; | 
				
			||||
		src_reset ; | 
				
			||||
		src_error ; | 
				
			||||
		src_strerror ; | 
				
			||||
		src_simple ; | 
				
			||||
		src_is_valid_ratio ; | 
				
			||||
		src_set_ratio ; | 
				
			||||
 | 
				
			||||
	local: | 
				
			||||
		*; | 
				
			||||
}; | 
				
			||||
 | 
				
			||||
@PACKAGE@.so.0.1 | 
				
			||||
{ | 
				
			||||
	global: | 
				
			||||
		src_callback_new ; | 
				
			||||
		src_callback_read ; | 
				
			||||
 | 
				
			||||
		src_short_to_float_array ; | 
				
			||||
		src_float_to_short_array ; | 
				
			||||
		src_int_to_float_array ; | 
				
			||||
		src_float_to_int_array ; | 
				
			||||
		src_get_channels ; | 
				
			||||
} @PACKAGE@.so.0.0; | 
				
			||||
 | 
				
			||||
@PACKAGE@.so.0.2 | 
				
			||||
{ | 
				
			||||
	global: | 
				
			||||
		src_clone ; | 
				
			||||
} @PACKAGE@.so.0.1; | 
				
			||||
@ -0,0 +1,47 @@ | 
				
			||||
#!/bin/sh | 
				
			||||
 | 
				
			||||
# 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. | 
				
			||||
 | 
				
			||||
#======================================================================= | 
				
			||||
# This short test script compiles the file src_sinc.c into assembler | 
				
			||||
# output and the greps the assembler output for the fldcw (FPU Load | 
				
			||||
# Control Word) instruction which is very detrimental to the perfromance | 
				
			||||
# of floating point code. | 
				
			||||
 | 
				
			||||
echo -n "    Checking assembler output for bad code : " | 
				
			||||
 | 
				
			||||
if [ $# -ne 1 ]; then | 
				
			||||
	echo "Error : Need the name of the input file." | 
				
			||||
	exit 1 | 
				
			||||
	fi | 
				
			||||
 | 
				
			||||
filename=$1 | 
				
			||||
 | 
				
			||||
if [ ! -f $filename ];then | 
				
			||||
	echo "Error : Can't find file $filename." | 
				
			||||
	exit 1 | 
				
			||||
	fi | 
				
			||||
 | 
				
			||||
count=`grep fldcw $filename | wc -l` | 
				
			||||
 | 
				
			||||
if [ $count -gt 0 ]; then | 
				
			||||
	echo -e "\n\nError : found $count bad instructions.\n\n" | 
				
			||||
	exit 1 | 
				
			||||
	fi | 
				
			||||
 | 
				
			||||
echo "ok" | 
				
			||||
 | 
				
			||||
@ -0,0 +1,252 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifndef COMMON_H_INCLUDED | 
				
			||||
#define COMMON_H_INCLUDED | 
				
			||||
 | 
				
			||||
#include <stdint.h> | 
				
			||||
#ifdef HAVE_STDBOOL_H | 
				
			||||
#include <stdbool.h> | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#if defined(__x86_64__) || defined(_M_X64) | 
				
			||||
#   define HAVE_SSE2_INTRINSICS | 
				
			||||
#elif defined(ENABLE_SSE2_LRINT) && (defined(_M_IX86) || defined(__i386__)) | 
				
			||||
#   if defined(_MSC_VER) | 
				
			||||
#       define HAVE_SSE2_INTRINSICS | 
				
			||||
#   elif defined(__clang__) | 
				
			||||
#       ifdef __SSE2__ | 
				
			||||
#           define HAVE_SSE2_INTRINSICS | 
				
			||||
#       elif (__has_attribute(target)) | 
				
			||||
#           define HAVE_SSE2_INTRINSICS | 
				
			||||
#           define USE_TARGET_ATTRIBUTE | 
				
			||||
#       endif | 
				
			||||
#   elif defined(__GNUC__) | 
				
			||||
#       ifdef __SSE2__ | 
				
			||||
#           define HAVE_SSE2_INTRINSICS | 
				
			||||
#       elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) | 
				
			||||
#           define HAVE_SSE2_INTRINSICS | 
				
			||||
#           define USE_TARGET_ATTRIBUTE | 
				
			||||
#       endif | 
				
			||||
#   endif | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef HAVE_SSE2_INTRINSICS | 
				
			||||
#ifdef HAVE_IMMINTRIN_H | 
				
			||||
#include <immintrin.h> | 
				
			||||
#else | 
				
			||||
#include <emmintrin.h> | 
				
			||||
#endif | 
				
			||||
#endif /* HAVE_SSE2_INTRINSICS */ | 
				
			||||
 | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#ifdef HAVE_VISIBILITY | 
				
			||||
  #define LIBSAMPLERATE_DLL_PRIVATE __attribute__ ((visibility ("hidden"))) | 
				
			||||
#elif defined (__APPLE__) | 
				
			||||
  #define LIBSAMPLERATE_DLL_PRIVATE __private_extern__ | 
				
			||||
#else | 
				
			||||
  #define LIBSAMPLERATE_DLL_PRIVATE | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#define	SRC_MAX_RATIO			256 | 
				
			||||
#define	SRC_MAX_RATIO_STR		"256" | 
				
			||||
 | 
				
			||||
#define	SRC_MIN_RATIO_DIFF		(1e-20) | 
				
			||||
 | 
				
			||||
#ifndef MAX | 
				
			||||
#define	MAX(a,b)	(((a) > (b)) ? (a) : (b)) | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifndef MIN | 
				
			||||
#define	MIN(a,b)	(((a) < (b)) ? (a) : (b)) | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#define	ARRAY_LEN(x)			((int) (sizeof (x) / sizeof ((x) [0]))) | 
				
			||||
#define OFFSETOF(type,member)	((int) (&((type*) 0)->member)) | 
				
			||||
 | 
				
			||||
#define	MAKE_MAGIC(a,b,c,d,e,f)	((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20)) | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
** Inspiration : http://sourcefrog.net/weblog/software/languages/C/unused.html
 | 
				
			||||
*/ | 
				
			||||
#ifdef UNUSED | 
				
			||||
#elif defined (__GNUC__) | 
				
			||||
#	define UNUSED(x) UNUSED_ ## x __attribute__ ((unused)) | 
				
			||||
#elif defined (__LCLINT__) | 
				
			||||
#	define UNUSED(x) /*@unused@*/ x | 
				
			||||
#else | 
				
			||||
#	define UNUSED(x) x | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef __GNUC__ | 
				
			||||
#	define WARN_UNUSED	__attribute__ ((warn_unused_result)) | 
				
			||||
#else | 
				
			||||
#	define WARN_UNUSED | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include "samplerate.h" | 
				
			||||
 | 
				
			||||
enum | 
				
			||||
{	SRC_FALSE	= 0, | 
				
			||||
	SRC_TRUE	= 1, | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
enum SRC_MODE | 
				
			||||
{ | 
				
			||||
	SRC_MODE_PROCESS	= 0, | 
				
			||||
	SRC_MODE_CALLBACK	= 1 | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
typedef enum SRC_ERROR | 
				
			||||
{ | 
				
			||||
	SRC_ERR_NO_ERROR = 0, | 
				
			||||
 | 
				
			||||
	SRC_ERR_MALLOC_FAILED, | 
				
			||||
	SRC_ERR_BAD_STATE, | 
				
			||||
	SRC_ERR_BAD_DATA, | 
				
			||||
	SRC_ERR_BAD_DATA_PTR, | 
				
			||||
	SRC_ERR_NO_PRIVATE, | 
				
			||||
	SRC_ERR_BAD_SRC_RATIO, | 
				
			||||
	SRC_ERR_BAD_PROC_PTR, | 
				
			||||
	SRC_ERR_SHIFT_BITS, | 
				
			||||
	SRC_ERR_FILTER_LEN, | 
				
			||||
	SRC_ERR_BAD_CONVERTER, | 
				
			||||
	SRC_ERR_BAD_CHANNEL_COUNT, | 
				
			||||
	SRC_ERR_SINC_BAD_BUFFER_LEN, | 
				
			||||
	SRC_ERR_SIZE_INCOMPATIBILITY, | 
				
			||||
	SRC_ERR_BAD_PRIV_PTR, | 
				
			||||
	SRC_ERR_BAD_SINC_STATE, | 
				
			||||
	SRC_ERR_DATA_OVERLAP, | 
				
			||||
	SRC_ERR_BAD_CALLBACK, | 
				
			||||
	SRC_ERR_BAD_MODE, | 
				
			||||
	SRC_ERR_NULL_CALLBACK, | 
				
			||||
	SRC_ERR_NO_VARIABLE_RATIO, | 
				
			||||
	SRC_ERR_SINC_PREPARE_DATA_BAD_LEN, | 
				
			||||
	SRC_ERR_BAD_INTERNAL_STATE, | 
				
			||||
 | 
				
			||||
	/* This must be the last error number. */ | 
				
			||||
	SRC_ERR_MAX_ERROR | 
				
			||||
} SRC_ERROR ; | 
				
			||||
 | 
				
			||||
typedef struct SRC_STATE_VT_tag | 
				
			||||
{ | 
				
			||||
	/* Varispeed process function. */ | 
				
			||||
	SRC_ERROR		(*vari_process) (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
 | 
				
			||||
	/* Constant speed process function. */ | 
				
			||||
	SRC_ERROR		(*const_process) (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
 | 
				
			||||
	/* State reset. */ | 
				
			||||
	void			(*reset) (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
	/* State clone. */ | 
				
			||||
	SRC_STATE		*(*copy) (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
	/* State close. */ | 
				
			||||
	void			(*close) (SRC_STATE *state) ; | 
				
			||||
} SRC_STATE_VT ; | 
				
			||||
 | 
				
			||||
struct SRC_STATE_tag | 
				
			||||
{ | 
				
			||||
	SRC_STATE_VT *vt ; | 
				
			||||
 | 
				
			||||
	double	last_ratio, last_position ; | 
				
			||||
 | 
				
			||||
	SRC_ERROR	error ; | 
				
			||||
	int		channels ; | 
				
			||||
 | 
				
			||||
	/* SRC_MODE_PROCESS or SRC_MODE_CALLBACK */ | 
				
			||||
	enum SRC_MODE	mode ; | 
				
			||||
 | 
				
			||||
	/* Data specific to SRC_MODE_CALLBACK. */ | 
				
			||||
	src_callback_t	callback_func ; | 
				
			||||
	void			*user_callback_data ; | 
				
			||||
	long			saved_frames ; | 
				
			||||
	const float		*saved_data ; | 
				
			||||
 | 
				
			||||
	/* Pointer to data to converter specific data. */ | 
				
			||||
	void	*private_data ; | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
/* In src_sinc.c */ | 
				
			||||
const char* sinc_get_name (int src_enum) ; | 
				
			||||
const char* sinc_get_description (int src_enum) ; | 
				
			||||
 | 
				
			||||
SRC_STATE *sinc_state_new (int converter_type, int channels, SRC_ERROR *error) ; | 
				
			||||
 | 
				
			||||
/* In src_linear.c */ | 
				
			||||
const char* linear_get_name (int src_enum) ; | 
				
			||||
const char* linear_get_description (int src_enum) ; | 
				
			||||
 | 
				
			||||
SRC_STATE *linear_state_new (int channels, SRC_ERROR *error) ; | 
				
			||||
 | 
				
			||||
/* In src_zoh.c */ | 
				
			||||
const char* zoh_get_name (int src_enum) ; | 
				
			||||
const char* zoh_get_description (int src_enum) ; | 
				
			||||
 | 
				
			||||
SRC_STATE *zoh_state_new (int channels, SRC_ERROR *error) ; | 
				
			||||
 | 
				
			||||
/*----------------------------------------------------------
 | 
				
			||||
** SIMD optimized math functions. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_SSE2_INTRINSICS | 
				
			||||
static inline int | 
				
			||||
#ifdef USE_TARGET_ATTRIBUTE | 
				
			||||
__attribute__((target("sse2"))) | 
				
			||||
#endif | 
				
			||||
psf_lrintf (float x) | 
				
			||||
{ | 
				
			||||
	return _mm_cvtss_si32 (_mm_load_ss (&x)) ; | 
				
			||||
} | 
				
			||||
static inline int | 
				
			||||
#ifdef USE_TARGET_ATTRIBUTE | 
				
			||||
__attribute__((target("sse2"))) | 
				
			||||
#endif | 
				
			||||
psf_lrint (double x) | 
				
			||||
{ | 
				
			||||
	return _mm_cvtsd_si32 (_mm_load_sd (&x)) ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
#else | 
				
			||||
 | 
				
			||||
static inline int psf_lrintf (float x) | 
				
			||||
{ | 
				
			||||
	return lrintf (x) ; | 
				
			||||
} /* psf_lrintf */ | 
				
			||||
 | 
				
			||||
static inline int psf_lrint (double x) | 
				
			||||
{ | 
				
			||||
	return lrint (x) ; | 
				
			||||
} /* psf_lrint */ | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
/*----------------------------------------------------------
 | 
				
			||||
**	Common static inline functions. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static inline double | 
				
			||||
fmod_one (double x) | 
				
			||||
{	double res ; | 
				
			||||
 | 
				
			||||
	res = x - psf_lrint (x) ; | 
				
			||||
	if (res < 0.0) | 
				
			||||
		return res + 1.0 ; | 
				
			||||
 | 
				
			||||
	return res ; | 
				
			||||
} /* fmod_one */ | 
				
			||||
 | 
				
			||||
static inline int | 
				
			||||
is_bad_src_ratio (double ratio) | 
				
			||||
{	return (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) ; | 
				
			||||
} /* is_bad_src_ratio */ | 
				
			||||
 | 
				
			||||
 | 
				
			||||
#endif	/* COMMON_H_INCLUDED */ | 
				
			||||
 | 
				
			||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						@ -0,0 +1,528 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include	"config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include	<stdio.h> | 
				
			||||
#include	<stdlib.h> | 
				
			||||
#include	<string.h> | 
				
			||||
#include	<math.h> | 
				
			||||
 | 
				
			||||
#include	"samplerate.h" | 
				
			||||
#include	"common.h" | 
				
			||||
 | 
				
			||||
static SRC_STATE *psrc_set_converter (int converter_type, int channels, int *error) ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
SRC_STATE * | 
				
			||||
src_new (int converter_type, int channels, int *error) | 
				
			||||
{ | 
				
			||||
	return psrc_set_converter (converter_type, channels, error) ; | 
				
			||||
} /* src_new */ | 
				
			||||
 | 
				
			||||
SRC_STATE* | 
				
			||||
src_clone (SRC_STATE* orig, int *error) | 
				
			||||
{ | 
				
			||||
	if (!orig) | 
				
			||||
	{ | 
				
			||||
		if (error) | 
				
			||||
			*error = SRC_ERR_BAD_STATE ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
	if (error) | 
				
			||||
		*error = SRC_ERR_NO_ERROR ; | 
				
			||||
 | 
				
			||||
	SRC_STATE *state = orig->vt->copy (orig) ; | 
				
			||||
	if (!state) | 
				
			||||
		if (error) | 
				
			||||
			*error = SRC_ERR_MALLOC_FAILED ; | 
				
			||||
 | 
				
			||||
	return state ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
SRC_STATE* | 
				
			||||
src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data) | 
				
			||||
{	SRC_STATE	*state ; | 
				
			||||
 | 
				
			||||
	if (func == NULL) | 
				
			||||
	{	if (error) | 
				
			||||
			*error = SRC_ERR_BAD_CALLBACK ; | 
				
			||||
		return NULL ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (error != NULL) | 
				
			||||
		*error = 0 ; | 
				
			||||
 | 
				
			||||
	if ((state = src_new (converter_type, channels, error)) == NULL) | 
				
			||||
		return NULL ; | 
				
			||||
 | 
				
			||||
	src_reset (state) ; | 
				
			||||
 | 
				
			||||
	state->mode = SRC_MODE_CALLBACK ; | 
				
			||||
	state->callback_func = func ; | 
				
			||||
	state->user_callback_data = cb_data ; | 
				
			||||
 | 
				
			||||
	return state ; | 
				
			||||
} /* src_callback_new */ | 
				
			||||
 | 
				
			||||
SRC_STATE * | 
				
			||||
src_delete (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	if (state) | 
				
			||||
		state->vt->close (state) ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* src_state */ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_process (SRC_STATE *state, SRC_DATA *data) | 
				
			||||
{ | 
				
			||||
	int error ; | 
				
			||||
 | 
				
			||||
	if (state == NULL) | 
				
			||||
		return SRC_ERR_BAD_STATE ; | 
				
			||||
 | 
				
			||||
	if (state->mode != SRC_MODE_PROCESS) | 
				
			||||
		return SRC_ERR_BAD_MODE ; | 
				
			||||
 | 
				
			||||
	/* Check for valid SRC_DATA first. */ | 
				
			||||
	if (data == NULL) | 
				
			||||
		return SRC_ERR_BAD_DATA ; | 
				
			||||
 | 
				
			||||
	/* And that data_in and data_out are valid. */ | 
				
			||||
	if ((data->data_in == NULL && data->input_frames > 0) | 
				
			||||
			|| (data->data_out == NULL && data->output_frames > 0)) | 
				
			||||
		return SRC_ERR_BAD_DATA_PTR ; | 
				
			||||
 | 
				
			||||
	/* Check src_ratio is in range. */ | 
				
			||||
	if (is_bad_src_ratio (data->src_ratio)) | 
				
			||||
		return SRC_ERR_BAD_SRC_RATIO ; | 
				
			||||
 | 
				
			||||
	if (data->input_frames < 0) | 
				
			||||
		data->input_frames = 0 ; | 
				
			||||
	if (data->output_frames < 0) | 
				
			||||
		data->output_frames = 0 ; | 
				
			||||
 | 
				
			||||
	if (data->data_in < data->data_out) | 
				
			||||
	{	if (data->data_in + data->input_frames * state->channels > data->data_out) | 
				
			||||
		{	/*-printf ("\n\ndata_in: %p    data_out: %p\n",
 | 
				
			||||
				(void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/ | 
				
			||||
			return SRC_ERR_DATA_OVERLAP ; | 
				
			||||
			} ; | 
				
			||||
		} | 
				
			||||
	else if (data->data_out + data->output_frames * state->channels > data->data_in) | 
				
			||||
	{	/*-printf ("\n\ndata_in : %p   ouput frames: %ld    data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ;
 | 
				
			||||
 | 
				
			||||
		printf ("data_out: %p (%p)    data_in: %p\n", (void*) data->data_out, | 
				
			||||
			(void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/ | 
				
			||||
		return SRC_ERR_DATA_OVERLAP ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Set the input and output counts to zero. */ | 
				
			||||
	data->input_frames_used = 0 ; | 
				
			||||
	data->output_frames_gen = 0 ; | 
				
			||||
 | 
				
			||||
	/* Special case for when last_ratio has not been set. */ | 
				
			||||
	if (state->last_ratio < (1.0 / SRC_MAX_RATIO)) | 
				
			||||
		state->last_ratio = data->src_ratio ; | 
				
			||||
 | 
				
			||||
	/* Now process. */ | 
				
			||||
	if (fabs (state->last_ratio - data->src_ratio) < 1e-15) | 
				
			||||
		error = state->vt->const_process (state, data) ; | 
				
			||||
	else | 
				
			||||
		error = state->vt->vari_process (state, data) ; | 
				
			||||
 | 
				
			||||
	return error ; | 
				
			||||
} /* src_process */ | 
				
			||||
 | 
				
			||||
long | 
				
			||||
src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) | 
				
			||||
{ | 
				
			||||
	SRC_DATA	src_data ; | 
				
			||||
 | 
				
			||||
	long	output_frames_gen ; | 
				
			||||
	int		error = 0 ; | 
				
			||||
 | 
				
			||||
	if (state == NULL) | 
				
			||||
		return 0 ; | 
				
			||||
 | 
				
			||||
	if (frames <= 0) | 
				
			||||
		return 0 ; | 
				
			||||
 | 
				
			||||
	if (state->mode != SRC_MODE_CALLBACK) | 
				
			||||
	{	state->error = SRC_ERR_BAD_MODE ; | 
				
			||||
		return 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (state->callback_func == NULL) | 
				
			||||
	{	state->error = SRC_ERR_NULL_CALLBACK ; | 
				
			||||
		return 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	memset (&src_data, 0, sizeof (src_data)) ; | 
				
			||||
 | 
				
			||||
	/* Check src_ratio is in range. */ | 
				
			||||
	if (is_bad_src_ratio (src_ratio)) | 
				
			||||
	{	state->error = SRC_ERR_BAD_SRC_RATIO ; | 
				
			||||
		return 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Switch modes temporarily. */ | 
				
			||||
	src_data.src_ratio = src_ratio ; | 
				
			||||
	src_data.data_out = data ; | 
				
			||||
	src_data.output_frames = frames ; | 
				
			||||
 | 
				
			||||
	src_data.data_in = state->saved_data ; | 
				
			||||
	src_data.input_frames = state->saved_frames ; | 
				
			||||
 | 
				
			||||
	output_frames_gen = 0 ; | 
				
			||||
	while (output_frames_gen < frames) | 
				
			||||
	{	/*	Use a dummy array for the case where the callback function
 | 
				
			||||
		**	returns without setting the ptr. | 
				
			||||
		*/ | 
				
			||||
		float dummy [1] ; | 
				
			||||
 | 
				
			||||
		if (src_data.input_frames == 0) | 
				
			||||
		{	float *ptr = dummy ; | 
				
			||||
 | 
				
			||||
			src_data.input_frames = state->callback_func (state->user_callback_data, &ptr) ; | 
				
			||||
			src_data.data_in = ptr ; | 
				
			||||
 | 
				
			||||
			if (src_data.input_frames == 0) | 
				
			||||
				src_data.end_of_input = 1 ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/*
 | 
				
			||||
		** Now call process function. However, we need to set the mode | 
				
			||||
		** to SRC_MODE_PROCESS first and when we return set it back to | 
				
			||||
		** SRC_MODE_CALLBACK. | 
				
			||||
		*/ | 
				
			||||
		state->mode = SRC_MODE_PROCESS ; | 
				
			||||
		error = src_process (state, &src_data) ; | 
				
			||||
		state->mode = SRC_MODE_CALLBACK ; | 
				
			||||
 | 
				
			||||
		if (error != 0) | 
				
			||||
			break ; | 
				
			||||
 | 
				
			||||
		src_data.data_in += src_data.input_frames_used * state->channels ; | 
				
			||||
		src_data.input_frames -= src_data.input_frames_used ; | 
				
			||||
 | 
				
			||||
		src_data.data_out += src_data.output_frames_gen * state->channels ; | 
				
			||||
		src_data.output_frames -= src_data.output_frames_gen ; | 
				
			||||
 | 
				
			||||
		output_frames_gen += src_data.output_frames_gen ; | 
				
			||||
 | 
				
			||||
		if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0) | 
				
			||||
			break ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	state->saved_data = src_data.data_in ; | 
				
			||||
	state->saved_frames = src_data.input_frames ; | 
				
			||||
 | 
				
			||||
	if (error != 0) | 
				
			||||
	{	state->error = (SRC_ERROR) error ; | 
				
			||||
		return 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return output_frames_gen ; | 
				
			||||
} /* src_callback_read */ | 
				
			||||
 | 
				
			||||
/*==========================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_set_ratio (SRC_STATE *state, double new_ratio) | 
				
			||||
{ | 
				
			||||
	if (state == NULL) | 
				
			||||
		return SRC_ERR_BAD_STATE ; | 
				
			||||
 | 
				
			||||
	if (is_bad_src_ratio (new_ratio)) | 
				
			||||
		return SRC_ERR_BAD_SRC_RATIO ; | 
				
			||||
 | 
				
			||||
	state->last_ratio = new_ratio ; | 
				
			||||
 | 
				
			||||
	return SRC_ERR_NO_ERROR ; | 
				
			||||
} /* src_set_ratio */ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_get_channels (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	if (state == NULL) | 
				
			||||
		return -SRC_ERR_BAD_STATE ; | 
				
			||||
 | 
				
			||||
	return state->channels ; | 
				
			||||
} /* src_get_channels */ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_reset (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	if (state == NULL) | 
				
			||||
		return SRC_ERR_BAD_STATE ; | 
				
			||||
 | 
				
			||||
	state->vt->reset (state) ; | 
				
			||||
 | 
				
			||||
	state->last_position = 0.0 ; | 
				
			||||
	state->last_ratio = 0.0 ; | 
				
			||||
 | 
				
			||||
	state->saved_data = NULL ; | 
				
			||||
	state->saved_frames = 0 ; | 
				
			||||
 | 
				
			||||
	state->error = SRC_ERR_NO_ERROR ; | 
				
			||||
 | 
				
			||||
	return SRC_ERR_NO_ERROR ; | 
				
			||||
} /* src_reset */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
**	Control functions. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
const char * | 
				
			||||
src_get_name (int converter_type) | 
				
			||||
{	const char *desc ; | 
				
			||||
 | 
				
			||||
	if ((desc = sinc_get_name (converter_type)) != NULL) | 
				
			||||
		return desc ; | 
				
			||||
 | 
				
			||||
	if ((desc = zoh_get_name (converter_type)) != NULL) | 
				
			||||
		return desc ; | 
				
			||||
 | 
				
			||||
	if ((desc = linear_get_name (converter_type)) != NULL) | 
				
			||||
		return desc ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* src_get_name */ | 
				
			||||
 | 
				
			||||
const char * | 
				
			||||
src_get_description (int converter_type) | 
				
			||||
{	const char *desc ; | 
				
			||||
 | 
				
			||||
	if ((desc = sinc_get_description (converter_type)) != NULL) | 
				
			||||
		return desc ; | 
				
			||||
 | 
				
			||||
	if ((desc = zoh_get_description (converter_type)) != NULL) | 
				
			||||
		return desc ; | 
				
			||||
 | 
				
			||||
	if ((desc = linear_get_description (converter_type)) != NULL) | 
				
			||||
		return desc ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* src_get_description */ | 
				
			||||
 | 
				
			||||
const char * | 
				
			||||
src_get_version (void) | 
				
			||||
{	return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ; | 
				
			||||
} /* src_get_version */ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_is_valid_ratio (double ratio) | 
				
			||||
{ | 
				
			||||
	if (is_bad_src_ratio (ratio)) | 
				
			||||
		return SRC_FALSE ; | 
				
			||||
 | 
				
			||||
	return SRC_TRUE ; | 
				
			||||
} /* src_is_valid_ratio */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
**	Error reporting functions. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_error (SRC_STATE *state) | 
				
			||||
{	if (state) | 
				
			||||
		return state->error ; | 
				
			||||
	return SRC_ERR_NO_ERROR ; | 
				
			||||
} /* src_error */ | 
				
			||||
 | 
				
			||||
const char* | 
				
			||||
src_strerror (int error) | 
				
			||||
{ | 
				
			||||
	switch (error) | 
				
			||||
	{	case SRC_ERR_NO_ERROR : | 
				
			||||
				return "No error." ; | 
				
			||||
		case SRC_ERR_MALLOC_FAILED : | 
				
			||||
				return "Malloc failed." ; | 
				
			||||
		case SRC_ERR_BAD_STATE : | 
				
			||||
				return "SRC_STATE pointer is NULL." ; | 
				
			||||
		case SRC_ERR_BAD_DATA : | 
				
			||||
				return "SRC_DATA pointer is NULL." ; | 
				
			||||
		case SRC_ERR_BAD_DATA_PTR : | 
				
			||||
				return "SRC_DATA->data_out or SRC_DATA->data_in is NULL." ; | 
				
			||||
		case SRC_ERR_NO_PRIVATE : | 
				
			||||
				return "Internal error. No private data." ; | 
				
			||||
 | 
				
			||||
		case SRC_ERR_BAD_SRC_RATIO : | 
				
			||||
				return "SRC ratio outside [1/" SRC_MAX_RATIO_STR ", " SRC_MAX_RATIO_STR "] range." ; | 
				
			||||
 | 
				
			||||
		case SRC_ERR_BAD_SINC_STATE : | 
				
			||||
				return "src_process() called without reset after end_of_input." ; | 
				
			||||
		case SRC_ERR_BAD_PROC_PTR : | 
				
			||||
				return "Internal error. No process pointer." ; | 
				
			||||
		case SRC_ERR_SHIFT_BITS : | 
				
			||||
				return "Internal error. SHIFT_BITS too large." ; | 
				
			||||
		case SRC_ERR_FILTER_LEN : | 
				
			||||
				return "Internal error. Filter length too large." ; | 
				
			||||
		case SRC_ERR_BAD_CONVERTER : | 
				
			||||
				return "Bad converter number." ; | 
				
			||||
		case SRC_ERR_BAD_CHANNEL_COUNT : | 
				
			||||
				return "Channel count must be >= 1." ; | 
				
			||||
		case SRC_ERR_SINC_BAD_BUFFER_LEN : | 
				
			||||
				return "Internal error. Bad buffer length. Please report this." ; | 
				
			||||
		case SRC_ERR_SIZE_INCOMPATIBILITY : | 
				
			||||
				return "Internal error. Input data / internal buffer size difference. Please report this." ; | 
				
			||||
		case SRC_ERR_BAD_PRIV_PTR : | 
				
			||||
				return "Internal error. Private pointer is NULL. Please report this." ; | 
				
			||||
		case SRC_ERR_DATA_OVERLAP : | 
				
			||||
				return "Input and output data arrays overlap." ; | 
				
			||||
		case SRC_ERR_BAD_CALLBACK : | 
				
			||||
				return "Supplied callback function pointer is NULL." ; | 
				
			||||
		case SRC_ERR_BAD_MODE : | 
				
			||||
				return "Calling mode differs from initialisation mode (ie process v callback)." ; | 
				
			||||
		case SRC_ERR_NULL_CALLBACK : | 
				
			||||
				return "Callback function pointer is NULL in src_callback_read ()." ; | 
				
			||||
		case SRC_ERR_NO_VARIABLE_RATIO : | 
				
			||||
				return "This converter only allows constant conversion ratios." ; | 
				
			||||
		case SRC_ERR_SINC_PREPARE_DATA_BAD_LEN : | 
				
			||||
				return "Internal error : Bad length in prepare_data ()." ; | 
				
			||||
		case SRC_ERR_BAD_INTERNAL_STATE : | 
				
			||||
				return "Error : Someone is trampling on my internal state." ; | 
				
			||||
 | 
				
			||||
		case SRC_ERR_MAX_ERROR : | 
				
			||||
				return "Placeholder. No error defined for this error number." ; | 
				
			||||
 | 
				
			||||
		default : 						break ; | 
				
			||||
		} | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* src_strerror */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
**	Simple interface for performing a single conversion from input buffer to | 
				
			||||
**	output buffer at a fixed conversion ratio. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
src_simple (SRC_DATA *src_data, int converter, int channels) | 
				
			||||
{	SRC_STATE	*src_state ; | 
				
			||||
	int 		error ; | 
				
			||||
 | 
				
			||||
	if ((src_state = src_new (converter, channels, &error)) == NULL) | 
				
			||||
		return error ; | 
				
			||||
 | 
				
			||||
	src_data->end_of_input = 1 ; /* Only one buffer worth of input. */ | 
				
			||||
 | 
				
			||||
	error = src_process (src_state, src_data) ; | 
				
			||||
 | 
				
			||||
	src_delete (src_state) ; | 
				
			||||
 | 
				
			||||
	return error ; | 
				
			||||
} /* src_simple */ | 
				
			||||
 | 
				
			||||
void | 
				
			||||
src_short_to_float_array (const short *in, float *out, int len) | 
				
			||||
{ | 
				
			||||
	for (int i = 0 ; i < len ; i++) | 
				
			||||
	{	out [i] = (float) (in [i] / (1.0 * 0x8000)) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* src_short_to_float_array */ | 
				
			||||
 | 
				
			||||
void | 
				
			||||
src_float_to_short_array (const float *in, short *out, int len) | 
				
			||||
{ | 
				
			||||
	for (int i = 0 ; i < len ; i++) | 
				
			||||
	{	float scaled_value ; | 
				
			||||
		scaled_value = in [i] * 32768.f ; | 
				
			||||
		if (scaled_value >= 32767.f) | 
				
			||||
			out [i] = 32767 ; | 
				
			||||
		else if (scaled_value <= -32768.f) | 
				
			||||
			out [i] = -32768 ; | 
				
			||||
		else | 
				
			||||
			out [i] = (short) (psf_lrintf (scaled_value)) ; | 
				
			||||
	} | 
				
			||||
} /* src_float_to_short_array */ | 
				
			||||
 | 
				
			||||
void | 
				
			||||
src_int_to_float_array (const int *in, float *out, int len) | 
				
			||||
{ | 
				
			||||
	for (int i = 0 ; i < len ; i++) | 
				
			||||
	{	out [i] = (float) (in [i] / (8.0 * 0x10000000)) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* src_int_to_float_array */ | 
				
			||||
 | 
				
			||||
void | 
				
			||||
src_float_to_int_array (const float *in, int *out, int len) | 
				
			||||
{	double scaled_value ; | 
				
			||||
 | 
				
			||||
	for (int i = 0 ; i < len ; i++) | 
				
			||||
	{	scaled_value = in [i] * (8.0 * 0x10000000) ; | 
				
			||||
#if CPU_CLIPS_POSITIVE == 0 | 
				
			||||
		if (scaled_value >= (1.0 * 0x7FFFFFFF)) | 
				
			||||
		{	out [i] = 0x7fffffff ; | 
				
			||||
			continue ; | 
				
			||||
			} ; | 
				
			||||
#endif | 
				
			||||
#if CPU_CLIPS_NEGATIVE == 0 | 
				
			||||
		if (scaled_value <= (-8.0 * 0x10000000)) | 
				
			||||
		{	out [i] = -1 - 0x7fffffff ; | 
				
			||||
			continue ; | 
				
			||||
			} ; | 
				
			||||
#endif | 
				
			||||
		out [i] = (int) psf_lrint (scaled_value) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
} /* src_float_to_int_array */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
**	Private functions. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static SRC_STATE * | 
				
			||||
psrc_set_converter (int converter_type, int channels, int *error) | 
				
			||||
{ | 
				
			||||
	SRC_ERROR temp_error; | 
				
			||||
	SRC_STATE *state ; | 
				
			||||
	switch (converter_type) | 
				
			||||
	{ | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
	case SRC_SINC_BEST_QUALITY : | 
				
			||||
		state = sinc_state_new (converter_type, channels, &temp_error) ; | 
				
			||||
		break ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
	case SRC_SINC_MEDIUM_QUALITY : | 
				
			||||
		state = sinc_state_new (converter_type, channels, &temp_error) ; | 
				
			||||
		break ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	case SRC_SINC_FASTEST : | 
				
			||||
		state = sinc_state_new (converter_type, channels, &temp_error) ; | 
				
			||||
		break ; | 
				
			||||
#endif | 
				
			||||
	case SRC_ZERO_ORDER_HOLD : | 
				
			||||
		state = zoh_state_new (channels, &temp_error) ; | 
				
			||||
		break ; | 
				
			||||
	case SRC_LINEAR : | 
				
			||||
		state = linear_state_new (channels, &temp_error) ; | 
				
			||||
		break ; | 
				
			||||
	default : | 
				
			||||
		temp_error = SRC_ERR_BAD_CONVERTER ; | 
				
			||||
		state = NULL ; | 
				
			||||
		break ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if (error) | 
				
			||||
		*error = (int) temp_error ; | 
				
			||||
 | 
				
			||||
	return state ; | 
				
			||||
} /* psrc_set_converter */ | 
				
			||||
 | 
				
			||||
@ -0,0 +1,301 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <assert.h> | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#include "common.h" | 
				
			||||
 | 
				
			||||
static SRC_ERROR linear_vari_process (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
static void linear_reset (SRC_STATE *state) ; | 
				
			||||
static SRC_STATE *linear_copy (SRC_STATE *state) ; | 
				
			||||
static void linear_close (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
/*========================================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#define	LINEAR_MAGIC_MARKER	MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r') | 
				
			||||
 | 
				
			||||
#define	SRC_DEBUG	0 | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	int		linear_magic_marker ; | 
				
			||||
	bool	dirty ; | 
				
			||||
	long	in_count, in_used ; | 
				
			||||
	long	out_count, out_gen ; | 
				
			||||
	float	*last_value ; | 
				
			||||
} LINEAR_DATA ; | 
				
			||||
 | 
				
			||||
static SRC_STATE_VT linear_state_vt = | 
				
			||||
{ | 
				
			||||
	linear_vari_process, | 
				
			||||
	linear_vari_process, | 
				
			||||
	linear_reset, | 
				
			||||
	linear_copy, | 
				
			||||
	linear_close | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
/*----------------------------------------------------------------------------------------
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static SRC_ERROR | 
				
			||||
linear_vari_process (SRC_STATE *state, SRC_DATA *data) | 
				
			||||
{	LINEAR_DATA *priv ; | 
				
			||||
	double		src_ratio, input_index, rem ; | 
				
			||||
	int			ch ; | 
				
			||||
 | 
				
			||||
	if (data->input_frames <= 0) | 
				
			||||
		return SRC_ERR_NO_ERROR ; | 
				
			||||
 | 
				
			||||
	if (state->private_data == NULL) | 
				
			||||
		return SRC_ERR_NO_PRIVATE ; | 
				
			||||
 | 
				
			||||
	priv = (LINEAR_DATA*) state->private_data ; | 
				
			||||
 | 
				
			||||
	if (!priv->dirty) | 
				
			||||
	{	/* If we have just been reset, set the last_value data. */ | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
			priv->last_value [ch] = data->data_in [ch] ; | 
				
			||||
		priv->dirty = true ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	priv->in_count = data->input_frames * state->channels ; | 
				
			||||
	priv->out_count = data->output_frames * state->channels ; | 
				
			||||
	priv->in_used = priv->out_gen = 0 ; | 
				
			||||
 | 
				
			||||
	src_ratio = state->last_ratio ; | 
				
			||||
 | 
				
			||||
	if (is_bad_src_ratio (src_ratio)) | 
				
			||||
		return SRC_ERR_BAD_INTERNAL_STATE ; | 
				
			||||
 | 
				
			||||
	input_index = state->last_position ; | 
				
			||||
 | 
				
			||||
	/* Calculate samples before first sample in input array. */ | 
				
			||||
	while (input_index < 1.0 && priv->out_gen < priv->out_count) | 
				
			||||
	{ | 
				
			||||
		if (priv->in_used + state->channels * (1.0 + input_index) >= priv->in_count) | 
				
			||||
			break ; | 
				
			||||
 | 
				
			||||
		if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) | 
				
			||||
			src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; | 
				
			||||
 | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
		{	data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index * | 
				
			||||
										((double) data->data_in [ch] - priv->last_value [ch])) ; | 
				
			||||
			priv->out_gen ++ ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/* Figure out the next index. */ | 
				
			||||
		input_index += 1.0 / src_ratio ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	rem = fmod_one (input_index) ; | 
				
			||||
	priv->in_used += state->channels * psf_lrint (input_index - rem) ; | 
				
			||||
	input_index = rem ; | 
				
			||||
 | 
				
			||||
	/* Main processing loop. */ | 
				
			||||
	while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index < priv->in_count) | 
				
			||||
	{ | 
				
			||||
		if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) | 
				
			||||
			src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; | 
				
			||||
 | 
				
			||||
#if SRC_DEBUG | 
				
			||||
		if (priv->in_used < state->channels && input_index < 1.0) | 
				
			||||
		{	printf ("Whoops!!!!   in_used : %ld     channels : %d     input_index : %f\n", priv->in_used, state->channels, input_index) ; | 
				
			||||
			exit (1) ; | 
				
			||||
			} ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
		{	data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - state->channels + ch] + input_index * | 
				
			||||
						((double) data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - state->channels + ch])) ; | 
				
			||||
			priv->out_gen ++ ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/* Figure out the next index. */ | 
				
			||||
		input_index += 1.0 / src_ratio ; | 
				
			||||
		rem = fmod_one (input_index) ; | 
				
			||||
 | 
				
			||||
		priv->in_used += state->channels * psf_lrint (input_index - rem) ; | 
				
			||||
		input_index = rem ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (priv->in_used > priv->in_count) | 
				
			||||
	{	input_index += (priv->in_used - priv->in_count) / state->channels ; | 
				
			||||
		priv->in_used = priv->in_count ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	state->last_position = input_index ; | 
				
			||||
 | 
				
			||||
	if (priv->in_used > 0) | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
			priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ; | 
				
			||||
 | 
				
			||||
	/* Save current ratio rather then target ratio. */ | 
				
			||||
	state->last_ratio = src_ratio ; | 
				
			||||
 | 
				
			||||
	data->input_frames_used = priv->in_used / state->channels ; | 
				
			||||
	data->output_frames_gen = priv->out_gen / state->channels ; | 
				
			||||
 | 
				
			||||
	return SRC_ERR_NO_ERROR ; | 
				
			||||
} /* linear_vari_process */ | 
				
			||||
 | 
				
			||||
/*------------------------------------------------------------------------------
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
LIBSAMPLERATE_DLL_PRIVATE const char* | 
				
			||||
linear_get_name (int src_enum) | 
				
			||||
{ | 
				
			||||
	if (src_enum == SRC_LINEAR) | 
				
			||||
		return "Linear Interpolator" ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* linear_get_name */ | 
				
			||||
 | 
				
			||||
LIBSAMPLERATE_DLL_PRIVATE const char* | 
				
			||||
linear_get_description (int src_enum) | 
				
			||||
{ | 
				
			||||
	if (src_enum == SRC_LINEAR) | 
				
			||||
		return "Linear interpolator, very fast, poor quality." ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* linear_get_descrition */ | 
				
			||||
 | 
				
			||||
static LINEAR_DATA * | 
				
			||||
linear_data_new (int channels) | 
				
			||||
{ | 
				
			||||
	assert (channels > 0) ; | 
				
			||||
 | 
				
			||||
	LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ; | 
				
			||||
	if (priv) | 
				
			||||
	{ | 
				
			||||
		priv->linear_magic_marker = LINEAR_MAGIC_MARKER ; | 
				
			||||
		priv->last_value = (float *) calloc (channels, sizeof (float)) ; | 
				
			||||
		if (!priv->last_value) | 
				
			||||
		{ | 
				
			||||
			free (priv) ; | 
				
			||||
			priv = NULL ; | 
				
			||||
		} | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	return priv ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
LIBSAMPLERATE_DLL_PRIVATE SRC_STATE * | 
				
			||||
linear_state_new (int channels, SRC_ERROR *error) | 
				
			||||
{ | 
				
			||||
	assert (channels > 0) ; | 
				
			||||
	assert (error != NULL) ; | 
				
			||||
 | 
				
			||||
	SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; | 
				
			||||
	if (!state) | 
				
			||||
	{ | 
				
			||||
		*error = SRC_ERR_MALLOC_FAILED ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	state->channels = channels ; | 
				
			||||
	state->mode = SRC_MODE_PROCESS ; | 
				
			||||
 | 
				
			||||
	state->private_data = linear_data_new (state->channels) ; | 
				
			||||
	if (!state->private_data) | 
				
			||||
	{ | 
				
			||||
		free (state) ; | 
				
			||||
		*error = SRC_ERR_MALLOC_FAILED ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	state->vt = &linear_state_vt ; | 
				
			||||
 | 
				
			||||
	linear_reset (state) ; | 
				
			||||
 | 
				
			||||
	*error = SRC_ERR_NO_ERROR ; | 
				
			||||
 | 
				
			||||
	return state ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
/*===================================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
linear_reset (SRC_STATE *state) | 
				
			||||
{	LINEAR_DATA *priv = NULL ; | 
				
			||||
 | 
				
			||||
	priv = (LINEAR_DATA*) state->private_data ; | 
				
			||||
	if (priv == NULL) | 
				
			||||
		return ; | 
				
			||||
 | 
				
			||||
	priv->dirty = false ; | 
				
			||||
	memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* linear_reset */ | 
				
			||||
 | 
				
			||||
SRC_STATE * | 
				
			||||
linear_copy (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	assert (state != NULL) ; | 
				
			||||
 | 
				
			||||
	if (state->private_data == NULL) | 
				
			||||
		return NULL ; | 
				
			||||
 | 
				
			||||
	SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; | 
				
			||||
	if (!to) | 
				
			||||
		return NULL ; | 
				
			||||
	memcpy (to, state, sizeof (SRC_STATE)) ; | 
				
			||||
 | 
				
			||||
	LINEAR_DATA* from_priv = (LINEAR_DATA*) state->private_data ; | 
				
			||||
	LINEAR_DATA *to_priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ; | 
				
			||||
	if (!to_priv) | 
				
			||||
	{ | 
				
			||||
		free (to) ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	memcpy (to_priv, from_priv, sizeof (LINEAR_DATA)) ; | 
				
			||||
	to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ; | 
				
			||||
	if (!to_priv->last_value) | 
				
			||||
	{ | 
				
			||||
		free (to) ; | 
				
			||||
		free (to_priv) ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
	memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ; | 
				
			||||
 | 
				
			||||
	to->private_data = to_priv ; | 
				
			||||
 | 
				
			||||
	return to ; | 
				
			||||
} /* linear_copy */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
linear_close (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	if (state) | 
				
			||||
	{ | 
				
			||||
		LINEAR_DATA *linear = (LINEAR_DATA *) state->private_data ; | 
				
			||||
		if (linear) | 
				
			||||
		{ | 
				
			||||
			if (linear->last_value) | 
				
			||||
			{ | 
				
			||||
				free (linear->last_value) ; | 
				
			||||
				linear->last_value = NULL ; | 
				
			||||
			} | 
				
			||||
			free (linear) ; | 
				
			||||
			linear = NULL ; | 
				
			||||
		} | 
				
			||||
		free (state) ; | 
				
			||||
		state = NULL ; | 
				
			||||
	} | 
				
			||||
} /* linear_close */ | 
				
			||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						@ -0,0 +1,290 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <assert.h> | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#include "common.h" | 
				
			||||
 | 
				
			||||
static SRC_ERROR zoh_vari_process (SRC_STATE *state, SRC_DATA *data) ; | 
				
			||||
static void zoh_reset (SRC_STATE *state) ; | 
				
			||||
static SRC_STATE *zoh_copy (SRC_STATE *state) ; | 
				
			||||
static void zoh_close (SRC_STATE *state) ; | 
				
			||||
 | 
				
			||||
/*========================================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#define	ZOH_MAGIC_MARKER	MAKE_MAGIC ('s', 'r', 'c', 'z', 'o', 'h') | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	int		zoh_magic_marker ; | 
				
			||||
	bool	dirty ; | 
				
			||||
	long	in_count, in_used ; | 
				
			||||
	long	out_count, out_gen ; | 
				
			||||
	float	*last_value ; | 
				
			||||
} ZOH_DATA ; | 
				
			||||
 | 
				
			||||
static SRC_STATE_VT zoh_state_vt = | 
				
			||||
{ | 
				
			||||
	zoh_vari_process, | 
				
			||||
	zoh_vari_process, | 
				
			||||
	zoh_reset, | 
				
			||||
	zoh_copy, | 
				
			||||
	zoh_close | 
				
			||||
} ; | 
				
			||||
 | 
				
			||||
/*----------------------------------------------------------------------------------------
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static SRC_ERROR | 
				
			||||
zoh_vari_process (SRC_STATE *state, SRC_DATA *data) | 
				
			||||
{	ZOH_DATA 	*priv ; | 
				
			||||
	double		src_ratio, input_index, rem ; | 
				
			||||
	int			ch ; | 
				
			||||
 | 
				
			||||
	if (data->input_frames <= 0) | 
				
			||||
		return SRC_ERR_NO_ERROR ; | 
				
			||||
 | 
				
			||||
	if (state->private_data == NULL) | 
				
			||||
		return SRC_ERR_NO_PRIVATE ; | 
				
			||||
 | 
				
			||||
	priv = (ZOH_DATA*) state->private_data ; | 
				
			||||
 | 
				
			||||
	if (!priv->dirty) | 
				
			||||
	{	/* If we have just been reset, set the last_value data. */ | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
			priv->last_value [ch] = data->data_in [ch] ; | 
				
			||||
		priv->dirty = true ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	priv->in_count = data->input_frames * state->channels ; | 
				
			||||
	priv->out_count = data->output_frames * state->channels ; | 
				
			||||
	priv->in_used = priv->out_gen = 0 ; | 
				
			||||
 | 
				
			||||
	src_ratio = state->last_ratio ; | 
				
			||||
 | 
				
			||||
	if (is_bad_src_ratio (src_ratio)) | 
				
			||||
		return SRC_ERR_BAD_INTERNAL_STATE ; | 
				
			||||
 | 
				
			||||
	input_index = state->last_position ; | 
				
			||||
 | 
				
			||||
	/* Calculate samples before first sample in input array. */ | 
				
			||||
	while (input_index < 1.0 && priv->out_gen < priv->out_count) | 
				
			||||
	{ | 
				
			||||
		if (priv->in_used + state->channels * input_index >= priv->in_count) | 
				
			||||
			break ; | 
				
			||||
 | 
				
			||||
		if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) | 
				
			||||
			src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; | 
				
			||||
 | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
		{	data->data_out [priv->out_gen] = priv->last_value [ch] ; | 
				
			||||
			priv->out_gen ++ ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/* Figure out the next index. */ | 
				
			||||
		input_index += 1.0 / src_ratio ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	rem = fmod_one (input_index) ; | 
				
			||||
	priv->in_used += state->channels * psf_lrint (input_index - rem) ; | 
				
			||||
	input_index = rem ; | 
				
			||||
 | 
				
			||||
	/* Main processing loop. */ | 
				
			||||
	while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index <= priv->in_count) | 
				
			||||
	{ | 
				
			||||
		if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) | 
				
			||||
			src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; | 
				
			||||
 | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
		{	data->data_out [priv->out_gen] = data->data_in [priv->in_used - state->channels + ch] ; | 
				
			||||
			priv->out_gen ++ ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		/* Figure out the next index. */ | 
				
			||||
		input_index += 1.0 / src_ratio ; | 
				
			||||
		rem = fmod_one (input_index) ; | 
				
			||||
 | 
				
			||||
		priv->in_used += state->channels * psf_lrint (input_index - rem) ; | 
				
			||||
		input_index = rem ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (priv->in_used > priv->in_count) | 
				
			||||
	{	input_index += (priv->in_used - priv->in_count) / state->channels ; | 
				
			||||
		priv->in_used = priv->in_count ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	state->last_position = input_index ; | 
				
			||||
 | 
				
			||||
	if (priv->in_used > 0) | 
				
			||||
		for (ch = 0 ; ch < state->channels ; ch++) | 
				
			||||
			priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ; | 
				
			||||
 | 
				
			||||
	/* Save current ratio rather then target ratio. */ | 
				
			||||
	state->last_ratio = src_ratio ; | 
				
			||||
 | 
				
			||||
	data->input_frames_used = priv->in_used / state->channels ; | 
				
			||||
	data->output_frames_gen = priv->out_gen / state->channels ; | 
				
			||||
 | 
				
			||||
	return SRC_ERR_NO_ERROR ; | 
				
			||||
} /* zoh_vari_process */ | 
				
			||||
 | 
				
			||||
/*------------------------------------------------------------------------------
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
LIBSAMPLERATE_DLL_PRIVATE const char* | 
				
			||||
zoh_get_name (int src_enum) | 
				
			||||
{ | 
				
			||||
	if (src_enum == SRC_ZERO_ORDER_HOLD) | 
				
			||||
		return "ZOH Interpolator" ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* zoh_get_name */ | 
				
			||||
 | 
				
			||||
LIBSAMPLERATE_DLL_PRIVATE const char* | 
				
			||||
zoh_get_description (int src_enum) | 
				
			||||
{ | 
				
			||||
	if (src_enum == SRC_ZERO_ORDER_HOLD) | 
				
			||||
		return "Zero order hold interpolator, very fast, poor quality." ; | 
				
			||||
 | 
				
			||||
	return NULL ; | 
				
			||||
} /* zoh_get_descrition */ | 
				
			||||
 | 
				
			||||
static ZOH_DATA * | 
				
			||||
zoh_data_new (int channels) | 
				
			||||
{ | 
				
			||||
	assert (channels > 0) ; | 
				
			||||
 | 
				
			||||
	ZOH_DATA *priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ; | 
				
			||||
	if (priv) | 
				
			||||
	{ | 
				
			||||
		priv->zoh_magic_marker = ZOH_MAGIC_MARKER ; | 
				
			||||
		priv->last_value = (float *) calloc (channels, sizeof (float)) ; | 
				
			||||
		if (!priv->last_value) | 
				
			||||
		{ | 
				
			||||
			free (priv) ; | 
				
			||||
			priv = NULL ; | 
				
			||||
		} | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	return priv ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
LIBSAMPLERATE_DLL_PRIVATE SRC_STATE * | 
				
			||||
zoh_state_new (int channels, SRC_ERROR *error) | 
				
			||||
{ | 
				
			||||
	assert (channels > 0) ; | 
				
			||||
	assert (error != NULL) ; | 
				
			||||
 | 
				
			||||
	SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; | 
				
			||||
	if (!state) | 
				
			||||
	{ | 
				
			||||
		*error = SRC_ERR_MALLOC_FAILED ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	state->channels = channels ; | 
				
			||||
	state->mode = SRC_MODE_PROCESS ; | 
				
			||||
 | 
				
			||||
	state->private_data = zoh_data_new (state->channels) ; | 
				
			||||
	if (!state->private_data) | 
				
			||||
	{ | 
				
			||||
		free (state) ; | 
				
			||||
		*error = SRC_ERR_MALLOC_FAILED ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	state->vt = &zoh_state_vt ; | 
				
			||||
 | 
				
			||||
	zoh_reset (state) ; | 
				
			||||
 | 
				
			||||
	*error = SRC_ERR_NO_ERROR ; | 
				
			||||
 | 
				
			||||
	return state ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
/*===================================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
zoh_reset (SRC_STATE *state) | 
				
			||||
{	ZOH_DATA *priv ; | 
				
			||||
 | 
				
			||||
	priv = (ZOH_DATA*) state->private_data ; | 
				
			||||
	if (priv == NULL) | 
				
			||||
		return ; | 
				
			||||
 | 
				
			||||
	priv->dirty = false ; | 
				
			||||
	memset (priv->last_value, 0, sizeof (float) * state->channels) ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* zoh_reset */ | 
				
			||||
 | 
				
			||||
static SRC_STATE * | 
				
			||||
zoh_copy (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	assert (state != NULL) ; | 
				
			||||
 | 
				
			||||
	if (state->private_data == NULL) | 
				
			||||
		return NULL ; | 
				
			||||
 | 
				
			||||
	SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; | 
				
			||||
	if (!to) | 
				
			||||
		return NULL ; | 
				
			||||
	memcpy (to, state, sizeof (SRC_STATE)) ; | 
				
			||||
 | 
				
			||||
	ZOH_DATA* from_priv = (ZOH_DATA*) state->private_data ; | 
				
			||||
	ZOH_DATA *to_priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ; | 
				
			||||
	if (!to_priv) | 
				
			||||
	{ | 
				
			||||
		free (to) ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	memcpy (to_priv, from_priv, sizeof (ZOH_DATA)) ; | 
				
			||||
	to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ; | 
				
			||||
	if (!to_priv->last_value) | 
				
			||||
	{ | 
				
			||||
		free (to) ; | 
				
			||||
		free (to_priv) ; | 
				
			||||
		return NULL ; | 
				
			||||
	} | 
				
			||||
	memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ; | 
				
			||||
 | 
				
			||||
	to->private_data = to_priv ; | 
				
			||||
 | 
				
			||||
	return to ; | 
				
			||||
} /* zoh_copy */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
zoh_close (SRC_STATE *state) | 
				
			||||
{ | 
				
			||||
	if (state) | 
				
			||||
	{ | 
				
			||||
		ZOH_DATA *zoh = (ZOH_DATA *) state->private_data ; | 
				
			||||
		if (zoh) | 
				
			||||
		{ | 
				
			||||
			if (zoh->last_value) | 
				
			||||
			{ | 
				
			||||
				free (zoh->last_value) ; | 
				
			||||
				zoh->last_value = NULL ; | 
				
			||||
			} | 
				
			||||
			free (zoh) ; | 
				
			||||
			zoh = NULL ; | 
				
			||||
		} | 
				
			||||
		free (state) ; | 
				
			||||
		state = NULL ; | 
				
			||||
	} | 
				
			||||
} /* zoh_close */ | 
				
			||||
@ -0,0 +1,95 @@ | 
				
			||||
check_include_file(sys/times.h HAVE_SYS_TIMES_H) | 
				
			||||
 | 
				
			||||
check_function_exists(alarm HAVE_ALARM) | 
				
			||||
check_function_exists(signal HAVE_SIGNAL) | 
				
			||||
 | 
				
			||||
check_symbol_exists(SIGALRM signal.h HAVE_SIGALRM) | 
				
			||||
 | 
				
			||||
if((NOT VCPKG_TOOLCHAIN) AND PKG_CONFIG_FOUND AND (NOT CMAKE_VERSION VERSION_LESS 3.6)) | 
				
			||||
  pkg_check_modules(FFTW3 fftw3 IMPORTED_TARGET) | 
				
			||||
  if(FFTW3_FOUND) | 
				
			||||
    add_library(FFTW3::fftw3 INTERFACE IMPORTED) | 
				
			||||
    target_link_libraries(FFTW3::fftw3 INTERFACE PkgConfig::FFTW3) | 
				
			||||
  endif() | 
				
			||||
else() | 
				
			||||
  find_package(FFTW3) | 
				
			||||
endif() | 
				
			||||
 | 
				
			||||
set(HAVE_FFTW3 ${FFTW3_FOUND} PARENT_SCOPE) | 
				
			||||
 | 
				
			||||
add_executable(misc_test misc_test.c util.c util.h) | 
				
			||||
target_link_libraries(misc_test PRIVATE samplerate) | 
				
			||||
add_test(NAME misc_test COMMAND misc_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(termination_test termination_test.c util.c util.h) | 
				
			||||
target_link_libraries(termination_test PRIVATE samplerate) | 
				
			||||
add_test(NAME termination_test COMMAND termination_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(callback_hang_test callback_hang_test.c util.c util.h) | 
				
			||||
target_link_libraries(callback_hang_test PRIVATE samplerate) | 
				
			||||
add_test(NAME callback_hang_test COMMAND callback_hang_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(downsample_test downsample_test.c util.c util.h) | 
				
			||||
target_link_libraries(downsample_test PRIVATE samplerate) | 
				
			||||
add_test(NAME downsample_test COMMAND downsample_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(simple_test simple_test.c util.c util.h) | 
				
			||||
target_link_libraries(simple_test PRIVATE samplerate) | 
				
			||||
add_test(NAME simple_test COMMAND simple_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(callback_test callback_test.c util.c util.h) | 
				
			||||
target_link_libraries(callback_test PRIVATE samplerate) | 
				
			||||
add_test(NAME callback_test COMMAND callback_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(reset_test reset_test.c util.c util.h) | 
				
			||||
target_link_libraries(reset_test PRIVATE samplerate) | 
				
			||||
add_test(NAME reset_test COMMAND reset_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(clone_test clone_test.c util.c util.h) | 
				
			||||
target_link_libraries(clone_test PRIVATE samplerate) | 
				
			||||
add_test(NAME clone_test COMMAND clone_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(nullptr_test nullptr_test.c util.c util.h) | 
				
			||||
target_link_libraries(nullptr_test PRIVATE samplerate) | 
				
			||||
add_test(NAME nullptr_test COMMAND nullptr_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(multi_channel_test multi_channel_test.c calc_snr.c util.c util.h) | 
				
			||||
target_link_libraries(multi_channel_test | 
				
			||||
  PRIVATE | 
				
			||||
    samplerate | 
				
			||||
    $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> | 
				
			||||
   ) | 
				
			||||
add_test(NAME multi_channel_test COMMAND multi_channel_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(varispeed_test varispeed_test.c calc_snr.c util.c util.h) | 
				
			||||
target_link_libraries(varispeed_test | 
				
			||||
  PRIVATE samplerate | 
				
			||||
    $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> | 
				
			||||
   ) | 
				
			||||
add_test(NAME varispeed_test COMMAND varispeed_test util.c util.h WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(float_short_test float_short_test.c) | 
				
			||||
target_link_libraries(float_short_test PRIVATE samplerate) | 
				
			||||
add_test(NAME float_short_test COMMAND float_short_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(snr_bw_test snr_bw_test.c calc_snr.c util.c util.h) | 
				
			||||
target_link_libraries(snr_bw_test | 
				
			||||
  PRIVATE | 
				
			||||
    samplerate | 
				
			||||
    $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> | 
				
			||||
   ) | 
				
			||||
add_test(NAME snr_bw_test COMMAND snr_bw_test util.c util.h WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) | 
				
			||||
 | 
				
			||||
add_executable(throughput_test throughput_test.c util.c util.h) | 
				
			||||
target_link_libraries(throughput_test PRIVATE samplerate) | 
				
			||||
 | 
				
			||||
add_executable(multichan_throughput_test multichan_throughput_test.c util.c util.h) | 
				
			||||
target_link_libraries(multichan_throughput_test PRIVATE samplerate) | 
				
			||||
 | 
				
			||||
add_executable(src-evaluate src-evaluate.c util.c util.h calc_snr.c) | 
				
			||||
target_link_libraries(src-evaluate | 
				
			||||
  PRIVATE | 
				
			||||
    samplerate | 
				
			||||
    $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> | 
				
			||||
    $<$<BOOL:${SndFile_FOUND}>:${SNDFILE_TARGET}> | 
				
			||||
   ) | 
				
			||||
@ -0,0 +1,243 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#if (HAVE_FFTW3) | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
 | 
				
			||||
	maxval = 0.0 ; | 
				
			||||
	for (k = 1 ; k < len / 2 ; k++) | 
				
			||||
	{	/*
 | 
				
			||||
		** From : http://www.fftw.org/doc/Real_002dto_002dReal-Transform-Kinds.html#Real_002dto_002dReal-Transform-Kinds
 | 
				
			||||
		** | 
				
			||||
		** FFTW_R2HC computes a real-input DFT with output in “halfcomplex” format, i.e. real and imaginary parts | 
				
			||||
		** for a transform of size n stored as: | 
				
			||||
		** | 
				
			||||
		**      r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1 | 
				
			||||
		*/ | 
				
			||||
		double re = magnitude [k] ; | 
				
			||||
		double im = magnitude [len - k] ; | 
				
			||||
		magnitude [k] = sqrt (re * re + im * im) ; | 
				
			||||
		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,127 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#ifdef HAVE_UNISTD_H | 
				
			||||
#include <unistd.h> | 
				
			||||
#endif | 
				
			||||
#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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	callback_hang_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
	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,238 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2003-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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]) ; | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	puts ("    Sinc interpolator :") ; | 
				
			||||
	for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | 
				
			||||
		callback_test (SRC_SINC_FASTEST, src_ratios [k]) ; | 
				
			||||
#endif | 
				
			||||
	puts ("") ; | 
				
			||||
 | 
				
			||||
	puts ("    End of stream test :") ; | 
				
			||||
	end_of_stream_test (SRC_ZERO_ORDER_HOLD) ; | 
				
			||||
	end_of_stream_test (SRC_LINEAR) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	end_of_stream_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	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_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 ; | 
				
			||||
	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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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) ; | 
				
			||||
		} | 
				
			||||
	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_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,134 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#define	BUFFER_LEN		(1 << 16) | 
				
			||||
#define NUM_CHANNELS 	2 | 
				
			||||
#define FRAMES_PER_PASS (BUFFER_LEN >> 1) | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
clone_test (int converter) | 
				
			||||
{	static float input_serial [BUFFER_LEN * NUM_CHANNELS], input_interleaved [BUFFER_LEN * NUM_CHANNELS] ; | 
				
			||||
	static float output [BUFFER_LEN * NUM_CHANNELS], output_cloned [BUFFER_LEN * NUM_CHANNELS] ; | 
				
			||||
	double sine_freq ; | 
				
			||||
 | 
				
			||||
	SRC_STATE* src_state ; | 
				
			||||
	SRC_STATE* src_state_cloned ; | 
				
			||||
	SRC_DATA src_data, src_data_cloned ; | 
				
			||||
 | 
				
			||||
	int error, frame, ch, idx ; | 
				
			||||
 | 
				
			||||
	printf ("        clone_test          (%-28s) ....... ", src_get_name (converter)) ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
 | 
				
			||||
	memset (input_serial, 0, sizeof (input_serial)) ; | 
				
			||||
	memset (input_interleaved, 0, sizeof (input_interleaved)) ; | 
				
			||||
	memset (output, 0, sizeof (output)) ; | 
				
			||||
	memset (output_cloned, 0, sizeof (output_cloned)) ; | 
				
			||||
 | 
				
			||||
	/* Fill input buffer with an n-channel interleaved sine wave */ | 
				
			||||
	sine_freq = 0.0111 ; | 
				
			||||
	gen_windowed_sines (1, &sine_freq, 1.0, input_serial, BUFFER_LEN) ; | 
				
			||||
	gen_windowed_sines (1, &sine_freq, 1.0, input_serial + BUFFER_LEN, BUFFER_LEN) ; | 
				
			||||
	interleave_data (input_serial, input_interleaved, BUFFER_LEN, NUM_CHANNELS) ; | 
				
			||||
 | 
				
			||||
	if ((src_state = src_new (converter, NUM_CHANNELS, &error)) == NULL) | 
				
			||||
	{	printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Perform initial pass using first half of buffer so that src_state has non-trivial state */ | 
				
			||||
	src_data.src_ratio = 1.1 ; | 
				
			||||
	src_data.input_frames = FRAMES_PER_PASS ; | 
				
			||||
	src_data.output_frames = FRAMES_PER_PASS ; | 
				
			||||
	src_data.data_in = input_interleaved ; | 
				
			||||
	src_data.data_out = output ; | 
				
			||||
	src_data.output_frames_gen = 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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Clone handle */ | 
				
			||||
	if ((src_state_cloned = src_clone (src_state, &error)) == NULL) | 
				
			||||
	{	printf ("\n\nLine %d : src_clone() failed : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Process second half of buffer with both handles */ | 
				
			||||
	src_data.data_in = input_interleaved + FRAMES_PER_PASS ; | 
				
			||||
 | 
				
			||||
	src_data_cloned = src_data ; | 
				
			||||
	src_data_cloned.data_out = output_cloned ; | 
				
			||||
 | 
				
			||||
	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 ((error = src_process (src_state_cloned, &src_data_cloned))) | 
				
			||||
	{	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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Check that both handles generated the same number of output frames */ | 
				
			||||
	if (src_data.output_frames_gen != src_data_cloned.output_frames_gen) | 
				
			||||
	{	printf ("\n\nLine %d : cloned output_frames_gen (%ld) != original (%ld)\n\n", __LINE__, | 
				
			||||
				src_data_cloned.output_frames_gen, src_data.output_frames_gen) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	for (ch = 0 ; ch < NUM_CHANNELS ; ch++) | 
				
			||||
	{	for (frame = 0 ; frame < src_data.output_frames_gen ; frame++) | 
				
			||||
		{	idx = ch * NUM_CHANNELS + ch ; | 
				
			||||
			if (output[idx] != output_cloned[idx]) | 
				
			||||
			{	printf ("\n\nLine %d : cloned data does not equal original data at channel %d, frame %d\n\n", | 
				
			||||
						__LINE__, ch, frame) ; | 
				
			||||
				exit (1) ; | 
				
			||||
				} ; | 
				
			||||
			} ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	src_delete (src_state) ; | 
				
			||||
	src_delete (src_state_cloned) ; | 
				
			||||
 | 
				
			||||
	puts ("ok") ; | 
				
			||||
} /* clone_test */ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (void) | 
				
			||||
{ | 
				
			||||
	puts(""); | 
				
			||||
 | 
				
			||||
	clone_test (SRC_ZERO_ORDER_HOLD) ; | 
				
			||||
	clone_test (SRC_LINEAR) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	clone_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
	puts(""); | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
@ -0,0 +1,61 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2008-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	downsample_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
	downsample_test (SRC_SINC_MEDIUM_QUALITY) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
	downsample_test (SRC_SINC_BEST_QUALITY) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
@ -0,0 +1,192 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2003-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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.95f, 0.99f, 1.0f, 1.01f, 1.1f, 2.0f, 11.1f, 111.1f, 2222.2f, 33333.3f, | 
				
			||||
		// Some "almost 1" as corner cases
 | 
				
			||||
		(float) (32767.0 / 32768.0), (float) ((32767.0 + 0.4) / 32768.0), (float) ((32767. + 0.5) / 32768.0), | 
				
			||||
		(float) ((32767.0 + 0.6) / 32768.0), (float) ((32767.0 + 0.9) / 32768.0), | 
				
			||||
		} ; | 
				
			||||
	static float fneg [] = | 
				
			||||
	{	-0.95f, -0.99f, -1.0f, -1.01f, -1.1f, -2.0f, -11.1f, -111.1f, -2222.2f, -33333.3f, | 
				
			||||
		// Some "almost 1" as corner cases
 | 
				
			||||
		(float) (-32767.0 / 32768.0), (float) (-(32767.0 + 0.4) / 32768.0), (float) (-(32767.0 + 0.5) / 32768.0), | 
				
			||||
		(float) (-(32767.0 + 0.6) / 32768.0), (float) (-(32767.0 + 0.9) / 32768.0), | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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.95f, 0.99f, 1.0f, 1.01f, 1.1f, 2.0f, 11.1f, 111.1f, 2222.2f, 33333.3f | 
				
			||||
		} ; | 
				
			||||
	static float fneg [] = | 
				
			||||
	{	-0.95f, -0.99f, -1.0f, -1.01f, -1.1f, -2.0f, -11.1f, -111.1f, -2222.2f, -33333.3f | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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,208 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
static void get_channels_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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	zero_input_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
	get_channels_test (SRC_ZERO_ORDER_HOLD) ; | 
				
			||||
	get_channels_test (SRC_LINEAR) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	get_channels_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
	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 *) (size_t) 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 */ | 
				
			||||
 | 
				
			||||
static void get_channels_test(int converter) | 
				
			||||
{ | 
				
			||||
	SRC_STATE *state; | 
				
			||||
	int channels_in, channels_out; | 
				
			||||
	const char *errorstr; | 
				
			||||
 | 
				
			||||
	state = NULL; | 
				
			||||
	if ((channels_out = src_get_channels(state)) >= 0) | 
				
			||||
	{ | 
				
			||||
		printf ("\n\nLine %d : Return value should be negative, was : %d.\n\n", __LINE__, channels_out) ; | 
				
			||||
		exit (1) ; | 
				
			||||
	} | 
				
			||||
	errorstr = src_strerror(-channels_out); | 
				
			||||
	if (!strstr(errorstr, "NULL")) | 
				
			||||
	{ | 
				
			||||
		printf ("\n\nLine %d : Inverted output should be valid error code mentioning a NULL pointer, was : %s.\n\n", __LINE__, errorstr) ; | 
				
			||||
		exit (1) ; | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	for (channels_in = 1; channels_in <= 8; channels_in++) | 
				
			||||
	{ | 
				
			||||
		int error; | 
				
			||||
		state = src_new(converter, channels_in, &error); | 
				
			||||
		if ((channels_out = src_get_channels(state)) != channels_in) | 
				
			||||
		{ | 
				
			||||
			printf ("\n\nLine %d : Return value should be %d, was : %d.\n\n", __LINE__, channels_in, channels_out) ; | 
				
			||||
			exit (1) ; | 
				
			||||
		} | 
				
			||||
		state = src_delete(state); | 
				
			||||
	} | 
				
			||||
} | 
				
			||||
@ -0,0 +1,368 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <math.h> | 
				
			||||
#include <assert.h> | 
				
			||||
 | 
				
			||||
#if (HAVE_FFTW3) | 
				
			||||
#include <fftw3.h> | 
				
			||||
#else | 
				
			||||
static inline void | 
				
			||||
fftw_cleanup (void) | 
				
			||||
{	return ; | 
				
			||||
} | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	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) ; | 
				
			||||
		} ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	fftw_cleanup () ; | 
				
			||||
	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,261 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2008-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <time.h> | 
				
			||||
#ifdef HAVE_UNISTD_H | 
				
			||||
#include <unistd.h> | 
				
			||||
#endif | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#ifdef _WIN32 | 
				
			||||
#ifndef WIN32_LEAN_AND_MEAN | 
				
			||||
#define WIN32_LEAN_AND_MEAN | 
				
			||||
#endif | 
				
			||||
#include <windows.h> | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#define BUFFER_LEN	(1<<17) | 
				
			||||
 | 
				
			||||
static float input [BUFFER_LEN] ; | 
				
			||||
 | 
				
			||||
#if (defined(ENABLE_SINC_FAST_CONVERTER) || defined(ENABLE_SINC_MEDIUM_CONVERTER) || \ | 
				
			||||
	defined(ENABLE_SINC_BEST_CONVERTER)) | 
				
			||||
static float output [BUFFER_LEN] ; | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
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 ; | 
				
			||||
 | 
				
			||||
#ifdef _WIN32 | 
				
			||||
	Sleep (2000) ; | 
				
			||||
#else | 
				
			||||
	sleep (2) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	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) | 
				
			||||
	{	printf ("%5.2f      %10ld\n", duration, throughput) ; | 
				
			||||
		} | 
				
			||||
	else | 
				
			||||
	{	*best_throughput = MAX (throughput, *best_throughput) ; | 
				
			||||
		printf ("%5.2f      %10ld       %10ld\n", duration, throughput, *best_throughput) ; | 
				
			||||
		} | 
				
			||||
 | 
				
			||||
} /* throughput_test */ | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
single_run (void) | 
				
			||||
{ | 
				
			||||
#if (defined(ENABLE_SINC_FAST_CONVERTER) || defined(ENABLE_SINC_MEDIUM_CONVERTER) || \ | 
				
			||||
	defined(ENABLE_SINC_BEST_CONVERTER)) | 
				
			||||
	const int max_channels = 10 ; | 
				
			||||
	int k ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	printf ("\n    CPU name : %s\n", get_cpu_name ()) ; | 
				
			||||
 | 
				
			||||
	puts ( | 
				
			||||
		"\n" | 
				
			||||
		"    Converter                        Channels    Duration      Throughput\n" | 
				
			||||
		"    ---------------------------------------------------------------------" | 
				
			||||
		) ; | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	for (k = 1 ; k <= max_channels / 2 ; k++) | 
				
			||||
		throughput_test (SRC_SINC_FASTEST, k, 0) ; | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
	for (k = 1 ; k <= max_channels / 2 ; k++) | 
				
			||||
		throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ; | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
	for (k = 1 ; k <= max_channels ; k++) | 
				
			||||
		throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ; | 
				
			||||
	puts ("") ; | 
				
			||||
#endif | 
				
			||||
	return ; | 
				
			||||
} /* single_run */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
multi_run (int run_count) | 
				
			||||
{	int channels[] = {1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18}; | 
				
			||||
 | 
				
			||||
	printf ("\n    CPU name : %s\n", get_cpu_name ()) ; | 
				
			||||
 | 
				
			||||
	puts ( | 
				
			||||
		"\n" | 
				
			||||
		"    Converter                        Channels    Duration      Throughput    Best Throughput\n" | 
				
			||||
		"    ----------------------------------------------------------------------------------------" | 
				
			||||
		) ; | 
				
			||||
 | 
				
			||||
	for (int i = 0 ; i < ARRAY_LEN(channels) ; i++) | 
				
			||||
	{ | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
		long sinc_fastest = 0 ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
		long sinc_medium = 0 ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
		long sinc_best = 0 ; | 
				
			||||
#endif | 
				
			||||
		int ch = channels[i]; | 
				
			||||
 | 
				
			||||
		for (int k = 0 ; k < run_count ; k++) | 
				
			||||
		{ | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
			throughput_test (SRC_SINC_FASTEST, ch, &sinc_fastest) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
			throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, &sinc_medium) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
			throughput_test (SRC_SINC_BEST_QUALITY, ch, &sinc_best) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
			puts ("") ; | 
				
			||||
 | 
				
			||||
			/* Let the CPU cool down. We might be running on a laptop. */ | 
				
			||||
#ifdef _WIN32 | 
				
			||||
			Sleep (10000) ; | 
				
			||||
#else | 
				
			||||
			sleep (10) ; | 
				
			||||
#endif | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		printf ( | 
				
			||||
			"\n" | 
				
			||||
			"    Converter (channels: %d)         Best Throughput\n" | 
				
			||||
			"    ------------------------------------------------\n", | 
				
			||||
			ch | 
				
			||||
			) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
		printf ("    %-30s    %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
		printf ("    %-30s    %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
		printf ("    %-30s    %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ; | 
				
			||||
#endif | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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,108 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#define	BUFFER_LEN		(1 << 16) | 
				
			||||
#define NUM_CHANNELS 	1 | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
nullptr_test (int converter) | 
				
			||||
{	static float input [BUFFER_LEN * NUM_CHANNELS] ; | 
				
			||||
	static float output [BUFFER_LEN * NUM_CHANNELS] ; | 
				
			||||
 | 
				
			||||
	SRC_STATE* src_state ; | 
				
			||||
	SRC_DATA src_data, src_data2 ; | 
				
			||||
 | 
				
			||||
	int error ; | 
				
			||||
 | 
				
			||||
	printf ("        nullptr_test        (%-28s) ....... ", src_get_name (converter)) ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
 | 
				
			||||
	memset (input, 0, sizeof (input)) ; | 
				
			||||
	memset (output, 0, sizeof (output)) ; | 
				
			||||
 | 
				
			||||
	if ((src_state = src_new (converter, NUM_CHANNELS, &error)) == NULL) | 
				
			||||
	{	printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	src_data.src_ratio = 1.1 ; | 
				
			||||
	src_data.input_frames = BUFFER_LEN ; | 
				
			||||
	src_data.output_frames = BUFFER_LEN ; | 
				
			||||
	src_data.data_in = input ; | 
				
			||||
	src_data.data_out = output ; | 
				
			||||
	src_data.output_frames_gen = 0 ; | 
				
			||||
 | 
				
			||||
	if ((error = src_process (src_state, &src_data))) | 
				
			||||
	{	printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	//Input is zero-length
 | 
				
			||||
	src_data2 = src_data; | 
				
			||||
	src_data2.data_in = NULL; | 
				
			||||
	src_data2.input_frames = 0; | 
				
			||||
 | 
				
			||||
	if ((error = src_process (src_state, &src_data2))) | 
				
			||||
	{	printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	//Output is zero-length
 | 
				
			||||
	src_data2 = src_data; | 
				
			||||
	src_data2.data_out = NULL; | 
				
			||||
	src_data2.output_frames = 0; | 
				
			||||
 | 
				
			||||
	if ((error = src_process (src_state, &src_data2))) | 
				
			||||
	{	printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	//Input and output are zero-length
 | 
				
			||||
	src_data2 = src_data; | 
				
			||||
	src_data2.data_in = NULL; | 
				
			||||
	src_data2.data_out = NULL; | 
				
			||||
	src_data2.input_frames = 0; | 
				
			||||
	src_data2.output_frames = 0; | 
				
			||||
 | 
				
			||||
	if ((error = src_process (src_state, &src_data2))) | 
				
			||||
	{	printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
	src_state = src_delete (src_state) ; | 
				
			||||
 | 
				
			||||
	puts ("ok") ; | 
				
			||||
} /* nullptr_test */ | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (void) | 
				
			||||
{ | 
				
			||||
	puts(""); | 
				
			||||
 | 
				
			||||
	nullptr_test (SRC_ZERO_ORDER_HOLD) ; | 
				
			||||
	nullptr_test (SRC_LINEAR) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	nullptr_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
	puts(""); | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
@ -0,0 +1,236 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	process_reset_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	callback_reset_test (SRC_ZERO_ORDER_HOLD) ; | 
				
			||||
	callback_reset_test (SRC_LINEAR) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	callback_reset_test (SRC_SINC_FASTEST) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	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 successful. */ | 
				
			||||
	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 successful. */ | 
				
			||||
	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,168 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
static void src_simple_produces_output (int converter, int channels, double src_ratio) ; | 
				
			||||
static void src_simple_produces_output_test (int converter, double src_ratio) ; | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (void) | 
				
			||||
{	static double src_ratios [] = | 
				
			||||
	{	1.0001, 0.099, 0.1, 0.33333333, 0.789, 1.9, 3.1, 9.9, 256.0, 1.0 / 256.0 | 
				
			||||
	} ; | 
				
			||||
 | 
				
			||||
	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]) ; | 
				
			||||
		src_simple_produces_output_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]) ; | 
				
			||||
		src_simple_produces_output_test (SRC_LINEAR, src_ratios [k]) ; | 
				
			||||
		} | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	puts ("    Sinc interpolator :") ; | 
				
			||||
	for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | 
				
			||||
	{	simple_test (SRC_SINC_FASTEST, src_ratios [k]) ; | 
				
			||||
		src_simple_produces_output_test (SRC_SINC_FASTEST, src_ratios [k]) ; | 
				
			||||
		} | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
src_simple_produces_output_test (int converter, double src_ratio) | 
				
			||||
{ | 
				
			||||
	for (int channels = 1; channels <= 9; channels++) | 
				
			||||
		src_simple_produces_output(converter, channels, src_ratio); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
src_simple_produces_output (int converter, int channels, double src_ratio) | 
				
			||||
{ | 
				
			||||
	// Choose a suitable number of frames.
 | 
				
			||||
	// At least 256 so a conversion ratio of 1/256 can produce any output
 | 
				
			||||
	const long NUM_FRAMES = 1000; | 
				
			||||
	int error; | 
				
			||||
 | 
				
			||||
	printf ("\tproduces_output\t(SRC ratio = %6.4f, channels = %d) ... ", src_ratio, channels) ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
 | 
				
			||||
	float *input = calloc (NUM_FRAMES * channels, sizeof (float)); | 
				
			||||
	float *output = calloc (NUM_FRAMES * channels, sizeof (float)); | 
				
			||||
 | 
				
			||||
	SRC_DATA src_data; | 
				
			||||
	memset (&src_data, 0, sizeof (src_data)) ; | 
				
			||||
	src_data.data_in = input; | 
				
			||||
	src_data.data_out = output; | 
				
			||||
	src_data.input_frames = NUM_FRAMES; | 
				
			||||
	src_data.output_frames = NUM_FRAMES; | 
				
			||||
	src_data.src_ratio = src_ratio; | 
				
			||||
 | 
				
			||||
	if ((error = src_simple (&src_data, converter, channels))) | 
				
			||||
	{	printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
	if (src_data.input_frames_used == 0) | 
				
			||||
	{	printf ("\n\nLine %d : No input frames used.\n\n", __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
	if (src_data.output_frames_gen == 0) | 
				
			||||
	{	printf ("\n\nLine %d : No output frames generated.\n\n", __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
	free(input); | 
				
			||||
	free(output); | 
				
			||||
	puts ("ok") ; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
 | 
				
			||||
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\t(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,404 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <math.h> | 
				
			||||
#include <time.h> | 
				
			||||
 | 
				
			||||
#if (HAVE_FFTW3) | 
				
			||||
 | 
				
			||||
#include <fftw3.h> | 
				
			||||
 | 
				
			||||
#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,	1.0 }, | 
				
			||||
				{	2,	{ 0.012345, 0.457 },	0.456789,	1,	 12.0,	1.0 }, | 
				
			||||
				{	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,	 15.0,	0.94 }, | 
				
			||||
				{	2,	{ 0.012345, 0.457 },	0.456789,	1,	 25.0,	0.96 }, | 
				
			||||
				{	1,	{ 0.3511111111 },		1.33,		1,	 22.0,	0.99 } | 
				
			||||
				} | 
				
			||||
			}, | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
		{	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 } | 
				
			||||
				} | 
				
			||||
			}, | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
		{	SRC_SINC_MEDIUM_QUALITY, | 
				
			||||
			9, | 
				
			||||
			BOOLEAN_TRUE, | 
				
			||||
			{	{	1,	{ 0.01111111111 },		3.0,		1,	145.0,	1.0 }, | 
				
			||||
				{	1,	{ 0.01111111111 },		0.6,		1,	132.0,	1.0 }, | 
				
			||||
				{	1,	{ 0.01111111111 },		0.3,		1,	138.0,	1.0 }, | 
				
			||||
				{	1,	{ 0.01111111111 },		1.0,		1,	157.0,	1.0 }, | 
				
			||||
				{	1,	{ 0.01111111111 },		1.001,		1,	148.0,	1.0 }, | 
				
			||||
				{	2,	{ 0.011111, 0.324 },	1.9999,		2,	127.0,	1.0 }, | 
				
			||||
				{	2,	{ 0.012345, 0.457 },	0.456789,	1,	123.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 } | 
				
			||||
				} | 
				
			||||
			}, | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
		{	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,	148.0,	1.0 }, | 
				
			||||
				{	1,	{ 0.01111111111 },		1.0,		1,	155.0,	1.0 }, | 
				
			||||
				{	1,	{ 0.01111111111 },		1.001,		1,	148.0,	1.0 }, | 
				
			||||
				{	2,	{ 0.011111, 0.324 },	1.9999,		2,	146.0,	1.0 }, | 
				
			||||
				{	2,	{ 0.012345, 0.457 },	0.456789,	1,	147.0,	0.5 }, | 
				
			||||
				{	2,	{ 0.011111, 0.45 },		0.6,		1,	144.0,	0.5 }, | 
				
			||||
				{	1,	{ 0.43111111111 },		1.33,		1,	145.0,	1.0 } | 
				
			||||
				} | 
				
			||||
			}, | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
		} ; /* 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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	fftw_cleanup () ; | 
				
			||||
 | 
				
			||||
	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 &= ((~0u) << 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 ((int) (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,530 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#ifdef HAVE_UNISTD_H | 
				
			||||
#include <unistd.h> | 
				
			||||
#endif | 
				
			||||
#include <string.h> | 
				
			||||
#include <ctype.h> | 
				
			||||
 | 
				
			||||
#if defined(_WIN32) | 
				
			||||
#define popen _popen | 
				
			||||
#define pclose _pclose | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#if (HAVE_FFTW3 && HAVE_SNDFILE && HAVE_SYS_TIMES_H) | 
				
			||||
 | 
				
			||||
#include <time.h> | 
				
			||||
#include <sys/times.h> | 
				
			||||
 | 
				
			||||
#include <sndfile.h> | 
				
			||||
#include <math.h> | 
				
			||||
#include <sys/utsname.h> | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#define	MAX_FREQS		4 | 
				
			||||
#define	BUFFER_LEN		80000 | 
				
			||||
 | 
				
			||||
#define SAFE_STRNCAT(dest,src,len)								\ | 
				
			||||
		{	int safe_strncat_count ;							\
 | 
				
			||||
			safe_strncat_count = (len) - strlen (dest) - 1 ;	\
 | 
				
			||||
			strncat ((dest), (src), safe_strncat_count) ;		\
 | 
				
			||||
			(dest) [(len) - 1] = 0 ;							\
 | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	int		freq_count ; | 
				
			||||
	double	freqs [MAX_FREQS] ; | 
				
			||||
 | 
				
			||||
	int		output_samplerate ; | 
				
			||||
	int		pass_band_peaks ; | 
				
			||||
 | 
				
			||||
	double	peak_value ; | 
				
			||||
} SNR_TEST ; | 
				
			||||
 | 
				
			||||
typedef struct | 
				
			||||
{	const char	*progname ; | 
				
			||||
	const char	*version_cmd ; | 
				
			||||
	const char	*version_start ; | 
				
			||||
	const char	*convert_cmd ; | 
				
			||||
	int			format ; | 
				
			||||
} RESAMPLE_PROG ; | 
				
			||||
 | 
				
			||||
static char *get_progname (char *) ; | 
				
			||||
static void usage_exit (const char *, const RESAMPLE_PROG *prog, int count) ; | 
				
			||||
static void measure_program (const RESAMPLE_PROG *prog, int verbose) ; | 
				
			||||
static void generate_source_wav (const char *filename, const double *freqs, int freq_count, int format) ; | 
				
			||||
static const char* get_machine_details (void) ; | 
				
			||||
 | 
				
			||||
static char	version_string [512] ; | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (int argc, char *argv []) | 
				
			||||
{	static RESAMPLE_PROG resample_progs [] = | 
				
			||||
	{	{	"sndfile-resample", | 
				
			||||
			"examples/sndfile-resample --version", | 
				
			||||
			"libsamplerate", | 
				
			||||
			"examples/sndfile-resample --max-speed -c 0 -to %d source.wav destination.wav", | 
				
			||||
			SF_FORMAT_WAV | SF_FORMAT_PCM_32 | 
				
			||||
			}, | 
				
			||||
		{	"sox", | 
				
			||||
			"sox -h 2>&1", | 
				
			||||
			"sox", | 
				
			||||
			"sox source.wav -r %d destination.wav resample 0.835", | 
				
			||||
			SF_FORMAT_WAV | SF_FORMAT_PCM_32 | 
				
			||||
			}, | 
				
			||||
		{	"ResampAudio", | 
				
			||||
			"ResampAudio --version", | 
				
			||||
			"ResampAudio", | 
				
			||||
			"ResampAudio -f cutoff=0.41,atten=100,ratio=128 -s %d source.wav destination.wav", | 
				
			||||
			SF_FORMAT_WAV | SF_FORMAT_PCM_32 | 
				
			||||
			}, | 
				
			||||
 | 
				
			||||
		/*-
 | 
				
			||||
		{	/+* | 
				
			||||
			** The Shibatch converter doesn't work for all combinations of | 
				
			||||
			** source and destination sample rates. Therefore it can't be | 
				
			||||
			** included in this test. | 
				
			||||
			*+/ | 
				
			||||
			"shibatch", | 
				
			||||
			"ssrc", | 
				
			||||
			"Shibatch", | 
				
			||||
			"ssrc --rate %d source.wav destination.wav", | 
				
			||||
			SF_FORMAT_WAV | SF_FORMAT_PCM_32 | 
				
			||||
			},-*/ | 
				
			||||
 | 
				
			||||
		/*-
 | 
				
			||||
		{	/+* | 
				
			||||
			** The resample program is not able to match the bandwidth and SNR | 
				
			||||
			** specs or sndfile-resample and hence will not be tested. | 
				
			||||
			*+/ | 
				
			||||
			"resample", | 
				
			||||
			"resample -version", | 
				
			||||
			"resample", | 
				
			||||
			"resample -to %d source.wav destination.wav", | 
				
			||||
			SF_FORMAT_WAV | SF_FORMAT_FLOAT | 
				
			||||
			},-*/ | 
				
			||||
 | 
				
			||||
		/*-
 | 
				
			||||
		{	"mplayer", | 
				
			||||
			"mplayer -v 2>&1", | 
				
			||||
			"MPlayer ", | 
				
			||||
			"mplayer -ao pcm -srate %d source.wav >/dev/null 2>&1 && mv audiodump.wav destination.wav", | 
				
			||||
			SF_FORMAT_WAV | SF_FORMAT_PCM_32 | 
				
			||||
			},-*/ | 
				
			||||
 | 
				
			||||
		} ; /* resample_progs */ | 
				
			||||
 | 
				
			||||
	char	*progname ; | 
				
			||||
	int 	prog = 0, verbose = 0 ; | 
				
			||||
 | 
				
			||||
	progname = get_progname (argv [0]) ; | 
				
			||||
 | 
				
			||||
	printf ("\n  %s : evaluate a sample rate converter.\n", progname) ; | 
				
			||||
 | 
				
			||||
	if (argc == 3 && strcmp ("--verbose", argv [1]) == 0) | 
				
			||||
	{	verbose = 1 ; | 
				
			||||
		prog = atoi (argv [2]) ; | 
				
			||||
		} | 
				
			||||
	else if (argc == 2) | 
				
			||||
	{	verbose = 0 ; | 
				
			||||
		prog = atoi (argv [1]) ; | 
				
			||||
		} | 
				
			||||
	else | 
				
			||||
		usage_exit (progname, resample_progs, ARRAY_LEN (resample_progs)) ; | 
				
			||||
 | 
				
			||||
	if (prog < 0 || prog >= ARRAY_LEN (resample_progs)) | 
				
			||||
		usage_exit (progname, resample_progs, ARRAY_LEN (resample_progs)) ; | 
				
			||||
 | 
				
			||||
	measure_program (& (resample_progs [prog]), verbose) ; | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static char * | 
				
			||||
get_progname (char *progname) | 
				
			||||
{	char *cptr ; | 
				
			||||
 | 
				
			||||
	if ((cptr = strrchr (progname, '/')) != NULL) | 
				
			||||
		progname = cptr + 1 ; | 
				
			||||
 | 
				
			||||
	if ((cptr = strrchr (progname, '\\')) != NULL) | 
				
			||||
		progname = cptr + 1 ; | 
				
			||||
 | 
				
			||||
	return progname ; | 
				
			||||
} /* get_progname */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
usage_exit (const char *progname, const RESAMPLE_PROG *prog, int count) | 
				
			||||
{	int k ; | 
				
			||||
 | 
				
			||||
	printf ("\n  Usage : %s <number>\n\n", progname) ; | 
				
			||||
 | 
				
			||||
	puts ("  where <number> specifies the program to test:\n") ; | 
				
			||||
 | 
				
			||||
	for (k = 0 ; k < count ; k++) | 
				
			||||
		printf ("    %d : %s\n", k, prog [k].progname) ; | 
				
			||||
 | 
				
			||||
	puts ("\n" | 
				
			||||
		" Obviously to test a given program you have to have it available on\n" | 
				
			||||
		" your system. See http://libsndfile.github.io/libsamplerate/quality.html for\n" | 
				
			||||
		" the download location of these programs.\n") ; | 
				
			||||
 | 
				
			||||
	exit (1) ; | 
				
			||||
} /* usage_exit */ | 
				
			||||
 | 
				
			||||
static const char* | 
				
			||||
get_machine_details (void) | 
				
			||||
{	static char namestr [262] ; | 
				
			||||
 | 
				
			||||
	struct utsname name ; | 
				
			||||
 | 
				
			||||
	if (uname (&name) != 0) | 
				
			||||
	{	snprintf (namestr, sizeof (namestr), "Unknown") ; | 
				
			||||
		return namestr ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	snprintf (namestr, sizeof (namestr), "%s (%s %s %s)", name.nodename, | 
				
			||||
			name.machine, name.sysname, name.release) ; | 
				
			||||
 | 
				
			||||
	return namestr ; | 
				
			||||
} /* get_machine_details */ | 
				
			||||
 | 
				
			||||
 | 
				
			||||
/*==============================================================================
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
get_version_string (const RESAMPLE_PROG *prog) | 
				
			||||
{	FILE *file ; | 
				
			||||
	char *cptr ; | 
				
			||||
 | 
				
			||||
	/* Default. */ | 
				
			||||
	snprintf (version_string, sizeof (version_string), "no version") ; | 
				
			||||
 | 
				
			||||
	if (prog->version_cmd == NULL) | 
				
			||||
		return ; | 
				
			||||
 | 
				
			||||
	if ((file = popen (prog->version_cmd, "r")) == NULL) | 
				
			||||
		return ; | 
				
			||||
 | 
				
			||||
	while ((cptr = fgets (version_string, sizeof (version_string), file)) != NULL) | 
				
			||||
	{ | 
				
			||||
		if (strstr (cptr, prog->version_start) != NULL) | 
				
			||||
			break ; | 
				
			||||
 | 
				
			||||
		version_string [0] = 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	pclose (file) ; | 
				
			||||
 | 
				
			||||
	/* Remove trailing newline. */ | 
				
			||||
	if ((cptr = strchr (version_string, '\n')) != NULL) | 
				
			||||
		cptr [0] = 0 ; | 
				
			||||
 | 
				
			||||
	/* Remove leading whitespace from version string. */ | 
				
			||||
	cptr = version_string ; | 
				
			||||
	while (cptr [0] != 0 && isspace (cptr [0])) | 
				
			||||
		cptr ++ ; | 
				
			||||
 | 
				
			||||
	if (cptr != version_string) | 
				
			||||
	{	strncpy (version_string, cptr, sizeof (version_string) - 1) ; | 
				
			||||
		version_string [sizeof (version_string) - 1] = 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* get_version_string */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
generate_source_wav (const char *filename, const double *freqs, int freq_count, int format) | 
				
			||||
{	static float buffer [BUFFER_LEN] ; | 
				
			||||
 | 
				
			||||
	SNDFILE *sndfile ; | 
				
			||||
	SF_INFO sfinfo ; | 
				
			||||
 | 
				
			||||
	sfinfo.channels = 1 ; | 
				
			||||
	sfinfo.samplerate = 44100 ; | 
				
			||||
	sfinfo.format = format ; | 
				
			||||
 | 
				
			||||
	if ((sndfile = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) | 
				
			||||
	{	printf ("Line %d : cound not open '%s' : %s\n", __LINE__, filename, sf_strerror (NULL)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; | 
				
			||||
 | 
				
			||||
	gen_windowed_sines (freq_count, freqs, 0.9, buffer, ARRAY_LEN (buffer)) ; | 
				
			||||
 | 
				
			||||
	if (sf_write_float (sndfile, buffer, ARRAY_LEN (buffer)) != ARRAY_LEN (buffer)) | 
				
			||||
	{	printf ("Line %d : sf_write_float short write.\n", __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	sf_close (sndfile) ; | 
				
			||||
} /* generate_source_wav */ | 
				
			||||
 | 
				
			||||
static double | 
				
			||||
measure_destination_wav (char *filename, int *output_samples, int expected_peaks) | 
				
			||||
{	static float buffer [250000] ; | 
				
			||||
 | 
				
			||||
	SNDFILE *sndfile ; | 
				
			||||
	SF_INFO sfinfo ; | 
				
			||||
	double snr ; | 
				
			||||
 | 
				
			||||
	if ((sndfile = sf_open (filename, SFM_READ, &sfinfo)) == NULL) | 
				
			||||
	{	printf ("Line %d : Cound not open '%s' : %s\n", __LINE__, filename, sf_strerror (NULL)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (sfinfo.channels != 1) | 
				
			||||
	{	printf ("Line %d : Bad channel count (%d). Should be 1.\n", __LINE__, sfinfo.channels) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (sfinfo.frames > ARRAY_LEN (buffer)) | 
				
			||||
	{	printf ("Line %d : Too many frames (%ld) of data in file.\n", __LINE__, (long) sfinfo.frames) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	*output_samples = (int) sfinfo.frames ; | 
				
			||||
 | 
				
			||||
	if (sf_read_float (sndfile, buffer, sfinfo.frames) != sfinfo.frames) | 
				
			||||
	{	printf ("Line %d : Bad read.\n", __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	sf_close (sndfile) ; | 
				
			||||
 | 
				
			||||
	snr = calculate_snr (buffer, sfinfo.frames, expected_peaks) ; | 
				
			||||
 | 
				
			||||
	return snr ; | 
				
			||||
} /* measure_desination_wav */ | 
				
			||||
 | 
				
			||||
static double | 
				
			||||
measure_snr (const RESAMPLE_PROG *prog, int *output_samples, int verbose) | 
				
			||||
{	static SNR_TEST snr_test [] = | 
				
			||||
	{ | 
				
			||||
		{	1,	{ 0.211111111111 },		48000,		1,	1.0 }, | 
				
			||||
		{	1,	{ 0.011111111111 },		132301,		1,	1.0 }, | 
				
			||||
		{	1,	{ 0.111111111111 },		92301,		1,	1.0 }, | 
				
			||||
		{	1,	{ 0.011111111111 },		26461,		1,	1.0 }, | 
				
			||||
		{	1,	{ 0.011111111111 },		13231,		1,	1.0 }, | 
				
			||||
		{	1,	{ 0.011111111111 },		44101,		1,	1.0 }, | 
				
			||||
		{	2,	{ 0.311111, 0.49 },		78199,		2,	1.0 }, | 
				
			||||
		{	2,	{ 0.011111, 0.49 },		12345,		1,	0.5 }, | 
				
			||||
		{	2,	{ 0.0123456, 0.4 },		20143,		1,	0.5 }, | 
				
			||||
		{	2,	{ 0.0111111, 0.4 },		26461,		1,	0.5 }, | 
				
			||||
		{	1,	{ 0.381111111111 },		58661,		1,	1.0 } | 
				
			||||
		} ; /* snr_test */ | 
				
			||||
	static char command [256] ; | 
				
			||||
 | 
				
			||||
	double snr, worst_snr = 500.0 ; | 
				
			||||
	int k , retval, sample_count ; | 
				
			||||
 | 
				
			||||
	*output_samples = 0 ; | 
				
			||||
 | 
				
			||||
	for (k = 0 ; k < ARRAY_LEN (snr_test) ; k++) | 
				
			||||
	{	remove ("source.wav") ; | 
				
			||||
		remove ("destination.wav") ; | 
				
			||||
 | 
				
			||||
		if (verbose) | 
				
			||||
			printf ("       SNR test #%d : ", k) ; | 
				
			||||
		fflush (stdout) ; | 
				
			||||
		generate_source_wav ("source.wav", snr_test [k].freqs, snr_test [k].freq_count, prog->format) ; | 
				
			||||
 | 
				
			||||
		snprintf (command, sizeof (command), prog->convert_cmd, snr_test [k].output_samplerate) ; | 
				
			||||
		SAFE_STRNCAT (command, " >/dev/null 2>&1", sizeof (command)) ; | 
				
			||||
		if ((retval = system (command)) != 0) | 
				
			||||
			printf ("system returned %d\n", retval) ; | 
				
			||||
 | 
				
			||||
		snr = measure_destination_wav ("destination.wav", &sample_count, snr_test->pass_band_peaks) ; | 
				
			||||
 | 
				
			||||
		*output_samples += sample_count ; | 
				
			||||
 | 
				
			||||
		if (fabs (snr) < fabs (worst_snr)) | 
				
			||||
			worst_snr = fabs (snr) ; | 
				
			||||
 | 
				
			||||
		if (verbose) | 
				
			||||
			printf ("%6.2f dB\n", snr) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return worst_snr ; | 
				
			||||
} /* measure_snr */ | 
				
			||||
 | 
				
			||||
/*------------------------------------------------------------------------------
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
static double | 
				
			||||
measure_destination_peak (const char *filename) | 
				
			||||
{	static float data [2 * BUFFER_LEN] ; | 
				
			||||
	SNDFILE		*sndfile ; | 
				
			||||
	SF_INFO		sfinfo ; | 
				
			||||
	double		peak = 0.0 ; | 
				
			||||
	int			k = 0 ; | 
				
			||||
 | 
				
			||||
	if ((sndfile = sf_open (filename, SFM_READ, &sfinfo)) == NULL) | 
				
			||||
	{	printf ("Line %d : failed to open file %s\n", __LINE__, filename) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (sfinfo.channels != 1) | 
				
			||||
	{	printf ("Line %d : bad channel count.\n", __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (sfinfo.frames > ARRAY_LEN (data) + 4 || sfinfo.frames < ARRAY_LEN (data) - 100) | 
				
			||||
	{	printf ("Line %d : bad frame count (got %d, expected %d).\n", __LINE__, (int) sfinfo.frames, ARRAY_LEN (data)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	if (sf_read_float (sndfile, data, sfinfo.frames) != sfinfo.frames) | 
				
			||||
	{	printf ("Line %d : bad read.\n", __LINE__) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	sf_close (sndfile) ; | 
				
			||||
 | 
				
			||||
	for (k = 0 ; k < (int) sfinfo.frames ; k++) | 
				
			||||
		if (fabs (data [k]) > peak) | 
				
			||||
			peak = fabs (data [k]) ; | 
				
			||||
 | 
				
			||||
	return peak ; | 
				
			||||
} /* measure_destination_peak */ | 
				
			||||
 | 
				
			||||
static double | 
				
			||||
find_attenuation (double freq, const RESAMPLE_PROG *prog, int verbose) | 
				
			||||
{	static char	command [256] ; | 
				
			||||
	double	output_peak ; | 
				
			||||
	int		retval ; | 
				
			||||
	char	*filename ; | 
				
			||||
 | 
				
			||||
	filename = "destination.wav" ; | 
				
			||||
 | 
				
			||||
	generate_source_wav ("source.wav", &freq, 1, prog->format) ; | 
				
			||||
 | 
				
			||||
	remove (filename) ; | 
				
			||||
 | 
				
			||||
	snprintf (command, sizeof (command), prog->convert_cmd, 88189) ; | 
				
			||||
	SAFE_STRNCAT (command, " >/dev/null 2>&1", sizeof (command)) ; | 
				
			||||
	if ((retval = system (command)) != 0) | 
				
			||||
		printf ("system returned %d\n", retval) ; | 
				
			||||
 | 
				
			||||
	output_peak = measure_destination_peak (filename) ; | 
				
			||||
 | 
				
			||||
	if (verbose) | 
				
			||||
		printf ("        freq : %f     peak : %f\n", freq, output_peak) ; | 
				
			||||
 | 
				
			||||
	return fabs (20.0 * log10 (output_peak)) ; | 
				
			||||
} /* find_attenuation */ | 
				
			||||
 | 
				
			||||
static double | 
				
			||||
bandwidth_test (const RESAMPLE_PROG *prog, int verbose) | 
				
			||||
{	double	f1, f2, a1, a2 ; | 
				
			||||
	double	freq, atten ; | 
				
			||||
 | 
				
			||||
	f1 = 0.35 ; | 
				
			||||
	a1 = find_attenuation (f1, prog, verbose) ; | 
				
			||||
 | 
				
			||||
	f2 = 0.49999 ; | 
				
			||||
	a2 = find_attenuation (f2, prog, verbose) ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
	if (fabs (a1) < 1e-2 && a2 < 3.0) | 
				
			||||
		return -1.0 ; | 
				
			||||
 | 
				
			||||
	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, prog, 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 */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
measure_program (const RESAMPLE_PROG *prog, int verbose) | 
				
			||||
{	double	snr, bandwidth, conversion_rate ; | 
				
			||||
	int		output_samples ; | 
				
			||||
	struct	tms	time_data ; | 
				
			||||
	time_t	time_now ; | 
				
			||||
 | 
				
			||||
	printf ("\n  Machine : %s\n", get_machine_details ()) ; | 
				
			||||
	time_now = time (NULL) ; | 
				
			||||
	printf ("  Date    : %s", ctime (&time_now)) ; | 
				
			||||
 | 
				
			||||
	get_version_string (prog) ; | 
				
			||||
	printf ("  Program : %s\n", version_string) ; | 
				
			||||
	printf ("  Command : %s\n\n", prog->convert_cmd) ; | 
				
			||||
 | 
				
			||||
	snr = measure_snr (prog, &output_samples, verbose) ; | 
				
			||||
 | 
				
			||||
	printf ("  Worst case SNR     : %6.2f dB\n", snr) ; | 
				
			||||
 | 
				
			||||
	times (&time_data) ; | 
				
			||||
 | 
				
			||||
	conversion_rate = (1.0 * output_samples * sysconf (_SC_CLK_TCK)) / time_data.tms_cutime ; | 
				
			||||
 | 
				
			||||
	printf ("  Conversion rate    : %5.0f samples/sec\n", conversion_rate) ; | 
				
			||||
 | 
				
			||||
	bandwidth = bandwidth_test (prog, verbose) ; | 
				
			||||
 | 
				
			||||
	if (bandwidth > 0.0) | 
				
			||||
		printf ("  Measured bandwidth : %5.2f %%\n", bandwidth) ; | 
				
			||||
	else | 
				
			||||
		printf ("  Could not measure bandwidth (no -3dB point found).\n") ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* measure_program */ | 
				
			||||
 | 
				
			||||
/*##############################################################################
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#else | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (void) | 
				
			||||
{	puts ("\n" | 
				
			||||
		"****************************************************************\n" | 
				
			||||
		" This program has been compiled without :\n" | 
				
			||||
		"	1) FFTW (http://www.fftw.org/).\n" | 
				
			||||
		"	2) libsndfile (http://www.zip.com.au/~erikd/libsndfile/).\n" | 
				
			||||
		" Without these two libraries there is not much it can do.\n" | 
				
			||||
		"****************************************************************\n") ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
#endif /* (HAVE_FFTW3 && HAVE_SNDFILE) */ | 
				
			||||
 | 
				
			||||
@ -0,0 +1,149 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#define	BUFFER_LEN		(1<<15) | 
				
			||||
 | 
				
			||||
#define BLOCK_LEN		100 | 
				
			||||
 | 
				
			||||
static void stream_test (int converter, double ratio) ; | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (void) | 
				
			||||
{	static double src_ratios [] = | 
				
			||||
	{	0.3, 0.9, 1.1, 3.0 | 
				
			||||
	} ; | 
				
			||||
 | 
				
			||||
	int k ; | 
				
			||||
 | 
				
			||||
	puts ("\n    Zero Order Hold interpolator:") ; | 
				
			||||
	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++) | 
				
			||||
		stream_test (SRC_LINEAR, src_ratios [k]) ; | 
				
			||||
 | 
				
			||||
	puts ("\n    Sinc interpolator:") ; | 
				
			||||
	for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | 
				
			||||
		stream_test (SRC_SINC_FASTEST, src_ratios [k]) ; | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
stream_test (int converter, double src_ratio) | 
				
			||||
{	static float input [BUFFER_LEN], output [BUFFER_LEN] ; | 
				
			||||
 | 
				
			||||
	SRC_STATE	*src_state ; | 
				
			||||
	SRC_DATA	src_data ; | 
				
			||||
 | 
				
			||||
	int input_len, output_len, current_in, current_out ; | 
				
			||||
	int error, terminate ; | 
				
			||||
 | 
				
			||||
	printf ("\tstreaming_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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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.input_frames = BLOCK_LEN ; | 
				
			||||
 | 
				
			||||
	src_data.src_ratio = src_ratio ; | 
				
			||||
 | 
				
			||||
	src_data.data_out = output ; | 
				
			||||
	src_data.output_frames = BLOCK_LEN ; | 
				
			||||
 | 
				
			||||
	while (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", src_data.output_frames) ; | 
				
			||||
 | 
				
			||||
			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 ; | 
				
			||||
		src_data.data_out	+= src_data.output_frames_gen ; | 
				
			||||
 | 
				
			||||
		src_data.input_frames	= MIN (BLOCK_LEN, input_len - current_in) ; | 
				
			||||
		src_data.output_frames	= MIN (BLOCK_LEN, output_len - current_out) ; | 
				
			||||
 | 
				
			||||
		src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	src_state = src_delete (src_state) ; | 
				
			||||
 | 
				
			||||
	terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; | 
				
			||||
 | 
				
			||||
	if (fabs (current_out - src_ratio * input_len) > 2 * terminate) | 
				
			||||
	{	printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, | 
				
			||||
					current_out, (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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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 */ | 
				
			||||
 | 
				
			||||
@ -0,0 +1,342 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
static void simple_test (int converter) ; | 
				
			||||
#endif | 
				
			||||
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]) ; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	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) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	return 0 ; | 
				
			||||
} /* main */ | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
static void | 
				
			||||
simple_test (int converter) | 
				
			||||
{ | 
				
			||||
	// MSVC doesn't support variable-length arrays
 | 
				
			||||
	#define ilen 199030 | 
				
			||||
	#define olen 1000 | 
				
			||||
	int 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 */ | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
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 (labs (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.0f ; | 
				
			||||
 | 
				
			||||
	/* 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,253 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2004-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <time.h> | 
				
			||||
#ifdef HAVE_UNISTD_H | 
				
			||||
#include <unistd.h> | 
				
			||||
#endif | 
				
			||||
#include <math.h> | 
				
			||||
 | 
				
			||||
#ifdef _WIN32 | 
				
			||||
#ifndef WIN32_LEAN_AND_MEAN | 
				
			||||
#define WIN32_LEAN_AND_MEAN | 
				
			||||
#endif | 
				
			||||
#include <windows.h> | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
 | 
				
			||||
#include "util.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 ; | 
				
			||||
 | 
				
			||||
#ifdef _WIN32 | 
				
			||||
	Sleep (2000) ; | 
				
			||||
#else | 
				
			||||
	sleep (2) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	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 ; | 
				
			||||
#ifdef __GNU__ /* Clock resolution is 10ms on GNU/Hurd */ | 
				
			||||
		duration = (10000.0 * clock_time) / CLOCKS_PER_SEC ; | 
				
			||||
#else | 
				
			||||
		duration = (1.0 * clock_time) / CLOCKS_PER_SEC ; | 
				
			||||
#endif | 
				
			||||
	} | 
				
			||||
	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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	throughput_test (SRC_SINC_FASTEST, 0) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
	throughput_test (SRC_SINC_MEDIUM_QUALITY, 0) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
	throughput_test (SRC_SINC_BEST_QUALITY, 0) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	puts ("") ; | 
				
			||||
	return ; | 
				
			||||
} /* single_run */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
multi_run (int run_count) | 
				
			||||
{	long zero_order_hold = 0, linear = 0 ; | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	long sinc_fastest = 0 ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
	long sinc_medium = 0 ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
	long sinc_best = 0 ; | 
				
			||||
#endif | 
				
			||||
	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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
		sinc_fastest =		throughput_test (SRC_SINC_FASTEST, sinc_fastest) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
		sinc_medium =		throughput_test (SRC_SINC_MEDIUM_QUALITY, sinc_medium) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
		sinc_best =			throughput_test (SRC_SINC_BEST_QUALITY, sinc_best) ; | 
				
			||||
#endif | 
				
			||||
		puts ("") ; | 
				
			||||
 | 
				
			||||
		/* Let the CPU cool down. We might be running on a laptop. */ | 
				
			||||
#ifdef _WIN32 | 
				
			||||
		Sleep (10000) ; | 
				
			||||
#else | 
				
			||||
		sleep (10) ; | 
				
			||||
#endif | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	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) ; | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	printf ("    %-30s    %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_MEDIUM_CONVERTER | 
				
			||||
	printf ("    %-30s    %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ; | 
				
			||||
#endif | 
				
			||||
#ifdef ENABLE_SINC_BEST_CONVERTER | 
				
			||||
	printf ("    %-30s    %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	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,228 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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] = (float) (output [k] + (amplitude * sin (freqs [freq] * (2 * k) * M_PI + phase))) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	/* Apply Hanning Window. */ | 
				
			||||
	for (k = 0 ; k < output_len ; k++) | 
				
			||||
		output [k] = (float) (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 | 
				
			||||
	(void) search ; | 
				
			||||
	(void) buffer ; | 
				
			||||
	(void) file ; | 
				
			||||
	(void) is_pipe ; | 
				
			||||
 | 
				
			||||
	return name; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#if defined (__linux__) || defined (__APPLE__) || defined (__FreeBSD__) | 
				
			||||
	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 ; | 
				
			||||
#endif | 
				
			||||
} /* get_cpu_name */ | 
				
			||||
 | 
				
			||||
@ -0,0 +1,41 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#define	ABS(a)			(((a) < 0) ? - (a) : (a)) | 
				
			||||
 | 
				
			||||
#ifndef MAX | 
				
			||||
#define	MAX(a,b)		(((a) > (b)) ? (a) : (b)) | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#ifndef MIN | 
				
			||||
#define	MIN(a,b)		(((a) < (b)) ? (a) : (b)) | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#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) ; | 
				
			||||
 | 
				
			||||
#define ASSERT(condition) \ | 
				
			||||
	if (!(condition)) \
 | 
				
			||||
	{	printf ("Condition failed on Line %d : %s\n\n", __LINE__, #condition) ; \
 | 
				
			||||
		exit (1) ; \
 | 
				
			||||
	    } ; | 
				
			||||
 | 
				
			||||
@ -0,0 +1,275 @@ | 
				
			||||
/*
 | 
				
			||||
** Copyright (c) 2006-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | 
				
			||||
** All rights reserved. | 
				
			||||
** | 
				
			||||
** This code is released under 2-clause BSD license. Please see the | 
				
			||||
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
#ifdef HAVE_CONFIG_H | 
				
			||||
#include "config.h" | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#include <stdio.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
#include <math.h> | 
				
			||||
#include <string.h> | 
				
			||||
 | 
				
			||||
#include <samplerate.h> | 
				
			||||
 | 
				
			||||
#include "util.h" | 
				
			||||
 | 
				
			||||
#if HAVE_FFTW3 | 
				
			||||
#include <fftw3.h> | 
				
			||||
#else | 
				
			||||
#define fftw_cleanup() | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
#define	BUFFER_LEN		(1 << 14) | 
				
			||||
 | 
				
			||||
static void varispeed_test (int converter, double target_snr) ; | 
				
			||||
static void varispeed_bounds_test (int converter) ; | 
				
			||||
static void set_ratio_test (int converter, int channels, double initial_ratio, double second_ratio) ; | 
				
			||||
 | 
				
			||||
int | 
				
			||||
main (void) | 
				
			||||
{ | 
				
			||||
	puts ("\n    Varispeed SNR test") ; | 
				
			||||
	printf ("        Zero Order Hold interpolator    : ") ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
	varispeed_test (SRC_ZERO_ORDER_HOLD, 10.0) ; | 
				
			||||
	puts ("ok") ; | 
				
			||||
 | 
				
			||||
	printf ("        Linear interpolator             : ") ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
	varispeed_test (SRC_LINEAR, 10.0) ; | 
				
			||||
	puts ("ok") ; | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	printf ("        Sinc interpolator               : ") ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
	varispeed_test (SRC_SINC_FASTEST, 115.0) ; | 
				
			||||
	puts ("ok") ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	puts ("\n    Varispeed bounds test") ; | 
				
			||||
	printf ("        Zero Order Hold interpolator    : ") ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
	varispeed_bounds_test (SRC_ZERO_ORDER_HOLD) ; | 
				
			||||
	puts ("ok") ; | 
				
			||||
 | 
				
			||||
	printf ("        Linear interpolator             : ") ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
	varispeed_bounds_test (SRC_LINEAR) ; | 
				
			||||
	puts ("ok") ; | 
				
			||||
 | 
				
			||||
#ifdef ENABLE_SINC_FAST_CONVERTER | 
				
			||||
	printf ("        Sinc interpolator               : ") ; | 
				
			||||
	fflush (stdout) ; | 
				
			||||
	varispeed_bounds_test (SRC_SINC_FASTEST) ; | 
				
			||||
	puts ("ok") ; | 
				
			||||
#endif | 
				
			||||
 | 
				
			||||
	fftw_cleanup () ; | 
				
			||||
	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) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* varispeed_test */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
varispeed_bounds_test (int converter) | 
				
			||||
{	double ratios [] = { 0.1, 0.01, 20 } ; | 
				
			||||
	int chan, r1, r2 ; | 
				
			||||
 | 
				
			||||
	for (chan = 1 ; chan <= 9 ; chan ++) | 
				
			||||
		for (r1 = 0 ; r1 < ARRAY_LEN (ratios) ; r1++) | 
				
			||||
			for (r2 = 0 ; r2 < ARRAY_LEN (ratios) ; r2 ++) | 
				
			||||
				if (r1 != r2) | 
				
			||||
					set_ratio_test (converter, chan, ratios [r1], ratios [r2]) ; | 
				
			||||
} /* varispeed_bounds_test */ | 
				
			||||
 | 
				
			||||
static void | 
				
			||||
set_ratio_test (int converter, int channels, double initial_ratio, double second_ratio) | 
				
			||||
{	const int total_input_frames = BUFFER_LEN ; | 
				
			||||
	/* Maximum upsample ratio is 20, use a value beigger. */ | 
				
			||||
	const int total_output_frames = 25 * BUFFER_LEN ; | 
				
			||||
 | 
				
			||||
	/* Interested in array boundary conditions, so all zero data here is fine. */ | 
				
			||||
	float *input = calloc (total_input_frames * channels, sizeof (float)) ; | 
				
			||||
	float *output = calloc (total_output_frames * channels, sizeof (float)) ; | 
				
			||||
 | 
				
			||||
	char details [128] ; | 
				
			||||
 | 
				
			||||
	const int max_loop_count = 100000 ; | 
				
			||||
	const int chunk_size = 128 ; | 
				
			||||
 | 
				
			||||
	SRC_STATE *src_state ; | 
				
			||||
	SRC_DATA src_data ; | 
				
			||||
 | 
				
			||||
	int error, k, total_frames_used, total_frames_gen ; | 
				
			||||
 | 
				
			||||
	snprintf (details, sizeof (details), "%d channels, ratio %g -> %g", channels, initial_ratio, second_ratio) ; | 
				
			||||
 | 
				
			||||
	if ((src_state = src_new (converter, channels, &error)) == NULL) | 
				
			||||
	{	printf ("\n\nLine %d : src_new () failed : %s\n\n", __LINE__, src_strerror (error)) ; | 
				
			||||
		exit (1) ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	total_frames_used = 0 ; | 
				
			||||
	total_frames_gen = 0 ; | 
				
			||||
 | 
				
			||||
	memset (&src_data, 0, sizeof (src_data)) ; | 
				
			||||
	src_data.end_of_input = 0 ; | 
				
			||||
	src_data.src_ratio = initial_ratio ; | 
				
			||||
	src_data.data_in = input ; | 
				
			||||
	src_data.data_out = output ; | 
				
			||||
	src_data.input_frames = chunk_size ; | 
				
			||||
	src_data.output_frames = total_output_frames ; | 
				
			||||
 | 
				
			||||
	/* Use a max_loop_count here to enable the detection of infinite loops
 | 
				
			||||
	** (due to end of input not being detected. | 
				
			||||
	*/ | 
				
			||||
	for (k = 0 ; k < max_loop_count ; k ++) | 
				
			||||
	{	if (k == 1) | 
				
			||||
		{	/* Hard switch to second_ratio after processing one chunk. */ | 
				
			||||
			src_data.src_ratio = second_ratio ; | 
				
			||||
			if ((error = src_set_ratio (src_state, second_ratio))) | 
				
			||||
			{	printf ("\n\nLine %d : %s : %s\n\n", __LINE__, details, src_strerror (error)) ; | 
				
			||||
				exit (1) ; | 
				
			||||
				} ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		if ((error = src_process (src_state, &src_data)) != 0) | 
				
			||||
		{	printf ("\n\nLine %d : %s : %s\n\n", __LINE__, details, src_strerror (error)) ; | 
				
			||||
			exit (1) ; | 
				
			||||
			} ; | 
				
			||||
 | 
				
			||||
		if (src_data.end_of_input && src_data.output_frames_gen == 0) | 
				
			||||
			break ; | 
				
			||||
 | 
				
			||||
		total_frames_used	+= src_data.input_frames_used ; | 
				
			||||
		total_frames_gen 	+= src_data.output_frames_gen ; | 
				
			||||
 | 
				
			||||
		src_data.data_in	+= src_data.input_frames_used * channels ; | 
				
			||||
		src_data.data_out	+= src_data.output_frames_gen * channels ; | 
				
			||||
 | 
				
			||||
		src_data.input_frames	= total_input_frames - total_frames_used ; | 
				
			||||
		src_data.output_frames	= total_output_frames - total_frames_gen ; | 
				
			||||
 | 
				
			||||
		src_data.end_of_input = total_frames_used >= total_input_frames ? 1 : 0 ; | 
				
			||||
		} ; | 
				
			||||
 | 
				
			||||
	ASSERT (k < max_loop_count) ; | 
				
			||||
	ASSERT (total_frames_gen > 0) ; | 
				
			||||
 | 
				
			||||
	for (k = 0 ; k < total_frames_gen * channels ; k ++) | 
				
			||||
		ASSERT (! isnan (output [k])) ; | 
				
			||||
 | 
				
			||||
	src_state = src_delete (src_state) ; | 
				
			||||
 | 
				
			||||
	free (input) ; | 
				
			||||
	free (output) ; | 
				
			||||
 | 
				
			||||
	return ; | 
				
			||||
} /* set_ratio_test */ | 
				
			||||
					Loading…
					
					
				
		Reference in new issue