summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorLorry <lorry@roadtrain.codethink.co.uk>2012-07-18 20:35:05 +0100
committerLorry <lorry@roadtrain.codethink.co.uk>2012-07-18 20:35:05 +0100
commitaceb1f30497619786f1827e4c65992b890a07410 (patch)
treece33ac9d0d076a8ec4f993e614cf71a4d5daa7e7 /tests
downloadlibsndfile-aceb1f30497619786f1827e4c65992b890a07410.tar.gz
Tarball conversion
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am211
-rw-r--r--tests/Makefile.in1077
-rw-r--r--tests/aiff_rw_test.c162
-rw-r--r--tests/alaw_test.c236
-rw-r--r--tests/benchmark.c545
-rw-r--r--tests/benchmark.def17
-rw-r--r--tests/benchmark.tpl360
-rw-r--r--tests/checksum_test.c128
-rw-r--r--tests/command_test.c1344
-rw-r--r--tests/cpp_test.cc313
-rw-r--r--tests/dft_cmp.c149
-rw-r--r--tests/dft_cmp.h25
-rw-r--r--tests/dither_test.c182
-rw-r--r--tests/dwvw_test.c109
-rw-r--r--tests/error_test.c246
-rw-r--r--tests/external_libs_test.c149
-rw-r--r--tests/fix_this.c326
-rw-r--r--tests/floating_point_test.c694
-rw-r--r--tests/floating_point_test.def32
-rw-r--r--tests/floating_point_test.tpl336
-rw-r--r--tests/format_check_test.c149
-rw-r--r--tests/generate.c73
-rw-r--r--tests/generate.h19
-rw-r--r--tests/header_test.c741
-rw-r--r--tests/header_test.def22
-rw-r--r--tests/header_test.tpl542
-rw-r--r--tests/headerless_test.c184
-rw-r--r--tests/largefile_test.c83
-rw-r--r--tests/locale_test.c167
-rw-r--r--tests/lossy_comp_test.c2371
-rw-r--r--tests/misc_test.c415
-rw-r--r--tests/multi_file_test.c237
-rw-r--r--tests/ogg_test.c341
-rw-r--r--tests/pcm_test.c1723
-rw-r--r--tests/pcm_test.def34
-rw-r--r--tests/pcm_test.tpl927
-rw-r--r--tests/peak_chunk_test.c362
-rw-r--r--tests/pedantic-header-test.sh.in58
-rw-r--r--tests/pipe_test.c525
-rw-r--r--tests/pipe_test.def14
-rw-r--r--tests/pipe_test.tpl374
-rw-r--r--tests/raw_test.c186
-rw-r--r--tests/rdwr_test.c240
-rw-r--r--tests/rdwr_test.def32
-rw-r--r--tests/rdwr_test.tpl105
-rw-r--r--tests/scale_clip_test.c1853
-rw-r--r--tests/scale_clip_test.def56
-rw-r--r--tests/scale_clip_test.tpl438
-rw-r--r--tests/sfversion.c45
-rw-r--r--tests/stdin_test.c204
-rw-r--r--tests/stdio_test.c153
-rw-r--r--tests/stdout_test.c161
-rw-r--r--tests/string_test.c663
-rw-r--r--tests/test_wrapper.sh.in359
-rw-r--r--tests/ulaw_test.c257
-rw-r--r--tests/utils.c1162
-rw-r--r--tests/utils.def52
-rw-r--r--tests/utils.h183
-rw-r--r--tests/utils.tpl890
-rw-r--r--tests/virtual_io_test.c237
-rw-r--r--tests/vorbis_test.c176
-rw-r--r--tests/win32_ordinal_test.c146
-rw-r--r--tests/win32_test.c318
-rw-r--r--tests/write_read_test.c3731
-rw-r--r--tests/write_read_test.def65
-rw-r--r--tests/write_read_test.tpl1150
66 files changed, 28864 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..1d2052b
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,211 @@
+## Process this file with automake to produce Makefile.in
+
+if ENABLE_TEST_COVERAGE
+CPP_TEST =
+else
+CPP_TEST = cpp_test
+endif
+
+INCLUDES = -I$(top_srcdir)/src
+
+check_PROGRAMS = sfversion floating_point_test write_read_test \
+ lossy_comp_test error_test ulaw_test alaw_test dwvw_test \
+ peak_chunk_test command_test stdin_test stdout_test stdio_test \
+ pcm_test headerless_test pipe_test benchmark header_test misc_test \
+ raw_test string_test multi_file_test dither_test \
+ scale_clip_test win32_test fix_this aiff_rw_test virtual_io_test \
+ locale_test largefile_test win32_ordinal_test ogg_test vorbis_test \
+ checksum_test external_libs_test rdwr_test format_check_test $(CPP_TEST)
+
+noinst_HEADERS = dft_cmp.h utils.h generate.h
+
+autogen_sources = write_read_test.tpl write_read_test.def \
+ pcm_test.tpl pcm_test.def \
+ header_test.tpl header_test.def \
+ utils.tpl utils.def \
+ scale_clip_test.tpl scale_clip_test.def \
+ pipe_test.tpl pipe_test.def \
+ rdwr_test.tpl rdwr_test.def \
+ floating_point_test.tpl floating_point_test.def \
+ benchmark.tpl benchmark.def
+
+EXTRA_DIST = $(autogen_sources)
+
+CLEANFILES = *~
+
+#===============================================================================
+# If we're cross compiling from Linux to Windows and running the test suite
+# under Wine, we need a symbolic link to the generated libsndfile DLL.
+
+if LINUX_MINGW_CROSS_TEST
+
+$(check_PROGRAMS) : libsndfile-1.dll
+
+libsndfile-1.dll :
+ ln -s $(top_builddir)/src/.libs/$@ $@
+
+clean-local :
+ -rm -f libsndfile-1.dll
+
+endif
+
+#===============================================================================
+
+check: test_wrapper.sh
+ sh test_wrapper.sh
+
+# Need this target to force building of test programs.
+checkprograms : $(check_PROGRAMS)
+
+#===============================================================================
+
+sfversion_SOURCES = sfversion.c
+sfversion_LDADD = $(top_builddir)/src/libsndfile.la
+
+write_read_test_SOURCES = utils.c generate.c write_read_test.c
+write_read_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+lossy_comp_test_SOURCES = utils.c lossy_comp_test.c
+lossy_comp_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+fix_this_SOURCES = utils.c fix_this.c
+fix_this_LDADD = $(top_builddir)/src/libsndfile.la
+
+error_test_SOURCES = error_test.c utils.c
+error_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+ulaw_test_SOURCES = utils.c ulaw_test.c
+ulaw_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+alaw_test_SOURCES = utils.c alaw_test.c
+alaw_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+aiff_rw_test_SOURCES = utils.c aiff_rw_test.c
+aiff_rw_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+command_test_SOURCES = command_test.c utils.c
+command_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+locale_test_SOURCES = locale_test.c utils.c
+locale_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+largefile_test_SOURCES = largefile_test.c utils.c
+largefile_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+pcm_test_SOURCES = pcm_test.c utils.c
+pcm_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+headerless_test_SOURCES = utils.c headerless_test.c
+headerless_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+stdin_test_SOURCES = stdin_test.c utils.c
+stdin_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+stdout_test_SOURCES = stdout_test.c
+stdout_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+stdio_test_SOURCES = stdio_test.c utils.c
+stdio_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+pipe_test_SOURCES = pipe_test.c utils.c
+pipe_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+benchmark_SOURCES = benchmark.c
+benchmark_LDADD = $(top_builddir)/src/libsndfile.la
+
+header_test_SOURCES = header_test.c utils.c
+header_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+misc_test_SOURCES = misc_test.c utils.c
+misc_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+raw_test_SOURCES = raw_test.c utils.c
+raw_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+string_test_SOURCES = string_test.c utils.c
+string_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+dither_test_SOURCES = dither_test.c utils.c
+dither_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+multi_file_test_SOURCES = multi_file_test.c utils.c
+multi_file_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+virtual_io_test_SOURCES = virtual_io_test.c utils.c
+virtual_io_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+ogg_test_SOURCES = ogg_test.c utils.c
+ogg_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+vorbis_test_SOURCES = vorbis_test.c utils.c
+vorbis_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+rdwr_test_SOURCES = rdwr_test.c utils.c
+rdwr_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+win32_test_SOURCES = win32_test.c
+# Link lib here so that generating the testsuite tarball works correctly.
+win32_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+win32_ordinal_test_SOURCES = win32_ordinal_test.c utils.c
+win32_ordinal_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+external_libs_test_SOURCES = external_libs_test.c utils.c
+external_libs_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+format_check_test_SOURCES = format_check_test.c utils.c
+format_check_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+cpp_test_SOURCES = cpp_test.cc utils.c
+cpp_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+checksum_test_SOURCES = checksum_test.c utils.c
+checksum_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+# Lite remove start
+dwvw_test_SOURCES = utils.c dwvw_test.c
+dwvw_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+floating_point_test_SOURCES = utils.c dft_cmp.c floating_point_test.c
+floating_point_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+peak_chunk_test_SOURCES = peak_chunk_test.c utils.c
+peak_chunk_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+scale_clip_test_SOURCES = scale_clip_test.c utils.c
+scale_clip_test_LDADD = $(top_builddir)/src/libsndfile.la
+# Lite remove end
+
+#===============================================================================
+
+write_read_test.c: write_read_test.def write_read_test.tpl
+ autogen --writable write_read_test.def
+
+pcm_test.c: pcm_test.def pcm_test.tpl
+ autogen --writable pcm_test.def
+
+header_test.c: header_test.def header_test.tpl
+ autogen --writable header_test.def
+
+utils.c utils.h : utils.def utils.tpl
+ autogen --writable utils.def
+
+scale_clip_test.c: scale_clip_test.def scale_clip_test.tpl
+ autogen --writable scale_clip_test.def
+
+pipe_test.c: pipe_test.def pipe_test.tpl
+ autogen --writable pipe_test.def
+
+rdwr_test.c: rdwr_test.def rdwr_test.tpl
+ autogen --writable rdwr_test.def
+
+floating_point_test.c: floating_point_test.def floating_point_test.tpl
+ autogen --writable floating_point_test.def
+
+benchmark.c: benchmark.def benchmark.tpl
+ autogen --writable benchmark.def
+
+genfiles : write_read_test.c pcm_test.c header_test.c utils.c \
+ scale_clip_test.c pipe_test.c floating_point_test.c rdwr_test.c \
+ benchmark.c
+
diff --git a/tests/Makefile.in b/tests/Makefile.in
new file mode 100644
index 0000000..083d77f
--- /dev/null
+++ b/tests/Makefile.in
@@ -0,0 +1,1077 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = sfversion$(EXEEXT) floating_point_test$(EXEEXT) \
+ write_read_test$(EXEEXT) lossy_comp_test$(EXEEXT) \
+ error_test$(EXEEXT) ulaw_test$(EXEEXT) alaw_test$(EXEEXT) \
+ dwvw_test$(EXEEXT) peak_chunk_test$(EXEEXT) \
+ command_test$(EXEEXT) stdin_test$(EXEEXT) stdout_test$(EXEEXT) \
+ stdio_test$(EXEEXT) pcm_test$(EXEEXT) headerless_test$(EXEEXT) \
+ pipe_test$(EXEEXT) benchmark$(EXEEXT) header_test$(EXEEXT) \
+ misc_test$(EXEEXT) raw_test$(EXEEXT) string_test$(EXEEXT) \
+ multi_file_test$(EXEEXT) dither_test$(EXEEXT) \
+ scale_clip_test$(EXEEXT) win32_test$(EXEEXT) fix_this$(EXEEXT) \
+ aiff_rw_test$(EXEEXT) virtual_io_test$(EXEEXT) \
+ locale_test$(EXEEXT) largefile_test$(EXEEXT) \
+ win32_ordinal_test$(EXEEXT) ogg_test$(EXEEXT) \
+ vorbis_test$(EXEEXT) checksum_test$(EXEEXT) \
+ external_libs_test$(EXEEXT) rdwr_test$(EXEEXT) \
+ format_check_test$(EXEEXT) $(am__EXEEXT_1)
+subdir = tests
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/pedantic-header-test.sh.in \
+ $(srcdir)/test_wrapper.sh.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/M4/add_cflags.m4 \
+ $(top_srcdir)/M4/add_cxxflags.m4 $(top_srcdir)/M4/clip_mode.m4 \
+ $(top_srcdir)/M4/endian.m4 $(top_srcdir)/M4/extra_largefile.m4 \
+ $(top_srcdir)/M4/extra_pkg.m4 \
+ $(top_srcdir)/M4/flexible_array.m4 \
+ $(top_srcdir)/M4/gcc_version.m4 $(top_srcdir)/M4/libtool.m4 \
+ $(top_srcdir)/M4/lrint.m4 $(top_srcdir)/M4/lrintf.m4 \
+ $(top_srcdir)/M4/ltoptions.m4 $(top_srcdir)/M4/ltsugar.m4 \
+ $(top_srcdir)/M4/ltversion.m4 $(top_srcdir)/M4/lt~obsolete.m4 \
+ $(top_srcdir)/M4/mkoctfile_version.m4 \
+ $(top_srcdir)/M4/octave.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = test_wrapper.sh pedantic-header-test.sh
+CONFIG_CLEAN_VPATH_FILES =
+@ENABLE_TEST_COVERAGE_FALSE@am__EXEEXT_1 = cpp_test$(EXEEXT)
+am_aiff_rw_test_OBJECTS = utils.$(OBJEXT) aiff_rw_test.$(OBJEXT)
+aiff_rw_test_OBJECTS = $(am_aiff_rw_test_OBJECTS)
+aiff_rw_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+am_alaw_test_OBJECTS = utils.$(OBJEXT) alaw_test.$(OBJEXT)
+alaw_test_OBJECTS = $(am_alaw_test_OBJECTS)
+alaw_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_benchmark_OBJECTS = benchmark.$(OBJEXT)
+benchmark_OBJECTS = $(am_benchmark_OBJECTS)
+benchmark_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_checksum_test_OBJECTS = checksum_test.$(OBJEXT) utils.$(OBJEXT)
+checksum_test_OBJECTS = $(am_checksum_test_OBJECTS)
+checksum_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_command_test_OBJECTS = command_test.$(OBJEXT) utils.$(OBJEXT)
+command_test_OBJECTS = $(am_command_test_OBJECTS)
+command_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_cpp_test_OBJECTS = cpp_test.$(OBJEXT) utils.$(OBJEXT)
+cpp_test_OBJECTS = $(am_cpp_test_OBJECTS)
+cpp_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_dither_test_OBJECTS = dither_test.$(OBJEXT) utils.$(OBJEXT)
+dither_test_OBJECTS = $(am_dither_test_OBJECTS)
+dither_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_dwvw_test_OBJECTS = utils.$(OBJEXT) dwvw_test.$(OBJEXT)
+dwvw_test_OBJECTS = $(am_dwvw_test_OBJECTS)
+dwvw_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_error_test_OBJECTS = error_test.$(OBJEXT) utils.$(OBJEXT)
+error_test_OBJECTS = $(am_error_test_OBJECTS)
+error_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_external_libs_test_OBJECTS = external_libs_test.$(OBJEXT) \
+ utils.$(OBJEXT)
+external_libs_test_OBJECTS = $(am_external_libs_test_OBJECTS)
+external_libs_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_fix_this_OBJECTS = utils.$(OBJEXT) fix_this.$(OBJEXT)
+fix_this_OBJECTS = $(am_fix_this_OBJECTS)
+fix_this_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_floating_point_test_OBJECTS = utils.$(OBJEXT) dft_cmp.$(OBJEXT) \
+ floating_point_test.$(OBJEXT)
+floating_point_test_OBJECTS = $(am_floating_point_test_OBJECTS)
+floating_point_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_format_check_test_OBJECTS = format_check_test.$(OBJEXT) \
+ utils.$(OBJEXT)
+format_check_test_OBJECTS = $(am_format_check_test_OBJECTS)
+format_check_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_header_test_OBJECTS = header_test.$(OBJEXT) utils.$(OBJEXT)
+header_test_OBJECTS = $(am_header_test_OBJECTS)
+header_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_headerless_test_OBJECTS = utils.$(OBJEXT) headerless_test.$(OBJEXT)
+headerless_test_OBJECTS = $(am_headerless_test_OBJECTS)
+headerless_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_largefile_test_OBJECTS = largefile_test.$(OBJEXT) utils.$(OBJEXT)
+largefile_test_OBJECTS = $(am_largefile_test_OBJECTS)
+largefile_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_locale_test_OBJECTS = locale_test.$(OBJEXT) utils.$(OBJEXT)
+locale_test_OBJECTS = $(am_locale_test_OBJECTS)
+locale_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_lossy_comp_test_OBJECTS = utils.$(OBJEXT) lossy_comp_test.$(OBJEXT)
+lossy_comp_test_OBJECTS = $(am_lossy_comp_test_OBJECTS)
+lossy_comp_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_misc_test_OBJECTS = misc_test.$(OBJEXT) utils.$(OBJEXT)
+misc_test_OBJECTS = $(am_misc_test_OBJECTS)
+misc_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_multi_file_test_OBJECTS = multi_file_test.$(OBJEXT) utils.$(OBJEXT)
+multi_file_test_OBJECTS = $(am_multi_file_test_OBJECTS)
+multi_file_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_ogg_test_OBJECTS = ogg_test.$(OBJEXT) utils.$(OBJEXT)
+ogg_test_OBJECTS = $(am_ogg_test_OBJECTS)
+ogg_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_pcm_test_OBJECTS = pcm_test.$(OBJEXT) utils.$(OBJEXT)
+pcm_test_OBJECTS = $(am_pcm_test_OBJECTS)
+pcm_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_peak_chunk_test_OBJECTS = peak_chunk_test.$(OBJEXT) utils.$(OBJEXT)
+peak_chunk_test_OBJECTS = $(am_peak_chunk_test_OBJECTS)
+peak_chunk_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_pipe_test_OBJECTS = pipe_test.$(OBJEXT) utils.$(OBJEXT)
+pipe_test_OBJECTS = $(am_pipe_test_OBJECTS)
+pipe_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_raw_test_OBJECTS = raw_test.$(OBJEXT) utils.$(OBJEXT)
+raw_test_OBJECTS = $(am_raw_test_OBJECTS)
+raw_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_rdwr_test_OBJECTS = rdwr_test.$(OBJEXT) utils.$(OBJEXT)
+rdwr_test_OBJECTS = $(am_rdwr_test_OBJECTS)
+rdwr_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_scale_clip_test_OBJECTS = scale_clip_test.$(OBJEXT) utils.$(OBJEXT)
+scale_clip_test_OBJECTS = $(am_scale_clip_test_OBJECTS)
+scale_clip_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_sfversion_OBJECTS = sfversion.$(OBJEXT)
+sfversion_OBJECTS = $(am_sfversion_OBJECTS)
+sfversion_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_stdin_test_OBJECTS = stdin_test.$(OBJEXT) utils.$(OBJEXT)
+stdin_test_OBJECTS = $(am_stdin_test_OBJECTS)
+stdin_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_stdio_test_OBJECTS = stdio_test.$(OBJEXT) utils.$(OBJEXT)
+stdio_test_OBJECTS = $(am_stdio_test_OBJECTS)
+stdio_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_stdout_test_OBJECTS = stdout_test.$(OBJEXT)
+stdout_test_OBJECTS = $(am_stdout_test_OBJECTS)
+stdout_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_string_test_OBJECTS = string_test.$(OBJEXT) utils.$(OBJEXT)
+string_test_OBJECTS = $(am_string_test_OBJECTS)
+string_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_ulaw_test_OBJECTS = utils.$(OBJEXT) ulaw_test.$(OBJEXT)
+ulaw_test_OBJECTS = $(am_ulaw_test_OBJECTS)
+ulaw_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_virtual_io_test_OBJECTS = virtual_io_test.$(OBJEXT) utils.$(OBJEXT)
+virtual_io_test_OBJECTS = $(am_virtual_io_test_OBJECTS)
+virtual_io_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_vorbis_test_OBJECTS = vorbis_test.$(OBJEXT) utils.$(OBJEXT)
+vorbis_test_OBJECTS = $(am_vorbis_test_OBJECTS)
+vorbis_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_win32_ordinal_test_OBJECTS = win32_ordinal_test.$(OBJEXT) \
+ utils.$(OBJEXT)
+win32_ordinal_test_OBJECTS = $(am_win32_ordinal_test_OBJECTS)
+win32_ordinal_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_win32_test_OBJECTS = win32_test.$(OBJEXT)
+win32_test_OBJECTS = $(am_win32_test_OBJECTS)
+win32_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+am_write_read_test_OBJECTS = utils.$(OBJEXT) generate.$(OBJEXT) \
+ write_read_test.$(OBJEXT)
+write_read_test_OBJECTS = $(am_write_read_test_OBJECTS)
+write_read_test_DEPENDENCIES = $(top_builddir)/src/libsndfile.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/Cfg/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_$(V))
+am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
+am__v_CXX_0 = @echo " CXX " $@;
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_$(V))
+am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(aiff_rw_test_SOURCES) $(alaw_test_SOURCES) \
+ $(benchmark_SOURCES) $(checksum_test_SOURCES) \
+ $(command_test_SOURCES) $(cpp_test_SOURCES) \
+ $(dither_test_SOURCES) $(dwvw_test_SOURCES) \
+ $(error_test_SOURCES) $(external_libs_test_SOURCES) \
+ $(fix_this_SOURCES) $(floating_point_test_SOURCES) \
+ $(format_check_test_SOURCES) $(header_test_SOURCES) \
+ $(headerless_test_SOURCES) $(largefile_test_SOURCES) \
+ $(locale_test_SOURCES) $(lossy_comp_test_SOURCES) \
+ $(misc_test_SOURCES) $(multi_file_test_SOURCES) \
+ $(ogg_test_SOURCES) $(pcm_test_SOURCES) \
+ $(peak_chunk_test_SOURCES) $(pipe_test_SOURCES) \
+ $(raw_test_SOURCES) $(rdwr_test_SOURCES) \
+ $(scale_clip_test_SOURCES) $(sfversion_SOURCES) \
+ $(stdin_test_SOURCES) $(stdio_test_SOURCES) \
+ $(stdout_test_SOURCES) $(string_test_SOURCES) \
+ $(ulaw_test_SOURCES) $(virtual_io_test_SOURCES) \
+ $(vorbis_test_SOURCES) $(win32_ordinal_test_SOURCES) \
+ $(win32_test_SOURCES) $(write_read_test_SOURCES)
+DIST_SOURCES = $(aiff_rw_test_SOURCES) $(alaw_test_SOURCES) \
+ $(benchmark_SOURCES) $(checksum_test_SOURCES) \
+ $(command_test_SOURCES) $(cpp_test_SOURCES) \
+ $(dither_test_SOURCES) $(dwvw_test_SOURCES) \
+ $(error_test_SOURCES) $(external_libs_test_SOURCES) \
+ $(fix_this_SOURCES) $(floating_point_test_SOURCES) \
+ $(format_check_test_SOURCES) $(header_test_SOURCES) \
+ $(headerless_test_SOURCES) $(largefile_test_SOURCES) \
+ $(locale_test_SOURCES) $(lossy_comp_test_SOURCES) \
+ $(misc_test_SOURCES) $(multi_file_test_SOURCES) \
+ $(ogg_test_SOURCES) $(pcm_test_SOURCES) \
+ $(peak_chunk_test_SOURCES) $(pipe_test_SOURCES) \
+ $(raw_test_SOURCES) $(rdwr_test_SOURCES) \
+ $(scale_clip_test_SOURCES) $(sfversion_SOURCES) \
+ $(stdin_test_SOURCES) $(stdio_test_SOURCES) \
+ $(stdout_test_SOURCES) $(string_test_SOURCES) \
+ $(ulaw_test_SOURCES) $(virtual_io_test_SOURCES) \
+ $(vorbis_test_SOURCES) $(win32_ordinal_test_SOURCES) \
+ $(win32_test_SOURCES) $(write_read_test_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CLEAN_VERSION = @CLEAN_VERSION@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTERNAL_CFLAGS = @EXTERNAL_CFLAGS@
+EXTERNAL_LIBS = @EXTERNAL_LIBS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCC_MAJOR_VERSION = @GCC_MAJOR_VERSION@
+GCC_MINOR_VERSION = @GCC_MINOR_VERSION@
+GCC_VERSION = @GCC_VERSION@
+GETCONF = @GETCONF@
+GREP = @GREP@
+HAVE_AUTOGEN = @HAVE_AUTOGEN@
+HAVE_MKOCTFILE = @HAVE_MKOCTFILE@
+HAVE_OCTAVE = @HAVE_OCTAVE@
+HAVE_OCTAVE_CONFIG = @HAVE_OCTAVE_CONFIG@
+HAVE_WINE = @HAVE_WINE@
+HOST_TRIPLET = @HOST_TRIPLET@
+HTML_BGCOLOUR = @HTML_BGCOLOUR@
+HTML_FGCOLOUR = @HTML_FGCOLOUR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKOCTFILE = @MKOCTFILE@
+MKOCTFILE_VERSION = @MKOCTFILE_VERSION@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OCTAVE = @OCTAVE@
+OCTAVE_CONFIG = @OCTAVE_CONFIG@
+OCTAVE_CONFIG_VERSION = @OCTAVE_CONFIG_VERSION@
+OCTAVE_DEST_MDIR = @OCTAVE_DEST_MDIR@
+OCTAVE_DEST_ODIR = @OCTAVE_DEST_ODIR@
+OCTAVE_VERSION = @OCTAVE_VERSION@
+OGG_CFLAGS = @OGG_CFLAGS@
+OGG_LIBS = @OGG_LIBS@
+OS_SPECIFIC_CFLAGS = @OS_SPECIFIC_CFLAGS@
+OS_SPECIFIC_LINKS = @OS_SPECIFIC_LINKS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SF_COUNT_MAX = @SF_COUNT_MAX@
+SHARED_VERSION_INFO = @SHARED_VERSION_INFO@
+SHELL = @SHELL@
+SHLIB_VERSION_ARG = @SHLIB_VERSION_ARG@
+SIZEOF_SF_COUNT_T = @SIZEOF_SF_COUNT_T@
+SNDIO_LIBS = @SNDIO_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+TYPEOF_SF_COUNT_T = @TYPEOF_SF_COUNT_T@
+VERSION = @VERSION@
+VORBISENC_CFLAGS = @VORBISENC_CFLAGS@
+VORBISENC_LIBS = @VORBISENC_LIBS@
+VORBIS_CFLAGS = @VORBIS_CFLAGS@
+VORBIS_LIBS = @VORBIS_LIBS@
+WIN_RC_VERSION = @WIN_RC_VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+htmldocdir = @htmldocdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@ENABLE_TEST_COVERAGE_FALSE@CPP_TEST = cpp_test
+@ENABLE_TEST_COVERAGE_TRUE@CPP_TEST =
+INCLUDES = -I$(top_srcdir)/src
+noinst_HEADERS = dft_cmp.h utils.h generate.h
+autogen_sources = write_read_test.tpl write_read_test.def \
+ pcm_test.tpl pcm_test.def \
+ header_test.tpl header_test.def \
+ utils.tpl utils.def \
+ scale_clip_test.tpl scale_clip_test.def \
+ pipe_test.tpl pipe_test.def \
+ rdwr_test.tpl rdwr_test.def \
+ floating_point_test.tpl floating_point_test.def \
+ benchmark.tpl benchmark.def
+
+EXTRA_DIST = $(autogen_sources)
+CLEANFILES = *~
+
+#===============================================================================
+sfversion_SOURCES = sfversion.c
+sfversion_LDADD = $(top_builddir)/src/libsndfile.la
+write_read_test_SOURCES = utils.c generate.c write_read_test.c
+write_read_test_LDADD = $(top_builddir)/src/libsndfile.la
+lossy_comp_test_SOURCES = utils.c lossy_comp_test.c
+lossy_comp_test_LDADD = $(top_builddir)/src/libsndfile.la
+fix_this_SOURCES = utils.c fix_this.c
+fix_this_LDADD = $(top_builddir)/src/libsndfile.la
+error_test_SOURCES = error_test.c utils.c
+error_test_LDADD = $(top_builddir)/src/libsndfile.la
+ulaw_test_SOURCES = utils.c ulaw_test.c
+ulaw_test_LDADD = $(top_builddir)/src/libsndfile.la
+alaw_test_SOURCES = utils.c alaw_test.c
+alaw_test_LDADD = $(top_builddir)/src/libsndfile.la
+aiff_rw_test_SOURCES = utils.c aiff_rw_test.c
+aiff_rw_test_LDADD = $(top_builddir)/src/libsndfile.la
+command_test_SOURCES = command_test.c utils.c
+command_test_LDADD = $(top_builddir)/src/libsndfile.la
+locale_test_SOURCES = locale_test.c utils.c
+locale_test_LDADD = $(top_builddir)/src/libsndfile.la
+largefile_test_SOURCES = largefile_test.c utils.c
+largefile_test_LDADD = $(top_builddir)/src/libsndfile.la
+pcm_test_SOURCES = pcm_test.c utils.c
+pcm_test_LDADD = $(top_builddir)/src/libsndfile.la
+headerless_test_SOURCES = utils.c headerless_test.c
+headerless_test_LDADD = $(top_builddir)/src/libsndfile.la
+stdin_test_SOURCES = stdin_test.c utils.c
+stdin_test_LDADD = $(top_builddir)/src/libsndfile.la
+stdout_test_SOURCES = stdout_test.c
+stdout_test_LDADD = $(top_builddir)/src/libsndfile.la
+stdio_test_SOURCES = stdio_test.c utils.c
+stdio_test_LDADD = $(top_builddir)/src/libsndfile.la
+pipe_test_SOURCES = pipe_test.c utils.c
+pipe_test_LDADD = $(top_builddir)/src/libsndfile.la
+benchmark_SOURCES = benchmark.c
+benchmark_LDADD = $(top_builddir)/src/libsndfile.la
+header_test_SOURCES = header_test.c utils.c
+header_test_LDADD = $(top_builddir)/src/libsndfile.la
+misc_test_SOURCES = misc_test.c utils.c
+misc_test_LDADD = $(top_builddir)/src/libsndfile.la
+raw_test_SOURCES = raw_test.c utils.c
+raw_test_LDADD = $(top_builddir)/src/libsndfile.la
+string_test_SOURCES = string_test.c utils.c
+string_test_LDADD = $(top_builddir)/src/libsndfile.la
+dither_test_SOURCES = dither_test.c utils.c
+dither_test_LDADD = $(top_builddir)/src/libsndfile.la
+multi_file_test_SOURCES = multi_file_test.c utils.c
+multi_file_test_LDADD = $(top_builddir)/src/libsndfile.la
+virtual_io_test_SOURCES = virtual_io_test.c utils.c
+virtual_io_test_LDADD = $(top_builddir)/src/libsndfile.la
+ogg_test_SOURCES = ogg_test.c utils.c
+ogg_test_LDADD = $(top_builddir)/src/libsndfile.la
+vorbis_test_SOURCES = vorbis_test.c utils.c
+vorbis_test_LDADD = $(top_builddir)/src/libsndfile.la
+rdwr_test_SOURCES = rdwr_test.c utils.c
+rdwr_test_LDADD = $(top_builddir)/src/libsndfile.la
+win32_test_SOURCES = win32_test.c
+# Link lib here so that generating the testsuite tarball works correctly.
+win32_test_LDADD = $(top_builddir)/src/libsndfile.la
+win32_ordinal_test_SOURCES = win32_ordinal_test.c utils.c
+win32_ordinal_test_LDADD = $(top_builddir)/src/libsndfile.la
+external_libs_test_SOURCES = external_libs_test.c utils.c
+external_libs_test_LDADD = $(top_builddir)/src/libsndfile.la
+format_check_test_SOURCES = format_check_test.c utils.c
+format_check_test_LDADD = $(top_builddir)/src/libsndfile.la
+cpp_test_SOURCES = cpp_test.cc utils.c
+cpp_test_LDADD = $(top_builddir)/src/libsndfile.la
+checksum_test_SOURCES = checksum_test.c utils.c
+checksum_test_LDADD = $(top_builddir)/src/libsndfile.la
+
+# Lite remove start
+dwvw_test_SOURCES = utils.c dwvw_test.c
+dwvw_test_LDADD = $(top_builddir)/src/libsndfile.la
+floating_point_test_SOURCES = utils.c dft_cmp.c floating_point_test.c
+floating_point_test_LDADD = $(top_builddir)/src/libsndfile.la
+peak_chunk_test_SOURCES = peak_chunk_test.c utils.c
+peak_chunk_test_LDADD = $(top_builddir)/src/libsndfile.la
+scale_clip_test_SOURCES = scale_clip_test.c utils.c
+scale_clip_test_LDADD = $(top_builddir)/src/libsndfile.la
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+test_wrapper.sh: $(top_builddir)/config.status $(srcdir)/test_wrapper.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+pedantic-header-test.sh: $(top_builddir)/config.status $(srcdir)/pedantic-header-test.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+aiff_rw_test$(EXEEXT): $(aiff_rw_test_OBJECTS) $(aiff_rw_test_DEPENDENCIES)
+ @rm -f aiff_rw_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(aiff_rw_test_OBJECTS) $(aiff_rw_test_LDADD) $(LIBS)
+alaw_test$(EXEEXT): $(alaw_test_OBJECTS) $(alaw_test_DEPENDENCIES)
+ @rm -f alaw_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(alaw_test_OBJECTS) $(alaw_test_LDADD) $(LIBS)
+benchmark$(EXEEXT): $(benchmark_OBJECTS) $(benchmark_DEPENDENCIES)
+ @rm -f benchmark$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(benchmark_OBJECTS) $(benchmark_LDADD) $(LIBS)
+checksum_test$(EXEEXT): $(checksum_test_OBJECTS) $(checksum_test_DEPENDENCIES)
+ @rm -f checksum_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(checksum_test_OBJECTS) $(checksum_test_LDADD) $(LIBS)
+command_test$(EXEEXT): $(command_test_OBJECTS) $(command_test_DEPENDENCIES)
+ @rm -f command_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(command_test_OBJECTS) $(command_test_LDADD) $(LIBS)
+cpp_test$(EXEEXT): $(cpp_test_OBJECTS) $(cpp_test_DEPENDENCIES)
+ @rm -f cpp_test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(cpp_test_OBJECTS) $(cpp_test_LDADD) $(LIBS)
+dither_test$(EXEEXT): $(dither_test_OBJECTS) $(dither_test_DEPENDENCIES)
+ @rm -f dither_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dither_test_OBJECTS) $(dither_test_LDADD) $(LIBS)
+dwvw_test$(EXEEXT): $(dwvw_test_OBJECTS) $(dwvw_test_DEPENDENCIES)
+ @rm -f dwvw_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dwvw_test_OBJECTS) $(dwvw_test_LDADD) $(LIBS)
+error_test$(EXEEXT): $(error_test_OBJECTS) $(error_test_DEPENDENCIES)
+ @rm -f error_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(error_test_OBJECTS) $(error_test_LDADD) $(LIBS)
+external_libs_test$(EXEEXT): $(external_libs_test_OBJECTS) $(external_libs_test_DEPENDENCIES)
+ @rm -f external_libs_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(external_libs_test_OBJECTS) $(external_libs_test_LDADD) $(LIBS)
+fix_this$(EXEEXT): $(fix_this_OBJECTS) $(fix_this_DEPENDENCIES)
+ @rm -f fix_this$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(fix_this_OBJECTS) $(fix_this_LDADD) $(LIBS)
+floating_point_test$(EXEEXT): $(floating_point_test_OBJECTS) $(floating_point_test_DEPENDENCIES)
+ @rm -f floating_point_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(floating_point_test_OBJECTS) $(floating_point_test_LDADD) $(LIBS)
+format_check_test$(EXEEXT): $(format_check_test_OBJECTS) $(format_check_test_DEPENDENCIES)
+ @rm -f format_check_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(format_check_test_OBJECTS) $(format_check_test_LDADD) $(LIBS)
+header_test$(EXEEXT): $(header_test_OBJECTS) $(header_test_DEPENDENCIES)
+ @rm -f header_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(header_test_OBJECTS) $(header_test_LDADD) $(LIBS)
+headerless_test$(EXEEXT): $(headerless_test_OBJECTS) $(headerless_test_DEPENDENCIES)
+ @rm -f headerless_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(headerless_test_OBJECTS) $(headerless_test_LDADD) $(LIBS)
+largefile_test$(EXEEXT): $(largefile_test_OBJECTS) $(largefile_test_DEPENDENCIES)
+ @rm -f largefile_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(largefile_test_OBJECTS) $(largefile_test_LDADD) $(LIBS)
+locale_test$(EXEEXT): $(locale_test_OBJECTS) $(locale_test_DEPENDENCIES)
+ @rm -f locale_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(locale_test_OBJECTS) $(locale_test_LDADD) $(LIBS)
+lossy_comp_test$(EXEEXT): $(lossy_comp_test_OBJECTS) $(lossy_comp_test_DEPENDENCIES)
+ @rm -f lossy_comp_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(lossy_comp_test_OBJECTS) $(lossy_comp_test_LDADD) $(LIBS)
+misc_test$(EXEEXT): $(misc_test_OBJECTS) $(misc_test_DEPENDENCIES)
+ @rm -f misc_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(misc_test_OBJECTS) $(misc_test_LDADD) $(LIBS)
+multi_file_test$(EXEEXT): $(multi_file_test_OBJECTS) $(multi_file_test_DEPENDENCIES)
+ @rm -f multi_file_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(multi_file_test_OBJECTS) $(multi_file_test_LDADD) $(LIBS)
+ogg_test$(EXEEXT): $(ogg_test_OBJECTS) $(ogg_test_DEPENDENCIES)
+ @rm -f ogg_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(ogg_test_OBJECTS) $(ogg_test_LDADD) $(LIBS)
+pcm_test$(EXEEXT): $(pcm_test_OBJECTS) $(pcm_test_DEPENDENCIES)
+ @rm -f pcm_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(pcm_test_OBJECTS) $(pcm_test_LDADD) $(LIBS)
+peak_chunk_test$(EXEEXT): $(peak_chunk_test_OBJECTS) $(peak_chunk_test_DEPENDENCIES)
+ @rm -f peak_chunk_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(peak_chunk_test_OBJECTS) $(peak_chunk_test_LDADD) $(LIBS)
+pipe_test$(EXEEXT): $(pipe_test_OBJECTS) $(pipe_test_DEPENDENCIES)
+ @rm -f pipe_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(pipe_test_OBJECTS) $(pipe_test_LDADD) $(LIBS)
+raw_test$(EXEEXT): $(raw_test_OBJECTS) $(raw_test_DEPENDENCIES)
+ @rm -f raw_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(raw_test_OBJECTS) $(raw_test_LDADD) $(LIBS)
+rdwr_test$(EXEEXT): $(rdwr_test_OBJECTS) $(rdwr_test_DEPENDENCIES)
+ @rm -f rdwr_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(rdwr_test_OBJECTS) $(rdwr_test_LDADD) $(LIBS)
+scale_clip_test$(EXEEXT): $(scale_clip_test_OBJECTS) $(scale_clip_test_DEPENDENCIES)
+ @rm -f scale_clip_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(scale_clip_test_OBJECTS) $(scale_clip_test_LDADD) $(LIBS)
+sfversion$(EXEEXT): $(sfversion_OBJECTS) $(sfversion_DEPENDENCIES)
+ @rm -f sfversion$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sfversion_OBJECTS) $(sfversion_LDADD) $(LIBS)
+stdin_test$(EXEEXT): $(stdin_test_OBJECTS) $(stdin_test_DEPENDENCIES)
+ @rm -f stdin_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(stdin_test_OBJECTS) $(stdin_test_LDADD) $(LIBS)
+stdio_test$(EXEEXT): $(stdio_test_OBJECTS) $(stdio_test_DEPENDENCIES)
+ @rm -f stdio_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(stdio_test_OBJECTS) $(stdio_test_LDADD) $(LIBS)
+stdout_test$(EXEEXT): $(stdout_test_OBJECTS) $(stdout_test_DEPENDENCIES)
+ @rm -f stdout_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(stdout_test_OBJECTS) $(stdout_test_LDADD) $(LIBS)
+string_test$(EXEEXT): $(string_test_OBJECTS) $(string_test_DEPENDENCIES)
+ @rm -f string_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(string_test_OBJECTS) $(string_test_LDADD) $(LIBS)
+ulaw_test$(EXEEXT): $(ulaw_test_OBJECTS) $(ulaw_test_DEPENDENCIES)
+ @rm -f ulaw_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(ulaw_test_OBJECTS) $(ulaw_test_LDADD) $(LIBS)
+virtual_io_test$(EXEEXT): $(virtual_io_test_OBJECTS) $(virtual_io_test_DEPENDENCIES)
+ @rm -f virtual_io_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(virtual_io_test_OBJECTS) $(virtual_io_test_LDADD) $(LIBS)
+vorbis_test$(EXEEXT): $(vorbis_test_OBJECTS) $(vorbis_test_DEPENDENCIES)
+ @rm -f vorbis_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(vorbis_test_OBJECTS) $(vorbis_test_LDADD) $(LIBS)
+win32_ordinal_test$(EXEEXT): $(win32_ordinal_test_OBJECTS) $(win32_ordinal_test_DEPENDENCIES)
+ @rm -f win32_ordinal_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(win32_ordinal_test_OBJECTS) $(win32_ordinal_test_LDADD) $(LIBS)
+win32_test$(EXEEXT): $(win32_test_OBJECTS) $(win32_test_DEPENDENCIES)
+ @rm -f win32_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(win32_test_OBJECTS) $(win32_test_LDADD) $(LIBS)
+write_read_test$(EXEEXT): $(write_read_test_OBJECTS) $(write_read_test_DEPENDENCIES)
+ @rm -f write_read_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(write_read_test_OBJECTS) $(write_read_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aiff_rw_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alaw_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checksum_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dft_cmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dither_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwvw_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/external_libs_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fix_this.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/floating_point_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/format_check_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/headerless_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/largefile_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/locale_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lossy_comp_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multi_file_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ogg_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcm_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peak_chunk_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipe_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdwr_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scale_clip_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sfversion.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdin_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdio_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdout_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ulaw_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtual_io_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vorbis_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32_ordinal_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_read_test.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@LINUX_MINGW_CROSS_TEST_FALSE@clean-local:
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool clean-local \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am
+
+
+#===============================================================================
+# If we're cross compiling from Linux to Windows and running the test suite
+# under Wine, we need a symbolic link to the generated libsndfile DLL.
+
+@LINUX_MINGW_CROSS_TEST_TRUE@$(check_PROGRAMS) : libsndfile-1.dll
+
+@LINUX_MINGW_CROSS_TEST_TRUE@libsndfile-1.dll :
+@LINUX_MINGW_CROSS_TEST_TRUE@ ln -s $(top_builddir)/src/.libs/$@ $@
+
+@LINUX_MINGW_CROSS_TEST_TRUE@clean-local :
+@LINUX_MINGW_CROSS_TEST_TRUE@ -rm -f libsndfile-1.dll
+
+#===============================================================================
+
+check: test_wrapper.sh
+ sh test_wrapper.sh
+
+# Need this target to force building of test programs.
+checkprograms : $(check_PROGRAMS)
+# Lite remove end
+
+#===============================================================================
+
+write_read_test.c: write_read_test.def write_read_test.tpl
+ autogen --writable write_read_test.def
+
+pcm_test.c: pcm_test.def pcm_test.tpl
+ autogen --writable pcm_test.def
+
+header_test.c: header_test.def header_test.tpl
+ autogen --writable header_test.def
+
+utils.c utils.h : utils.def utils.tpl
+ autogen --writable utils.def
+
+scale_clip_test.c: scale_clip_test.def scale_clip_test.tpl
+ autogen --writable scale_clip_test.def
+
+pipe_test.c: pipe_test.def pipe_test.tpl
+ autogen --writable pipe_test.def
+
+rdwr_test.c: rdwr_test.def rdwr_test.tpl
+ autogen --writable rdwr_test.def
+
+floating_point_test.c: floating_point_test.def floating_point_test.tpl
+ autogen --writable floating_point_test.def
+
+benchmark.c: benchmark.def benchmark.tpl
+ autogen --writable benchmark.def
+
+genfiles : write_read_test.c pcm_test.c header_test.c utils.c \
+ scale_clip_test.c pipe_test.c floating_point_test.c rdwr_test.c \
+ benchmark.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/aiff_rw_test.c b/tests/aiff_rw_test.c
new file mode 100644
index 0000000..273818d
--- /dev/null
+++ b/tests/aiff_rw_test.c
@@ -0,0 +1,162 @@
+/*
+** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+
+static unsigned char aifc_data [] =
+{ 'F' , 'O' , 'R' , 'M' ,
+ 0x00, 0x00, 0x01, 0xE8, /* FORM length */
+
+ 'A' , 'I' , 'F' , 'C' ,
+ 0x43, 0x4F, 0x4D, 0x4D, /* COMM */
+ 0x00, 0x00, 0x00, 0x26, /* COMM length */
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x10, 0x40, 0x0D, 0xAC, 0x44,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x4F, 0x4E, 0x45, 0x0D, 'N' ,
+ 'o' , 't' , ' ' , 'c' , 'o' , 'm' , 'p' , 'r' , 'e' , 's' , 's' , 'e' ,
+ 'd' , 0x00,
+
+ 'F' , 'V' , 'E' , 'R' , 0x00, 0x00, 0x00, 0x04, 0xA2, 0x80, 0x51, 0x40,
+
+ /* A 'MARK' chunk. */
+ 'M' , 'A' , 'R' , 'K' , 0x00, 0x00, 0x00, 0x36, 0x00, 0x05,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 'A' ,
+ 0x00, 0x02, 0x00, 0x00, 0x11, 0x3A, 0x02, 'B' , 'C' , 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x22, 0x74, 0x03, 'D' , 'E' , 'F',
+ 0x00, 0x04, 0x00, 0x00, 0x33, 0xAE, 0x04, 'G' , 'H' , 'I', 'J' , 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x44, 0xE8, 0x05, 'K' , 'L' , 'M', 'N' , 'O' ,
+
+ 'S' , 'S' , 'N' , 'D' ,
+ 0x00, 0x00, 0x01, 0x64, /* SSND length */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xE0, 0xFF, 0xDB, 0xFF, 0xD0, 0xFF, 0xD5, 0xFF, 0xD6, 0xFF, 0xD0,
+ 0xFF, 0xBF, 0xFF, 0xBE, 0xFF, 0xB9, 0xFF, 0xC8, 0xFF, 0xBF, 0xFF, 0xD5,
+ 0xFF, 0xC3, 0xFF, 0xBF, 0xFF, 0xB3, 0xFF, 0xBE, 0xFF, 0xB4, 0xFF, 0xAD,
+ 0xFF, 0xAC, 0xFF, 0xAF, 0xFF, 0xB9, 0xFF, 0xB3, 0xFF, 0xA4, 0xFF, 0xA5,
+ 0xFF, 0x93, 0xFF, 0x95, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, 0x9E,
+ 0xFF, 0x90, 0xFF, 0x80, 0xFF, 0x81, 0xFF, 0x7C, 0xFF, 0x80, 0xFF, 0x7C,
+ 0xFF, 0x72, 0xFF, 0x72, 0xFF, 0x6C, 0xFF, 0x75, 0xFF, 0x6E, 0xFF, 0x6F,
+ 0xFF, 0x66, 0xFF, 0x62, 0xFF, 0x5C, 0xFF, 0x64, 0xFF, 0x50, 0xFF, 0x56,
+ 0xFF, 0x56, 0xFF, 0x4A, 0xFF, 0x4A, 0xFF, 0x49, 0xFF, 0x44, 0xFF, 0x49,
+ 0xFF, 0x3B, 0xFF, 0x3F, 0xFF, 0x48, 0xFF, 0x46, 0xFF, 0x42, 0xFF, 0x49,
+ 0xFF, 0x43, 0xFF, 0x36, 0xFF, 0x40, 0xFF, 0x35, 0xFF, 0x3F, 0xFF, 0x36,
+ 0xFF, 0x37, 0xFF, 0x2E, 0xFF, 0x23, 0xFF, 0x23, 0xFF, 0x21, 0xFF, 0x1F,
+ 0xFF, 0x25, 0xFF, 0x2C, 0xFF, 0x1E, 0xFF, 0x22, 0xFF, 0x24, 0xFF, 0x2B,
+ 0xFF, 0x35, 0xFF, 0x27, 0xFF, 0x2E, 0xFF, 0x21, 0xFF, 0x18, 0xFF, 0x21,
+ 0xFF, 0x20, 0xFF, 0x0F, 0xFF, 0x21, 0xFF, 0x1A, 0xFF, 0x10, 0xFF, 0x09,
+ 0xFF, 0x1E, 0xFF, 0x19, 0xFF, 0x21, 0xFF, 0x13, 0xFF, 0x1B, 0xFF, 0x18,
+ 0xFF, 0x21, 0xFF, 0x0F, 0xFF, 0x1A, 0xFF, 0x16, 0xFF, 0x21, 0xFF, 0x1B,
+ 0xFF, 0x1B, 0xFF, 0x23, 0xFF, 0x1A, 0xFF, 0x21, 0xFF, 0x26, 0xFF, 0x23,
+ 0xFF, 0x26, 0xFF, 0x27, 0xFF, 0x30, 0xFF, 0x27, 0xFF, 0x2F, 0xFF, 0x28,
+ 0xFF, 0x2C, 0xFF, 0x27, 0xFF, 0x33, 0xFF, 0x29, 0xFF, 0x33, 0xFF, 0x3A,
+ 0xFF, 0x42, 0xFF, 0x3B, 0xFF, 0x4D, 0xFF, 0x4B, 0xFF, 0x4D, 0xFF, 0x4A,
+ 0xFF, 0x67, 0xFF, 0x77, 0xFF, 0x73, 0xFF, 0x7B, 0xFF, 0xDE, 0xFF, 0xAD,
+ 0x00, 0x4A, 0x00, 0x63, 0xEC, 0x8C, 0x03, 0xBB, 0x0E, 0xE4, 0x08, 0xF2,
+ 0x00, 0x70, 0xE3, 0xD1, 0xE5, 0xE4, 0x01, 0x6E, 0x0A, 0x67, 0x1C, 0x74,
+ 0xF8, 0x8E, 0x10, 0x7B, 0xEA, 0x3C, 0x09, 0x87, 0x1B, 0x24, 0xEF, 0x05,
+ 0x17, 0x76, 0x0D, 0x5B, 0x02, 0x43, 0xF5, 0xEF, 0x0C, 0x1D, 0xF7, 0x61,
+ 0x05, 0x95, 0x0B, 0xC2, 0xF1, 0x69, 0x1A, 0xA1, 0xEC, 0x75, 0xF4, 0x11,
+ 0x13, 0x4F, 0x13, 0x71, 0xFA, 0x33, 0xEC, 0x32, 0xC8, 0xCF, 0x05, 0xB0,
+ 0x0B, 0x61, 0x33, 0x19, 0xCE, 0x37, 0xEF, 0xD4, 0x21, 0x9D, 0xFA, 0xAE,
+} ;
+
+static void rw_test (const char *filename) ;
+
+int
+main (void)
+{ const char *filename = "rw.aifc" ;
+
+ print_test_name ("aiff_rw_test", filename) ;
+
+ dump_data_to_file (filename, aifc_data, sizeof (aifc_data)) ;
+
+ rw_test (filename) ;
+
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+rw_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo_rd, sfinfo_rw ;
+
+ memset (&sfinfo_rd, 0, sizeof (sfinfo_rd)) ;
+ memset (&sfinfo_rw, 0, sizeof (sfinfo_rw)) ;
+
+ /* Open the file in read only mode and fill in the SF_INFO struct. */
+ if ((file = sf_open (filename, SFM_READ, &sfinfo_rd)) == NULL)
+ { printf ("\n\nLine %d : sf_open SFM_READ failed : %s\n\n", __LINE__, sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ /* Now open read/write and close the file. */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo_rw)) == NULL)
+ { printf ("\n\nLine %d : sf_open SFM_RDWR failed : %s\n\n", __LINE__, sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ /* Open again as read only again and fill in a new SF_INFO struct. */
+ memset (&sfinfo_rw, 0, sizeof (sfinfo_rw)) ;
+ if ((file = sf_open (filename, SFM_READ, &sfinfo_rw)) == NULL)
+ { printf ("\n\nLine %d : sf_open SFM_RDWR failed : %s\n\n", __LINE__, sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ /* Now compare the two. */
+ if (sfinfo_rd.format != sfinfo_rw.format)
+ { printf ("\n\nLine %d : format mismatch (0x%08X != 0x%08X).\n\n", __LINE__,
+ sfinfo_rd.format, sfinfo_rw.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo_rd.channels != sfinfo_rw.channels)
+ { printf ("\n\nLine %d : channel count mismatch (%d != %d).\n\n", __LINE__,
+ sfinfo_rd.channels, sfinfo_rw.channels) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo_rd.frames != sfinfo_rw.frames)
+ { printf ("\n\nLine %d : frame count mismatch (rd %ld != rw %ld).\n\n", __LINE__,
+ SF_COUNT_TO_LONG (sfinfo_rd.frames), SF_COUNT_TO_LONG (sfinfo_rw.frames)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* rw_test */
+
diff --git a/tests/alaw_test.c b/tests/alaw_test.c
new file mode 100644
index 0000000..e25101d
--- /dev/null
+++ b/tests/alaw_test.c
@@ -0,0 +1,236 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (65536)
+
+static unsigned char alaw_encode (int sample) ;
+static int alaw_decode (unsigned int alawbyte) ;
+
+static short short_buffer [BUFFER_SIZE] ;
+static unsigned char alaw_buffer [BUFFER_SIZE] ;
+
+int
+main (void)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ const char *filename ;
+ int k ;
+
+ print_test_name ("alaw_test", "encoder") ;
+
+ filename = "test.raw" ;
+
+ sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ALAW, 44100, 1) ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { printf ("sf_open_write failed with error : ") ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ /* Generate a file containing all possible 16 bit sample values
+ ** and write it to disk as alaw encoded.frames.
+ */
+
+ for (k = 0 ; k < 0x10000 ; k++)
+ short_buffer [k] = k & 0xFFFF ;
+
+ sf_write_short (file, short_buffer, BUFFER_SIZE) ;
+ sf_close (file) ;
+
+ /* Now open that file and compare the alaw encoded sample values
+ ** with what they should be.
+ */
+
+ if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if (sf_read_raw (file, alaw_buffer, BUFFER_SIZE) != BUFFER_SIZE)
+ { printf ("sf_read_raw : ") ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < 0x10000 ; k++)
+ if (alaw_encode (short_buffer [k]) != alaw_buffer [k])
+ { printf ("Encoder error : sample #%d (0x%02X should be 0x%02X)\n", k, alaw_buffer [k], alaw_encode (short_buffer [k])) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ print_test_name ("alaw_test", "decoder") ;
+ /* Now generate a file containing all possible 8 bit encoded
+ ** sample values and write it to disk as alaw encoded.frames.
+ */
+
+ if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < 256 ; k++)
+ alaw_buffer [k] = k & 0xFF ;
+
+ sf_write_raw (file, alaw_buffer, 256) ;
+ sf_close (file) ;
+
+ /* Now open that file and compare the alaw decoded sample values
+ ** with what they should be.
+ */
+
+ if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if (sf_read_short (file, short_buffer, 256) != 256)
+ { printf ("sf_read_short : ") ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+
+ for (k = 0 ; k < 256 ; k++)
+ if (short_buffer [k] != alaw_decode (alaw_buffer [k]))
+ { printf ("Decoder error : sample #%d (0x%02X should be 0x%02X)\n", k, short_buffer [k], alaw_decode (alaw_buffer [k])) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ unlink (filename) ;
+
+ return 0 ;
+} /* main */
+
+
+/*=================================================================================
+** The following routines came from the sox-12.15 (Sound eXcahcnge) distribution.
+**
+** This code is not compiled into libsndfile. It is only used to test the
+** libsndfile lookup tables for correctness.
+**
+** I have included the original authors comments.
+*/
+
+/*
+** A-law routines by Graeme W. Gill.
+** Date: 93/5/7
+**
+** References:
+** 1) CCITT Recommendation G.711
+**
+*/
+
+#define ACLIP 31744
+
+static
+unsigned char alaw_encode (int sample)
+{ static int exp_lut [128] =
+ { 1, 1, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7
+ } ;
+
+ int sign, exponent, mantissa ;
+ unsigned char Alawbyte ;
+
+ /* Get the sample into sign-magnitude. */
+ sign = ((~sample) >> 8) & 0x80 ; /* set aside the sign */
+ if (sign == 0)
+ sample = -sample ; /* get magnitude */
+ if (sample > ACLIP)
+ sample = ACLIP ; /* clip the magnitude */
+
+ /* Convert from 16 bit linear to ulaw. */
+ if (sample >= 256)
+ { exponent = exp_lut [(sample >> 8) & 0x7F] ;
+ mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F ;
+ Alawbyte = ((exponent << 4) | mantissa) ;
+ }
+ else
+ Alawbyte = (sample >> 4) ;
+
+ Alawbyte ^= (sign ^ 0x55) ;
+
+ return Alawbyte ;
+} /* alaw_encode */
+
+static
+int alaw_decode (unsigned int Alawbyte)
+{ static int exp_lut [8] = { 0, 264, 528, 1056, 2112, 4224, 8448, 16896 } ;
+ int sign, exponent, mantissa, sample ;
+
+ Alawbyte ^= 0x55 ;
+ sign = (Alawbyte & 0x80) ;
+ Alawbyte &= 0x7f ; /* get magnitude */
+ if (Alawbyte >= 16)
+ { exponent = (Alawbyte >> 4 ) & 0x07 ;
+ mantissa = Alawbyte & 0x0F ;
+ sample = exp_lut [exponent] + (mantissa << ( exponent + 3 )) ;
+ }
+ else
+ sample = (Alawbyte << 4) + 8 ;
+ if (sign == 0)
+ sample = -sample ;
+
+ return sample ;
+} /* alaw_decode */
+
diff --git a/tests/benchmark.c b/tests/benchmark.c
new file mode 100644
index 0000000..f33bfee
--- /dev/null
+++ b/tests/benchmark.c
@@ -0,0 +1,545 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sndfile.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+/*
+** Neat solution to the Win32/OS2 binary file flage requirement.
+** If O_BINARY isn't already defined by the inclusion of the system
+** headers, set it to zero.
+*/
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)
+#define READ_FLAGS (O_RDONLY | O_BINARY)
+
+#if (defined (WIN32) || defined (_WIN32) || defined (__OS2__))
+ #define WRITE_PERMS 0777
+#else
+ #define WRITE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP)
+#endif
+
+#define BUFFER_SIZE (1<<18)
+#define BLOCK_COUNT (30)
+#define TEST_DURATION (5) /* 5 Seconds. */
+
+typedef struct
+{ double write_rate ;
+ double read_rate ;
+} PERF_STATS ;
+
+static void *data = NULL ;
+
+static void calc_raw_performance (PERF_STATS *stats) ;
+
+static void calc_short_performance (int format, double read_rate, double write_rate) ;
+static void calc_int_performance (int format, double read_rate, double write_rate) ;
+static void calc_float_performance (int format, double read_rate, double write_rate) ;
+
+
+static int cpu_is_big_endian (void) ;
+
+static const char* get_subtype_str (int subtype) ;
+
+int
+main (int argc, char *argv [])
+{ PERF_STATS stats ;
+ char buffer [256] = "Benchmarking " ;
+ int format_major ;
+
+ if (! (data = malloc (BUFFER_SIZE * sizeof (double))))
+ { perror ("Error : malloc failed") ;
+ exit (1) ;
+ } ;
+
+ sf_command (NULL, SFC_GET_LIB_VERSION, buffer + strlen (buffer), sizeof (buffer) - strlen (buffer)) ;
+
+ puts (buffer) ;
+ memset (buffer, '-', strlen (buffer)) ;
+ puts (buffer) ;
+ printf ("Each test takes a little over %d seconds.\n\n", TEST_DURATION) ;
+
+ calc_raw_performance (&stats) ;
+
+ if (argc < 2 || strcmp ("--native-only", argv [1]) == 0)
+ { puts ("\nNative endian I/O :") ;
+ format_major = cpu_is_big_endian () ? SF_FORMAT_AIFF : SF_FORMAT_WAV ;
+
+ calc_short_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_FLOAT , stats.read_rate, stats.write_rate) ;
+ } ;
+
+ if (argc < 2 || strcmp ("--swap-only", argv [1]) == 0)
+ { puts ("\nEndian swapped I/O :") ;
+ format_major = cpu_is_big_endian () ? SF_FORMAT_WAV : SF_FORMAT_AIFF ;
+
+ calc_short_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_FLOAT , stats.read_rate, stats.write_rate) ;
+ } ;
+
+ puts ("") ;
+
+ free (data) ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+calc_raw_performance (PERF_STATS *stats)
+{ clock_t start_clock, clock_time ;
+ int fd, k, byte_count, retval, op_count ;
+ const char *filename ;
+
+ filename = "benchmark.dat" ;
+
+ byte_count = BUFFER_SIZE * sizeof (short) ;
+
+ /* Collect write stats */
+ printf (" Raw write PCM_16 : ") ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if ((fd = open (filename, WRITE_FLAGS, WRITE_PERMS)) < 0)
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = write (fd, data, byte_count)) != byte_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, byte_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ close (fd) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ stats->write_rate = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ stats->write_rate *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%10.0f samples per sec\n", stats->write_rate) ;
+
+ /* Collect read stats */
+ printf (" Raw read PCM_16 : ") ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if ((fd = open (filename, READ_FLAGS)) < 0)
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = read (fd, data, byte_count)) != byte_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, byte_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ close (fd) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ stats->read_rate = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ stats->read_rate *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%10.0f samples per sec\n", stats->read_rate) ;
+
+ unlink (filename) ;
+} /* calc_raw_performance */
+
+/*------------------------------------------------------------------------------
+*/
+
+static void
+calc_short_performance (int format, double read_rate, double write_rate)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ clock_t start_clock, clock_time ;
+ double performance ;
+ int k, item_count, retval, op_count ;
+ const char* subtype ;
+ short *short_data ;
+ const char *filename ;
+
+ filename = "benchmark.dat" ;
+ subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
+
+ short_data = data ;
+ item_count = BUFFER_SIZE ;
+ for (k = 0 ; k < item_count ; k++)
+ short_data [k] = 32700.0 * sin (2 * M_PI * k / 32000.0) ;
+
+ /* Collect write stats */
+ printf (" Write %-5s to %s : ", "short", subtype) ;
+ fflush (stdout) ;
+
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+ sfinfo.frames = 1 ;
+ sfinfo.samplerate = 32000 ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ /* Turn off the addition of a PEAK chunk. */
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_write_short (file, short_data, item_count)) != item_count)
+ { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
+
+ /* Collect read stats */
+ printf (" Read %-5s from %s : ", "short", subtype) ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_read_short (file, short_data, item_count)) != item_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
+
+ unlink (filename) ;
+
+} /* calc_short_performance */
+static void
+calc_int_performance (int format, double read_rate, double write_rate)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ clock_t start_clock, clock_time ;
+ double performance ;
+ int k, item_count, retval, op_count ;
+ const char* subtype ;
+ int *int_data ;
+ const char *filename ;
+
+ filename = "benchmark.dat" ;
+ subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
+
+ int_data = data ;
+ item_count = BUFFER_SIZE ;
+ for (k = 0 ; k < item_count ; k++)
+ int_data [k] = 32700.0 * (1<<16) * sin (2 * M_PI * k / 32000.0) ;
+
+ /* Collect write stats */
+ printf (" Write %-5s to %s : ", "int", subtype) ;
+ fflush (stdout) ;
+
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+ sfinfo.frames = 1 ;
+ sfinfo.samplerate = 32000 ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ /* Turn off the addition of a PEAK chunk. */
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_write_int (file, int_data, item_count)) != item_count)
+ { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
+
+ /* Collect read stats */
+ printf (" Read %-5s from %s : ", "int", subtype) ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_read_int (file, int_data, item_count)) != item_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
+
+ unlink (filename) ;
+
+} /* calc_int_performance */
+static void
+calc_float_performance (int format, double read_rate, double write_rate)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ clock_t start_clock, clock_time ;
+ double performance ;
+ int k, item_count, retval, op_count ;
+ const char* subtype ;
+ float *float_data ;
+ const char *filename ;
+
+ filename = "benchmark.dat" ;
+ subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
+
+ float_data = data ;
+ item_count = BUFFER_SIZE ;
+ for (k = 0 ; k < item_count ; k++)
+ float_data [k] = 1.0 * sin (2 * M_PI * k / 32000.0) ;
+
+ /* Collect write stats */
+ printf (" Write %-5s to %s : ", "float", subtype) ;
+ fflush (stdout) ;
+
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+ sfinfo.frames = 1 ;
+ sfinfo.samplerate = 32000 ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ /* Turn off the addition of a PEAK chunk. */
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_write_float (file, float_data, item_count)) != item_count)
+ { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
+
+ /* Collect read stats */
+ printf (" Read %-5s from %s : ", "float", subtype) ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_read_float (file, float_data, item_count)) != item_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
+
+ unlink (filename) ;
+
+} /* calc_float_performance */
+
+
+/*==============================================================================
+*/
+
+static int
+cpu_is_big_endian (void)
+{ unsigned char *cptr ;
+ int endtest ;
+
+ endtest = 0x12345678 ;
+
+ cptr = (unsigned char*) (&endtest) ;
+
+ if (cptr [0] == 0x12 && cptr [1] == 0x34 && cptr [3] == 0x78)
+ return SF_TRUE ;
+
+ return SF_FALSE ;
+} /* cpu_is_big_endian */
+
+static const char*
+get_subtype_str (int subtype)
+{ switch (subtype)
+ { case SF_FORMAT_PCM_16 :
+ return "PCM_16" ;
+
+ case SF_FORMAT_PCM_24 :
+ return "PCM_24" ;
+
+ case SF_FORMAT_PCM_32 :
+ return "PCM_32" ;
+
+ case SF_FORMAT_FLOAT :
+ return "FLOAT " ;
+
+ case SF_FORMAT_DOUBLE :
+ return "DOUBLE" ;
+
+ default : break ;
+ } ;
+
+ return "UNKNOWN" ;
+} /* get_subtype_str */
+
diff --git a/tests/benchmark.def b/tests/benchmark.def
new file mode 100644
index 0000000..f2db29a
--- /dev/null
+++ b/tests/benchmark.def
@@ -0,0 +1,17 @@
+autogen definitions benchmark.tpl;
+
+data_type = {
+ type_name = short ;
+ multiplier = "32700.0" ;
+ };
+
+data_type = {
+ type_name = int ;
+ multiplier = "32700.0 * (1<<16)" ;
+ };
+
+data_type = {
+ type_name = float ;
+ multiplier = "1.0" ;
+ };
+
diff --git a/tests/benchmark.tpl b/tests/benchmark.tpl
new file mode 100644
index 0000000..2a3c790
--- /dev/null
+++ b/tests/benchmark.tpl
@@ -0,0 +1,360 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sndfile.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+/*
+** Neat solution to the Win32/OS2 binary file flage requirement.
+** If O_BINARY isn't already defined by the inclusion of the system
+** headers, set it to zero.
+*/
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)
+#define READ_FLAGS (O_RDONLY | O_BINARY)
+
+#if (defined (WIN32) || defined (_WIN32) || defined (__OS2__))
+ #define WRITE_PERMS 0777
+#else
+ #define WRITE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP)
+#endif
+
+#define BUFFER_SIZE (1<<18)
+#define BLOCK_COUNT (30)
+#define TEST_DURATION (5) /* 5 Seconds. */
+
+typedef struct
+{ double write_rate ;
+ double read_rate ;
+} PERF_STATS ;
+
+static void *data = NULL ;
+
+static void calc_raw_performance (PERF_STATS *stats) ;
+
+[+ FOR data_type
++]static void calc_[+ (get "type_name") +]_performance (int format, double read_rate, double write_rate) ;
+[+ ENDFOR data_type
++]
+
+static int cpu_is_big_endian (void) ;
+
+static const char* get_subtype_str (int subtype) ;
+
+int
+main (int argc, char *argv [])
+{ PERF_STATS stats ;
+ char buffer [256] = "Benchmarking " ;
+ int format_major ;
+
+ if (! (data = malloc (BUFFER_SIZE * sizeof (double))))
+ { perror ("Error : malloc failed") ;
+ exit (1) ;
+ } ;
+
+ sf_command (NULL, SFC_GET_LIB_VERSION, buffer + strlen (buffer), sizeof (buffer) - strlen (buffer)) ;
+
+ puts (buffer) ;
+ memset (buffer, '-', strlen (buffer)) ;
+ puts (buffer) ;
+ printf ("Each test takes a little over %d seconds.\n\n", TEST_DURATION) ;
+
+ calc_raw_performance (&stats) ;
+
+ if (argc < 2 || strcmp ("--native-only", argv [1]) == 0)
+ { puts ("\nNative endian I/O :") ;
+ format_major = cpu_is_big_endian () ? SF_FORMAT_AIFF : SF_FORMAT_WAV ;
+
+ calc_short_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_FLOAT , stats.read_rate, stats.write_rate) ;
+ } ;
+
+ if (argc < 2 || strcmp ("--swap-only", argv [1]) == 0)
+ { puts ("\nEndian swapped I/O :") ;
+ format_major = cpu_is_big_endian () ? SF_FORMAT_WAV : SF_FORMAT_AIFF ;
+
+ calc_short_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_int_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
+ calc_float_performance (format_major | SF_FORMAT_FLOAT , stats.read_rate, stats.write_rate) ;
+ } ;
+
+ puts ("") ;
+
+ free (data) ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+calc_raw_performance (PERF_STATS *stats)
+{ clock_t start_clock, clock_time ;
+ int fd, k, byte_count, retval, op_count ;
+ const char *filename ;
+
+ filename = "benchmark.dat" ;
+
+ byte_count = BUFFER_SIZE * sizeof (short) ;
+
+ /* Collect write stats */
+ printf (" Raw write PCM_16 : ") ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if ((fd = open (filename, WRITE_FLAGS, WRITE_PERMS)) < 0)
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = write (fd, data, byte_count)) != byte_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, byte_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ close (fd) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ stats->write_rate = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ stats->write_rate *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%10.0f samples per sec\n", stats->write_rate) ;
+
+ /* Collect read stats */
+ printf (" Raw read PCM_16 : ") ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if ((fd = open (filename, READ_FLAGS)) < 0)
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = read (fd, data, byte_count)) != byte_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, byte_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ close (fd) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ stats->read_rate = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ stats->read_rate *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%10.0f samples per sec\n", stats->read_rate) ;
+
+ unlink (filename) ;
+} /* calc_raw_performance */
+
+/*------------------------------------------------------------------------------
+*/
+
+[+ FOR data_type
++]static void
+calc_[+ (get "type_name") +]_performance (int format, double read_rate, double write_rate)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ clock_t start_clock, clock_time ;
+ double performance ;
+ int k, item_count, retval, op_count ;
+ const char* subtype ;
+ [+ (get "type_name") +] *[+ (get "type_name") +]_data ;
+ const char *filename ;
+
+ filename = "benchmark.dat" ;
+ subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
+
+ [+ (get "type_name") +]_data = data ;
+ item_count = BUFFER_SIZE ;
+ for (k = 0 ; k < item_count ; k++)
+ [+ (get "type_name") +]_data [k] = [+ (get "multiplier") +] * sin (2 * M_PI * k / 32000.0) ;
+
+ /* Collect write stats */
+ printf (" Write %-5s to %s : ", "[+ (get "type_name") +]", subtype) ;
+ fflush (stdout) ;
+
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+ sfinfo.frames = 1 ;
+ sfinfo.samplerate = 32000 ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ /* Turn off the addition of a PEAK chunk. */
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_write_[+ (get "type_name") +] (file, [+ (get "type_name") +]_data, item_count)) != item_count)
+ { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
+
+ /* Collect read stats */
+ printf (" Read %-5s from %s : ", "[+ (get "type_name") +]", subtype) ;
+ fflush (stdout) ;
+
+ clock_time = 0 ;
+ op_count = 0 ;
+ start_clock = clock () ;
+
+ while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
+ { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("Error : not able to open file : %s\n", filename) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BLOCK_COUNT ; k++)
+ { if ((retval = sf_read_[+ (get "type_name") +] (file, [+ (get "type_name") +]_data, item_count)) != item_count)
+ { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ clock_time = clock () - start_clock ;
+ op_count ++ ;
+ } ;
+
+ performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
+ performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
+ printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
+
+ unlink (filename) ;
+
+} /* calc_[+ (get "type_name") +]_performance */
+[+ ENDFOR data_type
++]
+
+/*==============================================================================
+*/
+
+static int
+cpu_is_big_endian (void)
+{ unsigned char *cptr ;
+ int endtest ;
+
+ endtest = 0x12345678 ;
+
+ cptr = (unsigned char*) (&endtest) ;
+
+ if (cptr [0] == 0x12 && cptr [1] == 0x34 && cptr [3] == 0x78)
+ return SF_TRUE ;
+
+ return SF_FALSE ;
+} /* cpu_is_big_endian */
+
+static const char*
+get_subtype_str (int subtype)
+{ switch (subtype)
+ { case SF_FORMAT_PCM_16 :
+ return "PCM_16" ;
+
+ case SF_FORMAT_PCM_24 :
+ return "PCM_24" ;
+
+ case SF_FORMAT_PCM_32 :
+ return "PCM_32" ;
+
+ case SF_FORMAT_FLOAT :
+ return "FLOAT " ;
+
+ case SF_FORMAT_DOUBLE :
+ return "DOUBLE" ;
+
+ default : break ;
+ } ;
+
+ return "UNKNOWN" ;
+} /* get_subtype_str */
+
diff --git a/tests/checksum_test.c b/tests/checksum_test.c
new file mode 100644
index 0000000..544da93
--- /dev/null
+++ b/tests/checksum_test.c
@@ -0,0 +1,128 @@
+/*
+** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define SAMPLE_RATE 8000
+
+typedef struct
+{ int enc_fmt ;
+
+ const char * enc_name ;
+ const char * dec_name ;
+
+ uint64_t enc_cksum ;
+ uint64_t dec_cksum ;
+} CHECKSUM ;
+
+static CHECKSUM
+checksum_orig [] =
+{
+ { SF_FORMAT_RAW | SF_FORMAT_ULAW,
+ "checksum.ulaw", "cksum_ulaw.pcm16",
+ 0x33aefae029e0c888LL, 0x595cd6e47edd0cffLL
+ },
+ { SF_FORMAT_RAW | SF_FORMAT_ALAW,
+ "checksum.alaw", "cksum_alaw.pcm16",
+ 0x48c798da3572d468LL, 0x6837d74869af5bb6LL
+ },
+ { SF_FORMAT_RAW | SF_FORMAT_GSM610,
+ "checksum.gsm", "cksum_gsm.pcm16",
+ 0x1b1f64ff2acf858fLL, 0x504179dbadd4bce6LL
+ },
+ { SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM,
+ "checksum.vox", "cksum_vox.pcm16",
+ 0xf1147fb3a298f4dfLL, 0xfc9c0cb8b12cb0abLL
+ },
+} ;
+
+static void checksum_test (const CHECKSUM * cksum) ;
+
+static float orig [1 << 14] ;
+static short data [1 << 14] ;
+
+int
+main (void)
+{ unsigned k ;
+
+ gen_windowed_sine_float (orig, ARRAY_LEN (orig), 0.9) ;
+
+ for (k = 0 ; k < ARRAY_LEN (checksum_orig) ; k++)
+ checksum_test (&checksum_orig [k]) ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+checksum_test (const CHECKSUM * cksum)
+{ SNDFILE * file ;
+ SF_INFO info ;
+
+ print_test_name (__func__, cksum->enc_name) ;
+
+ info.format = cksum->enc_fmt ;
+ info.channels = 1 ;
+ info.samplerate = SAMPLE_RATE ;
+
+ file = test_open_file_or_die (cksum->enc_name, SFM_WRITE, &info, 0, __LINE__) ;
+ test_write_float_or_die (file, 0, orig, ARRAY_LEN (orig), __LINE__) ;
+ sf_close (file) ;
+
+ check_file_hash_or_die (cksum->enc_name, cksum->enc_cksum, __LINE__) ;
+ puts ("ok") ;
+
+ /*------------------------------------------------------------------------*/
+
+ print_test_name (__func__, cksum->dec_name) ;
+
+ info.format = cksum->enc_fmt ;
+ info.channels = 1 ;
+ info.samplerate = SAMPLE_RATE ;
+
+ file = test_open_file_or_die (cksum->enc_name, SFM_READ, &info, 0, __LINE__) ;
+ test_read_short_or_die (file, 0, data, ARRAY_LEN (data), __LINE__) ;
+ sf_close (file) ;
+
+ info.format = SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_16 ;
+ info.channels = 1 ;
+ info.samplerate = SAMPLE_RATE ;
+
+ file = test_open_file_or_die (cksum->dec_name, SFM_WRITE, &info, 0, __LINE__) ;
+ test_write_short_or_die (file, 0, data, ARRAY_LEN (data), __LINE__) ;
+ sf_close (file) ;
+
+ check_file_hash_or_die (cksum->dec_name, cksum->dec_cksum, __LINE__) ;
+
+ remove (cksum->enc_name) ;
+ remove (cksum->dec_name) ;
+
+ puts ("ok") ;
+} /* checksum_test */
+
diff --git a/tests/command_test.c b/tests/command_test.c
new file mode 100644
index 0000000..be74804
--- /dev/null
+++ b/tests/command_test.c
@@ -0,0 +1,1344 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<10)
+#define LOG_BUFFER_SIZE 1024
+
+static void float_norm_test (const char *filename) ;
+static void double_norm_test (const char *filename) ;
+static void format_tests (void) ;
+static void calc_peak_test (int filetype, const char *filename) ;
+static void truncate_test (const char *filename, int filetype) ;
+static void instrument_test (const char *filename, int filetype) ;
+static void channel_map_test (const char *filename, int filetype) ;
+static void current_sf_info_test (const char *filename) ;
+static void raw_needs_endswap_test (const char *filename, int filetype) ;
+
+static void broadcast_test (const char *filename, int filetype) ;
+static void broadcast_rdwr_test (const char *filename, int filetype) ;
+static void broadcast_coding_history_test (const char *filename) ;
+static void broadcast_coding_history_size (const char *filename) ;
+
+/* Force the start of this buffer to be double aligned. Sparc-solaris will
+** choke if its not.
+*/
+
+static int int_data [BUFFER_LEN] ;
+static float float_data [BUFFER_LEN] ;
+static double double_data [BUFFER_LEN] ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" ver - test sf_command (SFC_GETLIB_VERSION)\n") ;
+ printf (" norm - test floating point normalisation\n") ;
+ printf (" format - test format string commands\n") ;
+ printf (" peak - test peak calculation\n") ;
+ printf (" trunc - test file truncation\n") ;
+ printf (" inst - test set/get of SF_INSTRUMENT.\n") ;
+ printf (" chanmap - test set/get of channel map data..\n") ;
+ printf (" bext - test set/get of SF_BROADCAST_INFO.\n") ;
+ printf (" bextch - test set/get of SF_BROADCAST_INFO coding_history.\n") ;
+ printf (" rawend - test SFC_RAW_NEEDS_ENDSWAP.\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all =! strcmp (argv [1], "all") ;
+
+ if (do_all || strcmp (argv [1], "ver") == 0)
+ { char buffer [128] ;
+
+ print_test_name ("version_test", "(none)") ;
+ buffer [0] = 0 ;
+ sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
+ if (strlen (buffer) < 1)
+ { printf ("Line %d: could not retrieve lib version.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ puts ("ok") ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "norm") == 0)
+ { /* Preliminary float/double normalisation tests. More testing
+ ** is done in the program 'floating_point_test'.
+ */
+ float_norm_test ("float.wav") ;
+ double_norm_test ("double.wav") ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "peak") == 0)
+ { calc_peak_test (SF_ENDIAN_BIG | SF_FORMAT_RAW, "be-peak.raw") ;
+ calc_peak_test (SF_ENDIAN_LITTLE | SF_FORMAT_RAW, "le-peak.raw") ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "format"))
+ { format_tests () ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "trunc") == 0)
+ { truncate_test ("truncate.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_32) ;
+ truncate_test ("truncate.au" , SF_FORMAT_AU | SF_FORMAT_PCM_16) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "inst") == 0)
+ { instrument_test ("instrument.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ instrument_test ("instrument.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_24) ;
+ /*-instrument_test ("instrument.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16) ;-*/
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "current_sf_info") == 0)
+ { current_sf_info_test ("current.wav") ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "bext") == 0)
+ { broadcast_test ("broadcast.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ broadcast_rdwr_test ("broadcast.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+
+ broadcast_test ("broadcast.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
+ broadcast_rdwr_test ("broadcast.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
+
+ broadcast_test ("broadcast.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
+ broadcast_rdwr_test ("broadcast.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "bextch") == 0)
+ { broadcast_coding_history_test ("coding_history.wav") ;
+ broadcast_coding_history_size ("coding_hist_size.wav") ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "chanmap") == 0)
+ { channel_map_test ("chanmap.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
+ channel_map_test ("chanmap.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
+ channel_map_test ("chanmap.aifc" , SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
+ channel_map_test ("chanmap.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_16) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "rawend") == 0)
+ { raw_needs_endswap_test ("raw_end.wav", SF_FORMAT_WAV) ;
+ raw_needs_endswap_test ("raw_end.wavex", SF_FORMAT_WAVEX) ;
+ raw_needs_endswap_test ("raw_end.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
+ raw_needs_endswap_test ("raw_end.aiff", SF_FORMAT_AIFF) ;
+ raw_needs_endswap_test ("raw_end.aiff_le", SF_ENDIAN_LITTLE | SF_FORMAT_AIFF) ;
+ test_count ++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+float_norm_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned int k ;
+
+ print_test_name ("float_norm_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (SF_FORMAT_RAW | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = BUFFER_LEN ;
+
+ /* Create float_data with all values being less than 1.0. */
+ for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
+ float_data [k] = (k + 5) / (2.0 * BUFFER_LEN) ;
+ for (k = BUFFER_LEN / 2 ; k < BUFFER_LEN ; k++)
+ float_data [k] = (k + 5) ;
+
+ if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("Line %d: sf_open_write failed with error : ", __LINE__) ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ /* Normalisation is on by default so no need to do anything here. */
+
+ if ((k = sf_write_float (file, float_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
+ { printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ /* Turn normalisation off. */
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ if ((k = sf_write_float (file, float_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
+ { printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* sfinfo struct should still contain correct data. */
+ if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("Line %d: sf_open_read failed with error : ", __LINE__) ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != (SF_FORMAT_RAW | SF_FORMAT_PCM_16))
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, (SF_FORMAT_RAW | SF_FORMAT_PCM_16), sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("\n\nLine %d: Incorrect number of.frames in file. (%d => %ld)\n", __LINE__, BUFFER_LEN, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Read float_data and check that it is normalised (ie default). */
+ if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN)
+ { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (float_data [k] >= 1.0)
+ { printf ("\n\nLine %d: float_data [%d] == %f which is greater than 1.0\n", __LINE__, k, float_data [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file, turn normalisation off, read float_data and check again. */
+ sf_seek (file, 0, SEEK_SET) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN)
+ { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (float_data [k] < 1.0)
+ { printf ("\n\nLine %d: float_data [%d] == %f which is less than 1.0\n", __LINE__, k, float_data [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file, turn normalisation on, read float_data and do final check. */
+ sf_seek (file, 0, SEEK_SET) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_TRUE) ;
+
+ if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN)
+ { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (float_data [k] > 1.0)
+ { printf ("\n\nLine %d: float_data [%d] == %f which is greater than 1.0\n", __LINE__, k, float_data [k]) ;
+ exit (1) ;
+ } ;
+
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+
+ printf ("ok\n") ;
+} /* float_norm_test */
+
+static void
+double_norm_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned int k ;
+
+ print_test_name ("double_norm_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (SF_FORMAT_RAW | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = BUFFER_LEN ;
+
+ /* Create double_data with all values being less than 1.0. */
+ for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
+ double_data [k] = (k + 5) / (2.0 * BUFFER_LEN) ;
+ for (k = BUFFER_LEN / 2 ; k < BUFFER_LEN ; k++)
+ double_data [k] = (k + 5) ;
+
+ if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("Line %d: sf_open_write failed with error : ", __LINE__) ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ /* Normailsation is on by default so no need to do anything here. */
+ /*-sf_command (file, "set-norm-double", "true", 0) ;-*/
+
+ if ((k = sf_write_double (file, double_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
+ { printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ /* Turn normalisation off. */
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ if ((k = sf_write_double (file, double_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
+ { printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("Line %d: sf_open_read failed with error : ", __LINE__) ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != (SF_FORMAT_RAW | SF_FORMAT_PCM_16))
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, (SF_FORMAT_RAW | SF_FORMAT_PCM_16), sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("\n\nLine %d: Incorrect number of.frames in file. (%d => %ld)\n", __LINE__, BUFFER_LEN, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Read double_data and check that it is normalised (ie default). */
+ if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN)
+ { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (double_data [k] >= 1.0)
+ { printf ("\n\nLine %d: double_data [%d] == %f which is greater than 1.0\n", __LINE__, k, double_data [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file, turn normalisation off, read double_data and check again. */
+ sf_seek (file, 0, SEEK_SET) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN)
+ { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (double_data [k] < 1.0)
+ { printf ("\n\nLine %d: double_data [%d] == %f which is less than 1.0\n", __LINE__, k, double_data [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file, turn normalisation on, read double_data and do final check. */
+ sf_seek (file, 0, SEEK_SET) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ;
+
+ if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN)
+ { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (double_data [k] > 1.0)
+ { printf ("\n\nLine %d: double_data [%d] == %f which is greater than 1.0\n", __LINE__, k, double_data [k]) ;
+ exit (1) ;
+ } ;
+
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+
+ printf ("ok\n") ;
+} /* double_norm_test */
+
+static void
+format_tests (void)
+{ SF_FORMAT_INFO format_info ;
+ SF_INFO sfinfo ;
+ const char *last_name ;
+ int k, count ;
+
+ print_test_name ("format_tests", "(null)") ;
+
+ /* Clear out SF_INFO struct and set channels > 0. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.channels = 1 ;
+
+ /* First test simple formats. */
+
+ sf_command (NULL, SFC_GET_SIMPLE_FORMAT_COUNT, &count, sizeof (int)) ;
+
+ if (count < 0 || count > 30)
+ { printf ("Line %d: Weird count.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ format_info.format = 0 ;
+ sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
+
+ last_name = format_info.name ;
+ for (k = 1 ; k < count ; k ++)
+ { format_info.format = k ;
+ sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
+ if (strcmp (last_name, format_info.name) >= 0)
+ { printf ("\n\nLine %d: format names out of sequence `%s' < `%s'.\n", __LINE__, last_name, format_info.name) ;
+ exit (1) ;
+ } ;
+ sfinfo.format = format_info.format ;
+
+ if (! sf_format_check (&sfinfo))
+ { printf ("\n\nLine %d: sf_format_check failed.\n", __LINE__) ;
+ printf (" Name : %s\n", format_info.name) ;
+ printf (" Format : 0x%X\n", sfinfo.format) ;
+ printf (" Channels : 0x%X\n", sfinfo.channels) ;
+ printf (" Sample Rate : 0x%X\n", sfinfo.samplerate) ;
+ exit (1) ;
+ } ;
+ last_name = format_info.name ;
+ } ;
+ format_info.format = 666 ;
+ sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
+
+ /* Now test major formats. */
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int)) ;
+
+ if (count < 0 || count > 30)
+ { printf ("Line %d: Weird count.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ format_info.format = 0 ;
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
+
+ last_name = format_info.name ;
+ for (k = 1 ; k < count ; k ++)
+ { format_info.format = k ;
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
+ if (strcmp (last_name, format_info.name) >= 0)
+ { printf ("\n\nLine %d: format names out of sequence (%d) `%s' < `%s'.\n", __LINE__, k, last_name, format_info.name) ;
+ exit (1) ;
+ } ;
+
+ last_name = format_info.name ;
+ } ;
+ format_info.format = 666 ;
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
+
+ /* Now test subtype formats. */
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ;
+
+ if (count < 0 || count > 30)
+ { printf ("Line %d: Weird count.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ format_info.format = 0 ;
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
+
+ last_name = format_info.name ;
+ for (k = 1 ; k < count ; k ++)
+ { format_info.format = k ;
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
+ } ;
+ format_info.format = 666 ;
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
+
+
+ printf ("ok\n") ;
+} /* format_tests */
+
+static void
+calc_peak_test (int filetype, const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, format ;
+ double peak ;
+
+ print_test_name ("calc_peak_test", filename) ;
+
+ format = (filetype | SF_FORMAT_PCM_16) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = format ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = BUFFER_LEN ;
+
+ /* Create double_data with max value of 0.5. */
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ double_data [k] = (k + 1) / (2.0 * BUFFER_LEN) ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("\n\nLine %d: Incorrect number of.frames in file. (%d => %ld)\n", __LINE__, BUFFER_LEN, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_CALC_SIGNAL_MAX, &peak, sizeof (peak)) ;
+ if (fabs (peak - (1 << 14)) > 1.0)
+ { printf ("Line %d : Peak value should be %d (is %f).\n", __LINE__, (1 << 14), peak) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_CALC_NORM_SIGNAL_MAX, &peak, sizeof (peak)) ;
+ if (fabs (peak - 0.5) > 4e-5)
+ { printf ("Line %d : Peak value should be %f (is %f).\n", __LINE__, 0.5, peak) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ format = (filetype | SF_FORMAT_FLOAT) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = format ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = BUFFER_LEN ;
+
+ /* Create double_data with max value of 0.5. */
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ double_data [k] = (k + 1) / (2.0 * BUFFER_LEN) ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("\n\nLine %d: Incorrect number of.frames in file. (%d => %ld)\n", __LINE__, BUFFER_LEN, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_CALC_SIGNAL_MAX, &peak, sizeof (peak)) ;
+ if (fabs (peak - 0.5) > 1e-5)
+ { printf ("Line %d : Peak value should be %f (is %f).\n", __LINE__, 0.5, peak) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_CALC_NORM_SIGNAL_MAX, &peak, sizeof (peak)) ;
+ if (fabs (peak - 0.5) > 1e-5)
+ { printf ("Line %d : Peak value should be %f (is %f).\n", __LINE__, 0.5, peak) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+
+ printf ("ok\n") ;
+} /* calc_peak_test */
+
+static void
+truncate_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t len ;
+
+ print_test_name ("truncate_test", filename) ;
+
+ sfinfo.samplerate = 11025 ;
+ sfinfo.format = filetype ;
+ sfinfo.channels = 2 ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, int_data, BUFFER_LEN, __LINE__) ;
+
+ len = 100 ;
+ if (sf_command (file, SFC_FILE_TRUNCATE, &len, sizeof (len)))
+ { printf ("Line %d: sf_command (SFC_FILE_TRUNCATE) returned error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, len, 2, __LINE__) ;
+ test_seek_or_die (file, 0, SEEK_END, len, 2, __LINE__) ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* truncate_test */
+
+/*------------------------------------------------------------------------------
+*/
+
+static void
+instrumet_rw_test (const char *filename)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+ SF_INSTRUMENT inst ;
+ memset (&sfinfo, 0, sizeof (SF_INFO)) ;
+
+ sndfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if (sf_command (sndfile, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) == SF_TRUE)
+ { inst.basenote = 22 ;
+
+ if (sf_command (sndfile, SFC_SET_INSTRUMENT, &inst, sizeof (inst)) == SF_TRUE)
+ printf ("Sucess: [%s] updated\n", filename) ;
+ else
+ printf ("Error: SFC_SET_INSTRUMENT on [%s] [%s]\n", filename, sf_strerror (sndfile)) ;
+ }
+ else
+ printf ("Error: SFC_GET_INSTRUMENT on [%s] [%s]\n", filename, sf_strerror (sndfile)) ;
+
+
+ if (sf_command (sndfile, SFC_UPDATE_HEADER_NOW, NULL, 0) != 0)
+ printf ("Error: SFC_UPDATE_HEADER_NOW on [%s] [%s]\n", filename, sf_strerror (sndfile)) ;
+
+ sf_write_sync (sndfile) ;
+ sf_close (sndfile) ;
+
+ return ;
+} /* instrumet_rw_test */
+
+static void
+instrument_test (const char *filename, int filetype)
+{ static SF_INSTRUMENT write_inst =
+ { 2, /* gain */
+ 3, /* detune */
+ 4, /* basenote */
+ 5, 6, /* key low and high */
+ 7, 8, /* velocity low and high */
+ 2, /* loop_count */
+ { { 801, 2, 3, 0 },
+ { 801, 3, 4, 0 },
+ }
+ } ;
+ SF_INSTRUMENT read_inst ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+
+ print_test_name ("instrument_test", filename) ;
+
+ sfinfo.samplerate = 11025 ;
+ sfinfo.format = filetype ;
+ sfinfo.channels = 1 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_SET_INSTRUMENT, &write_inst, sizeof (write_inst)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_INSTRUMENT) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&read_inst, 0, sizeof (read_inst)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_GET_INSTRUMENT, &read_inst, sizeof (read_inst)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_GET_INSTRUMENT) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ return ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)
+ { /*
+ ** For all the fields that WAV doesn't support, modify the
+ ** write_inst struct to hold the default value that the WAV
+ ** module should hold.
+ */
+ write_inst.detune = 0 ;
+ write_inst.key_lo = write_inst.velocity_lo = 0 ;
+ write_inst.key_hi = write_inst.velocity_hi = 127 ;
+ write_inst.gain = 1 ;
+ } ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_XI)
+ { /*
+ ** For all the fields that XI doesn't support, modify the
+ ** write_inst struct to hold the default value that the XI
+ ** module should hold.
+ */
+ write_inst.basenote = 0 ;
+ write_inst.detune = 0 ;
+ write_inst.key_lo = write_inst.velocity_lo = 0 ;
+ write_inst.key_hi = write_inst.velocity_hi = 127 ;
+ write_inst.gain = 1 ;
+ } ;
+
+ if (memcmp (&write_inst, &read_inst, sizeof (write_inst)) != 0)
+ { printf ("\n\nLine %d : instrument comparison failed.\n\n", __LINE__) ;
+ printf ("W Base Note : %u\n"
+ " Detune : %u\n"
+ " Low Note : %u\tHigh Note : %u\n"
+ " Low Vel. : %u\tHigh Vel. : %u\n"
+ " Gain : %d\tCount : %d\n"
+ " mode : %d\n"
+ " start : %d\tend : %d\tcount :%d\n"
+ " mode : %d\n"
+ " start : %d\tend : %d\tcount :%d\n\n",
+ write_inst.basenote,
+ write_inst.detune,
+ write_inst.key_lo, write_inst.key_hi,
+ write_inst.velocity_lo, write_inst.velocity_hi,
+ write_inst.gain, write_inst.loop_count,
+ write_inst.loops [0].mode, write_inst.loops [0].start,
+ write_inst.loops [0].end, write_inst.loops [0].count,
+ write_inst.loops [1].mode, write_inst.loops [1].start,
+ write_inst.loops [1].end, write_inst.loops [1].count) ;
+ printf ("R Base Note : %u\n"
+ " Detune : %u\n"
+ " Low Note : %u\tHigh Note : %u\n"
+ " Low Vel. : %u\tHigh Vel. : %u\n"
+ " Gain : %d\tCount : %d\n"
+ " mode : %d\n"
+ " start : %d\tend : %d\tcount :%d\n"
+ " mode : %d\n"
+ " start : %d\tend : %d\tcount :%d\n\n",
+ read_inst.basenote,
+ read_inst.detune,
+ read_inst.key_lo, read_inst.key_hi,
+ read_inst.velocity_lo, read_inst.velocity_hi,
+ read_inst.gain, read_inst.loop_count,
+ read_inst.loops [0].mode, read_inst.loops [0].start,
+ read_inst.loops [0].end, read_inst.loops [0].count,
+ read_inst.loops [1].mode, read_inst.loops [1].start,
+ read_inst.loops [1].end, read_inst.loops [1].count) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_XI)
+ exit (1) ;
+ } ;
+
+ if (0) instrumet_rw_test (filename) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* instrument_test */
+
+static void
+current_sf_info_test (const char *filename)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO outinfo, ininfo ;
+
+ print_test_name ("current_sf_info_test", filename) ;
+
+ outinfo.samplerate = 44100 ;
+ outinfo.format = (SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ outinfo.channels = 1 ;
+ outinfo.frames = 0 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &outinfo, SF_TRUE, __LINE__) ;
+ sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, 0) ;
+
+ exit_if_true (outinfo.frames != 0,
+ "\n\nLine %d : Initial sfinfo.frames is not zero.\n\n", __LINE__
+ ) ;
+
+ test_write_double_or_die (outfile, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_command (outfile, SFC_GET_CURRENT_SF_INFO, &outinfo, sizeof (outinfo)) ;
+
+ exit_if_true (outinfo.frames != BUFFER_LEN,
+ "\n\nLine %d : Initial sfinfo.frames (%ld) should be %d.\n\n", __LINE__,
+ SF_COUNT_TO_LONG (outinfo.frames), BUFFER_LEN
+ ) ;
+
+ /* Read file making sure no channel map exists. */
+ memset (&ininfo, 0, sizeof (ininfo)) ;
+ infile = test_open_file_or_die (filename, SFM_READ, &ininfo, SF_TRUE, __LINE__) ;
+
+ test_write_double_or_die (outfile, 0, double_data, BUFFER_LEN, __LINE__) ;
+
+ sf_command (infile, SFC_GET_CURRENT_SF_INFO, &ininfo, sizeof (ininfo)) ;
+
+ exit_if_true (ininfo.frames != BUFFER_LEN,
+ "\n\nLine %d : Initial sfinfo.frames (%ld) should be %d.\n\n", __LINE__,
+ SF_COUNT_TO_LONG (ininfo.frames), BUFFER_LEN
+ ) ;
+
+ sf_close (outfile) ;
+ sf_close (infile) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* current_sf_info_test */
+
+static void
+broadcast_test (const char *filename, int filetype)
+{ static SF_BROADCAST_INFO bc_write, bc_read ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int errors = 0 ;
+
+ print_test_name ("broadcast_test", filename) ;
+
+ sfinfo.samplerate = 11025 ;
+ sfinfo.format = filetype ;
+ sfinfo.channels = 1 ;
+
+ memset (&bc_write, 0, sizeof (bc_write)) ;
+
+ snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
+ snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
+ snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
+ snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
+ snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
+ snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
+ bc_write.coding_history_size = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&bc_read, 0, sizeof (bc_read)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_GET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ return ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ if (bc_read.version != 1)
+ { printf ("\n\nLine %d : Read bad version number %d.\n\n", __LINE__, bc_read.version) ;
+ exit (1) ;
+ return ;
+ } ;
+
+ bc_read.version = bc_write.version = 0 ;
+
+ if (memcmp (bc_write.description, bc_read.description, sizeof (bc_write.description)) != 0)
+ { printf ("\n\nLine %d : description mismatch :\n\twrite : '%s'\n\tread : '%s'\n\n", __LINE__, bc_write.description, bc_read.description) ;
+ errors ++ ;
+ } ;
+
+ if (memcmp (bc_write.originator, bc_read.originator, sizeof (bc_write.originator)) != 0)
+ { printf ("\n\nLine %d : originator mismatch :\n\twrite : '%s'\n\tread : '%s'\n\n", __LINE__, bc_write.originator, bc_read.originator) ;
+ errors ++ ;
+ } ;
+
+ if (memcmp (bc_write.originator_reference, bc_read.originator_reference, sizeof (bc_write.originator_reference)) != 0)
+ { printf ("\n\nLine %d : originator_reference mismatch :\n\twrite : '%s'\n\tread : '%s'\n\n", __LINE__, bc_write.originator_reference, bc_read.originator_reference) ;
+ errors ++ ;
+ } ;
+
+ if (memcmp (bc_write.origination_date, bc_read.origination_date, sizeof (bc_write.origination_date)) != 0)
+ { printf ("\n\nLine %d : origination_date mismatch :\n\twrite : '%s'\n\tread : '%s'\n\n", __LINE__, bc_write.origination_date, bc_read.origination_date) ;
+ errors ++ ;
+ } ;
+
+ if (memcmp (bc_write.origination_time, bc_read.origination_time, sizeof (bc_write.origination_time)) != 0)
+ { printf ("\n\nLine %d : origination_time mismatch :\n\twrite : '%s'\n\tread : '%s'\n\n", __LINE__, bc_write.origination_time, bc_read.origination_time) ;
+ errors ++ ;
+ } ;
+
+ if (memcmp (bc_write.umid, bc_read.umid, sizeof (bc_write.umid)) != 0)
+ { printf ("\n\nLine %d : umid mismatch :\n\twrite : '%s'\n\tread : '%s'\n\n", __LINE__, bc_write.umid, bc_read.umid) ;
+ errors ++ ;
+ } ;
+
+ if (errors)
+ exit (1) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* broadcast_test */
+
+static void
+broadcast_rdwr_test (const char *filename, int filetype)
+{ SF_BROADCAST_INFO binfo ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+
+ print_test_name (__func__, filename) ;
+
+ create_short_sndfile (filename, filetype, 2) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ memset (&binfo, 0, sizeof (binfo)) ;
+
+ snprintf (binfo.description, sizeof (binfo.description), "Test description") ;
+ snprintf (binfo.originator, sizeof (binfo.originator), "Test originator") ;
+ snprintf (binfo.originator_reference, sizeof (binfo.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
+ snprintf (binfo.origination_date, sizeof (binfo.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
+ snprintf (binfo.origination_time, sizeof (binfo.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
+ snprintf (binfo.umid, sizeof (binfo.umid), "Some umid") ;
+ binfo.coding_history_size = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+ frames = sfinfo.frames ;
+ if (sf_command (file, SFC_SET_BROADCAST_INFO, &binfo, sizeof (binfo)) != SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) should have failed but didn't.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (file) ;
+ exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %lld should be %lld.\n", __LINE__, sfinfo.frames, frames) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* broadcast_rdwr_test */
+
+static void
+check_coding_history_newlines (const char *filename)
+{ static SF_BROADCAST_INFO bc_write, bc_read ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k ;
+
+ sfinfo.samplerate = 22050 ;
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+
+ memset (&bc_write, 0, sizeof (bc_write)) ;
+
+ snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
+ snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
+ snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
+ snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
+ snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
+ snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
+ bc_write.coding_history_size = snprintf (bc_write.coding_history, sizeof (bc_write.coding_history), "This has\nUnix\nand\rMac OS9\rline endings.\nLast line") ; ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&bc_read, 0, sizeof (bc_read)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ if (bc_read.coding_history_size == 0)
+ { printf ("\n\nLine %d : missing coding history.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (strstr (bc_read.coding_history, "Last line") == NULL)
+ { printf ("\n\nLine %d : coding history truncated.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ for (k = 1 ; k < bc_read.coding_history_size ; k++)
+ { if (bc_read.coding_history [k] == '\n' && bc_read.coding_history [k - 1] != '\r')
+ { printf ("\n\nLine %d : '\\n' without '\\r' before.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (bc_read.coding_history [k] == '\r' && bc_read.coding_history [k + 1] != '\n')
+ { printf ("\n\nLine %d : '\\r' without '\\n' after.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (bc_read.coding_history [k] == 0 && k < bc_read.coding_history_size - 1)
+ { printf ("\n\nLine %d : '\\0' within coding history at index %d of %d.\n\n", __LINE__, k, bc_read.coding_history_size) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ return ;
+} /* check_coding_history_newlines */
+
+static void
+broadcast_coding_history_test (const char *filename)
+{ static SF_BROADCAST_INFO bc_write, bc_read ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ const char *default_history = "A=PCM,F=22050,W=16,M=mono" ;
+ const char *supplied_history =
+ "A=PCM,F=44100,W=24,M=mono,T=other\r\n"
+ "A=PCM,F=22050,W=16,M=mono,T=yet_another\r\n" ;
+
+ print_test_name ("broadcast_coding_history_test", filename) ;
+
+ sfinfo.samplerate = 22050 ;
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+
+ memset (&bc_write, 0, sizeof (bc_write)) ;
+
+ snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
+ snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
+ snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
+ snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
+ snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
+ snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
+ /* Coding history will be filled in by the library. */
+ bc_write.coding_history_size = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&bc_read, 0, sizeof (bc_read)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ if (bc_read.coding_history_size == 0)
+ { printf ("\n\nLine %d : missing coding history.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (bc_read.coding_history_size < strlen (default_history) || memcmp (bc_read.coding_history, default_history, strlen (default_history)) != 0)
+ { printf ("\n\n"
+ "Line %d : unexpected coding history '%.*s',\n"
+ " should be '%s'\n\n", __LINE__, bc_read.coding_history_size, bc_read.coding_history, default_history) ;
+ exit (1) ;
+ } ;
+
+ bc_write.coding_history_size = strlen (supplied_history) ;
+ bc_write.coding_history_size = snprintf (bc_write.coding_history, sizeof (bc_write.coding_history), "%s", supplied_history) ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&bc_read, 0, sizeof (bc_read)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ if (strstr (bc_read.coding_history, supplied_history) != bc_read.coding_history)
+ { printf ("\n\nLine %d : unexpected coding history :\n"
+ "----------------------------------------------------\n%s"
+ "----------------------------------------------------\n"
+ "should be this :\n"
+ "----------------------------------------------------\n%s"
+ "----------------------------------------------------\n"
+ "with one more line at the end.\n\n",
+ __LINE__, bc_read.coding_history, supplied_history) ;
+ exit (1) ;
+ } ;
+
+ check_coding_history_newlines (filename) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* broadcast_coding_history_test */
+
+/*==============================================================================
+*/
+
+static void
+broadcast_coding_history_size (const char *filename)
+{ /* SF_BROADCAST_INFO struct with coding_history field of 1024 bytes. */
+ static SF_BROADCAST_INFO_VAR (1024) bc_write ;
+ static SF_BROADCAST_INFO_VAR (1024) bc_read ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+
+ print_test_name (__func__, filename) ;
+
+ sfinfo.samplerate = 22050 ;
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+
+ memset (&bc_write, 0, sizeof (bc_write)) ;
+
+ snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
+ snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
+ snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
+ snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
+ snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
+ snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
+ bc_write.coding_history_size = 0 ;
+
+ for (k = 0 ; bc_write.coding_history_size < 512 ; k++)
+ { snprintf (bc_write.coding_history + bc_write.coding_history_size,
+ sizeof (bc_write.coding_history) - bc_write.coding_history_size, "line %4d\n", k) ;
+ bc_write.coding_history_size = strlen (bc_write.coding_history) ;
+ } ;
+
+ exit_if_true (bc_write.coding_history_size < 512,
+ "\n\nLine %d : bc_write.coding_history_size (%d) should be > 512.\n\n", __LINE__, bc_write.coding_history_size) ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&bc_read, 0, sizeof (bc_read)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
+ { printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ exit_if_true (bc_read.coding_history_size < 512,
+ "\n\nLine %d : unexpected coding history size %d (should be > 512).\n\n", __LINE__, bc_read.coding_history_size) ;
+
+ exit_if_true (strstr (bc_read.coding_history, "libsndfile") == NULL,
+ "\n\nLine %d : coding history incomplete (should contain 'libsndfile').\n\n", __LINE__) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* broadcast_coding_history_size */
+
+/*==============================================================================
+*/
+
+static void
+channel_map_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int channel_map_read [4], channel_map_write [4] =
+ { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE,
+ SF_CHANNEL_MAP_REAR_CENTER
+ } ;
+
+ print_test_name ("channel_map_test", filename) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 11025 ;
+ sfinfo.format = filetype ;
+ sfinfo.channels = ARRAY_LEN (channel_map_read) ;
+
+ switch (filetype & SF_FORMAT_TYPEMASK)
+ { /* WAVEX and RF64 have a default channel map, even if you don't specify one. */
+ case SF_FORMAT_WAVEX :
+ case SF_FORMAT_RF64 :
+ /* Write file without channel map. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ /* Read file making default channel map exists. */
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ exit_if_true (
+ sf_command (file, SFC_GET_CHANNEL_MAP_INFO, channel_map_read, sizeof (channel_map_read)) == SF_FALSE,
+ "\n\nLine %d : sf_command (SFC_GET_CHANNEL_MAP_INFO) should not have failed.\n\n", __LINE__
+ ) ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+ break ;
+
+ default :
+ break ;
+ } ;
+
+ /* Write file with a channel map. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ exit_if_true (
+ sf_command (file, SFC_SET_CHANNEL_MAP_INFO, channel_map_write, sizeof (channel_map_write)) == SF_FALSE,
+ "\n\nLine %d : sf_command (SFC_SET_CHANNEL_MAP_INFO) failed.\n\n", __LINE__
+ ) ;
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ /* Read file making sure no channel map exists. */
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ exit_if_true (
+ sf_command (file, SFC_GET_CHANNEL_MAP_INFO, channel_map_read, sizeof (channel_map_read)) != SF_TRUE,
+ "\n\nLine %d : sf_command (SFC_GET_CHANNEL_MAP_INFO) failed.\n\n", __LINE__
+ ) ;
+ check_log_buffer_or_die (file, __LINE__) ;
+ sf_close (file) ;
+
+ exit_if_true (
+ memcmp (channel_map_read, channel_map_write, sizeof (channel_map_read)) != 0,
+ "\n\nLine %d : Channel map read does not match channel map written.\n\n", __LINE__
+ ) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* channel_map_test */
+
+static void
+raw_needs_endswap_test (const char *filename, int filetype)
+{ static int subtypes [] =
+ { SF_FORMAT_FLOAT, SF_FORMAT_DOUBLE,
+ SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
+ } ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k ;
+ int needs_endswap ;
+
+ print_test_name (__func__, filename) ;
+
+ for (k = 0 ; k < ARRAY_LEN (subtypes) ; k++)
+ {
+ if (filetype == (SF_ENDIAN_LITTLE | SF_FORMAT_AIFF))
+ switch (subtypes [k])
+ { /* Little endian AIFF does not AFAIK support fl32 and fl64. */
+ case SF_FORMAT_FLOAT :
+ case SF_FORMAT_DOUBLE :
+ continue ;
+ default :
+ break ;
+ } ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 11025 ;
+ sfinfo.format = filetype | subtypes [k] ;
+ sfinfo.channels = 1 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ needs_endswap = sf_command (file, SFC_RAW_DATA_NEEDS_ENDSWAP, NULL, 0) ;
+
+ switch (filetype)
+ { case SF_FORMAT_WAV :
+ case SF_FORMAT_WAVEX :
+ case SF_FORMAT_AIFF | SF_ENDIAN_LITTLE :
+ exit_if_true (needs_endswap != CPU_IS_BIG_ENDIAN,
+ "\n\nLine %d : SFC_RAW_DATA_NEEDS_ENDSWAP failed for (%d | %d).\n\n", __LINE__, filetype, k) ;
+ break ;
+
+ case SF_FORMAT_AIFF :
+ case SF_FORMAT_WAV | SF_ENDIAN_BIG :
+ exit_if_true (needs_endswap != CPU_IS_LITTLE_ENDIAN,
+ "\n\nLine %d : SFC_RAW_DATA_NEEDS_ENDSWAP failed for (%d | %d).\n\n", __LINE__, filetype, k) ;
+ break ;
+
+ default :
+ printf ("\n\nLine %d : bad format value %d.\n\n", __LINE__, filetype) ;
+ exit (1) ;
+ break ;
+ } ;
+
+ sf_close (file) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* raw_needs_endswap_test */
diff --git a/tests/cpp_test.cc b/tests/cpp_test.cc
new file mode 100644
index 0000000..752f00e
--- /dev/null
+++ b/tests/cpp_test.cc
@@ -0,0 +1,313 @@
+/*
+** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <sndfile.hh>
+
+#include "utils.h"
+
+static short sbuffer [100] ;
+static int ibuffer [100] ;
+static float fbuffer [100] ;
+static double dbuffer [100] ;
+
+static void
+ceeplusplus_wchar_test (void)
+{
+#if 0
+ LPCWSTR filename = L"wchar_test.wav" ;
+
+ print_test_name (__func__, "ceeplusplus_wchar_test.wav") ;
+
+ /* Use this scope to make sure the created file is closed. */
+ {
+ SndfileHandle file (filename, SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 2, 44100) ;
+
+ if (file.refCount () != 1)
+ { printf ("\n\n%s %d : Error : Reference count (%d) should be 1.\n\n", __func__, __LINE__, file.refCount ()) ;
+ exit (1) ;
+ } ;
+
+ /* This should check that the file did in fact get created with a
+ ** wchar_t * filename.
+ */
+ exit_if_true (
+ GetFileAttributesW (filename) == INVALID_FILE_ATTRIBUTES,
+ "\n\nLine %d : GetFileAttributes failed.\n\n", __LINE__
+ ) ;
+ }
+
+ /* Use this because the file was created with CreateFileW. */
+ DeleteFileW (filename) ;
+
+ puts ("ok") ;
+#endif
+} /* ceeplusplus_wchar_test */
+
+
+
+static void
+create_file (const char * filename, int format)
+{ SndfileHandle file ;
+
+ if (file.refCount () != 0)
+ { printf ("\n\n%s %d : Error : Reference count (%d) should be zero.\n\n", __func__, __LINE__, file.refCount ()) ;
+ exit (1) ;
+ } ;
+
+ file = SndfileHandle (filename, SFM_WRITE, format, 2, 48000) ;
+
+ if (file.refCount () != 1)
+ { printf ("\n\n%s %d : Error : Reference count (%d) should be 1.\n\n", __func__, __LINE__, file.refCount ()) ;
+ exit (1) ;
+ } ;
+
+ file.setString (SF_STR_TITLE, filename) ;
+
+ /* Item write. */
+ file.write (sbuffer, ARRAY_LEN (sbuffer)) ;
+ file.write (ibuffer, ARRAY_LEN (ibuffer)) ;
+ file.write (fbuffer, ARRAY_LEN (fbuffer)) ;
+ file.write (dbuffer, ARRAY_LEN (dbuffer)) ;
+
+ /* Frame write. */
+ file.writef (sbuffer, ARRAY_LEN (sbuffer) / file.channels ()) ;
+ file.writef (ibuffer, ARRAY_LEN (ibuffer) / file.channels ()) ;
+ file.writef (fbuffer, ARRAY_LEN (fbuffer) / file.channels ()) ;
+ file.writef (dbuffer, ARRAY_LEN (dbuffer) / file.channels ()) ;
+
+ /* RAII takes care of the SndfileHandle. */
+} /* create_file */
+
+static void
+check_title (const SndfileHandle & file, const char * filename)
+{ const char *title = NULL ;
+
+ title = file.getString (SF_STR_TITLE) ;
+
+ if (title == NULL)
+ { printf ("\n\n%s %d : Error : No title.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (strcmp (filename, title) != 0)
+ { printf ("\n\n%s %d : Error : title '%s' should be '%s'\n\n", __func__, __LINE__, title, filename) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* check_title */
+
+static void
+read_file (const char * filename, int format)
+{ SndfileHandle file ;
+ sf_count_t count ;
+
+ if (file)
+ { printf ("\n\n%s %d : Error : should not be here.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ file = SndfileHandle (filename) ;
+
+ if (1)
+ { SndfileHandle file2 = file ;
+
+ if (file.refCount () != 2 || file2.refCount () != 2)
+ { printf ("\n\n%s %d : Error : Reference count (%d) should be two.\n\n", __func__, __LINE__, file.refCount ()) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ if (file.refCount () != 1)
+ { printf ("\n\n%s %d : Error : Reference count (%d) should be one.\n\n", __func__, __LINE__, file.refCount ()) ;
+ exit (1) ;
+ } ;
+
+ if (! file)
+ { printf ("\n\n%s %d : Error : should not be here.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (file.format () != format)
+ { printf ("\n\n%s %d : Error : format 0x%08x should be 0x%08x.\n\n", __func__, __LINE__, file.format (), format) ;
+ exit (1) ;
+ } ;
+
+ if (file.channels () != 2)
+ { printf ("\n\n%s %d : Error : channels %d should be 2.\n\n", __func__, __LINE__, file.channels ()) ;
+ exit (1) ;
+ } ;
+
+ if (file.frames () != ARRAY_LEN (sbuffer) * 4)
+ { printf ("\n\n%s %d : Error : frames %ld should be %lu.\n\n", __func__, __LINE__,
+ SF_COUNT_TO_LONG (file.frames ()), (long unsigned int) ARRAY_LEN (sbuffer) * 4 / 2) ;
+ exit (1) ;
+ } ;
+
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_AU :
+ break ;
+
+ default :
+ check_title (file, filename) ;
+ break ;
+ } ;
+
+ /* Item read. */
+ file.read (sbuffer, ARRAY_LEN (sbuffer)) ;
+ file.read (ibuffer, ARRAY_LEN (ibuffer)) ;
+ file.read (fbuffer, ARRAY_LEN (fbuffer)) ;
+ file.read (dbuffer, ARRAY_LEN (dbuffer)) ;
+
+ /* Frame read. */
+ file.readf (sbuffer, ARRAY_LEN (sbuffer) / file.channels ()) ;
+ file.readf (ibuffer, ARRAY_LEN (ibuffer) / file.channels ()) ;
+ file.readf (fbuffer, ARRAY_LEN (fbuffer) / file.channels ()) ;
+ file.readf (dbuffer, ARRAY_LEN (dbuffer) / file.channels ()) ;
+
+ count = file.seek (file.frames () - 10, SEEK_SET) ;
+ if (count != file.frames () - 10)
+ { printf ("\n\n%s %d : Error : offset (%ld) should be %ld\n\n", __func__, __LINE__,
+ SF_COUNT_TO_LONG (count), SF_COUNT_TO_LONG (file.frames () - 10)) ;
+ exit (1) ;
+ } ;
+
+ count = file.read (sbuffer, ARRAY_LEN (sbuffer)) ;
+ if (count != 10 * file.channels ())
+ { printf ("\n\n%s %d : Error : count (%ld) should be %ld\n\n", __func__, __LINE__,
+ SF_COUNT_TO_LONG (count), SF_COUNT_TO_LONG (10 * file.channels ())) ;
+ exit (1) ;
+ } ;
+
+ /* RAII takes care of the SndfileHandle. */
+} /* read_file */
+
+static void
+ceeplusplus_test (const char *filename, int format)
+{
+ print_test_name ("ceeplusplus_test", filename) ;
+
+ create_file (filename, format) ;
+ read_file (filename, format) ;
+
+ remove (filename) ;
+ puts ("ok") ;
+} /* ceeplusplus_test */
+
+static void
+ceeplusplus_extra_test (void)
+{ SndfileHandle file ;
+ const char * filename = "bad_file_name.wav" ;
+ int error ;
+
+ print_test_name ("ceeplusplus_extra_test", filename) ;
+
+ file = SndfileHandle (filename) ;
+
+ error = file.error () ;
+ if (error == 0)
+ { printf ("\n\n%s %d : error should be zero.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (file.strError () == NULL)
+ { printf ("\n\n%s %d : strError should not return NULL.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (file.seek (0, SEEK_SET) != 0)
+ { printf ("\n\n%s %d : bad seek ().\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ puts ("ok") ;
+} /* ceeplusplus_extra_test */
+
+
+static void
+ceeplusplus_rawhandle_test (const char *filename)
+{
+ SNDFILE* handle ;
+ {
+ SndfileHandle file (filename) ;
+ handle = file.rawHandle () ;
+ sf_read_float (handle, fbuffer, ARRAY_LEN (fbuffer)) ;
+ }
+} /* ceeplusplus_rawhandle_test */
+
+static void
+ceeplusplus_takeOwnership_test (const char *filename)
+{
+ SNDFILE* handle ;
+ {
+ SndfileHandle file (filename) ;
+ handle = file.takeOwnership () ;
+ }
+
+ if (sf_read_float (handle, fbuffer, ARRAY_LEN (fbuffer)) <= 0)
+ { printf ("\n\n%s %d : error when taking ownership of handle.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ }
+
+ if (sf_close (handle) != 0)
+ { printf ("\n\n%s %d : cannot close file.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ }
+
+ SndfileHandle file (filename) ;
+ SndfileHandle file2 (file) ;
+
+ if (file2.takeOwnership ())
+ { printf ("\n\n%s %d : taking ownership of shared handle is not allowed.\n\n", __func__, __LINE__) ;
+ exit (1) ;
+ }
+} /* ceeplusplus_takeOwnership_test */
+
+static void
+ceeplusplus_handle_test (const char *filename, int format)
+{
+ print_test_name ("ceeplusplus_handle_test", filename) ;
+
+ create_file (filename, format) ;
+
+ if (0) ceeplusplus_rawhandle_test (filename) ;
+ ceeplusplus_takeOwnership_test (filename) ;
+
+ remove (filename) ;
+ puts ("ok") ;
+} /* ceeplusplus_test */
+
+int
+main (void)
+{
+ ceeplusplus_test ("cpp_test.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ ceeplusplus_test ("cpp_test.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_S8) ;
+ ceeplusplus_test ("cpp_test.au", SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+
+ ceeplusplus_extra_test () ;
+ ceeplusplus_handle_test ("cpp_test.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+
+ ceeplusplus_wchar_test () ;
+
+ return 0 ;
+} /* main */
+
diff --git a/tests/dft_cmp.c b/tests/dft_cmp.c
new file mode 100644
index 0000000..c902769
--- /dev/null
+++ b/tests/dft_cmp.c
@@ -0,0 +1,149 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "dft_cmp.h"
+#include "utils.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+#define DFT_SPEC_LENGTH (DFT_DATA_LENGTH / 2)
+
+static void dft_magnitude (const double *data, double *spectrum) ;
+static double calc_max_spectral_difference (const double *spec1, const double *spec2) ;
+
+/*--------------------------------------------------------------------------------
+** Public functions.
+*/
+
+double
+dft_cmp_float (int linenum, const float *in_data, const float *test_data, int len, double target_snr, int allow_exit)
+{ static double orig [DFT_DATA_LENGTH] ;
+ static double test [DFT_DATA_LENGTH] ;
+ unsigned k ;
+
+ if (len != DFT_DATA_LENGTH)
+ { printf ("Error (line %d) : dft_cmp_float : Bad input array length.\n", linenum) ;
+ return 1 ;
+ } ;
+
+ for (k = 0 ; k < ARRAY_LEN (orig) ; k++)
+ { test [k] = test_data [k] ;
+ orig [k] = in_data [k] ;
+ } ;
+
+ return dft_cmp_double (linenum, orig, test, len, target_snr, allow_exit) ;
+} /* dft_cmp_float */
+
+double
+dft_cmp_double (int linenum, const double *orig, const double *test, int len, double target_snr, int allow_exit)
+{ static double orig_spec [DFT_SPEC_LENGTH] ;
+ static double test_spec [DFT_SPEC_LENGTH] ;
+ double snr ;
+
+ if (! orig || ! test)
+ { printf ("Error (line %d) : dft_cmp_double : Bad input arrays.\n", linenum) ;
+ return 1 ;
+ } ;
+
+ if (len != DFT_DATA_LENGTH)
+ { printf ("Error (line %d) : dft_cmp_double : Bad input array length.\n", linenum) ;
+ return 1 ;
+ } ;
+
+ dft_magnitude (orig, orig_spec) ;
+ dft_magnitude (test, test_spec) ;
+
+ snr = calc_max_spectral_difference (orig_spec, test_spec) ;
+
+ if (snr > target_snr)
+ { printf ("\n\nLine %d: Actual SNR (% 4.1f) > target SNR (% 4.1f).\n\n", linenum, snr, target_snr) ;
+ oct_save_double (orig, test, len) ;
+ if (allow_exit)
+ exit (1) ;
+ } ;
+
+ if (snr < -500.0)
+ snr = -500.0 ;
+
+ return snr ;
+} /* dft_cmp_double */
+
+/*--------------------------------------------------------------------------------
+** Quick dirty calculation of magnitude spectrum for real valued data using
+** Discrete Fourier Transform. Since the data is real, the DFT is only
+** calculated for positive frequencies.
+*/
+
+static void
+dft_magnitude (const double *data, double *spectrum)
+{ static double cos_angle [DFT_DATA_LENGTH] = { 0.0 } ;
+ static double sin_angle [DFT_DATA_LENGTH] ;
+
+ double real_part, imag_part ;
+ int k, n ;
+
+ /* If sine and cosine tables haven't been initialised, do so. */
+ if (cos_angle [0] == 0.0)
+ for (n = 0 ; n < DFT_DATA_LENGTH ; n++)
+ { cos_angle [n] = cos (2.0 * M_PI * n / DFT_DATA_LENGTH) ;
+ sin_angle [n] = -1.0 * sin (2.0 * M_PI * n / DFT_DATA_LENGTH) ;
+ } ;
+
+ /* DFT proper. Since the data is real, only generate a half spectrum. */
+ for (k = 1 ; k < DFT_SPEC_LENGTH ; k++)
+ { real_part = 0.0 ;
+ imag_part = 0.0 ;
+
+ for (n = 0 ; n < DFT_DATA_LENGTH ; n++)
+ { real_part += data [n] * cos_angle [(k * n) % DFT_DATA_LENGTH] ;
+ imag_part += data [n] * sin_angle [(k * n) % DFT_DATA_LENGTH] ;
+ } ;
+
+ spectrum [k] = sqrt (real_part * real_part + imag_part * imag_part) ;
+ } ;
+
+ spectrum [k] = 0.0 ;
+
+ spectrum [0] = spectrum [1] = spectrum [2] = spectrum [3] = spectrum [4] = 0.0 ;
+
+ return ;
+} /* dft_magnitude */
+
+static double
+calc_max_spectral_difference (const double *orig, const double *test)
+{ double orig_max = 0.0, max_diff = 0.0 ;
+ int k ;
+
+ for (k = 0 ; k < DFT_SPEC_LENGTH ; k++)
+ { if (orig_max < orig [k])
+ orig_max = orig [k] ;
+ if (max_diff < fabs (orig [k] - test [k]))
+ max_diff = fabs (orig [k] - test [k]) ;
+ } ;
+
+ if (max_diff < 1e-25)
+ return -500.0 ;
+
+ return 20.0 * log10 (max_diff / orig_max) ;
+} /* calc_max_spectral_difference */
diff --git a/tests/dft_cmp.h b/tests/dft_cmp.h
new file mode 100644
index 0000000..3cbdd11
--- /dev/null
+++ b/tests/dft_cmp.h
@@ -0,0 +1,25 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#define DFT_DATA_LENGTH (2048)
+
+double dft_cmp_float (int linenum, const float *orig, const float *test, int len, double tolerance, int allow_exit) ;
+
+double dft_cmp_double (int linenum, const double *orig, const double *test, int len, double tolerance, int allow_exit) ;
+
diff --git a/tests/dither_test.c b/tests/dither_test.c
new file mode 100644
index 0000000..6c570ff
--- /dev/null
+++ b/tests/dither_test.c
@@ -0,0 +1,182 @@
+/*
+** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<16)
+#define LOG_BUFFER_SIZE 1024
+
+static void dither_test (const char *filename, int filetype) ;
+
+/* Force the start of this buffer to be double aligned. Sparc-solaris will
+** choke if its not.
+*/
+static short data_out [BUFFER_LEN] ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file peak chunk\n") ;
+ printf (" aiff - test AIFF file PEAK chunk\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all=!strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { dither_test ("dither.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { dither_test ("dither.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { dither_test ("dither.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { dither_test ("dither.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { dither_test ("dither.nist", SF_FORMAT_NIST | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { dither_test ("dither.paf", SF_FORMAT_PAF | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { dither_test ("dither.ircam", SF_FORMAT_IRCAM | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { dither_test ("dither.voc", SF_FORMAT_VOC | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { dither_test ("dither.w64", SF_FORMAT_W64 | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { dither_test ("dither.mat4", SF_FORMAT_MAT4 | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { dither_test ("dither.mat5", SF_FORMAT_MAT5 | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { dither_test ("dither.pvf", SF_FORMAT_PVF | SF_FORMAT_PCM_S8) ;
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+dither_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ SF_DITHER_INFO dither ;
+
+ filetype = filetype ;
+
+ print_test_name ("dither_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = filetype ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /* Check for old version of the dither API. */
+ if (sf_command (file, SFC_SET_DITHER_ON_WRITE, NULL, SF_TRUE) == 0)
+ { printf ("\n\nLine %d: Should have an error here but don't.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ memset (&dither, 0, sizeof (dither)) ;
+ dither.type = SFD_WHITE ;
+ dither.level = 0 ;
+
+ if (sf_command (file, SFC_SET_DITHER_ON_WRITE, &dither, sizeof (dither)) != 0)
+ { printf ("\n\nLine %d: sf_command (SFC_SET_DITHER_ON_WRITE) returned error : %s\n\n",
+ __LINE__, sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Write data to file. */
+ test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("\n\nLine %d: Bad frame count %d (should be %d)\n\n", __LINE__, (int) sfinfo.frames, BUFFER_LEN) ;
+ } ;
+
+ sf_close (file) ;
+ /*-unlink (filename) ;-*/
+
+ puts ("ok") ;
+} /* dither_test */
+
diff --git a/tests/dwvw_test.c b/tests/dwvw_test.c
new file mode 100644
index 0000000..2bd11d1
--- /dev/null
+++ b/tests/dwvw_test.c
@@ -0,0 +1,109 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (10000)
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+static void dwvw_test (const char *filename, int format, int bit_width) ;
+
+int
+main (void)
+{
+ dwvw_test ("dwvw12.raw", SF_FORMAT_RAW | SF_FORMAT_DWVW_12, 12) ;
+ dwvw_test ("dwvw16.raw", SF_FORMAT_RAW | SF_FORMAT_DWVW_16, 16) ;
+ dwvw_test ("dwvw24.raw", SF_FORMAT_RAW | SF_FORMAT_DWVW_24, 24) ;
+
+ return 0 ;
+} /* main */
+
+static void
+dwvw_test (const char *filename, int format, int bit_width)
+{ static int write_buf [BUFFER_SIZE] ;
+ static int read_buf [BUFFER_SIZE] ;
+
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double value ;
+ int k, bit_mask ;
+
+ srand (123456) ;
+
+ /* Only want to grab the top bit_width bits. */
+ bit_mask = (-1 << (32 - bit_width)) ;
+
+ print_test_name ("dwvw_test", filename) ;
+
+ sf_info_setup (&sfinfo, format, 44100, 1) ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /* Generate random.frames. */
+ for (k = 0 ; k < BUFFER_SIZE / 2 ; k++)
+ { value = 0x7FFFFFFF * sin (123.0 / sfinfo.samplerate * 2 * k * M_PI) ;
+ write_buf [k] = bit_mask & lrint (value) ;
+ } ;
+
+ for ( ; k < BUFFER_SIZE ; k++)
+ write_buf [k] = bit_mask & ((rand () << 11) ^ (rand () >> 11)) ;
+
+ sf_write_int (file, write_buf, BUFFER_SIZE) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if ((k = sf_read_int (file, read_buf, BUFFER_SIZE)) != BUFFER_SIZE)
+ { printf ("Error (line %d) : Only read %d/%d.frames.\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ }
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ { if (read_buf [k] != write_buf [k])
+ { printf ("Error (line %d) : %d != %d at position %d/%d\n", __LINE__,
+ write_buf [k] >> (32 - bit_width), read_buf [k] >> (32 - bit_width),
+ k, BUFFER_SIZE) ;
+ oct_save_int (write_buf, read_buf, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+
+ return ;
+} /* dwvw_test */
+
diff --git a/tests/error_test.c b/tests/error_test.c
new file mode 100644
index 0000000..9df14b8
--- /dev/null
+++ b/tests/error_test.c
@@ -0,0 +1,246 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if OS_IS_WIN32
+#include <windows.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (1<<15)
+#define SHORT_BUFFER (256)
+
+static void
+error_number_test (void)
+{ const char *noerror, *errstr ;
+ int k ;
+
+ print_test_name ("error_number_test", "") ;
+
+ noerror = sf_error_number (0) ;
+
+ for (k = 1 ; k < 300 ; k++)
+ { errstr = sf_error_number (k) ;
+
+ /* Test for termination condition. */
+ if (errstr == noerror)
+ break ;
+
+ /* Test for error. */
+ if (strstr (errstr, "This is a bug in libsndfile."))
+ { printf ("\n\nError : error number %d : %s\n\n\n", k, errstr) ;
+ exit (1) ;
+ } ;
+ } ;
+
+
+ puts ("ok") ;
+ return ;
+} /* error_number_test */
+
+static void
+error_value_test (void)
+{ static unsigned char aiff_data [0x1b0] =
+ { 'F' , 'O' , 'R' , 'M' ,
+ 0x00, 0x00, 0x01, 0xA8, /* FORM length */
+
+ 'A' , 'I' , 'F' , 'C' ,
+ } ;
+
+ const char *filename = "error.aiff" ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int error_num ;
+
+ print_test_name ("error_value_test", filename) ;
+
+ dump_data_to_file (filename, aiff_data, sizeof (aiff_data)) ;
+
+ file = sf_open (filename, SFM_READ, &sfinfo) ;
+ if (file != NULL)
+ { printf ("\n\nLine %d : Should not have been able to open this file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((error_num = sf_error (NULL)) <= 1 || error_num > 300)
+ { printf ("\n\nLine %d : Should not have had an error number of %d.\n\n", __LINE__, error_num) ;
+ exit (1) ;
+ } ;
+
+ remove (filename) ;
+ puts ("ok") ;
+ return ;
+} /* error_value_test */
+
+static void
+no_file_test (const char * filename)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+
+ print_test_name (__func__, filename) ;
+
+ unlink (filename) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
+
+ exit_if_true (sndfile != NULL, "\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* no_file_test */
+
+static void
+zero_length_test (const char *filename)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+ FILE *file ;
+
+ print_test_name (__func__, filename) ;
+
+ /* Create a zero length file. */
+ file = fopen (filename, "w") ;
+ exit_if_true (file == NULL, "\n\nLine %d : fopen ('%s') failed.\n", __LINE__, filename) ;
+ fclose (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
+
+ exit_if_true (sndfile != NULL, "\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ;
+
+ exit_if_true (0 && sf_error (NULL) != SF_ERR_UNRECOGNISED_FORMAT,
+ "\n\nLine %3d : Error : %s\n should be : %s\n", __LINE__,
+ sf_strerror (NULL), sf_error_number (SF_ERR_UNRECOGNISED_FORMAT)) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* zero_length_test */
+
+static void
+bad_wav_test (const char * filename)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+
+ FILE *file ;
+ const char data [] = "RIFF WAVEfmt " ;
+
+ print_test_name (__func__, filename) ;
+
+ if ((file = fopen (filename, "w")) == NULL)
+ { printf ("\n\nLine %d : fopen returned NULL.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ exit_if_true (fwrite (data, sizeof (data), 1, file) != 1, "\n\nLine %d : fwrite failed.\n", __LINE__) ;
+ fclose (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
+
+ if (sndfile)
+ { printf ("\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* bad_wav_test */
+
+static void
+error_close_test (void)
+{ static short buffer [SHORT_BUFFER] ;
+ const char *filename = "error_close.wav" ;
+ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+ FILE *file ;
+
+ print_test_name (__func__, filename) ;
+
+ /* Open a FILE* from which we will extract a file descriptor. */
+ if ((file = fopen (filename, "w")) == NULL)
+ { printf ("\n\nLine %d : fopen returned NULL.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Set parameters for writing the file. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+
+ sndfile = sf_open_fd (fileno (file), SFM_WRITE, &sfinfo, SF_TRUE) ;
+ if (sndfile == NULL)
+ { printf ("\n\nLine %d : sf_open_fd failed : %s\n", __LINE__, sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ test_write_short_or_die (sndfile, 0, buffer, ARRAY_LEN (buffer), __LINE__) ;
+
+ /* Now close the fd associated with file before calling sf_close. */
+ fclose (file) ;
+
+ if (sf_close (sndfile) == 0)
+ {
+#if OS_IS_WIN32
+ OSVERSIONINFOEX osvi ;
+
+ memset (&osvi, 0, sizeof (OSVERSIONINFOEX)) ;
+ osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX) ;
+
+ if (GetVersionEx ((OSVERSIONINFO *) &osvi))
+ { printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ;
+ printf ("\nHowever, this is a known bug in version %d.%d of windows so we'll ignore it.\n\n",
+ (int) osvi.dwMajorVersion, (int) osvi.dwMinorVersion) ;
+ } ;
+#else
+ printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ;
+ exit (1) ;
+#endif
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* error_close_test */
+
+int
+main (void)
+{
+ error_number_test () ;
+ error_value_test () ;
+
+ error_close_test () ;
+
+ no_file_test ("no_file.wav") ;
+ zero_length_test ("zero_length.wav") ;
+ bad_wav_test ("bad_wav.wav") ;
+
+ return 0 ;
+} /* main */
+
diff --git a/tests/external_libs_test.c b/tests/external_libs_test.c
new file mode 100644
index 0000000..86b0290
--- /dev/null
+++ b/tests/external_libs_test.c
@@ -0,0 +1,149 @@
+/*
+** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation ; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+static void major_format_test (void) ;
+static void subtype_format_test (void) ;
+static void simple_format_test (void) ;
+
+int
+main (void)
+{
+ major_format_test () ;
+ subtype_format_test () ;
+ simple_format_test () ;
+
+ return 0 ;
+} /* main */
+
+static void
+major_format_test (void)
+{ SF_FORMAT_INFO info ;
+ int have_ogg = 0, have_flac = 0 ;
+ int m, major_count ;
+
+ print_test_name (__func__, NULL) ;
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)) ;
+
+ for (m = 0 ; m < major_count ; m++)
+ { info.format = m ;
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof (info)) ;
+
+ have_flac = info.format == SF_FORMAT_FLAC ? 1 : have_flac ;
+ have_ogg = info.format == SF_FORMAT_OGG ? 1 : have_ogg ;
+ } ;
+
+ if (HAVE_EXTERNAL_LIBS)
+ { exit_if_true (have_flac == 0, "\n\nLine %d : FLAC should be available.\n\n", __LINE__) ;
+ exit_if_true (have_ogg == 0, "\n\nLine %d : Ogg/Vorbis should be available.\n\n", __LINE__) ;
+ }
+ else
+ { exit_if_true (have_flac, "\n\nLine %d : FLAC should not be available.\n\n", __LINE__) ;
+ exit_if_true (have_ogg, "\n\nLine %d : Ogg/Vorbis should not be available.\n\n", __LINE__) ;
+ } ;
+
+ puts ("ok") ;
+} /* major_format_test */
+
+static void
+subtype_format_test (void)
+{ SF_FORMAT_INFO info ;
+ int have_vorbis = 0 ;
+ int s, subtype_count ;
+
+ print_test_name (__func__, NULL) ;
+
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &subtype_count, sizeof (int)) ;
+
+ for (s = 0 ; s < subtype_count ; s++)
+ { info.format = s ;
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &info, sizeof (info)) ;
+
+ have_vorbis = info.format == SF_FORMAT_VORBIS ? 1 : have_vorbis ;
+ } ;
+
+ if (HAVE_EXTERNAL_LIBS)
+ exit_if_true (have_vorbis == 0, "\n\nLine %d : Ogg/Vorbis should be available.\n\n", __LINE__) ;
+ else
+ exit_if_true (have_vorbis, "\n\nLine %d : Ogg/Vorbis should not be available.\n\n", __LINE__) ;
+
+ puts ("ok") ;
+} /* subtype_format_test */
+
+static void
+simple_format_test (void)
+{ SF_FORMAT_INFO info ;
+ int have_flac = 0, have_ogg = 0, have_vorbis = 0 ;
+ int s, simple_count ;
+
+ print_test_name (__func__, NULL) ;
+
+ sf_command (NULL, SFC_GET_SIMPLE_FORMAT_COUNT, &simple_count, sizeof (int)) ;
+
+ for (s = 0 ; s < simple_count ; s++)
+ { info.format = s ;
+ sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &info, sizeof (info)) ;
+
+ switch (info.format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_FLAC :
+ have_flac = 1 ;
+ break ;
+
+ case SF_FORMAT_OGG :
+ have_ogg = 1 ;
+ break ;
+
+ default :
+ break ;
+ } ;
+
+ switch (info.format & SF_FORMAT_SUBMASK)
+ { case SF_FORMAT_VORBIS :
+ have_vorbis = 1 ;
+ break ;
+
+ default :
+ break ;
+ } ;
+
+ } ;
+
+ if (HAVE_EXTERNAL_LIBS)
+ { exit_if_true (have_flac == 0, "\n\nLine %d : FLAC should be available.\n\n", __LINE__) ;
+ exit_if_true (have_ogg == 0, "\n\nLine %d : Ogg/Vorbis should be available.\n\n", __LINE__) ;
+ exit_if_true (have_vorbis == 0, "\n\nLine %d : Ogg/Vorbis should be available.\n\n", __LINE__) ;
+ }
+ else
+ { exit_if_true (have_flac, "\n\nLine %d : FLAC should not be available.\n\n", __LINE__) ;
+ exit_if_true (have_ogg, "\n\nLine %d : Ogg/Vorbis should not be available.\n\n", __LINE__) ;
+ exit_if_true (have_vorbis, "\n\nLine %d : Ogg/Vorbis should not be available.\n\n", __LINE__) ;
+ } ;
+
+ puts ("ok") ;
+} /* simple_format_test */
diff --git a/tests/fix_this.c b/tests/fix_this.c
new file mode 100644
index 0000000..8eabad2
--- /dev/null
+++ b/tests/fix_this.c
@@ -0,0 +1,326 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (1<<14) /* Should be (1<<14) */
+#define SAMPLE_RATE (11025)
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+static void lcomp_test_int (const char *str, const char *filename, int filetype, double margin) ;
+
+static int error_function (double data, double orig, double margin) ;
+static int decay_response (int k) ;
+
+static void gen_signal_double (double *data, double scale, int datalen) ;
+
+/* Force the start of these buffers to be double aligned. Sparc-solaris will
+** choke if they are not.
+*/
+
+typedef union
+{ double d [BUFFER_SIZE + 1] ;
+ int i [BUFFER_SIZE + 1] ;
+} BUFFER ;
+
+static BUFFER data_buffer ;
+static BUFFER orig_buffer ;
+
+int
+main (void)
+{ const char *filename = "test.au" ;
+
+ lcomp_test_int ("au_g721", filename, SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G721_32, 0.06) ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+lcomp_test_int (const char *str, const char *filename, int filetype, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, *orig, *data, sum_abs ;
+ long datalen, seekpos ;
+ double scale ;
+
+ printf ("\nThis is program is not part of the libsndfile test suite.\n\n") ;
+
+ printf (" lcomp_test_int : %s ... ", str) ;
+ fflush (stdout) ;
+
+ datalen = BUFFER_SIZE ;
+
+ scale = 1.0 * 0x10000 ;
+
+ data = data_buffer.i ;
+ orig = orig_buffer.i ;
+
+ gen_signal_double (orig_buffer.d, 32000.0 * scale, datalen) ;
+ for (k = 0 ; k < datalen ; k++)
+ orig [k] = orig_buffer.d [k] ;
+
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_writef_int (file, orig, datalen)) != datalen)
+ { printf ("sf_writef_int failed with short write (%ld => %d).\n", datalen, k) ;
+ exit (1) ;
+ } ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (int)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("sf_open_read failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + datalen / 2))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != datalen)
+ { printf ("Line %d: short read (%d should be %ld).\n", __LINE__, k, datalen) ;
+ exit (1) ;
+ } ;
+
+ sum_abs = 0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (data [k] / scale, orig [k] / scale, margin))
+ { printf ("Line %d: Incorrect sample (#%d : %f should be %f).\n", __LINE__, k, data [k] / scale, orig [k] / scale) ;
+ oct_save_int (orig, data, datalen) ;
+ exit (1) ;
+ } ;
+ sum_abs = abs (sum_abs + abs (data [k])) ;
+ } ;
+
+ if (sum_abs < 1.0)
+ { printf ("Line %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("Line %d: Incorrect read length (%ld should be %d).\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames - datalen), k) ;
+ exit (1) ;
+ } ;
+
+ /* This check is only for block based encoders which must append silence
+ ** to the end of a file so as to fill out a block.
+ */
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [k] / scale) > decay_response (k))
+ { printf ("Line %d : Incorrect sample B (#%d : abs (%d) should be < %d).\n", __LINE__, k, data [k], decay_response (k)) ;
+ exit (1) ;
+ } ;
+
+ if (! sfinfo.seekable)
+ { printf ("ok\n") ;
+ return ;
+ } ;
+
+ /* Now test sf_seek function. */
+
+ if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("Line %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { int n ;
+
+ if ((k = sf_readf_int (file, data, 11)) != 11)
+ { printf ("Line %d: Incorrect read length (11 => %d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < 11 ; k++)
+ if (error_function (data [k] / scale, orig [k + m * 11] / scale, margin))
+ { printf ("Line %d: Incorrect sample (m = %d) (#%d : %d => %d).\n", __LINE__, m, k + m * 11, orig [k + m * 11], data [k]) ;
+ for (n = 0 ; n < 1 ; n++)
+ printf ("%d ", data [n]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ;
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %ld failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_int (file, data, 1)) != 1)
+ { printf ("Line %d: sf_readf_int (file, data, 1) returned %d.\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ if (error_function ((double) data [0], (double) orig [seekpos], margin))
+ { printf ("Line %d: sf_seek (SEEK_SET) followed by sf_readf_int failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("Line %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %ld)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ sf_readf_int (file, data, 1) ;
+ if (error_function ((double) data [0], (double) orig [seekpos], margin) || k != seekpos)
+ { printf ("Line %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", __LINE__, data [0], orig [seekpos], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ sf_readf_int (file, data, 1) ;
+ if (error_function ((double) data [0], (double) orig [seekpos], margin) || k != seekpos)
+ { printf ("sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", data [0], orig [seekpos], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, (int) sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != 0)
+ { printf ("Line %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+ if ((k = sf_seek (file, 5 - (int) sfinfo.frames, SEEK_END)) != 5)
+ { printf ("sf_seek (SEEK_END) returned %d instead of %d.\n", k, 5) ;
+ exit (1) ;
+ } ;
+
+ sf_readf_int (file, data, 1) ;
+ if (error_function (data [0] / scale, orig [5] / scale, margin))
+ { printf ("Line %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%d should be %d).\n", __LINE__, data [0], orig [5]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+} /* lcomp_test_int */
+
+/*========================================================================================
+** Auxiliary functions
+*/
+
+#define SIGNAL_MAXVAL 30000.0
+#define DECAY_COUNT 800
+
+static int
+decay_response (int k)
+{ if (k < 1)
+ return (int) (1.2 * SIGNAL_MAXVAL) ;
+ if (k > DECAY_COUNT)
+ return 0 ;
+ return (int) (1.2 * SIGNAL_MAXVAL * (DECAY_COUNT - k) / (1.0 * DECAY_COUNT)) ;
+} /* decay_response */
+
+static void
+gen_signal_double (double *data, double scale, int datalen)
+{ int k, ramplen ;
+ double amp = 0.0 ;
+
+ ramplen = datalen / 18 ;
+
+ for (k = 0 ; k < datalen ; k++)
+ { if (k <= ramplen)
+ amp = scale * k / ((double) ramplen) ;
+ else if (k > datalen - ramplen)
+ amp = scale * (datalen - k) / ((double) ramplen) ;
+
+ data [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k + 1)) / ((double) SAMPLE_RATE))
+ + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k + 1)) / ((double) SAMPLE_RATE))) ;
+ } ;
+
+ return ;
+} /* gen_signal_double */
+
+static int
+error_function (double data, double orig, double margin)
+{ double error ;
+
+ if (fabs (orig) <= 500.0)
+ error = fabs (fabs (data) - fabs (orig)) / 2000.0 ;
+ else if (fabs (orig) <= 1000.0)
+ error = fabs (data - orig) / 3000.0 ;
+ else
+ error = fabs (data - orig) / fabs (orig) ;
+
+ if (error > margin)
+ { printf ("\n\n*******************\nError : %f\n", error) ;
+ return 1 ;
+ } ;
+ return 0 ;
+} /* error_function */
+
diff --git a/tests/floating_point_test.c b/tests/floating_point_test.c
new file mode 100644
index 0000000..aaf5386
--- /dev/null
+++ b/tests/floating_point_test.c
@@ -0,0 +1,694 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "dft_cmp.h"
+#include "utils.h"
+
+#define SAMPLE_RATE 16000
+
+static void float_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ;
+static void double_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ;
+
+static void float_short_little_test (const char * filename) ;
+static void float_short_big_test (const char * filename) ;
+static void float_int_little_test (const char * filename) ;
+static void float_int_big_test (const char * filename) ;
+static void double_short_little_test (const char * filename) ;
+static void double_short_big_test (const char * filename) ;
+static void double_int_little_test (const char * filename) ;
+static void double_int_big_test (const char * filename) ;
+
+
+static double double_data [DFT_DATA_LENGTH] ;
+static double double_test [DFT_DATA_LENGTH] ;
+
+static float float_data [DFT_DATA_LENGTH] ;
+static float float_test [DFT_DATA_LENGTH] ;
+
+static double double_data [DFT_DATA_LENGTH] ;
+static short short_data [DFT_DATA_LENGTH] ;
+static int int_data [DFT_DATA_LENGTH] ;
+
+int
+main (int argc, char *argv [])
+{ int allow_exit = 1 ;
+
+ if (argc == 2 && ! strstr (argv [1], "no-exit"))
+ allow_exit = 0 ;
+
+#if ((HAVE_LRINTF == 0) && (HAVE_LRINT_REPLACEMENT == 0))
+ puts ("*** Cannot run this test on this platform because it lacks lrintf().") ;
+ exit (0) ;
+#endif
+
+ /* Float tests. */
+ float_scaled_test ("float.raw", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ;
+
+ /* Test both signed and unsigned 8 bit files. */
+ float_scaled_test ("pcm_s8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_S8, -39.0) ;
+ float_scaled_test ("pcm_u8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_U8, -39.0) ;
+
+ float_scaled_test ("pcm_16.raw", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_16, -87.0) ;
+ float_scaled_test ("pcm_24.raw", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_24, -138.0) ;
+ float_scaled_test ("pcm_32.raw", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_32, -163.0) ;
+
+ float_scaled_test ("ulaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ULAW, -50.0) ;
+ float_scaled_test ("alaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ALAW, -49.0) ;
+
+ float_scaled_test ("ima_adpcm.wav", allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, -47.0) ;
+ float_scaled_test ("ms_adpcm.wav" , allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, -40.0) ;
+ float_scaled_test ("gsm610.raw" , allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_GSM610, -33.0) ;
+
+ float_scaled_test ("g721_32.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G721_32, -34.0) ;
+ float_scaled_test ("g723_24.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_24, -34.0) ;
+ float_scaled_test ("g723_40.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_40, -40.0) ;
+
+ /* PAF files do not use the same encoding method for 24 bit PCM data as other file
+ ** formats so we need to explicitly test it here.
+ */
+ float_scaled_test ("le_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -149.0) ;
+ float_scaled_test ("be_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -149.0) ;
+
+ float_scaled_test ("dwvw_12.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_12, -64.0) ;
+ float_scaled_test ("dwvw_16.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_16, -92.0) ;
+ float_scaled_test ("dwvw_24.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_24, -151.0) ;
+
+ float_scaled_test ("adpcm.vox", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, -40.0) ;
+
+ float_scaled_test ("dpcm_16.xi", allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_16, -90.0) ;
+ float_scaled_test ("dpcm_8.xi" , allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_8 , -41.0) ;
+
+ float_scaled_test ("pcm_s8.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_S8, -90.0) ;
+ float_scaled_test ("pcm_16.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_16, -140.0) ;
+ float_scaled_test ("pcm_24.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_24, -170.0) ;
+
+#if HAVE_EXTERNAL_LIBS
+ float_scaled_test ("flac_8.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_S8, -39.0) ;
+ float_scaled_test ("flac_16.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_16, -87.0) ;
+ float_scaled_test ("flac_24.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_24, -138.0) ;
+
+ float_scaled_test ("vorbis.oga", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_VORBIS, -31.0) ;
+#endif
+
+ float_scaled_test ("replace_float.raw", allow_exit, SF_TRUE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ;
+
+ /*==============================================================================
+ ** Double tests.
+ */
+
+ double_scaled_test ("double.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -300.0) ;
+
+ /* Test both signed (AIFF) and unsigned (WAV) 8 bit files. */
+ double_scaled_test ("pcm_s8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_S8, -39.0) ;
+ double_scaled_test ("pcm_u8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_U8, -39.0) ;
+
+ double_scaled_test ("pcm_16.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_16, -87.0) ;
+ double_scaled_test ("pcm_24.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_24, -135.0) ;
+ double_scaled_test ("pcm_32.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_32, -184.0) ;
+
+ double_scaled_test ("ulaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ULAW, -50.0) ;
+ double_scaled_test ("alaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ALAW, -49.0) ;
+
+ double_scaled_test ("ima_adpcm.wav", allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, -47.0) ;
+ double_scaled_test ("ms_adpcm.wav" , allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, -40.0) ;
+ double_scaled_test ("gsm610.raw" , allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_GSM610, -33.0) ;
+
+ double_scaled_test ("g721_32.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G721_32, -34.0) ;
+ double_scaled_test ("g723_24.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_24, -34.0) ;
+ double_scaled_test ("g723_40.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_40, -40.0) ;
+
+ /* 24 bit PCM PAF files tested here. */
+ double_scaled_test ("be_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -151.0) ;
+ double_scaled_test ("le_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -151.0) ;
+
+ double_scaled_test ("dwvw_12.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_12, -64.0) ;
+ double_scaled_test ("dwvw_16.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_16, -92.0) ;
+ double_scaled_test ("dwvw_24.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_24, -151.0) ;
+
+ double_scaled_test ("adpcm.vox" , allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, -40.0) ;
+
+ double_scaled_test ("dpcm_16.xi", allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_16, -90.0) ;
+ double_scaled_test ("dpcm_8.xi" , allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_8 , -42.0) ;
+
+ double_scaled_test ("pcm_s8.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_S8, -90.0) ;
+ double_scaled_test ("pcm_16.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_16, -140.0) ;
+ double_scaled_test ("pcm_24.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_24, -180.0) ;
+
+#if HAVE_EXTERNAL_LIBS
+ double_scaled_test ("flac_8.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_S8, -39.0) ;
+ double_scaled_test ("flac_16.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_16, -87.0) ;
+ double_scaled_test ("flac_24.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_24, -138.0) ;
+
+ double_scaled_test ("vorbis.oga", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_VORBIS, -29.0) ;
+#endif
+
+ double_scaled_test ("replace_double.raw", allow_exit, SF_TRUE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -300.0) ;
+
+ putchar ('\n') ;
+ /* Float int tests. */
+ float_short_little_test ("float_short_little.au") ;
+ float_short_big_test ("float_short_big.au") ;
+ float_int_little_test ("float_int_little.au") ;
+ float_int_big_test ("float_int_big.au") ;
+ double_short_little_test ("double_short_little.au") ;
+ double_short_big_test ("double_short_big.au") ;
+ double_int_little_test ("double_int_little.au") ;
+ double_int_big_test ("double_int_big.au") ;
+
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+ * Here are the test functions.
+ */
+
+static void
+float_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double snr ;
+
+ print_test_name ("float_scaled_test", filename) ;
+
+ gen_windowed_sine_float (float_data, DFT_DATA_LENGTH, 1.0) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DFT_DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ test_write_float_or_die (file, 0, float_data, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_test, 0, sizeof (float_test)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ exit_if_true (sfinfo.format != filetype, "\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit_if_true (sfinfo.frames < DFT_DATA_LENGTH, "\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit_if_true (sfinfo.channels != 1, "\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, float_test, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ snr = dft_cmp_float (__LINE__, float_data, float_test, DFT_DATA_LENGTH, target_snr, allow_exit) ;
+
+ exit_if_true (snr > target_snr, "% 6.1fdB SNR\n\n Error : should be better than % 6.1fdB\n\n", snr, target_snr) ;
+
+ printf ("% 6.1fdB SNR ... ok\n", snr) ;
+
+ unlink (filename) ;
+
+ return ;
+} /* float_scaled_test */
+
+static void
+double_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double snr ;
+
+ print_test_name ("double_scaled_test", filename) ;
+
+ gen_windowed_sine_double (double_data, DFT_DATA_LENGTH, 0.95) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DFT_DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ test_write_double_or_die (file, 0, double_data, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_test, 0, sizeof (double_test)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ exit_if_true (sfinfo.format != filetype, "\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit_if_true (sfinfo.frames < DFT_DATA_LENGTH, "\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit_if_true (sfinfo.channels != 1, "\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, double_test, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ snr = dft_cmp_double (__LINE__, double_data, double_test, DFT_DATA_LENGTH, target_snr, allow_exit) ;
+
+ exit_if_true (snr > target_snr, "% 6.1fdB SNR\n\n Error : should be better than % 6.1fdB\n\n", snr, target_snr) ;
+
+ printf ("% 6.1fdB SNR ... ok\n", snr) ;
+
+ unlink (filename) ;
+
+ return ;
+} /* double_scaled_test */
+
+/*==============================================================================
+*/
+
+
+static void
+float_short_little_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("float_short_little_test", filename) ;
+
+ gen_windowed_sine_float (float_data, ARRAY_LEN (float_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (short_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_float_or_die (file, 0, float_data, ARRAY_LEN (float_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (float_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_short_or_die (file, 0, short_data, ARRAY_LEN (short_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (short_data) ; k++)
+ if ((unsigned) abs (short_data [k]) > max)
+ max = abs (short_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFF) / 0x7FFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* float_short_little_test */
+
+static void
+float_short_big_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("float_short_big_test", filename) ;
+
+ gen_windowed_sine_float (float_data, ARRAY_LEN (float_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (short_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_float_or_die (file, 0, float_data, ARRAY_LEN (float_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (float_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_short_or_die (file, 0, short_data, ARRAY_LEN (short_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (short_data) ; k++)
+ if ((unsigned) abs (short_data [k]) > max)
+ max = abs (short_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFF) / 0x7FFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* float_short_big_test */
+
+static void
+float_int_little_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("float_int_little_test", filename) ;
+
+ gen_windowed_sine_float (float_data, ARRAY_LEN (float_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (int_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_float_or_die (file, 0, float_data, ARRAY_LEN (float_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (float_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_int_or_die (file, 0, int_data, ARRAY_LEN (int_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (int_data) ; k++)
+ if ((unsigned) abs (int_data [k]) > max)
+ max = abs (int_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFFFFFF) / 0x7FFFFFFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFFFFFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* float_int_little_test */
+
+static void
+float_int_big_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("float_int_big_test", filename) ;
+
+ gen_windowed_sine_float (float_data, ARRAY_LEN (float_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (int_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_float_or_die (file, 0, float_data, ARRAY_LEN (float_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (float_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_int_or_die (file, 0, int_data, ARRAY_LEN (int_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (int_data) ; k++)
+ if ((unsigned) abs (int_data [k]) > max)
+ max = abs (int_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFFFFFF) / 0x7FFFFFFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFFFFFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* float_int_big_test */
+
+static void
+double_short_little_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("double_short_little_test", filename) ;
+
+ gen_windowed_sine_double (double_data, ARRAY_LEN (double_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (short_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, double_data, ARRAY_LEN (double_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (double_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_short_or_die (file, 0, short_data, ARRAY_LEN (short_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (short_data) ; k++)
+ if ((unsigned) abs (short_data [k]) > max)
+ max = abs (short_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFF) / 0x7FFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* double_short_little_test */
+
+static void
+double_short_big_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("double_short_big_test", filename) ;
+
+ gen_windowed_sine_double (double_data, ARRAY_LEN (double_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (short_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, double_data, ARRAY_LEN (double_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (double_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_short_or_die (file, 0, short_data, ARRAY_LEN (short_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (short_data) ; k++)
+ if ((unsigned) abs (short_data [k]) > max)
+ max = abs (short_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFF) / 0x7FFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* double_short_big_test */
+
+static void
+double_int_little_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("double_int_little_test", filename) ;
+
+ gen_windowed_sine_double (double_data, ARRAY_LEN (double_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (int_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, double_data, ARRAY_LEN (double_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (double_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_int_or_die (file, 0, int_data, ARRAY_LEN (int_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (int_data) ; k++)
+ if ((unsigned) abs (int_data [k]) > max)
+ max = abs (int_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFFFFFF) / 0x7FFFFFFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFFFFFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* double_int_little_test */
+
+static void
+double_int_big_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("double_int_big_test", filename) ;
+
+ gen_windowed_sine_double (double_data, ARRAY_LEN (double_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN (int_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, double_data, ARRAY_LEN (double_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN (double_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_int_or_die (file, 0, int_data, ARRAY_LEN (int_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN (int_data) ; k++)
+ if ((unsigned) abs (int_data [k]) > max)
+ max = abs (int_data [k]) ;
+
+ if (1.0 * abs (max - 0x7FFFFFFF) / 0x7FFFFFFF > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, 0x7FFFFFFF) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* double_int_big_test */
+
+
diff --git a/tests/floating_point_test.def b/tests/floating_point_test.def
new file mode 100644
index 0000000..3441d34
--- /dev/null
+++ b/tests/floating_point_test.def
@@ -0,0 +1,32 @@
+autogen definitions floating_point_test.tpl;
+
+endian_type = {
+ end_name = little ;
+ end_type = SF_ENDIAN_LITTLE ;
+ } ;
+
+endian_type = {
+ end_name = big ;
+ end_type = SF_ENDIAN_BIG ;
+ } ;
+
+float_type = {
+ float_name = float ;
+ minor_type = SF_FORMAT_FLOAT ;
+ } ;
+
+float_type = {
+ float_name = double ;
+ minor_type = SF_FORMAT_DOUBLE ;
+ } ;
+
+int_type = {
+ int_name = short ;
+ int_max = 0x7FFF ;
+ } ;
+
+int_type = {
+ int_name = int ;
+ int_max = 0x7FFFFFFF ;
+ } ;
+
diff --git a/tests/floating_point_test.tpl b/tests/floating_point_test.tpl
new file mode 100644
index 0000000..2bb6b86
--- /dev/null
+++ b/tests/floating_point_test.tpl
@@ -0,0 +1,336 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "dft_cmp.h"
+#include "utils.h"
+
+#define SAMPLE_RATE 16000
+
+static void float_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ;
+static void double_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ;
+
+[+ FOR float_type +][+ FOR int_type +][+ FOR endian_type
++]static void [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename) ;
+[+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type
++]
+
+static double double_data [DFT_DATA_LENGTH] ;
+static double double_test [DFT_DATA_LENGTH] ;
+
+static float float_data [DFT_DATA_LENGTH] ;
+static float float_test [DFT_DATA_LENGTH] ;
+
+static double double_data [DFT_DATA_LENGTH] ;
+static short short_data [DFT_DATA_LENGTH] ;
+static int int_data [DFT_DATA_LENGTH] ;
+
+int
+main (int argc, char *argv [])
+{ int allow_exit = 1 ;
+
+ if (argc == 2 && ! strstr (argv [1], "no-exit"))
+ allow_exit = 0 ;
+
+#if ((HAVE_LRINTF == 0) && (HAVE_LRINT_REPLACEMENT == 0))
+ puts ("*** Cannot run this test on this platform because it lacks lrintf().") ;
+ exit (0) ;
+#endif
+
+ /* Float tests. */
+ float_scaled_test ("float.raw", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ;
+
+ /* Test both signed and unsigned 8 bit files. */
+ float_scaled_test ("pcm_s8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_S8, -39.0) ;
+ float_scaled_test ("pcm_u8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_U8, -39.0) ;
+
+ float_scaled_test ("pcm_16.raw", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_16, -87.0) ;
+ float_scaled_test ("pcm_24.raw", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_24, -138.0) ;
+ float_scaled_test ("pcm_32.raw", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_32, -163.0) ;
+
+ float_scaled_test ("ulaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ULAW, -50.0) ;
+ float_scaled_test ("alaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ALAW, -49.0) ;
+
+ float_scaled_test ("ima_adpcm.wav", allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, -47.0) ;
+ float_scaled_test ("ms_adpcm.wav" , allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, -40.0) ;
+ float_scaled_test ("gsm610.raw" , allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_GSM610, -33.0) ;
+
+ float_scaled_test ("g721_32.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G721_32, -34.0) ;
+ float_scaled_test ("g723_24.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_24, -34.0) ;
+ float_scaled_test ("g723_40.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_40, -40.0) ;
+
+ /* PAF files do not use the same encoding method for 24 bit PCM data as other file
+ ** formats so we need to explicitly test it here.
+ */
+ float_scaled_test ("le_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -149.0) ;
+ float_scaled_test ("be_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -149.0) ;
+
+ float_scaled_test ("dwvw_12.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_12, -64.0) ;
+ float_scaled_test ("dwvw_16.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_16, -92.0) ;
+ float_scaled_test ("dwvw_24.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_24, -151.0) ;
+
+ float_scaled_test ("adpcm.vox", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, -40.0) ;
+
+ float_scaled_test ("dpcm_16.xi", allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_16, -90.0) ;
+ float_scaled_test ("dpcm_8.xi" , allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_8 , -41.0) ;
+
+ float_scaled_test ("pcm_s8.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_S8, -90.0) ;
+ float_scaled_test ("pcm_16.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_16, -140.0) ;
+ float_scaled_test ("pcm_24.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_24, -170.0) ;
+
+#if HAVE_EXTERNAL_LIBS
+ float_scaled_test ("flac_8.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_S8, -39.0) ;
+ float_scaled_test ("flac_16.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_16, -87.0) ;
+ float_scaled_test ("flac_24.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_24, -138.0) ;
+
+ float_scaled_test ("vorbis.oga", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_VORBIS, -31.0) ;
+#endif
+
+ float_scaled_test ("replace_float.raw", allow_exit, SF_TRUE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ;
+
+ /*==============================================================================
+ ** Double tests.
+ */
+
+ double_scaled_test ("double.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -300.0) ;
+
+ /* Test both signed (AIFF) and unsigned (WAV) 8 bit files. */
+ double_scaled_test ("pcm_s8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_S8, -39.0) ;
+ double_scaled_test ("pcm_u8.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_U8, -39.0) ;
+
+ double_scaled_test ("pcm_16.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_16, -87.0) ;
+ double_scaled_test ("pcm_24.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_24, -135.0) ;
+ double_scaled_test ("pcm_32.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_PCM_32, -184.0) ;
+
+ double_scaled_test ("ulaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ULAW, -50.0) ;
+ double_scaled_test ("alaw.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_ALAW, -49.0) ;
+
+ double_scaled_test ("ima_adpcm.wav", allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, -47.0) ;
+ double_scaled_test ("ms_adpcm.wav" , allow_exit, SF_FALSE, SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, -40.0) ;
+ double_scaled_test ("gsm610.raw" , allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_GSM610, -33.0) ;
+
+ double_scaled_test ("g721_32.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G721_32, -34.0) ;
+ double_scaled_test ("g723_24.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_24, -34.0) ;
+ double_scaled_test ("g723_40.au", allow_exit, SF_FALSE, SF_FORMAT_AU | SF_FORMAT_G723_40, -40.0) ;
+
+ /* 24 bit PCM PAF files tested here. */
+ double_scaled_test ("be_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -151.0) ;
+ double_scaled_test ("le_paf_24.paf", allow_exit, SF_FALSE, SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_24, -151.0) ;
+
+ double_scaled_test ("dwvw_12.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_12, -64.0) ;
+ double_scaled_test ("dwvw_16.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_16, -92.0) ;
+ double_scaled_test ("dwvw_24.raw", allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_DWVW_24, -151.0) ;
+
+ double_scaled_test ("adpcm.vox" , allow_exit, SF_FALSE, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, -40.0) ;
+
+ double_scaled_test ("dpcm_16.xi", allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_16, -90.0) ;
+ double_scaled_test ("dpcm_8.xi" , allow_exit, SF_FALSE, SF_FORMAT_XI | SF_FORMAT_DPCM_8 , -42.0) ;
+
+ double_scaled_test ("pcm_s8.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_S8, -90.0) ;
+ double_scaled_test ("pcm_16.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_16, -140.0) ;
+ double_scaled_test ("pcm_24.sds", allow_exit, SF_FALSE, SF_FORMAT_SDS | SF_FORMAT_PCM_24, -180.0) ;
+
+#if HAVE_EXTERNAL_LIBS
+ double_scaled_test ("flac_8.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_S8, -39.0) ;
+ double_scaled_test ("flac_16.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_16, -87.0) ;
+ double_scaled_test ("flac_24.flac", allow_exit, SF_FALSE, SF_FORMAT_FLAC | SF_FORMAT_PCM_24, -138.0) ;
+
+ double_scaled_test ("vorbis.oga", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_VORBIS, -29.0) ;
+#endif
+
+ double_scaled_test ("replace_double.raw", allow_exit, SF_TRUE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -300.0) ;
+
+ putchar ('\n') ;
+ /* Float int tests. */
+[+ FOR float_type +][+ FOR int_type +][+ FOR endian_type
++] [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +].au") ;
+[+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type
++]
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+ * Here are the test functions.
+ */
+
+static void
+float_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double snr ;
+
+ print_test_name ("float_scaled_test", filename) ;
+
+ gen_windowed_sine_float (float_data, DFT_DATA_LENGTH, 1.0) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DFT_DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ test_write_float_or_die (file, 0, float_data, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_test, 0, sizeof (float_test)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ exit_if_true (sfinfo.format != filetype, "\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit_if_true (sfinfo.frames < DFT_DATA_LENGTH, "\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit_if_true (sfinfo.channels != 1, "\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, float_test, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ snr = dft_cmp_float (__LINE__, float_data, float_test, DFT_DATA_LENGTH, target_snr, allow_exit) ;
+
+ exit_if_true (snr > target_snr, "% 6.1fdB SNR\n\n Error : should be better than % 6.1fdB\n\n", snr, target_snr) ;
+
+ printf ("% 6.1fdB SNR ... ok\n", snr) ;
+
+ unlink (filename) ;
+
+ return ;
+} /* float_scaled_test */
+
+static void
+double_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double snr ;
+
+ print_test_name ("double_scaled_test", filename) ;
+
+ gen_windowed_sine_double (double_data, DFT_DATA_LENGTH, 0.95) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DFT_DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ test_write_double_or_die (file, 0, double_data, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_test, 0, sizeof (double_test)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+
+ exit_if_true (sfinfo.format != filetype, "\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit_if_true (sfinfo.frames < DFT_DATA_LENGTH, "\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit_if_true (sfinfo.channels != 1, "\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, double_test, DFT_DATA_LENGTH, __LINE__) ;
+
+ sf_close (file) ;
+
+ snr = dft_cmp_double (__LINE__, double_data, double_test, DFT_DATA_LENGTH, target_snr, allow_exit) ;
+
+ exit_if_true (snr > target_snr, "% 6.1fdB SNR\n\n Error : should be better than % 6.1fdB\n\n", snr, target_snr) ;
+
+ printf ("% 6.1fdB SNR ... ok\n", snr) ;
+
+ unlink (filename) ;
+
+ return ;
+} /* double_scaled_test */
+
+/*==============================================================================
+*/
+
+[+ FOR float_type +][+ FOR int_type +][+ FOR endian_type
++]
+static void
+[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ unsigned k, max ;
+
+ print_test_name ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test", filename) ;
+
+ gen_windowed_sine_[+ (get "float_name") +] ([+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), 0.98) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = ARRAY_LEN ([+ (get "int_name") +]_data) ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = [+ (get "end_type") +] | SF_FORMAT_AU | [+ (get "minor_type") +] ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_[+ (get "float_name") +]_or_die (file, 0, [+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.frames != ARRAY_LEN ([+ (get "float_name") +]_data))
+ { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), DFT_DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ test_read_[+ (get "int_name") +]_or_die (file, 0, [+ (get "int_name") +]_data, ARRAY_LEN ([+ (get "int_name") +]_data), __LINE__) ;
+ sf_close (file) ;
+
+ max = 0 ;
+ for (k = 0 ; k < ARRAY_LEN ([+ (get "int_name") +]_data) ; k++)
+ if ((unsigned) abs ([+ (get "int_name") +]_data [k]) > max)
+ max = abs ([+ (get "int_name") +]_data [k]) ;
+
+ if (1.0 * abs (max - [+ (get "int_max") +]) / [+ (get "int_max") +] > 0.01)
+ { printf ("\n\nLine %d: Bad maximum (%d should be %d).\n\n", __LINE__, max, [+ (get "int_max") +]) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test */
+[+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type +]
+
diff --git a/tests/format_check_test.c b/tests/format_check_test.c
new file mode 100644
index 0000000..a371c71
--- /dev/null
+++ b/tests/format_check_test.c
@@ -0,0 +1,149 @@
+/*
+** Copyright (C) 2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "sndfile.h"
+#include "utils.h"
+
+static void format_error_test (void) ;
+static void format_combo_test (void) ;
+
+int
+main (void)
+{
+ format_error_test () ;
+ format_combo_test () ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+format_error_test (void)
+{ const char *filename = "format-error.wav" ;
+ SNDFILE *file ;
+ SF_INFO info ;
+
+ print_test_name (__func__, NULL) ;
+
+ memset (&info, 0, sizeof (info)) ;
+ info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+ info.channels = 1 ;
+ info.samplerate = 44100 ;
+
+ info.format = SF_FORMAT_WAV ;
+ file = sf_open (filename, SFM_WRITE, &info) ;
+ exit_if_true (file != NULL, "\n\nLine %d : Format should not be valid.\n\n", __LINE__) ;
+ exit_if_true (
+ strstr (sf_strerror (NULL), "minor format") == NULL,
+ "\n\nLine %d : Error string should reference bad 'minor format'.\n\n", __LINE__
+ ) ;
+
+ info.format = SF_FORMAT_PCM_16 ;
+ file = sf_open (filename, SFM_WRITE, &info) ;
+ exit_if_true (file != NULL, "\n\nLine %d : Format should not be valid.\n\n", __LINE__) ;
+ exit_if_true (
+ strstr (sf_strerror (NULL), "major format") == NULL,
+ "\n\nLine %d : Error string should reference bad 'major format'.\n\n", __LINE__
+ ) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* format_error_test */
+
+static void
+format_combo_test (void)
+{ int container_max, codec_max, cont, codec ;
+
+ print_test_name (__func__, NULL) ;
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &container_max, sizeof (container_max)) ;
+ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &codec_max, sizeof (codec_max)) ;
+
+ for (cont = 0 ; cont < container_max + 10 ; cont ++)
+ { SF_FORMAT_INFO major_fmt_info ;
+
+ memset (&major_fmt_info, 0, sizeof (major_fmt_info)) ;
+ major_fmt_info.format = cont ;
+ (void) sf_command (NULL, SFC_GET_FORMAT_MAJOR, &major_fmt_info, sizeof (major_fmt_info)) ;
+
+ for (codec = 0 ; codec < codec_max + 10 ; codec ++)
+ { SF_FORMAT_INFO subtype_fmt_info ;
+ SNDFILE * sndfile ;
+ SF_INFO info ;
+ char filename [128] ;
+ int subtype_is_valid, check_is_valid ;
+
+ memset (&subtype_fmt_info, 0, sizeof (subtype_fmt_info)) ;
+ subtype_fmt_info.format = codec ;
+ subtype_is_valid = sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &subtype_fmt_info, sizeof (subtype_fmt_info)) == 0 ;
+
+ sf_info_setup (&info, major_fmt_info.format | subtype_fmt_info.format, 22050, 1) ;
+
+ check_is_valid = sf_format_check (&info) ;
+
+ exit_if_true (
+ NOT (subtype_is_valid) && check_is_valid,
+ "\n\nLine %d : Subtype is not valid but checks ok.\n",
+ __LINE__
+ ) ;
+
+ snprintf (filename, sizeof (filename), "format-check.%s", major_fmt_info.extension) ;
+
+ sndfile = sf_open (filename, SFM_WRITE, &info) ;
+
+ sf_close (sndfile) ;
+ unlink (filename) ;
+
+ if (major_fmt_info.extension != NULL && strcmp (major_fmt_info.extension, "sd2") == 0)
+ { snprintf (filename, sizeof (filename), "._format-check.%s", major_fmt_info.extension) ;
+ unlink (filename) ;
+ } ;
+
+ exit_if_true (
+ sndfile && NOT (check_is_valid),
+ "\n\nError : Format was not valid but file opened correctly.\n"
+ " Container : %s\n"
+ " Codec : %s\n\n",
+ major_fmt_info.name, subtype_fmt_info.name
+ ) ;
+
+ exit_if_true (
+ NOT (sndfile) && check_is_valid,
+ "\n\nError : Format was valid but file failed to open.\n"
+ " Container : %s\n"
+ " Codec : %s\n\n",
+ major_fmt_info.name, subtype_fmt_info.name
+ ) ;
+ } ;
+ } ;
+
+ puts ("ok") ;
+} /* format_combo_test */
+
diff --git a/tests/generate.c b/tests/generate.c
new file mode 100644
index 0000000..d759385
--- /dev/null
+++ b/tests/generate.c
@@ -0,0 +1,73 @@
+/*
+** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+#include "generate.h"
+
+#define SF_MAX(x,y) ((x) > (y) ? (x) : (y))
+
+static float crappy_snare (float *output, int len, int offset, float gain, float maxabs) ;
+
+void
+generate_file (const char * filename, int format, int len)
+{ float * output ;
+ float maxabs = 0.0 ;
+
+ output = calloc (len, sizeof (float)) ;
+
+ maxabs = crappy_snare (output, len, 0, 0.95, maxabs) ;
+ maxabs = crappy_snare (output, len, len / 4, 0.85, maxabs) ;
+ maxabs = crappy_snare (output, len, 2 * len / 4, 0.85, maxabs) ;
+ crappy_snare (output, len, 3 * len / 4, 0.85, maxabs) ;
+
+ write_mono_file (filename, format, 44100, output, len) ;
+
+ free (output) ;
+} /* generate_file */
+
+static inline float
+rand_float (void)
+{ return rand () / (0.5 * RAND_MAX) - 1.0 ;
+} /* rand_float */
+
+static float
+crappy_snare (float *output, int len, int offset, float gain, float maxabs)
+{ int k ;
+ float env = 0.0 ;
+
+ for (k = offset ; k < len && env < gain ; k++)
+ { env += 0.03 ;
+ output [k] += env * rand_float () ;
+ maxabs = SF_MAX (maxabs, fabs (output [k])) ;
+ } ;
+
+ for ( ; k < len && env > 1e-8 ; k++)
+ { env *= 0.995 ;
+ output [k] += env * rand_float () ;
+ maxabs = SF_MAX (maxabs, fabs (output [k])) ;
+ } ;
+
+ return maxabs ;
+} /* crappy_snare */
diff --git a/tests/generate.h b/tests/generate.h
new file mode 100644
index 0000000..709ea61
--- /dev/null
+++ b/tests/generate.h
@@ -0,0 +1,19 @@
+/*
+** Copyright (C) 2007-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.
+*/
+
+void generate_file (const char * filename, int format, int len) ;
diff --git a/tests/header_test.c b/tests/header_test.c
new file mode 100644
index 0000000..9802fd9
--- /dev/null
+++ b/tests/header_test.c
@@ -0,0 +1,741 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation ; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <io.h>
+#include <direct.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<10)
+#define LOG_BUFFER_SIZE 1024
+
+static void update_header_test (const char *filename, int typemajor) ;
+
+static void update_seek_short_test (const char *filename, int filetype) ;
+static void update_seek_int_test (const char *filename, int filetype) ;
+static void update_seek_float_test (const char *filename, int filetype) ;
+static void update_seek_double_test (const char *filename, int filetype) ;
+
+
+static void extra_header_test (const char *filename, int filetype) ;
+
+static void header_shrink_test (const char *filename, int filetype) ;
+
+/* Force the start of this buffer to be double aligned. Sparc-solaris will
+** choke if its not.
+*/
+static int data_out [BUFFER_LEN] ;
+static int data_in [BUFFER_LEN] ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file peak chunk\n") ;
+ printf (" aiff - test AIFF file PEAK chunk\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all=!strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { update_header_test ("header.wav", SF_FORMAT_WAV) ;
+ update_seek_short_test ("header_short.wav", SF_FORMAT_WAV) ;
+ update_seek_int_test ("header_int.wav", SF_FORMAT_WAV) ;
+ update_seek_float_test ("header_float.wav", SF_FORMAT_WAV) ;
+ update_seek_double_test ("header_double.wav", SF_FORMAT_WAV) ;
+ header_shrink_test ("header_shrink.wav", SF_FORMAT_WAV) ;
+ extra_header_test ("extra.wav", SF_FORMAT_WAV) ;
+
+ update_header_test ("header.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_short_test ("header_short.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_int_test ("header_int.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_float_test ("header_float.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_double_test ("header_double.wavex", SF_FORMAT_WAVEX) ;
+ header_shrink_test ("header_shrink.wavex", SF_FORMAT_WAVEX) ;
+ extra_header_test ("extra.wavex", SF_FORMAT_WAVEX) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { update_header_test ("header.aiff", SF_FORMAT_AIFF) ;
+ update_seek_short_test ("header_short.aiff", SF_FORMAT_AIFF) ;
+ update_seek_int_test ("header_int.aiff", SF_FORMAT_AIFF) ;
+ update_seek_float_test ("header_float.aiff", SF_FORMAT_AIFF) ;
+ update_seek_double_test ("header_double.aiff", SF_FORMAT_AIFF) ;
+ header_shrink_test ("header_shrink.wav", SF_FORMAT_AIFF) ;
+ extra_header_test ("extra.aiff", SF_FORMAT_AIFF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { update_header_test ("header.au", SF_FORMAT_AU) ;
+ update_seek_short_test ("header_short.au", SF_FORMAT_AU) ;
+ update_seek_int_test ("header_int.au", SF_FORMAT_AU) ;
+ update_seek_float_test ("header_float.au", SF_FORMAT_AU) ;
+ update_seek_double_test ("header_double.au", SF_FORMAT_AU) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "caf"))
+ { update_header_test ("header.caf", SF_FORMAT_CAF) ;
+ update_seek_short_test ("header_short.caf", SF_FORMAT_CAF) ;
+ update_seek_int_test ("header_int.caf", SF_FORMAT_CAF) ;
+ update_seek_float_test ("header_float.caf", SF_FORMAT_CAF) ;
+ update_seek_double_test ("header_double.caf", SF_FORMAT_CAF) ;
+ /* extra_header_test ("extra.caf", SF_FORMAT_CAF) ; */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { update_header_test ("header.nist", SF_FORMAT_NIST) ;
+ update_seek_short_test ("header_short.nist", SF_FORMAT_NIST) ;
+ update_seek_int_test ("header_int.nist", SF_FORMAT_NIST) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { update_header_test ("header.paf", SF_FORMAT_PAF) ;
+ update_seek_short_test ("header_short.paf", SF_FORMAT_PAF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { update_header_test ("header.ircam", SF_FORMAT_IRCAM) ;
+ update_seek_short_test ("header_short.ircam", SF_FORMAT_IRCAM) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { update_header_test ("header.w64", SF_FORMAT_W64) ;
+ update_seek_short_test ("header_short.w64", SF_FORMAT_W64) ;
+ update_seek_int_test ("header_int.w64", SF_FORMAT_W64) ;
+ update_seek_float_test ("header_float.w64", SF_FORMAT_W64) ;
+ update_seek_double_test ("header_double.w64", SF_FORMAT_W64) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "rf64"))
+ { update_header_test ("header.rf64", SF_FORMAT_RF64) ;
+ update_seek_short_test ("header_short.rf64", SF_FORMAT_RF64) ;
+ update_seek_int_test ("header_int.rf64", SF_FORMAT_RF64) ;
+ update_seek_float_test ("header_float.rf64", SF_FORMAT_RF64) ;
+ update_seek_double_test ("header_double.rf64", SF_FORMAT_RF64) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { update_header_test ("header.mat4", SF_FORMAT_MAT4) ;
+ update_seek_short_test ("header_short.mat4", SF_FORMAT_MAT4) ;
+ update_seek_int_test ("header_int.mat4", SF_FORMAT_MAT4) ;
+ update_seek_float_test ("header_float.mat4", SF_FORMAT_MAT4) ;
+ update_seek_double_test ("header_double.mat4", SF_FORMAT_MAT4) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { update_header_test ("header.mat5", SF_FORMAT_MAT5) ;
+ update_seek_short_test ("header_short.mat5", SF_FORMAT_MAT5) ;
+ update_seek_int_test ("header_int.mat5", SF_FORMAT_MAT5) ;
+ update_seek_float_test ("header_float.mat5", SF_FORMAT_MAT5) ;
+ update_seek_double_test ("header_double.mat5", SF_FORMAT_MAT5) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { update_header_test ("header.pvf", SF_FORMAT_PVF) ;
+ update_seek_short_test ("header_short.pvf", SF_FORMAT_PVF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "avr"))
+ { update_header_test ("header.avr", SF_FORMAT_AVR) ;
+ update_seek_short_test ("header_short.avr", SF_FORMAT_AVR) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "htk"))
+ { update_header_test ("header.htk", SF_FORMAT_HTK) ;
+ update_seek_short_test ("header_short.htk", SF_FORMAT_HTK) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { update_header_test ("header.svx", SF_FORMAT_SVX) ;
+ update_seek_short_test ("header_short.svx", SF_FORMAT_SVX) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { update_header_test ("header.voc", SF_FORMAT_VOC) ;
+ /*-update_seek_short_test ("header_short.voc", SF_FORMAT_VOC) ;-*/
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sds"))
+ { update_header_test ("header.sds", SF_FORMAT_SDS) ;
+ /*-update_seek_short_test ("header_short.sds", SF_FORMAT_SDS) ;-*/
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mpc2k"))
+ { update_header_test ("header.mpc", SF_FORMAT_MPC2K) ;
+ update_seek_short_test ("header_short.mpc", SF_FORMAT_MPC2K) ;
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+update_header_sub (const char *filename, int typemajor, int write_mode)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ int k ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ outfile = test_open_file_or_die (filename, write_mode, &sfinfo, SF_TRUE, __LINE__) ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ data_out [k] = k + 1 ;
+ test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ if (typemajor != SF_FORMAT_HTK)
+ { /* The HTK header is not correct when the file is first written. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (infile) ;
+ } ;
+
+ sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
+
+ /*
+ ** Open file and check log buffer for an error. If header update failed
+ ** the the log buffer will contain errors.
+ */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+
+ if (sfinfo.frames < BUFFER_LEN || sfinfo.frames > BUFFER_LEN + 50)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), BUFFER_LEN) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ test_read_int_or_die (infile, 0, data_in, BUFFER_LEN, __LINE__) ;
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (data_out [k] != k + 1)
+ printf ("Error : line %d\n", __LINE__) ;
+
+ sf_close (infile) ;
+
+ /* Set auto update on. */
+ sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+
+ /* Write more data_out. */
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ data_out [k] = k + 2 ;
+ test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+
+ if (sfinfo.frames < 2 * BUFFER_LEN || sfinfo.frames > 2 * BUFFER_LEN + 50)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * BUFFER_LEN) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ sf_close (infile) ;
+
+ sf_close (outfile) ;
+
+ unlink (filename) ;
+} /* update_header_sub */
+
+static void
+update_header_test (const char *filename, int typemajor)
+{
+ print_test_name ("update_header_test", filename) ;
+
+ update_header_sub (filename, typemajor, SFM_WRITE) ;
+ update_header_sub (filename, typemajor, SFM_RDWR) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* update_header_test */
+
+/*==============================================================================
+*/
+
+static void
+update_seek_short_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ short buffer [8] ;
+ int k ;
+
+ print_test_name ("update_seek_short_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound outfile with no data. */
+ sfinfo.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo.samplerate = 48000 ;
+ sfinfo.channels = 2 ;
+
+ if (sf_format_check (&sfinfo) == SF_FALSE)
+ sfinfo.channels = 1 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 0 ; k < 6 ; k++)
+ { test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, __LINE__) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+ sf_close (infile) ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_short_or_die (outfile, k, buffer, sfinfo.channels * frames, __LINE__) ;
+ else
+ test_writef_short_or_die (outfile, k, buffer, frames, __LINE__) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* update_seek_short_test */
+
+static void
+update_seek_int_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ int buffer [8] ;
+ int k ;
+
+ print_test_name ("update_seek_int_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound outfile with no data. */
+ sfinfo.format = filetype | SF_FORMAT_PCM_32 ;
+ sfinfo.samplerate = 48000 ;
+ sfinfo.channels = 2 ;
+
+ if (sf_format_check (&sfinfo) == SF_FALSE)
+ sfinfo.channels = 1 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 0 ; k < 6 ; k++)
+ { test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, __LINE__) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+ sf_close (infile) ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_int_or_die (outfile, k, buffer, sfinfo.channels * frames, __LINE__) ;
+ else
+ test_writef_int_or_die (outfile, k, buffer, frames, __LINE__) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* update_seek_int_test */
+
+static void
+update_seek_float_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ float buffer [8] ;
+ int k ;
+
+ print_test_name ("update_seek_float_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound outfile with no data. */
+ sfinfo.format = filetype | SF_FORMAT_FLOAT ;
+ sfinfo.samplerate = 48000 ;
+ sfinfo.channels = 2 ;
+
+ if (sf_format_check (&sfinfo) == SF_FALSE)
+ sfinfo.channels = 1 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 0 ; k < 6 ; k++)
+ { test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, __LINE__) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+ sf_close (infile) ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_float_or_die (outfile, k, buffer, sfinfo.channels * frames, __LINE__) ;
+ else
+ test_writef_float_or_die (outfile, k, buffer, frames, __LINE__) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* update_seek_float_test */
+
+static void
+update_seek_double_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ double buffer [8] ;
+ int k ;
+
+ print_test_name ("update_seek_double_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound outfile with no data. */
+ sfinfo.format = filetype | SF_FORMAT_DOUBLE ;
+ sfinfo.samplerate = 48000 ;
+ sfinfo.channels = 2 ;
+
+ if (sf_format_check (&sfinfo) == SF_FALSE)
+ sfinfo.channels = 1 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 0 ; k < 6 ; k++)
+ { test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, __LINE__) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+ sf_close (infile) ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_double_or_die (outfile, k, buffer, sfinfo.channels * frames, __LINE__) ;
+ else
+ test_writef_double_or_die (outfile, k, buffer, frames, __LINE__) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* update_seek_double_test */
+
+
+
+static void
+header_shrink_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ float buffer [8], bufferin [8] ;
+
+ print_test_name ("header_shrink_test", filename) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = filetype | SF_FORMAT_FLOAT ;
+ sfinfo.channels = 1 ;
+
+ memset (buffer, 0xA0, sizeof (buffer)) ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ /* Test the file with extra header data. */
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+
+ sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+ sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, SF_FALSE) ;
+ sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ test_writef_float_or_die (outfile, 0, buffer, frames, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ test_readf_float_or_die (infile, 0, bufferin, frames, __LINE__) ;
+ sf_close (infile) ;
+
+ compare_float_or_die (buffer, bufferin, frames, __LINE__) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+ return ;
+} /* header_shrink_test */
+
+
+static void
+extra_header_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ short buffer [8] ;
+ int k = 0 ;
+
+ print_test_name ("extra_header_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (filetype | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+
+ memset (buffer, 0xA0, sizeof (buffer)) ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ /* Test the file with extra header data. */
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, 462) ;
+ sf_set_string (outfile, SF_STR_TITLE, filename) ;
+ test_writef_short_or_die (outfile, k, buffer, frames, 464) ;
+ sf_set_string (outfile, SF_STR_COPYRIGHT, "(c) 1980 Erik") ;
+ sf_close (outfile) ;
+
+#if 1
+ /*
+ ** Erik de Castro Lopo <erikd@mega-nerd.com> May 23 2004.
+ **
+ ** This file has extra string data in the header and therefore cannot
+ ** currently be opened in SFM_RDWR mode. This is fixable, but its in
+ ** a part of the code I don't want to fiddle with until the Ogg/Vorbis
+ ** integration is done.
+ */
+
+ if ((infile = sf_open (filename, SFM_RDWR, &sfinfo)) != NULL)
+ { printf ("\n\nError : should not be able to open this file in SFM_RDWR.\n\n") ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+ return ;
+#else
+
+ hexdump_file (filename, 0, 100000) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, 491) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 1 ; k < 6 ; k++)
+ {
+ printf ("\n*** pass %d\n", k) ;
+ memset (buffer, 0xA0 + k, sizeof (buffer)) ;
+
+
+ test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, 512) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, 513) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ if (0)
+ { infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, 517) ;
+ check_log_buffer_or_die (infile, 518) ;
+ sf_close (infile) ;
+ } ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", 523, SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_short_or_die (outfile, k, buffer, sfinfo.channels * frames, 529) ;
+ else
+ test_writef_short_or_die (outfile, k, buffer, frames, 531) ;
+ hexdump_file (filename, 0, 100000) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+#endif
+} /* extra_header_test */
+
diff --git a/tests/header_test.def b/tests/header_test.def
new file mode 100644
index 0000000..959703e
--- /dev/null
+++ b/tests/header_test.def
@@ -0,0 +1,22 @@
+autogen definitions header_test.tpl;
+
+data_type = {
+ name = "short" ;
+ format = "SF_FORMAT_PCM_16" ;
+ } ;
+
+data_type = {
+ name = "int" ;
+ format = "SF_FORMAT_PCM_32" ;
+ } ;
+
+data_type = {
+ name = "float" ;
+ format = "SF_FORMAT_FLOAT" ;
+ } ;
+
+data_type = {
+ name = "double" ;
+ format = "SF_FORMAT_DOUBLE" ;
+ } ;
+
diff --git a/tests/header_test.tpl b/tests/header_test.tpl
new file mode 100644
index 0000000..ef8c97d
--- /dev/null
+++ b/tests/header_test.tpl
@@ -0,0 +1,542 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation ; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <io.h>
+#include <direct.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<10)
+#define LOG_BUFFER_SIZE 1024
+
+static void update_header_test (const char *filename, int typemajor) ;
+
+[+ FOR data_type
++]static void update_seek_[+ (get "name") +]_test (const char *filename, int filetype) ;
+[+ ENDFOR data_type
++]
+
+static void extra_header_test (const char *filename, int filetype) ;
+
+static void header_shrink_test (const char *filename, int filetype) ;
+
+/* Force the start of this buffer to be double aligned. Sparc-solaris will
+** choke if its not.
+*/
+static int data_out [BUFFER_LEN] ;
+static int data_in [BUFFER_LEN] ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file peak chunk\n") ;
+ printf (" aiff - test AIFF file PEAK chunk\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all=!strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { update_header_test ("header.wav", SF_FORMAT_WAV) ;
+ update_seek_short_test ("header_short.wav", SF_FORMAT_WAV) ;
+ update_seek_int_test ("header_int.wav", SF_FORMAT_WAV) ;
+ update_seek_float_test ("header_float.wav", SF_FORMAT_WAV) ;
+ update_seek_double_test ("header_double.wav", SF_FORMAT_WAV) ;
+ header_shrink_test ("header_shrink.wav", SF_FORMAT_WAV) ;
+ extra_header_test ("extra.wav", SF_FORMAT_WAV) ;
+
+ update_header_test ("header.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_short_test ("header_short.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_int_test ("header_int.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_float_test ("header_float.wavex", SF_FORMAT_WAVEX) ;
+ update_seek_double_test ("header_double.wavex", SF_FORMAT_WAVEX) ;
+ header_shrink_test ("header_shrink.wavex", SF_FORMAT_WAVEX) ;
+ extra_header_test ("extra.wavex", SF_FORMAT_WAVEX) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { update_header_test ("header.aiff", SF_FORMAT_AIFF) ;
+ update_seek_short_test ("header_short.aiff", SF_FORMAT_AIFF) ;
+ update_seek_int_test ("header_int.aiff", SF_FORMAT_AIFF) ;
+ update_seek_float_test ("header_float.aiff", SF_FORMAT_AIFF) ;
+ update_seek_double_test ("header_double.aiff", SF_FORMAT_AIFF) ;
+ header_shrink_test ("header_shrink.wav", SF_FORMAT_AIFF) ;
+ extra_header_test ("extra.aiff", SF_FORMAT_AIFF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { update_header_test ("header.au", SF_FORMAT_AU) ;
+ update_seek_short_test ("header_short.au", SF_FORMAT_AU) ;
+ update_seek_int_test ("header_int.au", SF_FORMAT_AU) ;
+ update_seek_float_test ("header_float.au", SF_FORMAT_AU) ;
+ update_seek_double_test ("header_double.au", SF_FORMAT_AU) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "caf"))
+ { update_header_test ("header.caf", SF_FORMAT_CAF) ;
+ update_seek_short_test ("header_short.caf", SF_FORMAT_CAF) ;
+ update_seek_int_test ("header_int.caf", SF_FORMAT_CAF) ;
+ update_seek_float_test ("header_float.caf", SF_FORMAT_CAF) ;
+ update_seek_double_test ("header_double.caf", SF_FORMAT_CAF) ;
+ /* extra_header_test ("extra.caf", SF_FORMAT_CAF) ; */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { update_header_test ("header.nist", SF_FORMAT_NIST) ;
+ update_seek_short_test ("header_short.nist", SF_FORMAT_NIST) ;
+ update_seek_int_test ("header_int.nist", SF_FORMAT_NIST) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { update_header_test ("header.paf", SF_FORMAT_PAF) ;
+ update_seek_short_test ("header_short.paf", SF_FORMAT_PAF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { update_header_test ("header.ircam", SF_FORMAT_IRCAM) ;
+ update_seek_short_test ("header_short.ircam", SF_FORMAT_IRCAM) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { update_header_test ("header.w64", SF_FORMAT_W64) ;
+ update_seek_short_test ("header_short.w64", SF_FORMAT_W64) ;
+ update_seek_int_test ("header_int.w64", SF_FORMAT_W64) ;
+ update_seek_float_test ("header_float.w64", SF_FORMAT_W64) ;
+ update_seek_double_test ("header_double.w64", SF_FORMAT_W64) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "rf64"))
+ { update_header_test ("header.rf64", SF_FORMAT_RF64) ;
+ update_seek_short_test ("header_short.rf64", SF_FORMAT_RF64) ;
+ update_seek_int_test ("header_int.rf64", SF_FORMAT_RF64) ;
+ update_seek_float_test ("header_float.rf64", SF_FORMAT_RF64) ;
+ update_seek_double_test ("header_double.rf64", SF_FORMAT_RF64) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { update_header_test ("header.mat4", SF_FORMAT_MAT4) ;
+ update_seek_short_test ("header_short.mat4", SF_FORMAT_MAT4) ;
+ update_seek_int_test ("header_int.mat4", SF_FORMAT_MAT4) ;
+ update_seek_float_test ("header_float.mat4", SF_FORMAT_MAT4) ;
+ update_seek_double_test ("header_double.mat4", SF_FORMAT_MAT4) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { update_header_test ("header.mat5", SF_FORMAT_MAT5) ;
+ update_seek_short_test ("header_short.mat5", SF_FORMAT_MAT5) ;
+ update_seek_int_test ("header_int.mat5", SF_FORMAT_MAT5) ;
+ update_seek_float_test ("header_float.mat5", SF_FORMAT_MAT5) ;
+ update_seek_double_test ("header_double.mat5", SF_FORMAT_MAT5) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { update_header_test ("header.pvf", SF_FORMAT_PVF) ;
+ update_seek_short_test ("header_short.pvf", SF_FORMAT_PVF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "avr"))
+ { update_header_test ("header.avr", SF_FORMAT_AVR) ;
+ update_seek_short_test ("header_short.avr", SF_FORMAT_AVR) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "htk"))
+ { update_header_test ("header.htk", SF_FORMAT_HTK) ;
+ update_seek_short_test ("header_short.htk", SF_FORMAT_HTK) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { update_header_test ("header.svx", SF_FORMAT_SVX) ;
+ update_seek_short_test ("header_short.svx", SF_FORMAT_SVX) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { update_header_test ("header.voc", SF_FORMAT_VOC) ;
+ /*-update_seek_short_test ("header_short.voc", SF_FORMAT_VOC) ;-*/
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sds"))
+ { update_header_test ("header.sds", SF_FORMAT_SDS) ;
+ /*-update_seek_short_test ("header_short.sds", SF_FORMAT_SDS) ;-*/
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mpc2k"))
+ { update_header_test ("header.mpc", SF_FORMAT_MPC2K) ;
+ update_seek_short_test ("header_short.mpc", SF_FORMAT_MPC2K) ;
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+update_header_sub (const char *filename, int typemajor, int write_mode)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ int k ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ outfile = test_open_file_or_die (filename, write_mode, &sfinfo, SF_TRUE, __LINE__) ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ data_out [k] = k + 1 ;
+ test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ if (typemajor != SF_FORMAT_HTK)
+ { /* The HTK header is not correct when the file is first written. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (infile) ;
+ } ;
+
+ sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
+
+ /*
+ ** Open file and check log buffer for an error. If header update failed
+ ** the the log buffer will contain errors.
+ */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+
+ if (sfinfo.frames < BUFFER_LEN || sfinfo.frames > BUFFER_LEN + 50)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), BUFFER_LEN) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ test_read_int_or_die (infile, 0, data_in, BUFFER_LEN, __LINE__) ;
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (data_out [k] != k + 1)
+ printf ("Error : line %d\n", __LINE__) ;
+
+ sf_close (infile) ;
+
+ /* Set auto update on. */
+ sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+
+ /* Write more data_out. */
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ data_out [k] = k + 2 ;
+ test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+
+ if (sfinfo.frames < 2 * BUFFER_LEN || sfinfo.frames > 2 * BUFFER_LEN + 50)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * BUFFER_LEN) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ sf_close (infile) ;
+
+ sf_close (outfile) ;
+
+ unlink (filename) ;
+} /* update_header_sub */
+
+static void
+update_header_test (const char *filename, int typemajor)
+{
+ print_test_name ("update_header_test", filename) ;
+
+ update_header_sub (filename, typemajor, SFM_WRITE) ;
+ update_header_sub (filename, typemajor, SFM_RDWR) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* update_header_test */
+
+/*==============================================================================
+*/
+
+[+ FOR data_type
++]static void
+update_seek_[+ (get "name") +]_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ [+ (get "name") +] buffer [8] ;
+ int k ;
+
+ print_test_name ("update_seek_[+ (get "name") +]_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound outfile with no data. */
+ sfinfo.format = filetype | [+ (get "format") +] ;
+ sfinfo.samplerate = 48000 ;
+ sfinfo.channels = 2 ;
+
+ if (sf_format_check (&sfinfo) == SF_FALSE)
+ sfinfo.channels = 1 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 0 ; k < 6 ; k++)
+ { test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, __LINE__) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, __LINE__) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (infile, __LINE__) ;
+ sf_close (infile) ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_[+ (get "name") +]_or_die (outfile, k, buffer, sfinfo.channels * frames, __LINE__) ;
+ else
+ test_writef_[+ (get "name") +]_or_die (outfile, k, buffer, frames, __LINE__) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* update_seek_[+ (get "name") +]_test */
+
+[+ ENDFOR data_type
++]
+
+static void
+header_shrink_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ float buffer [8], bufferin [8] ;
+
+ print_test_name ("header_shrink_test", filename) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = filetype | SF_FORMAT_FLOAT ;
+ sfinfo.channels = 1 ;
+
+ memset (buffer, 0xA0, sizeof (buffer)) ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ /* Test the file with extra header data. */
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+
+ sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+ sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, SF_FALSE) ;
+ sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ test_writef_float_or_die (outfile, 0, buffer, frames, __LINE__) ;
+ sf_close (outfile) ;
+
+ /* Open again for read. */
+ infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ test_readf_float_or_die (infile, 0, bufferin, frames, __LINE__) ;
+ sf_close (infile) ;
+
+ compare_float_or_die (buffer, bufferin, frames, __LINE__) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+ return ;
+} /* header_shrink_test */
+
+
+static void
+extra_header_test (const char *filename, int filetype)
+{ SNDFILE *outfile, *infile ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ short buffer [8] ;
+ int k = 0 ;
+
+ print_test_name ("extra_header_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (filetype | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+
+ memset (buffer, 0xA0, sizeof (buffer)) ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ /* Test the file with extra header data. */
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, [+ (tpl-file-line "%2$d") +]) ;
+ sf_set_string (outfile, SF_STR_TITLE, filename) ;
+ test_writef_short_or_die (outfile, k, buffer, frames, [+ (tpl-file-line "%2$d") +]) ;
+ sf_set_string (outfile, SF_STR_COPYRIGHT, "(c) 1980 Erik") ;
+ sf_close (outfile) ;
+
+#if 1
+ /*
+ ** Erik de Castro Lopo <erikd@mega-nerd.com> May 23 2004.
+ **
+ ** This file has extra string data in the header and therefore cannot
+ ** currently be opened in SFM_RDWR mode. This is fixable, but its in
+ ** a part of the code I don't want to fiddle with until the Ogg/Vorbis
+ ** integration is done.
+ */
+
+ if ((infile = sf_open (filename, SFM_RDWR, &sfinfo)) != NULL)
+ { printf ("\n\nError : should not be able to open this file in SFM_RDWR.\n\n") ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+ return ;
+#else
+
+ hexdump_file (filename, 0, 100000) ;
+
+ /* Open again for read/write. */
+ outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, [+ (tpl-file-line "%2$d") +]) ;
+
+ /*
+ ** In auto header update mode, seeking to the end of the file with
+ ** SEEK_SET will fail from the 2nd seek on. seeking to 0, SEEK_END
+ ** will seek to 0 anyway
+ */
+ if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
+ { printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ /* Now write some frames. */
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ for (k = 1 ; k < 6 ; k++)
+ {
+ printf ("\n*** pass %d\n", k) ;
+ memset (buffer, 0xA0 + k, sizeof (buffer)) ;
+
+
+ test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, [+ (tpl-file-line "%2$d") +]) ;
+ test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, [+ (tpl-file-line "%2$d") +]) ;
+
+ /* Open file again and make sure no errors in log buffer. */
+ if (0)
+ { infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, [+ (tpl-file-line "%2$d") +]) ;
+ check_log_buffer_or_die (infile, [+ (tpl-file-line "%2$d") +]) ;
+ sf_close (infile) ;
+ } ;
+
+ if (sfinfo.frames != k * frames)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %ld)\n", [+ (tpl-file-line "%2$d") +], SF_COUNT_TO_LONG (sfinfo.frames), SF_COUNT_TO_LONG (k + frames)) ;
+ dump_log_buffer (infile) ;
+ exit (1) ;
+ } ;
+
+ if ((k & 1) == 0)
+ test_write_short_or_die (outfile, k, buffer, sfinfo.channels * frames, [+ (tpl-file-line "%2$d") +]) ;
+ else
+ test_writef_short_or_die (outfile, k, buffer, frames, [+ (tpl-file-line "%2$d") +]) ;
+ hexdump_file (filename, 0, 100000) ;
+ } ;
+
+ sf_close (outfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+#endif
+} /* extra_header_test */
+
diff --git a/tests/headerless_test.c b/tests/headerless_test.c
new file mode 100644
index 0000000..6203589
--- /dev/null
+++ b/tests/headerless_test.c
@@ -0,0 +1,184 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (2000)
+
+static void old_test (void) ;
+static void headerless_test (const char * filename, int format, int expected) ;
+
+int
+main (void)
+{
+ old_test () ;
+
+ headerless_test ("raw.vox", SF_FORMAT_VOX_ADPCM, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM) ;
+ headerless_test ("raw.gsm", SF_FORMAT_GSM610, SF_FORMAT_RAW | SF_FORMAT_GSM610) ;
+
+ headerless_test ("raw.snd", SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ;
+ headerless_test ("raw.au" , SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ;
+
+ return 0 ;
+} /* main */
+
+static void
+headerless_test (const char * filename, int format, int expected)
+{ static short buffer [BUFFER_SIZE] ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+
+ format &= SF_FORMAT_SUBMASK ;
+
+ print_test_name (__func__, filename) ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ buffer [k] = k ;
+
+ sfinfo.samplerate = 8000 ;
+ sfinfo.frames = 0 ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = SF_FORMAT_RAW | format ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if ((k = sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE)
+ { printf ("Line %d: sf_write_short failed with short write (%d => %d).\n", __LINE__, BUFFER_SIZE, k) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* We should be able to detect these so clear sfinfo. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != expected)
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, expected, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < BUFFER_SIZE)
+ { printf ("Line %d: Incorrect number of.frames in file. (%d => %ld)\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* headerless_test */
+
+static void
+old_test (void)
+{ static short buffer [BUFFER_SIZE] ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, filetype ;
+ const char *filename = "headerless.wav" ;
+
+ print_test_name (__func__, "") ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ buffer [k] = k ;
+
+ filetype = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+
+ sfinfo.samplerate = 32000 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if ((k = sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE)
+ { printf ("Line %d: sf_write_short failed with short write (%d => %d).\n", __LINE__, BUFFER_SIZE, k) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Read as RAW but get the bit width and endian-ness correct. */
+ sfinfo.format = filetype = SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_16 ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < BUFFER_SIZE)
+ { printf ("Line %d: Incorrect number of.frames in file. (%d => %ld)\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if ((k = sf_read_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE)
+ { printf ("Line %d: short read (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < BUFFER_SIZE - 22 ; k++)
+ if (buffer [k + 22] != k)
+ { printf ("Line %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, k, buffer [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* old_test */
+
diff --git a/tests/largefile_test.c b/tests/largefile_test.c
new file mode 100644
index 0000000..328a589
--- /dev/null
+++ b/tests/largefile_test.c
@@ -0,0 +1,83 @@
+/*
+** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1024 * 1024)
+#define BUFFER_COUNT (768)
+
+static void largefile_test (int filetype, const char * filename) ;
+
+int
+main (void)
+{
+ largefile_test (SF_FORMAT_WAV, "largefile.wav") ;
+ largefile_test (SF_FORMAT_AIFF, "largefile.aiff") ;
+
+ return 0 ;
+} /* main */
+
+static void
+largefile_test (int filetype, const char * filename)
+{ static float data [BUFFER_LEN] ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+
+ print_test_name ("largefile_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = 2 ;
+ sfinfo.frames = 0 ;
+ sfinfo.format = (filetype | SF_FORMAT_PCM_32) ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ for (k = 0 ; k < BUFFER_COUNT ; k++)
+ test_write_float_or_die (file, k, data, BUFFER_LEN, __LINE__) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if ((sfinfo.frames * sfinfo.channels) / BUFFER_LEN != BUFFER_COUNT)
+ { printf ("\n\nLine %d : bad frame count.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+
+
+ return ;
+} /* largefile_test */
+
diff --git a/tests/locale_test.c b/tests/locale_test.c
new file mode 100644
index 0000000..b67d549
--- /dev/null
+++ b/tests/locale_test.c
@@ -0,0 +1,167 @@
+/*
+** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#if OS_IS_WIN32
+#include <windows.h>
+#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
+#endif
+
+#include "sndfile.h"
+#include "utils.h"
+
+static void utf8_test (void) ;
+static void wchar_test (void) ;
+
+int
+main (void)
+{
+ utf8_test () ;
+ wchar_test () ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+wchar_test (void)
+{
+#if OS_IS_WIN32
+ SNDFILE * file ;
+ SF_INFO info ;
+ LPCWSTR filename = L"test.wav" ;
+
+ print_test_name (__func__, "test.wav") ;
+
+ info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+ info.channels = 1 ;
+ info.samplerate = 44100 ;
+
+ file = sf_wchar_open (filename, SFM_WRITE, &info) ;
+ exit_if_true (file == NULL, "\n\nLine %d : sf_wchar_open failed : %s\n\n", __LINE__, sf_strerror (NULL)) ;
+ sf_close (file) ;
+
+ /* This should check that the file did in fact get created with a
+ ** wchar_t * filename.
+ */
+ exit_if_true (
+ GetFileAttributesW (filename) == INVALID_FILE_ATTRIBUTES,
+ "\n\nLine %d : GetFileAttributes failed.\n\n", __LINE__
+ ) ;
+
+ /* Use this because the file was created with CreateFileW. */
+ DeleteFileW (filename) ;
+
+ puts ("ok") ;
+#endif
+} /* wchar_test */
+
+/*==============================================================================
+*/
+
+typedef struct
+{ const char *locale ;
+ int utf8 ;
+ const char *filename ;
+ int width ;
+} LOCALE_DATA ;
+
+static void locale_test (const LOCALE_DATA * locdata) ;
+
+static void
+utf8_test (void)
+{ LOCALE_DATA ldata [] =
+ { { "de_DE", 1, "F\303\274\303\237e.au", 7 },
+ { "en_AU", 1, "kangaroo.au", 11 },
+ { "POSIX", 0, "posix.au", 8 },
+ { "pt_PT", 1, "concei\303\247\303\243o.au", 12 },
+
+#if OS_IS_WIN32 == 0
+ { "ja_JP", 1, "\343\201\212\343\201\257\343\202\210\343\201\206\343\201\224\343\201\226\343\201\204\343\201\276\343\201\231.au", 21 },
+#endif
+
+ { "vi_VN", 1, "qu\341\273\221c ng\341\273\257.au", 11 },
+ { NULL, 0, NULL, 0 }
+ } ;
+ int k ;
+
+ for (k = 0 ; ldata [k].locale != NULL ; k++)
+ locale_test (ldata + k) ;
+} /* utf8_test */
+
+
+static void
+locale_test (const LOCALE_DATA * ldata)
+{
+#if (HAVE_LOCALE_H == 0 || HAVE_SETLOCALE == 0)
+ locname = filename = NULL ;
+ width = 0 ;
+ return ;
+#else
+ const short wdata [] = { 1, 2, 3, 4, 5, 6, 7, 8 } ;
+ short rdata [ARRAY_LEN (wdata)] ;
+ const char *old_locale ;
+ char utf8_locname [32] ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+
+ snprintf (utf8_locname, sizeof (utf8_locname), "%s%s", ldata->locale, ldata->utf8 ? ".UTF-8" : "") ;
+
+ /* Change the locale saving the old one. */
+ if ((old_locale = setlocale (LC_CTYPE, utf8_locname)) == NULL)
+ return ;
+
+ printf (" locale_test %-8s : %s %*c ", ldata->locale, ldata->filename, 24 - ldata->width, ' ') ;
+ fflush (stdout) ;
+
+ sfinfo.format = SF_FORMAT_AU | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = 44100 ;
+
+ file = test_open_file_or_die (ldata->filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
+ test_write_short_or_die (file, 0, wdata, ARRAY_LEN (wdata), __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (ldata->filename, SFM_READ, &sfinfo, 0, __LINE__) ;
+ test_read_short_or_die (file, 0, rdata, ARRAY_LEN (rdata), __LINE__) ;
+ sf_close (file) ;
+
+ unlink (ldata->filename) ;
+
+ /* Restore old locale. */
+ setlocale (LC_CTYPE, old_locale) ;
+
+ puts ("ok") ;
+#endif
+} /* locale_test */
+
diff --git a/tests/lossy_comp_test.c b/tests/lossy_comp_test.c
new file mode 100644
index 0000000..e871760
--- /dev/null
+++ b/tests/lossy_comp_test.c
@@ -0,0 +1,2371 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (1<<14) /* Should be (1<<14) */
+#define SAMPLE_RATE 11025
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+#define LCT_MAX(x,y) ((x) > (y) ? (x) : (y))
+
+static void lcomp_test_short (const char *filename, int filetype, int chan, double margin) ;
+static void lcomp_test_int (const char *filename, int filetype, int chan, double margin) ;
+static void lcomp_test_float (const char *filename, int filetype, int chan, double margin) ;
+static void lcomp_test_double (const char *filename, int filetype, int chan, double margin) ;
+
+static void sdlcomp_test_short (const char *filename, int filetype, int chan, double margin) ;
+static void sdlcomp_test_int (const char *filename, int filetype, int chan, double margin) ;
+static void sdlcomp_test_float (const char *filename, int filetype, int chan, double margin) ;
+static void sdlcomp_test_double (const char *filename, int filetype, int chan, double margin) ;
+
+static void read_raw_test (const char *filename, int filetype, int chan) ;
+
+static int error_function (double data, double orig, double margin) ;
+static int decay_response (int k) ;
+
+static void gen_signal_double (double *data, double scale, int channels, int datalen) ;
+
+static void smoothed_diff_short (short *data, unsigned int datalen) ;
+static void smoothed_diff_int (int *data, unsigned int datalen) ;
+static void smoothed_diff_float (float *data, unsigned int datalen) ;
+static void smoothed_diff_double (double *data, unsigned int datalen) ;
+
+static void check_comment (SNDFILE * file, int format, int lineno) ;
+
+static int is_lossy (int filetype) ;
+
+/*
+** Force the start of these buffers to be double aligned. Sparc-solaris will
+** choke if they are not.
+*/
+typedef union
+{ double d [BUFFER_SIZE + 1] ;
+ float f [BUFFER_SIZE + 1] ;
+ int i [BUFFER_SIZE + 1] ;
+ short s [BUFFER_SIZE + 1] ;
+ char c [BUFFER_SIZE + 1] ;
+} BUFFER ;
+
+static BUFFER data_buffer ;
+static BUFFER orig_buffer ;
+static BUFFER smooth_buffer ;
+
+static const char *long_comment =
+ "This is really quite a long comment. It is designed to be long enough "
+ "to screw up the encoders and decoders if the file container format does "
+ "not handle things correctly. If everything is working correctly, the "
+ "decoder will only decode the actual audio data, and not this string at "
+ "the end of the file." ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav_ima - test IMA ADPCM WAV file functions\n") ;
+ printf (" wav_msadpcm - test MS ADPCM WAV file functions\n") ;
+ printf (" wav_gsm610 - test GSM 6.10 WAV file functions\n") ;
+ printf (" wav_ulaw - test u-law WAV file functions\n") ;
+ printf (" wav_alaw - test A-law WAV file functions\n") ;
+ printf (" wve - test Psion WVE file functions\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all = ! strcmp (argv [1], "all") ;
+
+ if (do_all || strcmp (argv [1], "wav_pcm") == 0)
+ { /* This is just a sanity test for PCM encoding. */
+ lcomp_test_short ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16, 2, 1e-50) ;
+ lcomp_test_int ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_32, 2, 1e-50) ;
+ lcomp_test_short ("pcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_16, 2, 1e-50) ;
+ lcomp_test_int ("pcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_32, 2, 1e-50) ;
+ /* Lite remove start */
+ lcomp_test_float ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT, 2, 1e-50) ;
+ lcomp_test_double ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_DOUBLE, 2, 1e-50) ;
+ /* Lite remove end */
+
+ read_raw_test ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 2) ;
+ test_count++ ;
+ } ;
+
+ /* For all the rest, if the file format supports more than 1 channel, use stereo. */
+ /* Lite remove start */
+ if (do_all || strcmp (argv [1], "wav_ima") == 0)
+ { lcomp_test_short ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_int ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.65) ;
+ lcomp_test_float ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_double ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+
+ lcomp_test_short ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_int ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_float ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_double ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+
+ sdlcomp_test_short ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ sdlcomp_test_int ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ sdlcomp_test_float ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ sdlcomp_test_double ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "wav_msadpcm") == 0)
+ { lcomp_test_short ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_int ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_float ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_double ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+
+ lcomp_test_short ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_int ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_float ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_double ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+
+ sdlcomp_test_short ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ sdlcomp_test_int ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ sdlcomp_test_float ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ sdlcomp_test_double ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "wav_g721") == 0)
+ { printf ("**** Fix this later : error bound should be 0.06 ****\n") ;
+ lcomp_test_short ("g721.wav", SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
+ lcomp_test_int ("g721.wav", SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
+
+ lcomp_test_short ("g721.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
+ lcomp_test_int ("g721.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
+
+ test_count++ ;
+ } ;
+ /* Lite remove end */
+
+ if (do_all || strcmp (argv [1], "wav_ulaw") == 0)
+ { lcomp_test_short ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
+
+ lcomp_test_short ("ulaw.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
+
+ /* Lite remove start */
+ lcomp_test_float ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "wav_alaw") == 0)
+ { lcomp_test_short ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "wav_gsm610") == 0)
+ { /* Don't do lcomp_test_XXX as the errors are too big. */
+ sdlcomp_test_short ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_int ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
+
+ sdlcomp_test_short ("gsm610.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_int ("gsm610.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
+
+ /* Lite remove start */
+ sdlcomp_test_float ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_double ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "aiff_ulaw") == 0)
+ { lcomp_test_short ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "aiff_alaw") == 0)
+ { lcomp_test_short ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "aiff_gsm610") == 0)
+ { /* Don't do lcomp_test_XXX as the errors are too big. */
+ sdlcomp_test_short ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_int ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
+ /* Lite remove start */
+ sdlcomp_test_float ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_double ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (strcmp (argv [1], "aiff_ima") == 0)
+ { lcomp_test_short ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_int ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ /* Lite remove start */
+ lcomp_test_float ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_double ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ /* Lite remove end */
+ } ;
+
+ if (do_all || strcmp (argv [1], "au_ulaw") == 0)
+ { lcomp_test_short ("ulaw.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("ulaw.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "au_alaw") == 0)
+ { lcomp_test_short ("alaw.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("alaw.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ /* Lite remove start */
+ if (do_all || strcmp (argv [1], "au_g721") == 0)
+ { printf ("**** Fix this later : error bound should be 0.06 ****\n") ;
+ lcomp_test_short ("g721.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
+ lcomp_test_int ("g721.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
+ lcomp_test_float ("g721.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
+ lcomp_test_double ("g721.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
+
+/*- sdlcomp_test_short ("g721.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.07) ;
+ sdlcomp_test_int ("g721.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.07) ;
+ sdlcomp_test_float ("g721.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.07) ;
+ sdlcomp_test_double ("g721.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.12) ;
+-*/
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "au_g723") == 0)
+ { printf ("**** Fix this later : error bound should be 0.16 ****\n") ;
+ lcomp_test_short ("g723_24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
+ lcomp_test_int ("g723_24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
+ lcomp_test_float ("g723_24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
+ lcomp_test_double ("g723_24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
+
+ lcomp_test_short ("g723_40.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.85) ;
+ lcomp_test_int ("g723_40.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.84) ;
+ lcomp_test_float ("g723_40.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.86) ;
+ lcomp_test_double ("g723_40.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.86) ;
+
+/*- sdlcomp_test_short ("g723.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
+ sdlcomp_test_int ("g723.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
+ sdlcomp_test_float ("g723.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
+ sdlcomp_test_double ("g723.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
+-*/
+ test_count++ ;
+ } ;
+ /* Lite remove end */
+
+ if (do_all || strcmp (argv [1], "caf_ulaw") == 0)
+ { lcomp_test_short ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "caf_alaw") == 0)
+ { lcomp_test_short ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2) ;
+ test_count++ ;
+ } ;
+
+
+ if (do_all || strcmp (argv [1], "raw_ulaw") == 0)
+ { lcomp_test_short ("ulaw.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("ulaw.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "raw_alaw") == 0)
+ { lcomp_test_short ("alaw.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("alaw.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "raw_gsm610") == 0)
+ { /* Don't do lcomp_test_XXX as the errors are too big. */
+ sdlcomp_test_short ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_int ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_float ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
+ sdlcomp_test_double ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "ogg_vorbis") == 0)
+ { if (HAVE_EXTERNAL_LIBS)
+ { /* Don't do lcomp_test_XXX as the errors are too big. */
+ sdlcomp_test_short ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
+ sdlcomp_test_int ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
+ sdlcomp_test_float ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
+ sdlcomp_test_double ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
+ }
+ else
+ puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
+
+ test_count++ ;
+ } ;
+
+ /* Lite remove start */
+ if (do_all || strcmp (argv [1], "ircam_ulaw") == 0)
+ { lcomp_test_short ("ulaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.ircam", SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_float ("ulaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.ircam", SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "ircam_alaw") == 0)
+ { lcomp_test_short ("alaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.ircam", SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_float ("alaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.ircam", SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "nist_ulaw") == 0)
+ { lcomp_test_short ("ulaw.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_float ("ulaw.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "nist_alaw") == 0)
+ { lcomp_test_short ("alaw.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_float ("alaw.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "voc_ulaw") == 0)
+ { lcomp_test_short ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_float ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "voc_alaw") == 0)
+ { lcomp_test_short ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_float ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
+ test_count++ ;
+ } ;
+ /* Lite remove end */
+
+ if (do_all || strcmp (argv [1], "w64_ulaw") == 0)
+ { lcomp_test_short ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_int ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
+ lcomp_test_double ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "w64_alaw") == 0)
+ { lcomp_test_short ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_int ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
+ lcomp_test_double ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
+ /* Lite remove end */
+
+ read_raw_test ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2) ;
+ test_count++ ;
+ } ;
+
+ /* Lite remove start */
+ if (do_all || strcmp (argv [1], "w64_ima") == 0)
+ { lcomp_test_short ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_int ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_float ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ lcomp_test_double ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+
+ sdlcomp_test_short ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ sdlcomp_test_int ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ sdlcomp_test_float ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ sdlcomp_test_double ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "w64_msadpcm") == 0)
+ { lcomp_test_short ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_int ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_float ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ lcomp_test_double ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+
+ sdlcomp_test_short ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ sdlcomp_test_int ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ sdlcomp_test_float ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ sdlcomp_test_double ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "wve") == 0)
+ { lcomp_test_short ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
+ lcomp_test_int ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
+ /* Lite remove start */
+ lcomp_test_float ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
+ lcomp_test_double ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ /* Lite remove end */
+
+ if (do_all || strcmp (argv [1], "w64_gsm610") == 0)
+ { /* Don't do lcomp_test_XXX as the errors are too big. */
+ sdlcomp_test_short ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
+ sdlcomp_test_int ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
+ /* Lite remove start */
+ sdlcomp_test_float ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
+ sdlcomp_test_double ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ /* Lite remove start */
+ if (do_all || strcmp (argv [1], "vox_adpcm") == 0)
+ { lcomp_test_short ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
+ lcomp_test_int ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
+ lcomp_test_float ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
+ lcomp_test_double ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
+
+ sdlcomp_test_short ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
+ sdlcomp_test_int ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
+ sdlcomp_test_float ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
+ sdlcomp_test_double ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || strcmp (argv [1], "xi_dpcm") == 0)
+ { lcomp_test_short ("8bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_8, 1, 0.25) ;
+ lcomp_test_int ("8bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_8, 1, 0.25) ;
+
+ lcomp_test_short ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
+ lcomp_test_int ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
+ lcomp_test_float ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
+ lcomp_test_double ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
+ test_count++ ;
+ } ;
+ /* Lite remove end */
+
+ if (test_count == 0)
+ { printf ("************************************\n") ;
+ printf ("* No '%s' test defined.\n", argv [1]) ;
+ printf ("************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+lcomp_test_short (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos, half_max_abs ;
+ long datalen ;
+ short *orig, *data ;
+
+ print_test_name ("lcomp_test_short", filename) ;
+
+ datalen = BUFFER_SIZE / channels ;
+
+ data = data_buffer.s ;
+ orig = orig_buffer.s ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+ for (k = 0 ; k < channels * datalen ; k++)
+ orig [k] = (short) (orig_buffer.d [k]) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_writef_short_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (short)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + datalen / 20))
+ { printf ("Too many frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, data, datalen, __LINE__) ;
+
+ half_max_abs = 0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (data [k], orig [k], margin))
+ { printf ("\n\nLine %d: Incorrect sample A (#%d : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ;
+ oct_save_short (orig, data, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ;
+ } ;
+
+ if (half_max_abs < 1.0)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_short (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
+ SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
+ exit (1) ;
+ } ;
+
+ /* This check is only for block based encoders which must append silence
+ ** to the end of a file so as to fill out a block.
+ */
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [channels * k]) > decay_response (channels * k))
+ { printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%d) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
+ exit (1) ;
+ } ;
+
+ if (! sfinfo.seekable)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("ok\n") ;
+ return ;
+ } ;
+
+ /* Now test sf_seek function. */
+
+ if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_readf_short_or_die (file, m, data, 11, __LINE__) ;
+
+ for (k = 0 ; k < channels * 11 ; k++)
+ if (error_function (1.0 * data [k], 1.0 * orig [k + channels * m * 11], margin))
+ { printf ("\n\nLine %d: Incorrect sample (m = %d) (#%d : %d => %d).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
+ for (m = 0 ; m < channels ; m++)
+ printf ("%d ", data [m]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ;
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
+ { printf ("\n\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_short failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\n\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
+ oct_save_short (orig, data, datalen) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_readf_short (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_readf_short past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [5 * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%d should be %d).\n", __LINE__, data [0], orig [5 * channels]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* lcomp_test_short */
+
+/*--------------------------------------------------------------------------------------------
+*/
+
+static void
+lcomp_test_int (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, half_max_abs ;
+ long datalen, seekpos ;
+ double scale, max_val ;
+ int *orig, *data ;
+
+ print_test_name ("lcomp_test_int", filename) ;
+
+ datalen = BUFFER_SIZE / channels ;
+
+ if (is_lossy (filetype))
+ { scale = 1.0 * 0x10000 ;
+ max_val = 32000.0 * scale ;
+ }
+ else
+ { scale = 1.0 ;
+ max_val = 0x7fffffff * scale ;
+ } ;
+
+ data = data_buffer.i ;
+ orig = orig_buffer.i ;
+
+ gen_signal_double (orig_buffer.d, max_val, channels, datalen) ;
+
+ for (k = 0 ; k < channels * datalen ; k++)
+ orig [k] = lrint (orig_buffer.d [k]) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_writef_int_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (int)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + datalen / 20))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, data, datalen, __LINE__) ;
+
+ half_max_abs = 0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (data [k] / scale, orig [k] / scale, margin))
+ { printf ("\nLine %d: Incorrect sample (#%d : %f should be %f).\n", __LINE__, k, data [k] / scale, orig [k] / scale) ;
+ oct_save_int (orig, data, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ;
+ } ;
+
+ if (half_max_abs < 1.0)
+ { printf ("\n\nLine %d: Signal is all zeros (%d, 0x%X).\n", __LINE__, half_max_abs, half_max_abs) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
+ SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
+ exit (1) ;
+ } ;
+
+ /* This check is only for block based encoders which must append silence
+ ** to the end of a file so as to fill out a block.
+ */
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [channels * k] / scale) > decay_response (channels * k))
+ { printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%d) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
+ exit (1) ;
+ } ;
+
+ if (! sfinfo.seekable)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("ok\n") ;
+ return ;
+ } ;
+
+ /* Now test sf_seek function. */
+
+ if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_readf_int_or_die (file, m, data, 11, __LINE__) ;
+
+ for (k = 0 ; k < channels * 11 ; k++)
+ if (error_function (data [k] / scale, orig [k + channels * m * 11] / scale, margin))
+ { printf ("\nLine %d: Incorrect sample (m = %d) (#%d : %d => %d).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
+ for (m = 0 ; m < channels ; m++)
+ printf ("%d ", data [m]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ;
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %ld failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_int failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %ld)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0] / scale, orig [5 * channels] / scale, margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%d should be %d).\n", __LINE__, data [0], orig [5]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* lcomp_test_int */
+
+/*--------------------------------------------------------------------------------------------
+*/
+
+static void
+lcomp_test_float (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos ;
+ long datalen ;
+ float *orig, *data ;
+ double half_max_abs ;
+
+ print_test_name ("lcomp_test_float", filename) ;
+
+ datalen = BUFFER_SIZE / channels ;
+
+ data = data_buffer.f ;
+ orig = orig_buffer.f ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+ for (k = 0 ; k < channels * datalen ; k++)
+ orig [k] = orig_buffer.d [k] ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_writef_float_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (float)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + datalen / 20))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_readf_float_or_die (file, 0, data, datalen, __LINE__) ;
+
+ half_max_abs = 0.0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (data [k], orig [k], margin))
+ { printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ;
+ oct_save_float (orig, data, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, fabs (0.5 * data [k])) ;
+ } ;
+
+ if (half_max_abs < 1.0)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_float (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
+ SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
+ exit (1) ;
+ } ;
+
+ /* This check is only for block based encoders which must append silence
+ ** to the end of a file so as to fill out a block.
+ */
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [channels * k]) > decay_response (channels * k))
+ { printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%f) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
+ exit (1) ;
+ } ;
+
+ if (! sfinfo.seekable)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("ok\n") ;
+ return ;
+ } ;
+
+ /* Now test sf_seek function. */
+
+ if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_readf_float_or_die (file, 0, data, 11, __LINE__) ;
+
+ for (k = 0 ; k < channels * 11 ; k++)
+ if (error_function (data [k], orig [k + channels * m * 11], margin))
+ { printf ("\nLine %d: Incorrect sample (m = %d) (#%d : %f => %f).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
+ for (m = 0 ; m < channels ; m++)
+ printf ("%f ", data [m]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ;
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+
+ test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
+
+ if (error_function (data [0], orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_float failed (%f, %f).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_readf_float (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_readf_float past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0], orig [5 * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* lcomp_test_float */
+
+/*--------------------------------------------------------------------------------------------
+*/
+
+static void
+lcomp_test_double (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos ;
+ long datalen ;
+ double *orig, *data ;
+ double half_max_abs ;
+
+ print_test_name ("lcomp_test_double", filename) ;
+
+ datalen = BUFFER_SIZE / channels ;
+
+ data = data_buffer.d ;
+ orig = orig_buffer.d ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+ for (k = 0 ; k < channels * datalen ; k++)
+ orig [k] = orig_buffer.d [k] ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_writef_double_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + datalen / 20))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_readf_double_or_die (file, 0, data, datalen, __LINE__) ;
+
+ half_max_abs = 0.0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (data [k], orig [k], margin))
+ { printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ;
+ oct_save_double (orig, data, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, abs (0.5 * data [k])) ;
+ } ;
+
+ if (half_max_abs < 1.0)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_double (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
+ SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
+ exit (1) ;
+ } ;
+
+ /* This check is only for block based encoders which must append silence
+ ** to the end of a file so as to fill out a block.
+ */
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [channels * k]) > decay_response (channels * k))
+ { printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%f) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
+ exit (1) ;
+ } ;
+
+ if (! sfinfo.seekable)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("ok\n") ;
+ return ;
+ } ;
+
+ /* Now test sf_seek function. */
+
+ if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_readf_double_or_die (file, m, data, 11, __LINE__) ;
+
+ for (k = 0 ; k < channels * 11 ; k++)
+ if (error_function (data [k], orig [k + channels * m * 11], margin))
+ { printf ("\nLine %d: Incorrect sample (m = %d) (#%d : %f => %f).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
+ for (m = 0 ; m < channels ; m++)
+ printf ("%f ", data [m]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ;
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+
+ test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
+
+ if (error_function (data [0], orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_double failed (%f, %f).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_readf_double (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_readf_double past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0], orig [5 * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* lcomp_test_double */
+
+/*========================================================================================
+** Smoothed differential loss compression tests.
+*/
+
+static void
+sdlcomp_test_short (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos, half_max_abs ;
+ long datalen ;
+ short *orig, *data, *smooth ;
+
+channels = 1 ;
+ print_test_name ("sdlcomp_test_short", filename) ;
+
+ datalen = BUFFER_SIZE ;
+
+ orig = orig_buffer.s ;
+ data = data_buffer.s ;
+ smooth = smooth_buffer.s ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+ for (k = 0 ; k < datalen ; k++)
+ orig [k] = lrint (orig_buffer.d [k]) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ /* The Vorbis encoder has a bug on PowerPC and X86-64 with sample rates
+ ** <= 22050. Increasing the sample rate to 32000 avoids triggering it.
+ ** See https://trac.xiph.org/ticket/1229
+ */
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { const char * errstr ;
+
+ errstr = sf_strerror (NULL) ;
+ if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") == NULL)
+ { printf ("Line %d: sf_open_fd (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
+ dump_log_buffer (NULL) ;
+ exit (1) ;
+ } ;
+
+ printf ("\n Sample rate -> 32kHz ") ;
+ sfinfo.samplerate = 32000 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ } ;
+
+ test_write_short_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (short)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + 400))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, data, datalen, __LINE__) ;
+
+ memcpy (smooth, orig, datalen * sizeof (short)) ;
+ smoothed_diff_short (data, datalen) ;
+ smoothed_diff_short (smooth, datalen) ;
+
+ half_max_abs = 0.0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (1.0 * data [k], 1.0 * smooth [k], margin))
+ { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ;
+ oct_save_short (orig, smooth, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, abs (0.5 * data [k])) ;
+ } ;
+
+ if (half_max_abs < 1)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_read_short (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
+ exit (1) ;
+ } ;
+
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [k]) > decay_response (k))
+ { printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, data [k], decay_response (k)) ;
+ exit (1) ;
+ } ;
+
+ /* Now test sf_seek function. */
+ if (sfinfo.seekable)
+ { if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_readf_short_or_die (file, m, data, datalen / 7, __LINE__) ;
+
+ smoothed_diff_short (data, datalen / 7) ;
+ memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (short)) ;
+ smoothed_diff_short (smooth, datalen / 7) ;
+
+ for (k = 0 ; k < datalen / 7 ; k++)
+ if (error_function (1.0 * data [k], 1.0 * smooth [k], margin))
+ { printf ("\nLine %d: Incorrect sample C (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), smooth [k], data [k]) ;
+ for (m = 0 ; m < 10 ; m++)
+ printf ("%d ", data [k]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ; /* for (m = 0 ; m < 3 ; m++) */
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_short failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_read_short (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_read_short past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_read_short_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [5 * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_short failed (%d should be %d).\n", __LINE__, data [0], orig [5 * channels]) ;
+ exit (1) ;
+ } ;
+ } /* if (sfinfo.seekable) */
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* sdlcomp_test_short */
+
+static void
+sdlcomp_test_int (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos, half_max_abs ;
+ long datalen ;
+ int *orig, *data, *smooth ;
+ double scale ;
+
+channels = 1 ;
+
+ print_test_name ("sdlcomp_test_int", filename) ;
+
+ datalen = BUFFER_SIZE ;
+ scale = 1.0 * 0x10000 ;
+
+ orig = orig_buffer.i ;
+ data = data_buffer.i ;
+ smooth = smooth_buffer.i ;
+
+ gen_signal_double (orig_buffer.d, 32000.0 * scale, channels, datalen) ;
+ for (k = 0 ; k < datalen ; k++)
+ orig [k] = lrint (orig_buffer.d [k]) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ /* The Vorbis encoder has a bug on PowerPC and X86-64 with sample rates
+ ** <= 22050. Increasing the sample rate to 32000 avoids triggering it.
+ ** See https://trac.xiph.org/ticket/1229
+ */
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { const char * errstr ;
+
+ errstr = sf_strerror (NULL) ;
+ if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") == NULL)
+ { printf ("Line %d: sf_open_fd (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
+ dump_log_buffer (NULL) ;
+ exit (1) ;
+ } ;
+
+ printf ("\n Sample rate -> 32kHz ") ;
+ sfinfo.samplerate = 32000 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ } ;
+
+ test_writef_int_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (int)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("Returned format incorrect (0x%08X => 0x%08X).\n", filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + 400))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, data, datalen, __LINE__) ;
+
+ memcpy (smooth, orig, datalen * sizeof (int)) ;
+ smoothed_diff_int (data, datalen) ;
+ smoothed_diff_int (smooth, datalen) ;
+
+ half_max_abs = abs (data [0] >> 16) ;
+ for (k = 1 ; k < datalen ; k++)
+ { if (error_function (data [k] / scale, smooth [k] / scale, margin))
+ { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ;
+ oct_save_int (orig, smooth, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ;
+ } ;
+
+ if (half_max_abs < 1)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
+ exit (1) ;
+ } ;
+
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_IMA_ADPCM &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610 &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_G721_32 &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_G723_24)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [k]) > decay_response (k))
+ { printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, data [k], decay_response (k)) ;
+ exit (1) ;
+ } ;
+
+ /* Now test sf_seek function. */
+ if (sfinfo.seekable)
+ { if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_readf_int_or_die (file, m, data, datalen / 7, __LINE__) ;
+
+ smoothed_diff_int (data, datalen / 7) ;
+ memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (int)) ;
+ smoothed_diff_int (smooth, datalen / 7) ;
+
+ for (k = 0 ; k < datalen / 7 ; k++)
+ if (error_function (data [k] / scale, smooth [k] / scale, margin))
+ { printf ("\nLine %d: Incorrect sample (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), smooth [k], data [k]) ;
+ for (m = 0 ; m < 10 ; m++)
+ printf ("%d ", data [k]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ; /* for (m = 0 ; m < 3 ; m++) */
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_int failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_readf_int (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
+ if (error_function (data [0] / scale, orig [5] / scale, margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_int failed (%d should be %d).\n", __LINE__, data [0], orig [5]) ;
+ exit (1) ;
+ } ;
+ } /* if (sfinfo.seekable) */
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* sdlcomp_test_int */
+
+static void
+sdlcomp_test_float (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos ;
+ long datalen ;
+ float *orig, *data, *smooth ;
+ double half_max_abs ;
+
+channels = 1 ;
+
+ print_test_name ("sdlcomp_test_float", filename) ;
+
+ if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
+ { puts ("Not working for this format.") ;
+ return ;
+ } ;
+
+printf ("** fix this ** ") ;
+
+ datalen = BUFFER_SIZE ;
+
+ orig = orig_buffer.f ;
+ data = data_buffer.f ;
+ smooth = smooth_buffer.f ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+ for (k = 0 ; k < datalen ; k++)
+ orig [k] = lrint (orig_buffer.d [k]) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_write_float_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (float)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + 400))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, data, datalen, __LINE__) ;
+
+ memcpy (smooth, orig, datalen * sizeof (float)) ;
+ smoothed_diff_float (data, datalen) ;
+ smoothed_diff_float (smooth, datalen) ;
+
+ half_max_abs = fabs (data [0]) ;
+ for (k = 1 ; k < datalen ; k++)
+ { if (error_function (data [k], smooth [k], margin))
+ { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) data [k], (int) smooth [k]) ;
+ oct_save_float (orig, smooth, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, abs (0.5 * data [k])) ;
+ } ;
+
+ if (half_max_abs <= 0.0)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ printf ("half_max_abs : % 10.6f\n", half_max_abs) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_read_float (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
+ exit (1) ;
+ } ;
+
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [k]) > decay_response (k))
+ { printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, (int) data [k], (int) decay_response (k)) ;
+ exit (1) ;
+ } ;
+
+ /* Now test sf_seek function. */
+ if (sfinfo.seekable)
+ { if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_read_float_or_die (file, 0, data, datalen / 7, __LINE__) ;
+
+ smoothed_diff_float (data, datalen / 7) ;
+ memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (float)) ;
+ smoothed_diff_float (smooth, datalen / 7) ;
+
+ for (k = 0 ; k < datalen / 7 ; k++)
+ if (error_function (data [k], smooth [k], margin))
+ { printf ("\nLine %d: Incorrect sample C (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) smooth [k], (int) data [k]) ;
+ for (m = 0 ; m < 10 ; m++)
+ printf ("%d ", (int) data [k]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ; /* for (m = 0 ; m < 3 ; m++) */
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+ test_read_float_or_die (file, 0, data, channels, __LINE__) ;
+
+ if (error_function (data [0], orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_float failed (%d, %d).\n", __LINE__, (int) orig [1], (int) data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_read_float_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_read_float_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_read_float (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_read_float past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_read_float_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (data [0], orig [5 * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_float failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
+ exit (1) ;
+ } ;
+ } /* if (sfinfo.seekable) */
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* sdlcomp_test_float */
+
+static void
+sdlcomp_test_double (const char *filename, int filetype, int channels, double margin)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, m, seekpos ;
+ long datalen ;
+ double *orig, *data, *smooth, half_max_abs ;
+
+channels = 1 ;
+ print_test_name ("sdlcomp_test_double", filename) ;
+
+ if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
+ { puts ("Not working for this format.") ;
+ return ;
+ } ;
+
+ datalen = BUFFER_SIZE ;
+
+ orig = orig_buffer.d ;
+ data = data_buffer.d ;
+ smooth = smooth_buffer.d ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_write_double_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("Returned format incorrect (0x%08X => 0x%08X).\n", filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + 400))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, datalen, __LINE__) ;
+
+ memcpy (smooth, orig, datalen * sizeof (double)) ;
+ smoothed_diff_double (data, datalen) ;
+ smoothed_diff_double (smooth, datalen) ;
+
+ half_max_abs = 0.0 ;
+ for (k = 0 ; k < datalen ; k++)
+ { if (error_function (data [k], smooth [k], margin))
+ { printf ("\n\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) data [k], (int) smooth [k]) ;
+ oct_save_double (orig, smooth, datalen) ;
+ exit (1) ;
+ } ;
+ half_max_abs = LCT_MAX (half_max_abs, 0.5 * fabs (data [k])) ;
+ } ;
+
+ if (half_max_abs < 1.0)
+ { printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_read_double (file, data, datalen)) != sfinfo.frames - datalen)
+ { printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
+ exit (1) ;
+ } ;
+
+ if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
+ (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610)
+ for (k = 0 ; k < sfinfo.frames - datalen ; k++)
+ if (abs (data [k]) > decay_response (k))
+ { printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, (int) data [k], (int) decay_response (k)) ;
+ exit (1) ;
+ } ;
+
+ /* Now test sf_seek function. */
+ if (sfinfo.seekable)
+ { if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
+ { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ for (m = 0 ; m < 3 ; m++)
+ { test_read_double_or_die (file, m, data, datalen / 7, __LINE__) ;
+
+ smoothed_diff_double (data, datalen / 7) ;
+ memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (double)) ;
+ smoothed_diff_double (smooth, datalen / 7) ;
+
+ for (k = 0 ; k < datalen / 7 ; k++)
+ if (error_function (data [k], smooth [k], margin))
+ { printf ("\nLine %d: Incorrect sample C (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) smooth [k], (int) data [k]) ;
+ for (m = 0 ; m < 10 ; m++)
+ printf ("%d ", (int) data [k]) ;
+ printf ("\n") ;
+ exit (1) ;
+ } ;
+ } ; /* for (m = 0 ; m < 3 ; m++) */
+
+ seekpos = BUFFER_SIZE / 10 ;
+
+ /* Check seek from start of file. */
+ if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
+ { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
+ exit (1) ;
+ } ;
+ test_read_double_or_die (file, 0, data, channels, __LINE__) ;
+
+ if (error_function (data [0], orig [seekpos * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_double failed (%d, %d).\n", __LINE__, (int) orig [1], (int) data [0]) ;
+ exit (1) ;
+ } ;
+
+ if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
+ { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
+ k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
+ test_read_double_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos + 1) ;
+ exit (1) ;
+ } ;
+
+ seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
+ /* Check seek backward from current position. */
+ k = sf_seek (file, -20, SEEK_CUR) ;
+ test_read_double_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
+ { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos) ;
+ exit (1) ;
+ } ;
+
+ /* Check that read past end of file returns number of items. */
+ sf_seek (file, sfinfo.frames, SEEK_SET) ;
+
+ if ((k = sf_read_double (file, data, datalen)) != 0)
+ { printf ("\n\nLine %d: Return value from sf_read_double past end of file incorrect (%d).\n", __LINE__, k) ;
+ exit (1) ;
+ } ;
+
+ /* Check seek backward from end. */
+
+ if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
+ { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
+ exit (1) ;
+ } ;
+
+ test_read_double_or_die (file, 0, data, channels, __LINE__) ;
+ if (error_function (data [0], orig [5 * channels], margin))
+ { printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_double failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
+ exit (1) ;
+ } ;
+ } /* if (sfinfo.seekable) */
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* sdlcomp_test_double */
+
+static void
+read_raw_test (const char *filename, int filetype, int channels)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t count ;
+ long datalen ;
+ short *orig, *data ;
+ int k ;
+
+ print_test_name ("read_raw_test", filename) ;
+
+ datalen = ARRAY_LEN (orig_buffer.s) / 2 ;
+
+ orig = orig_buffer.s ;
+ data = data_buffer.s ;
+
+ gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+ for (k = 0 ; k < datalen ; k++)
+ orig [k] = lrint (orig_buffer.d [k]) ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = 123456789 ; /* Ridiculous value. */
+ sfinfo.channels = channels ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_write_short_or_die (file, 0, orig, datalen, __LINE__) ;
+ sf_set_string (file, SF_STR_COMMENT, long_comment) ;
+ sf_close (file) ;
+
+ memset (data, 0, datalen * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("Returned format incorrect (0x%08X => 0x%08X).\n", filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < datalen / channels)
+ { printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames > (datalen + 400))
+ { printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != channels)
+ { printf ("Incorrect number of channels in file.\n") ;
+ exit (1) ;
+ } ;
+
+ check_comment (file, filetype, __LINE__) ;
+
+ count = sf_read_raw (file, orig_buffer.c, datalen + 5 * channels) ;
+ if (count != sfinfo.channels * sfinfo.frames)
+ { printf ("\nLine %d : sf_read_raw returned %ld should be %ld\n", __LINE__, SF_COUNT_TO_LONG (count), sfinfo.channels * SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* read_raw_test */
+
+/*========================================================================================
+** Auxiliary functions
+*/
+
+#define SIGNAL_MAXVAL 30000.0
+#define DECAY_COUNT 1000
+
+static int
+decay_response (int k)
+{ if (k < 1)
+ return (int) (1.2 * SIGNAL_MAXVAL) ;
+ if (k > DECAY_COUNT)
+ return 0 ;
+ return (int) (1.2 * SIGNAL_MAXVAL * (DECAY_COUNT - k) / (1.0 * DECAY_COUNT)) ;
+} /* decay_response */
+
+static void
+gen_signal_double (double *data, double scale, int channels, int datalen)
+{ int k, ramplen ;
+ double amp = 0.0 ;
+
+ ramplen = DECAY_COUNT ;
+
+ if (channels == 1)
+ { for (k = 0 ; k < datalen ; k++)
+ { if (k <= ramplen)
+ amp = scale * k / ((double) ramplen) ;
+ else if (k > datalen - ramplen)
+ amp = scale * (datalen - k) / ((double) ramplen) ;
+
+/*-printf ("%3d : %g\n", k, amp) ;-*/
+
+ data [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
+ + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
+ } ;
+ }
+ else
+ { for (k = 0 ; k < datalen ; k ++)
+ { if (k <= ramplen)
+ amp = scale * k / ((double) ramplen) ;
+ else if (k > datalen - ramplen)
+ amp = scale * (datalen - k) / ((double) ramplen) ;
+
+ data [2 * k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
+ + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
+ data [2 * k + 1] = amp * (0.4 * sin (55.5 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
+ + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
+ } ;
+ } ;
+
+ return ;
+} /* gen_signal_double */
+
+static int
+error_function (double data, double orig, double margin)
+{ double error ;
+
+ if (fabs (orig) <= 500.0)
+ error = fabs (fabs (data) - fabs (orig)) / 2000.0 ;
+ else if (fabs (orig) <= 1000.0)
+ error = fabs (data - orig) / 3000.0 ;
+ else
+ error = fabs (data - orig) / fabs (orig) ;
+
+ if (error > margin)
+ { printf ("\n\nerror_function (data = %f, orig = %f, margin = %f) -> %f\n", data, orig, margin, error) ;
+ return 1 ;
+ } ;
+ return 0 ;
+} /* error_function */
+
+static void
+smoothed_diff_short (short *data, unsigned int datalen)
+{ unsigned int k ;
+ double memory = 0.0 ;
+
+ /* Calculate the smoothed sample-to-sample difference. */
+ for (k = 0 ; k < datalen - 1 ; k++)
+ { memory = 0.7 * memory + (1 - 0.7) * (double) (data [k+1] - data [k]) ;
+ data [k] = (short) memory ;
+ } ;
+ data [datalen-1] = data [datalen-2] ;
+
+} /* smoothed_diff_short */
+
+static void
+smoothed_diff_int (int *data, unsigned int datalen)
+{ unsigned int k ;
+ double memory = 0.0 ;
+
+ /* Calculate the smoothed sample-to-sample difference. */
+ for (k = 0 ; k < datalen - 1 ; k++)
+ { memory = 0.7 * memory + (1 - 0.7) * (double) (data [k+1] - data [k]) ;
+ data [k] = (int) memory ;
+ } ;
+ data [datalen-1] = data [datalen-2] ;
+
+} /* smoothed_diff_int */
+
+static void
+smoothed_diff_float (float *data, unsigned int datalen)
+{ unsigned int k ;
+ float memory = 0.0 ;
+
+ /* Calculate the smoothed sample-to-sample difference. */
+ for (k = 0 ; k < datalen - 1 ; k++)
+ { memory = 0.7 * memory + (1 - 0.7) * (data [k+1] - data [k]) ;
+ data [k] = memory ;
+ } ;
+ data [datalen-1] = data [datalen-2] ;
+
+} /* smoothed_diff_float */
+
+static void
+smoothed_diff_double (double *data, unsigned int datalen)
+{ unsigned int k ;
+ double memory = 0.0 ;
+
+ /* Calculate the smoothed sample-to-sample difference. */
+ for (k = 0 ; k < datalen - 1 ; k++)
+ { memory = 0.7 * memory + (1 - 0.7) * (data [k+1] - data [k]) ;
+ data [k] = memory ;
+ } ;
+ data [datalen-1] = data [datalen-2] ;
+
+} /* smoothed_diff_double */
+
+static void
+check_comment (SNDFILE * file, int format, int lineno)
+{ const char *comment ;
+
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_AIFF :
+ case SF_FORMAT_WAV :
+ case SF_FORMAT_WAVEX :
+ break ;
+ default :
+ return ;
+ } ;
+
+ comment = sf_get_string (file, SF_STR_COMMENT) ;
+ if (comment == NULL)
+ { printf ("\n\nLine %d : File does not contain a comment string.\n\n", lineno) ;
+ exit (1) ;
+ } ;
+
+ if (strcmp (comment, long_comment) != 0)
+ { printf ("\n\nLine %d : File comment does not match comment written.\n\n", lineno) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* check_comment */
+
+static int
+is_lossy (int filetype)
+{
+ switch (SF_FORMAT_SUBMASK & filetype)
+ { case SF_FORMAT_PCM_U8 :
+ case SF_FORMAT_PCM_S8 :
+ case SF_FORMAT_PCM_16 :
+ case SF_FORMAT_PCM_24 :
+ case SF_FORMAT_PCM_32 :
+ case SF_FORMAT_FLOAT :
+ case SF_FORMAT_DOUBLE :
+ return 0 ;
+
+ default :
+ break ;
+ } ;
+
+ return 1 ;
+} /* is_lossy */
+
diff --git a/tests/misc_test.c b/tests/misc_test.c
new file mode 100644
index 0000000..55a30cc
--- /dev/null
+++ b/tests/misc_test.c
@@ -0,0 +1,415 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation ; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <io.h>
+#include <direct.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<10)
+#define LOG_BUFFER_SIZE 1024
+
+static void zero_data_test (const char *filename, int format) ;
+static void filesystem_full_test (int format) ;
+static void permission_test (const char *filename, int typemajor) ;
+static void wavex_amb_test (const char *filename) ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file peak chunk\n") ;
+ printf (" aiff - test AIFF file PEAK chunk\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all=!strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { zero_data_test ("zerolen.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.wav", SF_FORMAT_WAV) ;
+ wavex_amb_test ("ambisonic.wav") ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { zero_data_test ("zerolen.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.aiff", SF_FORMAT_AIFF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { zero_data_test ("zerolen.au", SF_FORMAT_AU | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_AU | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.au", SF_FORMAT_AU) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "caf"))
+ { zero_data_test ("zerolen.caf", SF_FORMAT_CAF | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_CAF | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.caf", SF_FORMAT_CAF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { zero_data_test ("zerolen.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_SVX | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.svx", SF_FORMAT_SVX) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { zero_data_test ("zerolen.nist", SF_FORMAT_NIST | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_NIST | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.nist", SF_FORMAT_NIST) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { zero_data_test ("zerolen.paf", SF_FORMAT_PAF | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_PAF | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.paf", SF_FORMAT_PAF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { zero_data_test ("zerolen.ircam", SF_FORMAT_IRCAM | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_IRCAM | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.ircam", SF_FORMAT_IRCAM) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { zero_data_test ("zerolen.voc", SF_FORMAT_VOC | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_VOC | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.voc", SF_FORMAT_VOC) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { zero_data_test ("zerolen.w64", SF_FORMAT_W64 | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_W64 | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.w64", SF_FORMAT_W64) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "rf64"))
+ { zero_data_test ("zerolen.rf64", SF_FORMAT_W64 | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_W64 | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.rf64", SF_FORMAT_W64) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { zero_data_test ("zerolen.mat4", SF_FORMAT_MAT4 | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_MAT4 | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.mat4", SF_FORMAT_MAT4) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { zero_data_test ("zerolen.mat5", SF_FORMAT_MAT5 | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_MAT5 | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.mat5", SF_FORMAT_MAT5) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { zero_data_test ("zerolen.pvf", SF_FORMAT_PVF | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_PVF | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.pvf", SF_FORMAT_PVF) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "htk"))
+ { zero_data_test ("zerolen.htk", SF_FORMAT_HTK | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_HTK | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.htk", SF_FORMAT_HTK) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "avr"))
+ { zero_data_test ("zerolen.avr", SF_FORMAT_AVR | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_AVR | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.avr", SF_FORMAT_AVR) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sds"))
+ { zero_data_test ("zerolen.sds", SF_FORMAT_SDS | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_SDS | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.sds", SF_FORMAT_SDS) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mpc2k"))
+ { zero_data_test ("zerolen.mpc", SF_FORMAT_MPC2K | SF_FORMAT_PCM_16) ;
+ filesystem_full_test (SF_FORMAT_MPC2K | SF_FORMAT_PCM_16) ;
+ permission_test ("readonly.mpc", SF_FORMAT_MPC2K) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ogg"))
+ { zero_data_test ("zerolen.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS) ;
+ /*-filesystem_full_test (SF_FORMAT_OGG | SF_FORMAT_VORBIS) ;-*/
+ permission_test ("readonly.oga", SF_FORMAT_OGG) ;
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+zero_data_test (const char *filename, int format)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_OGG :
+ if (HAVE_EXTERNAL_LIBS == 0)
+ return ;
+ break ;
+ default :
+ break ;
+ } ;
+
+ print_test_name ("zero_data_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = format ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* zero_data_test */
+
+static void
+filesystem_full_test (int format)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ struct stat buf ;
+
+ const char *filename = "/dev/full", *errorstr ;
+
+#if (defined (WIN32) || defined (_WIN32))
+ /* Can't run this test on Win32 so return. */
+ return ;
+#endif
+
+ /* Make sure errno is zero before doing anything else. */
+ errno = 0 ;
+
+ print_test_name ("filesystem_full_test", filename) ;
+
+ if (stat (filename, &buf) != 0)
+ { puts ("/dev/full missing") ;
+ return ;
+ } ;
+
+ if (S_ISCHR (buf.st_mode) == 0 && S_ISBLK (buf.st_mode) == 0)
+ { puts ("/dev/full is not a device file") ;
+ return ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = format ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) != NULL)
+ { printf ("\n\nLine %d : Error, file should not have openned.\n", __LINE__ - 1) ;
+ exit (1) ;
+ } ;
+
+ errorstr = sf_strerror (file) ;
+
+ if (strstr (errorstr, " space ") == NULL || strstr (errorstr, "device") == NULL)
+ { printf ("\n\nLine %d : Error bad error string : %s.\n", __LINE__ - 1, errorstr) ;
+ exit (1) ;
+ } ;
+
+ puts ("ok") ;
+} /* filesystem_full_test */
+
+static void
+permission_test (const char *filename, int typemajor)
+{
+#if (OS_IS_WIN32)
+ /* Avoid compiler warnings. */
+ filename = filename ;
+ typemajor = typemajor ;
+
+ /* Can't run this test on Win32 so return. */
+ return ;
+#else
+
+ FILE *textfile ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ const char *errorstr ;
+
+ /* Make sure errno is zero before doing anything else. */
+ errno = 0 ;
+
+ if (getuid () == 0)
+ { /* If running as root bypass this test.
+ ** Root is allowed to open a readonly file for write.
+ */
+ return ;
+ } ;
+
+ print_test_name ("permission_test", filename) ;
+
+ if (access (filename, F_OK) == 0)
+ { chmod (filename, S_IWUSR) ;
+ unlink (filename) ;
+ } ;
+
+ if ((textfile = fopen (filename, "w")) == NULL)
+ { printf ("\n\nLine %d : not able to open text file for write.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ fprintf (textfile, "This is a read only file.\n") ;
+ fclose (textfile) ;
+
+ if (chmod (filename, S_IRUSR | S_IRGRP))
+ { printf ("\n\nLine %d : chmod failed", __LINE__) ;
+ fflush (stdout) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) != NULL)
+ { printf ("\n\nLine %d : Error, file should not have opened.\n", __LINE__ - 1) ;
+ exit (1) ;
+ } ;
+
+ errorstr = sf_strerror (file) ;
+
+ if (strstr (errorstr, "ermission denied") == NULL)
+ { printf ("\n\nLine %d : Error bad error string : %s.\n", __LINE__ - 1, errorstr) ;
+ exit (1) ;
+ } ;
+
+ if (chmod (filename, S_IWUSR | S_IWGRP))
+ { printf ("\n\nLine %d : chmod failed", __LINE__) ;
+ fflush (stdout) ;
+ perror ("") ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+
+ puts ("ok") ;
+
+#endif
+} /* permission_test */
+
+static void
+wavex_amb_test (const char *filename)
+{ static short buffer [800] ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+
+ print_test_name (__func__, filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = SF_FORMAT_WAVEX | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 4 ;
+
+ frames = ARRAY_LEN (buffer) / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_WAVEX_SET_AMBISONIC, NULL, SF_AMBISONIC_B_FORMAT) ;
+ test_writef_short_or_die (file, 0, buffer, frames, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ exit_if_true (
+ sf_command (file, SFC_WAVEX_GET_AMBISONIC, NULL, 0) != SF_AMBISONIC_B_FORMAT,
+ "\n\nLine %d : Error, this file should be in Ambisonic B format.\n", __LINE__
+ ) ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* wavex_amb_test */
diff --git a/tests/multi_file_test.c b/tests/multi_file_test.c
new file mode 100644
index 0000000..041f398
--- /dev/null
+++ b/tests/multi_file_test.c
@@ -0,0 +1,237 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define DATA_LENGTH (512)
+
+static void write_file_at_end (int fd, int filetype, int channels, int file_num) ;
+
+static void multi_file_test (const char *filename, int *formats, int format_count) ;
+
+static short data [DATA_LENGTH] ;
+
+static int wav_formats [] =
+{ SF_FORMAT_WAV | SF_FORMAT_PCM_16,
+ SF_FORMAT_WAV | SF_FORMAT_PCM_24,
+ SF_FORMAT_WAV | SF_FORMAT_ULAW,
+ SF_FORMAT_WAV | SF_FORMAT_ALAW,
+ /* Lite remove start */
+ SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM,
+ SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM,
+ /* Lite remove end */
+ /*-SF_FORMAT_WAV | SF_FORMAT_GSM610 Doesn't work yet. -*/
+} ;
+
+static int aiff_formats [] =
+{ SF_FORMAT_AIFF | SF_FORMAT_PCM_16,
+ SF_FORMAT_AIFF | SF_FORMAT_PCM_24,
+ SF_FORMAT_AIFF | SF_FORMAT_ULAW,
+ SF_FORMAT_AIFF | SF_FORMAT_ALAW
+} ;
+
+static int au_formats [] =
+{ SF_FORMAT_AU | SF_FORMAT_PCM_16,
+ SF_FORMAT_AU | SF_FORMAT_PCM_24,
+ SF_FORMAT_AU | SF_FORMAT_ULAW,
+ SF_FORMAT_AU | SF_FORMAT_ALAW
+} ;
+
+static int verbose = SF_FALSE ;
+
+int
+main (int argc, char **argv)
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc == 3 && strcmp (argv [2], "-v") == 0)
+ { verbose = SF_TRUE ;
+ argc -- ;
+ } ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file functions (little endian)\n") ;
+ printf (" aiff - test AIFF file functions (big endian)\n") ;
+ printf (" au - test AU file functions\n") ;
+#if 0
+ printf (" svx - test 8SVX/16SV file functions\n") ;
+ printf (" nist - test NIST Sphere file functions\n") ;
+ printf (" ircam - test IRCAM file functions\n") ;
+ printf (" voc - Create Voice file functions\n") ;
+ printf (" w64 - Sonic Foundry's W64 file functions\n") ;
+#endif
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all = !strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { multi_file_test ("multi_wav.dat", wav_formats, ARRAY_LEN (wav_formats)) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { multi_file_test ("multi_aiff.dat", aiff_formats, ARRAY_LEN (aiff_formats)) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { multi_file_test ("multi_au.dat", au_formats, ARRAY_LEN (au_formats)) ;
+ test_count++ ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+/*======================================================================================
+*/
+
+static void
+multi_file_test (const char *filename, int *formats, int format_count)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+ SF_EMBED_FILE_INFO embed_info ;
+ sf_count_t filelen ;
+ int fd, k, file_count = 0 ;
+
+ print_test_name ("multi_file_test", filename) ;
+
+ unlink (filename) ;
+
+ if ((fd = open (filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
+ { printf ("\n\nLine %d: open failed : %s\n", __LINE__, strerror (errno)) ;
+ exit (1) ;
+ } ;
+
+ k = write (fd, "1234", 4) ;
+
+ for (k = 0 ; k < format_count ; k++)
+ write_file_at_end (fd, formats [k], 2, k) ;
+
+ filelen = file_length_fd (fd) ;
+
+ embed_info.offset = 4 ;
+ embed_info.length = 0 ;
+
+
+ for (file_count = 1 ; embed_info.offset + embed_info.length < filelen ; file_count ++)
+ {
+ if (verbose)
+ { puts ("\n------------------------------------") ;
+ printf ("This offset : %ld\n", SF_COUNT_TO_LONG (embed_info.offset + embed_info.length)) ;
+ } ;
+
+ if (lseek (fd, embed_info.offset + embed_info.length, SEEK_SET) < 0)
+ { printf ("\n\nLine %d: lseek failed : %s\n", __LINE__, strerror (errno)) ;
+ exit (1) ;
+ } ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ if ((sndfile = sf_open_fd (fd, SFM_READ, &sfinfo, SF_FALSE)) == NULL)
+ { printf ("\n\nLine %d: sf_open_fd failed\n", __LINE__) ;
+ printf ("Embedded file number : %d offset : %ld\n", file_count, SF_COUNT_TO_LONG (embed_info.offset)) ;
+ puts (sf_strerror (sndfile)) ;
+ dump_log_buffer (sndfile) ;
+ exit (1) ;
+ } ;
+
+ sf_command (sndfile, SFC_GET_EMBED_FILE_INFO, &embed_info, sizeof (embed_info)) ;
+
+ sf_close (sndfile) ;
+
+ if (verbose)
+ printf ("\nNext offset : %ld\nNext length : %ld\n", SF_COUNT_TO_LONG (embed_info.offset), SF_COUNT_TO_LONG (embed_info.length)) ;
+ } ;
+
+ file_count -- ;
+
+ if (file_count != format_count)
+ { printf ("\n\nLine %d: file count (%d) not equal to %d.\n\n", __LINE__, file_count, format_count) ;
+ printf ("Embedded file number : %d\n", file_count) ;
+ exit (1) ;
+ } ;
+
+ close (fd) ;
+ unlink (filename) ;
+ printf ("ok\n") ;
+
+ return ;
+} /* multi_file_test */
+
+/*======================================================================================
+*/
+
+static void
+write_file_at_end (int fd, int filetype, int channels, int file_num)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+
+ int frames, k ;
+
+ lseek (fd, 0, SEEK_END) ;
+
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ data [k] = k ;
+
+ frames = DATA_LENGTH / channels ;
+
+ sfinfo.format = filetype ;
+ sfinfo.channels = channels ;
+ sfinfo.samplerate = 44100 ;
+
+ if ((sndfile = sf_open_fd (fd, SFM_WRITE, &sfinfo, SF_FALSE)) == NULL)
+ { printf ("\n\nLine %d: sf_open_fd failed\n", __LINE__) ;
+ printf ("Embedded file number : %d\n", file_num) ;
+ puts (sf_strerror (sndfile)) ;
+ dump_log_buffer (sndfile) ;
+ exit (1) ;
+ } ;
+
+ if (sf_writef_short (sndfile, data, frames) != frames)
+ { printf ("\n\nLine %d: short write\n", __LINE__) ;
+ printf ("Embedded file number : %d\n", file_num) ;
+ exit (1) ;
+ } ;
+
+ sf_close (sndfile) ;
+} /* write_file_at_end */
+
diff --git a/tests/ogg_test.c b/tests/ogg_test.c
new file mode 100644
index 0000000..63f3bda
--- /dev/null
+++ b/tests/ogg_test.c
@@ -0,0 +1,341 @@
+/*
+** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define SAMPLE_RATE 44100
+#define DATA_LENGTH (SAMPLE_RATE / 8)
+
+typedef union
+{ double d [DATA_LENGTH] ;
+ float f [DATA_LENGTH] ;
+ int i [DATA_LENGTH] ;
+ short s [DATA_LENGTH] ;
+} BUFFER ;
+
+static BUFFER data_out ;
+static BUFFER data_in ;
+
+static void
+ogg_short_test (void)
+{ const char * filename = "vorbis_short.oga" ;
+
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+ short seek_data [10] ;
+ unsigned k ;
+
+ print_test_name ("ogg_short_test", filename) ;
+
+ /* Generate float data. */
+ gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7F00) ;
+
+ /* Convert to shorteger. */
+ for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++)
+ data_out.s [k] = lrintf (data_out.f [k]) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ /* Set up output file type. */
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_write_short_or_die (file, 0, data_out.s, ARRAY_LEN (data_out.s), __LINE__) ;
+ sf_close (file) ;
+
+ /* Read the file in again. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+ test_read_short_or_die (file, 0, data_in.s, ARRAY_LEN (data_in.s), __LINE__) ;
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ /* Test seeking. */
+ print_test_name ("ogg_seek_test", filename) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+ test_read_short_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
+ compare_short_or_die (seek_data, data_in.s + 10, ARRAY_LEN (seek_data), __LINE__) ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ unlink (filename) ;
+} /* ogg_short_test */
+
+static void
+ogg_int_test (void)
+{ const char * filename = "vorbis_int.oga" ;
+
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+ int seek_data [10] ;
+ unsigned k ;
+
+ print_test_name ("ogg_int_test", filename) ;
+
+ /* Generate float data. */
+ gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7FFF0000) ;
+
+ /* Convert to integer. */
+ for (k = 0 ; k < ARRAY_LEN (data_out.i) ; k++)
+ data_out.i [k] = lrintf (data_out.f [k]) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ /* Set up output file type. */
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_write_int_or_die (file, 0, data_out.i, ARRAY_LEN (data_out.i), __LINE__) ;
+ sf_close (file) ;
+
+ /* Read the file in again. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+ test_read_int_or_die (file, 0, data_in.i, ARRAY_LEN (data_in.i), __LINE__) ;
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ /* Test seeking. */
+ print_test_name ("ogg_seek_test", filename) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+ test_read_int_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
+ compare_int_or_die (seek_data, data_in.i + 10, ARRAY_LEN (seek_data), __LINE__) ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ unlink (filename) ;
+} /* ogg_int_test */
+
+static void
+ogg_float_test (void)
+{ const char * filename = "vorbis_float.oga" ;
+
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+ float seek_data [10] ;
+
+ print_test_name ("ogg_float_test", filename) ;
+
+ gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 0.95) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ /* Set up output file type. */
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_write_float_or_die (file, 0, data_out.f, ARRAY_LEN (data_out.f), __LINE__) ;
+ sf_close (file) ;
+
+ /* Read the file in again. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+ test_read_float_or_die (file, 0, data_in.f, ARRAY_LEN (data_in.f), __LINE__) ;
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ /* Test seeking. */
+ print_test_name ("ogg_seek_test", filename) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+ test_read_float_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
+ compare_float_or_die (seek_data, data_in.f + 10, ARRAY_LEN (seek_data), __LINE__) ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ unlink (filename) ;
+} /* ogg_float_test */
+
+static void
+ogg_double_test (void)
+{ const char * filename = "vorbis_double.oga" ;
+
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+ double seek_data [10] ;
+
+ print_test_name ("ogg_double_test", filename) ;
+
+ gen_windowed_sine_double (data_out.d, ARRAY_LEN (data_out.d), 0.95) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ /* Set up output file type. */
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ;
+ sf_close (file) ;
+
+ /* Read the file in again. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+ test_read_double_or_die (file, 0, data_in.d, ARRAY_LEN (data_in.d), __LINE__) ;
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ /* Test seeking. */
+ print_test_name ("ogg_seek_test", filename) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+ test_read_double_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ;
+ compare_double_or_die (seek_data, data_in.d + 10, ARRAY_LEN (seek_data), __LINE__) ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ unlink (filename) ;
+} /* ogg_double_test */
+
+
+static void
+ogg_stereo_seek_test (const char * filename, int format)
+{ static float data [SAMPLE_RATE] ;
+ static float stereo_out [SAMPLE_RATE * 2] ;
+
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+ sf_count_t pos ;
+ unsigned k ;
+
+ print_test_name (__func__, filename) ;
+
+ gen_windowed_sine_float (data, ARRAY_LEN (data), 0.95) ;
+ for (k = 0 ; k < ARRAY_LEN (data) ; k++)
+ { stereo_out [2 * k] = data [k] ;
+ stereo_out [2 * k + 1] = data [ARRAY_LEN (data) - k - 1] ;
+ } ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ /* Set up output file type. */
+ sfinfo.format = format ;
+ sfinfo.channels = 2 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ test_write_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ;
+ sf_close (file) ;
+
+ /* Open file in again for reading. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ /* Read in the whole file. */
+ test_read_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ;
+
+ /* Now hammer seeking code. */
+ test_seek_or_die (file, 234, SEEK_SET, 234, sfinfo.channels, __LINE__) ;
+ test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
+ compare_float_or_die (data, stereo_out + (234 * sfinfo.channels), 10, __LINE__) ;
+
+ test_seek_or_die (file, 442, SEEK_SET, 442, sfinfo.channels, __LINE__) ;
+ test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
+ compare_float_or_die (data, stereo_out + (442 * sfinfo.channels), 10, __LINE__) ;
+
+ test_seek_or_die (file, 12, SEEK_CUR, 442 + 10 + 12, sfinfo.channels, __LINE__) ;
+ test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
+ compare_float_or_die (data, stereo_out + ((442 + 10 + 12) * sfinfo.channels), 10, __LINE__) ;
+
+ test_seek_or_die (file, 12, SEEK_CUR, 442 + 20 + 24, sfinfo.channels, __LINE__) ;
+ test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
+ compare_float_or_die (data, stereo_out + ((442 + 20 + 24) * sfinfo.channels), 10, __LINE__) ;
+
+ pos = 500 - sfinfo.frames ;
+ test_seek_or_die (file, pos, SEEK_END, 500, sfinfo.channels, __LINE__) ;
+ test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
+ compare_float_or_die (data, stereo_out + (500 * sfinfo.channels), 10, __LINE__) ;
+
+ pos = 10 - sfinfo.frames ;
+ test_seek_or_die (file, pos, SEEK_END, 10, sfinfo.channels, __LINE__) ;
+ test_readf_float_or_die (file, 0, data, 10, __LINE__) ;
+ compare_float_or_die (data, stereo_out + (10 * sfinfo.channels), 10, __LINE__) ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+ unlink (filename) ;
+} /* ogg_stereo_seek_test */
+
+
+int
+main (void)
+{
+ if (HAVE_EXTERNAL_LIBS)
+ { ogg_short_test () ;
+ ogg_int_test () ;
+ ogg_float_test () ;
+ ogg_double_test () ;
+
+ /*-ogg_stereo_seek_test ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;-*/
+ ogg_stereo_seek_test ("vorbis_seek.ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS) ;
+ }
+ else
+ puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
+
+ return 0 ;
+} /* main */
diff --git a/tests/pcm_test.c b/tests/pcm_test.c
new file mode 100644
index 0000000..86511f6
--- /dev/null
+++ b/tests/pcm_test.c
@@ -0,0 +1,1723 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (1<<12)
+
+static void lrintf_test (void) ;
+
+static void pcm_test_bits_8 (const char *filename, int filetype, uint64_t hash) ;
+static void pcm_test_bits_16 (const char *filename, int filetype, uint64_t hash) ;
+static void pcm_test_bits_24 (const char *filename, int filetype, uint64_t hash) ;
+static void pcm_test_bits_32 (const char *filename, int filetype, uint64_t hash) ;
+
+static void pcm_test_float (const char *filename, int filetype, uint64_t hash, int replace_float) ;
+static void pcm_test_double (const char *filename, int filetype, uint64_t hash, int replace_float) ;
+
+typedef union
+{ double d [BUFFER_SIZE + 1] ;
+ float f [BUFFER_SIZE + 1] ;
+ int i [BUFFER_SIZE + 1] ;
+ short s [BUFFER_SIZE + 1] ;
+} BUFFER ;
+
+/* Data written to the file. */
+static BUFFER data_out ;
+
+/* Data read back from the file. */
+static BUFFER data_in ;
+
+int
+main (void)
+{
+ lrintf_test () ;
+
+ pcm_test_bits_8 ("pcm-s8.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_S8, 0x1cda335091249dbfLL) ;
+ pcm_test_bits_8 ("pcm-u8.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_U8, 0x7f748c433d695f3fLL) ;
+
+ pcm_test_bits_16 ("le-pcm16.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_16, 0x3a2b956c881ebf08LL) ;
+ pcm_test_bits_16 ("be-pcm16.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_16, 0xd9e2f840c55750f8LL) ;
+
+ pcm_test_bits_24 ("le-pcm24.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_24, 0x933b6a759ab496f8LL) ;
+ pcm_test_bits_24 ("be-pcm24.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_24, 0xbb1f3eaf9c30b6f8LL) ;
+
+ pcm_test_bits_32 ("le-pcm32.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_32, 0xa77aece1c1c17f08LL) ;
+ pcm_test_bits_32 ("be-pcm32.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_32, 0x3099ddf142d0b0f8LL) ;
+
+ /* Lite remove start */
+ pcm_test_float ("le-float.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x3c2ad04f7554267aLL, SF_FALSE) ;
+ pcm_test_float ("be-float.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x074de3e248fa9186LL, SF_FALSE) ;
+
+ pcm_test_double ("le-double.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xc682726f958f669cLL, SF_FALSE) ;
+ pcm_test_double ("be-double.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xd9a3583f8ee51164LL, SF_FALSE) ;
+
+ pcm_test_float ("le-float.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x3c2ad04f7554267aLL, SF_TRUE) ;
+ pcm_test_float ("be-float.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x074de3e248fa9186LL, SF_TRUE) ;
+
+ pcm_test_double ("le-double.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xc682726f958f669cLL, SF_TRUE) ;
+ pcm_test_double ("be-double.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xd9a3583f8ee51164LL, SF_TRUE) ;
+ /* Lite remove end */
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+lrintf_test (void)
+{ int k, items ;
+ float *float_data ;
+ int *int_data ;
+
+ print_test_name ("lrintf_test", "") ;
+
+ items = 1024 ;
+
+ float_data = data_out.f ;
+ int_data = data_in.i ;
+
+ for (k = 0 ; k < items ; k++)
+ float_data [k] = (k * ((k % 2) ? 333333.0 : -333333.0)) ;
+
+ for (k = 0 ; k < items ; k++)
+ int_data [k] = lrintf (float_data [k]) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (int_data [k] - float_data [k]) > 1.0)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %d).\n", __LINE__, k, float_data [k], int_data [k]) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+} /* lrintf_test */
+
+static void
+pcm_test_bits_8 (const char *filename, int filetype, uint64_t hash)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, zero_count ;
+ short *short_out, *short_in ;
+ int *int_out, *int_in ;
+ /* Lite remove start */
+ float *float_out, *float_in ;
+ double *double_out, *double_in ;
+ /* Lite remove end */
+
+ print_test_name ("pcm_test_bits_8", filename) ;
+
+ items = 127 ;
+
+ short_out = data_out.s ;
+ short_in = data_in.s ;
+
+ zero_count = 0 ;
+ for (k = 0 ; k < items ; k++)
+ { short_out [k] = ((k * ((k % 2) ? 1 : -1)) << 8) ;
+ zero_count = short_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_short_or_die (file, 0, short_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (short_in, 0, items * sizeof (short)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, short_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (short_out [k] != short_in [k])
+ { printf ("\n\nLine %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, short_out [k], short_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Finally, check the file hash. */
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_int ()
+ */
+ zero_count = 0 ;
+
+ int_out = data_out.i ;
+ int_in = data_in.i ;
+ for (k = 0 ; k < items ; k++)
+ { int_out [k] = ((k * ((k % 2) ? 1 : -1)) << 24) ;
+ zero_count = int_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, int_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (int_in, 0, items * sizeof (int)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, int_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (int_out [k] != int_in [k])
+ { printf ("\n\nLine %d: int : Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, int_out [k], int_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Lite remove start */
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_float ()
+ */
+ zero_count = 0 ;
+
+ float_out = data_out.f ;
+ float_in = data_in.f ;
+ for (k = 0 ; k < items ; k++)
+ { float_out [k] = (k * ((k % 2) ? 1 : -1)) ;
+ zero_count = (fabs (float_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_write_float_or_die (file, 0, float_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_in, 0, items * sizeof (float)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_read_float_or_die (file, 0, float_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (float_out [k] - float_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, (double) float_out [k], (double) float_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_double ()
+ */
+ zero_count = 0 ;
+
+ double_out = data_out.d ;
+ double_in = data_in.d ;
+ for (k = 0 ; k < items ; k++)
+ { double_out [k] = (k * ((k % 2) ? 1 : -1)) ;
+ zero_count = (fabs (double_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_write_double_or_die (file, 0, double_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_in, 0, items * sizeof (double)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_read_double_or_die (file, 0, double_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (double_out [k] - double_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: double : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, double_out [k], double_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ /* Lite remove end */
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* pcm_test_bits_8 */
+
+static void
+pcm_test_bits_16 (const char *filename, int filetype, uint64_t hash)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, zero_count ;
+ short *short_out, *short_in ;
+ int *int_out, *int_in ;
+ /* Lite remove start */
+ float *float_out, *float_in ;
+ double *double_out, *double_in ;
+ /* Lite remove end */
+
+ print_test_name ("pcm_test_bits_16", filename) ;
+
+ items = 1024 ;
+
+ short_out = data_out.s ;
+ short_in = data_in.s ;
+
+ zero_count = 0 ;
+ for (k = 0 ; k < items ; k++)
+ { short_out [k] = (k * ((k % 2) ? 3 : -3)) ;
+ zero_count = short_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_short_or_die (file, 0, short_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (short_in, 0, items * sizeof (short)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, short_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (short_out [k] != short_in [k])
+ { printf ("\n\nLine %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, short_out [k], short_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Finally, check the file hash. */
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_int ()
+ */
+ zero_count = 0 ;
+
+ int_out = data_out.i ;
+ int_in = data_in.i ;
+ for (k = 0 ; k < items ; k++)
+ { int_out [k] = ((k * ((k % 2) ? 3 : -3)) << 16) ;
+ zero_count = int_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, int_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (int_in, 0, items * sizeof (int)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, int_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (int_out [k] != int_in [k])
+ { printf ("\n\nLine %d: int : Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, int_out [k], int_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Lite remove start */
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_float ()
+ */
+ zero_count = 0 ;
+
+ float_out = data_out.f ;
+ float_in = data_in.f ;
+ for (k = 0 ; k < items ; k++)
+ { float_out [k] = (k * ((k % 2) ? 3 : -3)) ;
+ zero_count = (fabs (float_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_write_float_or_die (file, 0, float_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_in, 0, items * sizeof (float)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_read_float_or_die (file, 0, float_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (float_out [k] - float_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, (double) float_out [k], (double) float_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_double ()
+ */
+ zero_count = 0 ;
+
+ double_out = data_out.d ;
+ double_in = data_in.d ;
+ for (k = 0 ; k < items ; k++)
+ { double_out [k] = (k * ((k % 2) ? 3 : -3)) ;
+ zero_count = (fabs (double_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_write_double_or_die (file, 0, double_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_in, 0, items * sizeof (double)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_read_double_or_die (file, 0, double_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (double_out [k] - double_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: double : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, double_out [k], double_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ /* Lite remove end */
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* pcm_test_bits_16 */
+
+static void
+pcm_test_bits_24 (const char *filename, int filetype, uint64_t hash)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, zero_count ;
+ short *short_out, *short_in ;
+ int *int_out, *int_in ;
+ /* Lite remove start */
+ float *float_out, *float_in ;
+ double *double_out, *double_in ;
+ /* Lite remove end */
+
+ print_test_name ("pcm_test_bits_24", filename) ;
+
+ items = 1024 ;
+
+ short_out = data_out.s ;
+ short_in = data_in.s ;
+
+ zero_count = 0 ;
+ for (k = 0 ; k < items ; k++)
+ { short_out [k] = (k * ((k % 2) ? 3 : -3)) ;
+ zero_count = short_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_short_or_die (file, 0, short_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (short_in, 0, items * sizeof (short)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, short_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (short_out [k] != short_in [k])
+ { printf ("\n\nLine %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, short_out [k], short_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Finally, check the file hash. */
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_int ()
+ */
+ zero_count = 0 ;
+
+ int_out = data_out.i ;
+ int_in = data_in.i ;
+ for (k = 0 ; k < items ; k++)
+ { int_out [k] = ((k * ((k % 2) ? 3333 : -3333)) << 8) ;
+ zero_count = int_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, int_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (int_in, 0, items * sizeof (int)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, int_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (int_out [k] != int_in [k])
+ { printf ("\n\nLine %d: int : Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, int_out [k], int_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Lite remove start */
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_float ()
+ */
+ zero_count = 0 ;
+
+ float_out = data_out.f ;
+ float_in = data_in.f ;
+ for (k = 0 ; k < items ; k++)
+ { float_out [k] = (k * ((k % 2) ? 3333 : -3333)) ;
+ zero_count = (fabs (float_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_write_float_or_die (file, 0, float_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_in, 0, items * sizeof (float)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_read_float_or_die (file, 0, float_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (float_out [k] - float_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, (double) float_out [k], (double) float_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_double ()
+ */
+ zero_count = 0 ;
+
+ double_out = data_out.d ;
+ double_in = data_in.d ;
+ for (k = 0 ; k < items ; k++)
+ { double_out [k] = (k * ((k % 2) ? 3333 : -3333)) ;
+ zero_count = (fabs (double_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_write_double_or_die (file, 0, double_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_in, 0, items * sizeof (double)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_read_double_or_die (file, 0, double_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (double_out [k] - double_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: double : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, double_out [k], double_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ /* Lite remove end */
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* pcm_test_bits_24 */
+
+static void
+pcm_test_bits_32 (const char *filename, int filetype, uint64_t hash)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, zero_count ;
+ short *short_out, *short_in ;
+ int *int_out, *int_in ;
+ /* Lite remove start */
+ float *float_out, *float_in ;
+ double *double_out, *double_in ;
+ /* Lite remove end */
+
+ print_test_name ("pcm_test_bits_32", filename) ;
+
+ items = 1024 ;
+
+ short_out = data_out.s ;
+ short_in = data_in.s ;
+
+ zero_count = 0 ;
+ for (k = 0 ; k < items ; k++)
+ { short_out [k] = (k * ((k % 2) ? 3 : -3)) ;
+ zero_count = short_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_short_or_die (file, 0, short_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (short_in, 0, items * sizeof (short)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, short_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (short_out [k] != short_in [k])
+ { printf ("\n\nLine %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, short_out [k], short_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Finally, check the file hash. */
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_int ()
+ */
+ zero_count = 0 ;
+
+ int_out = data_out.i ;
+ int_in = data_in.i ;
+ for (k = 0 ; k < items ; k++)
+ { int_out [k] = (k * ((k % 2) ? 333333 : -333333)) ;
+ zero_count = int_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, int_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (int_in, 0, items * sizeof (int)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, int_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (int_out [k] != int_in [k])
+ { printf ("\n\nLine %d: int : Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, int_out [k], int_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Lite remove start */
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_float ()
+ */
+ zero_count = 0 ;
+
+ float_out = data_out.f ;
+ float_in = data_in.f ;
+ for (k = 0 ; k < items ; k++)
+ { float_out [k] = (k * ((k % 2) ? 333333 : -333333)) ;
+ zero_count = (fabs (float_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_write_float_or_die (file, 0, float_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_in, 0, items * sizeof (float)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_read_float_or_die (file, 0, float_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (float_out [k] - float_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, (double) float_out [k], (double) float_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_double ()
+ */
+ zero_count = 0 ;
+
+ double_out = data_out.d ;
+ double_in = data_in.d ;
+ for (k = 0 ; k < items ; k++)
+ { double_out [k] = (k * ((k % 2) ? 333333 : -333333)) ;
+ zero_count = (fabs (double_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_write_double_or_die (file, 0, double_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_in, 0, items * sizeof (double)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_read_double_or_die (file, 0, double_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (double_out [k] - double_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: double : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, double_out [k], double_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ /* Lite remove end */
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* pcm_test_bits_32 */
+
+
+
+/*==============================================================================
+*/
+
+static void
+pcm_test_float (const char *filename, int filetype, uint64_t hash, int replace_float)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, frames ;
+ int sign ;
+ double *data, error ;
+
+ print_test_name (replace_float ? "pcm_test_float (replace)" : "pcm_test_float", filename) ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = 1, k = 0 ; k < items ; k++)
+ { data [k] = ((double) (k * sign)) / 100.0 ;
+ sign = (sign > 0) ? -1 : 1 ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, data, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, items, __LINE__) ;
+
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Now test Stereo. */
+
+ if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_SVX) /* SVX is mono only */
+ { printf ("ok\n") ;
+ return ;
+ } ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = -1, k = 0 ; k < items ; k++)
+ data [k] = ((double) k) / 100.0 * (sign *= -1) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 2 ;
+ sfinfo.format = filetype ;
+
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_writef_double_or_die (file, 0, data, frames, __LINE__) ;
+
+ sf_close (file) ;
+
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Stereo : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != frames)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, frames, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data, frames, __LINE__) ;
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 40, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* pcm_test_float */
+
+static void
+pcm_test_double (const char *filename, int filetype, uint64_t hash, int replace_float)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, frames ;
+ int sign ;
+ double *data, error ;
+
+ /* This is the best test routine. Other should be brought up to this standard. */
+
+ print_test_name (replace_float ? "pcm_test_double (replace)" : "pcm_test_double", filename) ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = 1, k = 0 ; k < items ; k++)
+ { data [k] = ((double) (k * sign)) / 100.0 ;
+ sign = (sign > 0) ? -1 : 1 ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, data, items, __LINE__) ;
+
+ sf_close (file) ;
+
+#if (defined (WIN32) || defined (_WIN32))
+ /* File hashing on Win32 fails due to slighty different
+ ** calculated values of the sin() function.
+ */
+ hash = hash ; /* Avoid compiler warning. */
+#else
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+#endif
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, items, __LINE__) ;
+
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, 14, sfinfo.channels, __LINE__) ;
+
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Now test Stereo. */
+
+ if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_SVX) /* SVX is mono only */
+ { printf ("ok\n") ;
+ return ;
+ } ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = -1, k = 0 ; k < items ; k++)
+ data [k] = ((double) k) / 100.0 * (sign *= -1) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 2 ;
+ sfinfo.format = filetype ;
+
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_writef_double_or_die (file, 0, data, frames, __LINE__) ;
+
+ sf_close (file) ;
+
+#if (defined (WIN32) || defined (_WIN32))
+ /* File hashing on Win32 fails due to slighty different
+ ** calculated values.
+ */
+ hash = hash ; /* Avoid compiler warning. */
+#else
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+#endif
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Stereo : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != frames)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, frames, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data, frames, __LINE__) ;
+
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 40, 4, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames -10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* pcm_test_double */
+
+/*==============================================================================
+*/
diff --git a/tests/pcm_test.def b/tests/pcm_test.def
new file mode 100644
index 0000000..b81f059
--- /dev/null
+++ b/tests/pcm_test.def
@@ -0,0 +1,34 @@
+autogen definitions pcm_test.tpl;
+
+data_type = {
+ name = "bits_8" ;
+ item_count = 127 ;
+ short_func = "((k * ((k % 2) ? 1 : -1)) << 8)" ;
+ int_func = "((k * ((k % 2) ? 1 : -1)) << 24)" ;
+ float_func = "(k * ((k % 2) ? 1 : -1))" ;
+ } ;
+
+data_type = {
+ name = "bits_16" ;
+ item_count = 1024 ;
+ short_func = "(k * ((k % 2) ? 3 : -3))" ;
+ int_func = "((k * ((k % 2) ? 3 : -3)) << 16)" ;
+ float_func = "(k * ((k % 2) ? 3 : -3))" ;
+ } ;
+
+data_type = {
+ name = "bits_24" ;
+ item_count = 1024 ;
+ short_func = "(k * ((k % 2) ? 3 : -3))" ;
+ int_func = "((k * ((k % 2) ? 3333 : -3333)) << 8)" ;
+ float_func = "(k * ((k % 2) ? 3333 : -3333))" ;
+ } ;
+
+data_type = {
+ name = "bits_32" ;
+ item_count = 1024 ;
+ short_func = "(k * ((k % 2) ? 3 : -3))" ;
+ int_func = "(k * ((k % 2) ? 333333 : -333333))" ;
+ float_func = "(k * ((k % 2) ? 333333 : -333333))" ;
+ } ;
+
diff --git a/tests/pcm_test.tpl b/tests/pcm_test.tpl
new file mode 100644
index 0000000..949ad4e
--- /dev/null
+++ b/tests/pcm_test.tpl
@@ -0,0 +1,927 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (1<<12)
+
+static void lrintf_test (void) ;
+
+[+ FOR data_type
++]static void pcm_test_[+ (get "name") +] (const char *filename, int filetype, uint64_t hash) ;
+[+ ENDFOR data_type
++]
+static void pcm_test_float (const char *filename, int filetype, uint64_t hash, int replace_float) ;
+static void pcm_test_double (const char *filename, int filetype, uint64_t hash, int replace_float) ;
+
+typedef union
+{ double d [BUFFER_SIZE + 1] ;
+ float f [BUFFER_SIZE + 1] ;
+ int i [BUFFER_SIZE + 1] ;
+ short s [BUFFER_SIZE + 1] ;
+} BUFFER ;
+
+/* Data written to the file. */
+static BUFFER data_out ;
+
+/* Data read back from the file. */
+static BUFFER data_in ;
+
+int
+main (void)
+{
+ lrintf_test () ;
+
+ pcm_test_bits_8 ("pcm-s8.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_S8, 0x1cda335091249dbfLL) ;
+ pcm_test_bits_8 ("pcm-u8.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_U8, 0x7f748c433d695f3fLL) ;
+
+ pcm_test_bits_16 ("le-pcm16.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_16, 0x3a2b956c881ebf08LL) ;
+ pcm_test_bits_16 ("be-pcm16.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_16, 0xd9e2f840c55750f8LL) ;
+
+ pcm_test_bits_24 ("le-pcm24.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_24, 0x933b6a759ab496f8LL) ;
+ pcm_test_bits_24 ("be-pcm24.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_24, 0xbb1f3eaf9c30b6f8LL) ;
+
+ pcm_test_bits_32 ("le-pcm32.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_32, 0xa77aece1c1c17f08LL) ;
+ pcm_test_bits_32 ("be-pcm32.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_32, 0x3099ddf142d0b0f8LL) ;
+
+ /* Lite remove start */
+ pcm_test_float ("le-float.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x3c2ad04f7554267aLL, SF_FALSE) ;
+ pcm_test_float ("be-float.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x074de3e248fa9186LL, SF_FALSE) ;
+
+ pcm_test_double ("le-double.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xc682726f958f669cLL, SF_FALSE) ;
+ pcm_test_double ("be-double.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xd9a3583f8ee51164LL, SF_FALSE) ;
+
+ pcm_test_float ("le-float.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x3c2ad04f7554267aLL, SF_TRUE) ;
+ pcm_test_float ("be-float.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0x074de3e248fa9186LL, SF_TRUE) ;
+
+ pcm_test_double ("le-double.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xc682726f958f669cLL, SF_TRUE) ;
+ pcm_test_double ("be-double.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0xd9a3583f8ee51164LL, SF_TRUE) ;
+ /* Lite remove end */
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+lrintf_test (void)
+{ int k, items ;
+ float *float_data ;
+ int *int_data ;
+
+ print_test_name ("lrintf_test", "") ;
+
+ items = 1024 ;
+
+ float_data = data_out.f ;
+ int_data = data_in.i ;
+
+ for (k = 0 ; k < items ; k++)
+ float_data [k] = (k * ((k % 2) ? 333333.0 : -333333.0)) ;
+
+ for (k = 0 ; k < items ; k++)
+ int_data [k] = lrintf (float_data [k]) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (int_data [k] - float_data [k]) > 1.0)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %d).\n", __LINE__, k, float_data [k], int_data [k]) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+} /* lrintf_test */
+
+[+ FOR data_type
++]static void
+pcm_test_[+ (get "name") +] (const char *filename, int filetype, uint64_t hash)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, zero_count ;
+ short *short_out, *short_in ;
+ int *int_out, *int_in ;
+ /* Lite remove start */
+ float *float_out, *float_in ;
+ double *double_out, *double_in ;
+ /* Lite remove end */
+
+ print_test_name ("pcm_test_[+ (get "name") +]", filename) ;
+
+ items = [+ (get "item_count") +] ;
+
+ short_out = data_out.s ;
+ short_in = data_in.s ;
+
+ zero_count = 0 ;
+ for (k = 0 ; k < items ; k++)
+ { short_out [k] = [+ (get "short_func") +] ;
+ zero_count = short_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_short_or_die (file, 0, short_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (short_in, 0, items * sizeof (short)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, short_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (short_out [k] != short_in [k])
+ { printf ("\n\nLine %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, short_out [k], short_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Finally, check the file hash. */
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_int ()
+ */
+ zero_count = 0 ;
+
+ int_out = data_out.i ;
+ int_in = data_in.i ;
+ for (k = 0 ; k < items ; k++)
+ { int_out [k] = [+ (get "int_func") +] ;
+ zero_count = int_out [k] ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, int_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (int_in, 0, items * sizeof (int)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, int_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (int_out [k] != int_in [k])
+ { printf ("\n\nLine %d: int : Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, int_out [k], int_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Lite remove start */
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_float ()
+ */
+ zero_count = 0 ;
+
+ float_out = data_out.f ;
+ float_in = data_in.f ;
+ for (k = 0 ; k < items ; k++)
+ { float_out [k] = [+ (get "float_func") +] ;
+ zero_count = (fabs (float_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_write_float_or_die (file, 0, float_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (float_in, 0, items * sizeof (float)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+
+ test_read_float_or_die (file, 0, float_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (float_out [k] - float_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, (double) float_out [k], (double) float_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /*--------------------------------------------------------------------------
+ ** Test sf_read/write_double ()
+ */
+ zero_count = 0 ;
+
+ double_out = data_out.d ;
+ double_in = data_in.d ;
+ for (k = 0 ; k < items ; k++)
+ { double_out [k] = [+ (get "float_func") +] ;
+ zero_count = (fabs (double_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
+ } ;
+
+ if (zero_count > items / 4)
+ { printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
+ exit (1) ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_write_double_or_die (file, 0, double_out, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ memset (double_in, 0, items * sizeof (double)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+
+ test_read_double_or_die (file, 0, double_in, items, __LINE__) ;
+
+ for (k = 0 ; k < items ; k++)
+ if (fabs (double_out [k] - double_in [k]) > 1e-10)
+ { printf ("\n\nLine %d: double : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, double_out [k], double_in [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ /* Lite remove end */
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* pcm_test_[+ (get "name") +] */
+
+[+ ENDFOR data_type
++]
+
+/*==============================================================================
+*/
+
+static void
+pcm_test_float (const char *filename, int filetype, uint64_t hash, int replace_float)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, frames ;
+ int sign ;
+ double *data, error ;
+
+ print_test_name (replace_float ? "pcm_test_float (replace)" : "pcm_test_float", filename) ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = 1, k = 0 ; k < items ; k++)
+ { data [k] = ((double) (k * sign)) / 100.0 ;
+ sign = (sign > 0) ? -1 : 1 ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, data, items, __LINE__) ;
+
+ sf_close (file) ;
+
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, items, __LINE__) ;
+
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Now test Stereo. */
+
+ if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_SVX) /* SVX is mono only */
+ { printf ("ok\n") ;
+ return ;
+ } ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = -1, k = 0 ; k < items ; k++)
+ data [k] = ((double) k) / 100.0 * (sign *= -1) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 2 ;
+ sfinfo.format = filetype ;
+
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_writef_double_or_die (file, 0, data, frames, __LINE__) ;
+
+ sf_close (file) ;
+
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Stereo : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != frames)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, frames, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data, frames, __LINE__) ;
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 40, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* pcm_test_float */
+
+static void
+pcm_test_double (const char *filename, int filetype, uint64_t hash, int replace_float)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, items, frames ;
+ int sign ;
+ double *data, error ;
+
+ /* This is the best test routine. Other should be brought up to this standard. */
+
+ print_test_name (replace_float ? "pcm_test_double (replace)" : "pcm_test_double", filename) ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = 1, k = 0 ; k < items ; k++)
+ { data [k] = ((double) (k * sign)) / 100.0 ;
+ sign = (sign > 0) ? -1 : 1 ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_write_double_or_die (file, 0, data, items, __LINE__) ;
+
+ sf_close (file) ;
+
+#if (defined (WIN32) || defined (_WIN32))
+ /* File hashing on Win32 fails due to slighty different
+ ** calculated values of the sin() function.
+ */
+ hash = hash ; /* Avoid compiler warning. */
+#else
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+#endif
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != items)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, items, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, items, __LINE__) ;
+
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, 14, sfinfo.channels, __LINE__) ;
+
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Now test Stereo. */
+
+ if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_SVX) /* SVX is mono only */
+ { printf ("ok\n") ;
+ return ;
+ } ;
+
+ items = BUFFER_SIZE ;
+
+ data = data_out.d ;
+ for (sign = -1, k = 0 ; k < items ; k++)
+ data [k] = ((double) k) / 100.0 * (sign *= -1) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = items ;
+ sfinfo.channels = 2 ;
+ sfinfo.format = filetype ;
+
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ test_writef_double_or_die (file, 0, data, frames, __LINE__) ;
+
+ sf_close (file) ;
+
+#if (defined (WIN32) || defined (_WIN32))
+ /* File hashing on Win32 fails due to slighty different
+ ** calculated values.
+ */
+ hash = hash ; /* Avoid compiler warning. */
+#else
+ check_file_hash_or_die (filename, hash, __LINE__) ;
+#endif
+
+ memset (data, 0, items * sizeof (double)) ;
+
+ if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
+ if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
+ { printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nError (%s:%d) Stereo : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != frames)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of frames in file. (%d => %ld)\n", __FILE__, __LINE__, frames, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data, frames, __LINE__) ;
+
+ for (sign = -1, k = 0 ; k < items ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 40, 4, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames -10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, data + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ { error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
+ if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
+ { printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ sf_close (file) ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* pcm_test_double */
+
+/*==============================================================================
+*/
diff --git a/tests/peak_chunk_test.c b/tests/peak_chunk_test.c
new file mode 100644
index 0000000..14656aa
--- /dev/null
+++ b/tests/peak_chunk_test.c
@@ -0,0 +1,362 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<15)
+#define LOG_BUFFER_SIZE 1024
+
+
+static void test_float_peak (const char *filename, int filetype) ;
+static void read_write_peak_test (const char *filename, int filetype) ;
+
+static void check_logged_peaks (char *buffer) ;
+
+/* Force the start of this buffer to be double aligned. Sparc-solaris will
+** choke if its not.
+*/
+static double data [BUFFER_LEN] ;
+static char log_buffer [LOG_BUFFER_SIZE] ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" aiff - test AIFF file PEAK chunk\n") ;
+ printf (" caf - test CAF file PEAK chunk\n") ;
+ printf (" wav - test WAV file peak chunk\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all = ! strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { test_float_peak ("peak_float.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
+ test_float_peak ("peak_float.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ;
+ test_float_peak ("peak_float.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
+
+ read_write_peak_test ("rw_peak.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
+ read_write_peak_test ("rw_peak.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { test_float_peak ("peak_float.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
+
+ read_write_peak_test ("rw_peak.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "caf"))
+ { test_float_peak ("peak_float.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ;
+
+ read_write_peak_test ("rw_peak.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ;
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+test_float_peak (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, frames, count ;
+
+ print_test_name ("test_float_peak", filename) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = filetype ;
+ sfinfo.channels = 4 ;
+ sfinfo.frames = 0 ;
+
+ frames = BUFFER_LEN / sfinfo.channels ;
+
+ /* Create some random data with a peak value of 0.66. */
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ data [k] = (rand () % 2000) / 3000.0 ;
+
+ /* Insert some larger peaks a know locations. */
+ data [4 * (frames / 8) + 0] = (frames / 8) * 0.01 ; /* First channel */
+ data [4 * (frames / 6) + 1] = (frames / 6) * 0.01 ; /* Second channel */
+ data [4 * (frames / 4) + 2] = (frames / 4) * 0.01 ; /* Third channel */
+ data [4 * (frames / 2) + 3] = (frames / 2) * 0.01 ; /* Fourth channel */
+
+ /* Write a file with PEAK chunks. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
+
+ /* Try to confuse the header writer by adding a removing the PEAK chunk. */
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+
+ /* Write the data in four passed. The data is designed so that peaks will
+ ** be written in the different calls to sf_write_double ().
+ */
+ for (count = 0 ; count < 4 ; count ++)
+ test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ;
+
+ if (sfinfo.format != filetype)
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != frames)
+ { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, frames, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 4)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Check these two commands. */
+ if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)) == SF_FALSE)
+ { printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data [0] - (frames / 2) * 0.01) > 0.01)
+ { printf ("\n\nLine %d: Bad peak value (%f should be %f) for command SFC_GET_SIGNAL_MAX.\n", __LINE__, data [0], (frames / 2) * 0.01) ;
+ exit (1) ;
+ } ;
+
+ if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels) == SF_FALSE)
+ { printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data [3] - (frames / 2) * 0.01) > 0.01)
+ { printf ("\n\nLine %d: Bad peak value (%f should be %f) for command SFC_GET_MAX_ALL_CHANNELS.\n", __LINE__, data [0], (frames / 2) * 0.01) ;
+ exit (1) ;
+ } ;
+
+ /* Get the log buffer data. */
+ log_buffer [0] = 0 ;
+ sf_command (file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ;
+
+ if (strlen (log_buffer) == 0)
+ { printf ("\n\nLine %d: Empty log buffer,\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_logged_peaks (log_buffer) ;
+
+ sf_close (file) ;
+
+ /* Write a file ***without*** PEAK chunks. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
+
+ /* Try to confuse the header writer by adding a removing the PEAK chunk. */
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+
+ /* Write the data in four passed. The data is designed so that peaks will
+ ** be written in the different calls to sf_write_double ().
+ */
+ for (count = 0 ; count < 4 ; count ++)
+ test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ;
+
+ /* Check these two commands. */
+ if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)))
+ { printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels))
+ { printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Get the log buffer data. */
+ log_buffer [0] = 0 ;
+ sf_command (file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ;
+
+ if (strlen (log_buffer) == 0)
+ { printf ("\n\nLine %d: Empty log buffer,\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (strstr (log_buffer, "PEAK :") != NULL)
+ { printf ("\n\nLine %d: Should not have a PEAK chunk in this file.\n\n", __LINE__) ;
+ puts (log_buffer) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ printf ("ok\n") ;
+} /* test_float_peak */
+
+static void
+check_logged_peaks (char *buffer)
+{ char *cptr ;
+ int k, chan, channel_count, position ;
+ float value ;
+
+ if (strstr (buffer, "should") || strstr (buffer, "*"))
+ { printf ("\n\nLine %d: Something wrong in buffer. Dumping.\n", __LINE__) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ channel_count = 0 ;
+ cptr = strstr (buffer, "Channels") ;
+ if (cptr && sscanf (cptr, "Channels : %d", &k) == 1)
+ channel_count = k ;
+ else if (cptr && sscanf (cptr, "Channels / frame : %d", &k) == 1)
+ channel_count = k ;
+ else
+ { printf ("\n\nLine %d: Couldn't find channel count.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (channel_count != 4)
+ { printf ("\n\nLine %d: Wrong channel count (4 ->%d).\n", __LINE__, channel_count) ;
+ exit (1) ;
+ } ;
+
+ if (! (cptr = strstr (buffer, "Ch Position Value")))
+ { printf ("\n\nLine %d: Can't find PEAK data.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < channel_count ; k++)
+ { if (! (cptr = strchr (cptr, '\n')))
+ { printf ("\n\nLine %d: Got lost.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ if (sscanf (cptr, "%d %d %f", &chan, &position, &value) != 3)
+ { printf ("\n\nLine %d: sscanf failed.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ if (position == 0)
+ { printf ("\n\nLine %d: peak position for channel %d should not be at offset 0.\n", __LINE__, chan) ;
+ printf ("%s", buffer) ;
+ exit (1) ;
+ } ;
+ if (chan != k || fabs ((position) * 0.01 - value) > 1e-6)
+ { printf ("\n\nLine %d: Error : peak value incorrect!\n", __LINE__) ;
+ printf ("%s", buffer) ;
+ printf ("\n\nLine %d: %d %f %f\n", __LINE__, chan, position * 0.01, value) ;
+ exit (1) ;
+ } ;
+ cptr ++ ; /* Move past current newline. */
+ } ;
+
+} /* check_logged_peaks */
+
+static void
+read_write_peak_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+
+ double small_data [10] ;
+ double max_peak = 0.0 ;
+ unsigned k ;
+
+ print_test_name (__func__, filename) ;
+
+ for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++)
+ small_data [k] = 0.1 ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = 2 ;
+ sfinfo.format = filetype ;
+ sfinfo.frames = 0 ;
+
+ /* Open the file, add peak chunk and write samples with value 0.1. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+
+ sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+
+ test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ;
+
+ sf_close (file) ;
+
+ /* Open the fiel RDWR, write sample valied 1.25. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
+
+ for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++)
+ small_data [k] = 1.0 ;
+
+ test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ;
+
+ sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (max_peak)) ;
+
+ sf_close (file) ;
+
+ exit_if_true (max_peak < 0.1, "\n\nLine %d : max peak (%5.3f) should not be 0.1.\n\n", __LINE__, max_peak) ;
+
+ /* Open the file and test the values written to the PEAK chunk. */
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ exit_if_true (sfinfo.channels * sfinfo.frames != 2 * ARRAY_LEN (small_data),
+ "Line %d : frame count is %ld, should be %d\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * ARRAY_LEN (small_data)) ;
+
+ sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (double)) ;
+
+ sf_close (file) ;
+
+ exit_if_true (max_peak < 1.0, "\n\nLine %d : max peak (%5.3f) should be 1.0.\n\n", __LINE__, max_peak) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* read_write_peak_test */
+
diff --git a/tests/pedantic-header-test.sh.in b/tests/pedantic-header-test.sh.in
new file mode 100644
index 0000000..8b19628
--- /dev/null
+++ b/tests/pedantic-header-test.sh.in
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# Copyright (C) 2010-2011 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:
+#
+# * 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.
+# * Neither the author nor the names of any contributors may be used
+# to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# 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 OWNER 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.
+
+
+if test ! -f @top_srcdir@/tests/sfversion.c ; then
+ exit 0
+ fi
+
+echo -n " Pedantic header test : "
+
+# Only do this if the compiler is GCC.
+if test -n "@GCC_MAJOR_VERSION@" ; then
+
+ CC=`echo "@CC@" | sed "s/.*shave cc //"`
+ # Compile with -Werror and -pedantic.
+ $CC -std=c99 -Werror -pedantic -I@top_builddir@/src -c @top_srcdir@/tests/sfversion.c -o /dev/null
+
+ # Check compiler return status.
+ if test $? -ne 0 ; then
+ echo
+ exit 1
+ fi
+
+ echo "ok"
+else
+ echo "n/a"
+ fi
+
+exit 0
diff --git a/tests/pipe_test.c b/tests/pipe_test.c
new file mode 100644
index 0000000..10fa572
--- /dev/null
+++ b/tests/pipe_test.c
@@ -0,0 +1,525 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU 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 is a test program which tests reading from and writing to pipes.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if (OS_IS_WIN32 || HAVE_PIPE == 0 || HAVE_WAITPID == 0)
+
+int
+main (void)
+{
+ puts (" pipe_test : this test doesn't work on this OS.") ;
+ return 0 ;
+} /* main */
+
+#else
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+typedef struct
+{ int format ;
+ const char *ext ;
+} FILETYPE ;
+
+static int file_exists (const char *filename) ;
+static void useek_pipe_rw_test (int filetype, const char *ext) ;
+static void pipe_read_test (int filetype, const char *ext) ;
+static void pipe_write_test (const char *ext) ;
+static void pipe_test_others (FILETYPE*, FILETYPE*) ;
+
+static FILETYPE read_write_types [] =
+{ { SF_FORMAT_RAW , "raw" },
+ { SF_FORMAT_AU , "au" },
+ /* Lite remove start */
+ { SF_FORMAT_PAF , "paf" },
+ { SF_FORMAT_IRCAM , "ircam" },
+ { SF_FORMAT_PVF , "pvf" },
+ /* Lite remove end */
+ { 0 , NULL }
+} ;
+
+static FILETYPE read_only_types [] =
+{ { SF_FORMAT_RAW , "raw" },
+ { SF_FORMAT_AU , "au" },
+ { SF_FORMAT_AIFF , "aiff" },
+ { SF_FORMAT_WAV , "wav" },
+ { SF_FORMAT_W64 , "w64" },
+ /* Lite remove start */
+ { SF_FORMAT_PAF , "paf" },
+ { SF_FORMAT_NIST , "nist" },
+ { SF_FORMAT_IRCAM , "ircam" },
+ { SF_FORMAT_MAT4 , "mat4" },
+ { SF_FORMAT_MAT5 , "mat5" },
+ { SF_FORMAT_SVX , "svx" },
+ { SF_FORMAT_PVF , "pvf" },
+ /* Lite remove end */
+ { 0 , NULL }
+} ;
+
+int
+main (void)
+{ int k ;
+
+ if (file_exists ("libsndfile.spec.in"))
+ exit_if_true (chdir ("tests") != 0, "\n Error : chdir ('tests') failed.\n") ;
+
+ for (k = 0 ; read_only_types [k].format ; k++)
+ pipe_read_test (read_only_types [k].format, read_only_types [k].ext) ;
+
+ for (k = 0 ; read_write_types [k].format ; k++)
+ pipe_write_test (read_write_types [k].ext) ;
+
+ for (k = 0 ; read_write_types [k].format ; k++)
+ useek_pipe_rw_test (read_write_types [k].format, read_write_types [k].ext) ;
+
+ if (0)
+ pipe_test_others (read_write_types, read_only_types) ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+pipe_read_test (int filetype, const char *ext)
+{ static short data [PIPE_TEST_LEN] ;
+ static char buffer [256] ;
+ static char filename [256] ;
+
+ SNDFILE *outfile ;
+ SF_INFO sfinfo ;
+ int k, retval ;
+
+ snprintf (filename, sizeof (filename), "pipe_in.%s", ext) ;
+ print_test_name ("pipe_read_test", filename) ;
+
+ sfinfo.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = 44100 ;
+
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ sf_close (outfile) ;
+
+ snprintf (buffer, sizeof (buffer), "cat %s | ./stdin_test %s ", filename, ext) ;
+ if ((retval = system (buffer)) != 0)
+ { retval = WEXITSTATUS (retval) ;
+ printf ("\n\n Line %d : pipe test returned error for file type \"%s\".\n\n", __LINE__, ext) ;
+ exit (retval) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+
+ return ;
+} /* pipe_read_test */
+
+static void
+pipe_write_test (const char *ext)
+{ static char buffer [256] ;
+
+ int retval ;
+
+ print_test_name ("pipe_write_test", ext) ;
+
+ snprintf (buffer, sizeof (buffer), "./stdout_test %s | ./stdin_test %s ", ext, ext) ;
+ if ((retval = system (buffer)))
+ { retval = WEXITSTATUS (retval) ;
+ printf ("\n\n Line %d : pipe test returned error file type \"%s\".\n\n", __LINE__, ext) ;
+ exit (retval) ;
+ } ;
+
+ puts ("ok") ;
+
+ return ;
+} /* pipe_write_test */
+
+/*==============================================================================
+*/
+
+
+static void
+useek_pipe_rw_short (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
+{ static short buffer [PIPE_TEST_LEN] ;
+ static short data [PIPE_TEST_LEN] ;
+ SNDFILE *outfile ;
+ SNDFILE *infile_piped ;
+
+ int k, status = 0 ;
+ int pipefd [2] ;
+ pid_t pida ;
+
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ /*
+ ** Create the pipe.
+ */
+ exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
+
+ /*
+ ** Attach the write end of the pipe to be written to.
+ */
+ if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
+ printf ("\t%s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (outfile) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /*
+ ** Attach the read end of the pipe to be read from.
+ */
+ if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Fork a child process that will write directly into the pipe. */
+ if ((pida = fork ()) == 0) /* child process */
+ { test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ exit (0) ;
+ } ;
+
+ /* In the parent process, read from the pipe and compare what is read
+ ** to what is written, if they match everything went as planned.
+ */
+ test_readf_short_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
+ if (memcmp (buffer, data, sizeof (buffer)) != 0)
+ { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Wait for the child process to return. */
+ waitpid (pida, &status, 0) ;
+ status = WEXITSTATUS (status) ;
+ sf_close (outfile) ;
+ sf_close (infile_piped) ;
+
+ if (status != 0)
+ { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* useek_pipe_rw_short */
+
+
+static void
+useek_pipe_rw_float (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
+{ static float buffer [PIPE_TEST_LEN] ;
+ static float data [PIPE_TEST_LEN] ;
+ SNDFILE *outfile ;
+ SNDFILE *infile_piped ;
+
+ int k, status = 0 ;
+ int pipefd [2] ;
+ pid_t pida ;
+
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ /*
+ ** Create the pipe.
+ */
+ exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
+
+ /*
+ ** Attach the write end of the pipe to be written to.
+ */
+ if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
+ printf ("\t%s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (outfile) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /*
+ ** Attach the read end of the pipe to be read from.
+ */
+ if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Fork a child process that will write directly into the pipe. */
+ if ((pida = fork ()) == 0) /* child process */
+ { test_writef_float_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ exit (0) ;
+ } ;
+
+ /* In the parent process, read from the pipe and compare what is read
+ ** to what is written, if they match everything went as planned.
+ */
+ test_readf_float_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
+ if (memcmp (buffer, data, sizeof (buffer)) != 0)
+ { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Wait for the child process to return. */
+ waitpid (pida, &status, 0) ;
+ status = WEXITSTATUS (status) ;
+ sf_close (outfile) ;
+ sf_close (infile_piped) ;
+
+ if (status != 0)
+ { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* useek_pipe_rw_float */
+
+
+static void
+useek_pipe_rw_double (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
+{ static double buffer [PIPE_TEST_LEN] ;
+ static double data [PIPE_TEST_LEN] ;
+ SNDFILE *outfile ;
+ SNDFILE *infile_piped ;
+
+ int k, status = 0 ;
+ int pipefd [2] ;
+ pid_t pida ;
+
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ /*
+ ** Create the pipe.
+ */
+ exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
+
+ /*
+ ** Attach the write end of the pipe to be written to.
+ */
+ if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
+ printf ("\t%s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (outfile) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /*
+ ** Attach the read end of the pipe to be read from.
+ */
+ if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Fork a child process that will write directly into the pipe. */
+ if ((pida = fork ()) == 0) /* child process */
+ { test_writef_double_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ exit (0) ;
+ } ;
+
+ /* In the parent process, read from the pipe and compare what is read
+ ** to what is written, if they match everything went as planned.
+ */
+ test_readf_double_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
+ if (memcmp (buffer, data, sizeof (buffer)) != 0)
+ { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Wait for the child process to return. */
+ waitpid (pida, &status, 0) ;
+ status = WEXITSTATUS (status) ;
+ sf_close (outfile) ;
+ sf_close (infile_piped) ;
+
+ if (status != 0)
+ { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* useek_pipe_rw_double */
+
+
+
+
+static void
+useek_pipe_rw_test (int filetype, const char *ext)
+{ SF_INFO sfinfo_write ;
+ SF_INFO sfinfo_read ;
+
+ print_test_name ("useek_pipe_rw_test", ext) ;
+
+ /*
+ ** Setup the INFO structures for the filetype we will be
+ ** working with.
+ */
+ sfinfo_write.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo_write.channels = 1 ;
+ sfinfo_write.samplerate = 44100 ;
+
+
+ sfinfo_read.format = 0 ;
+ if (filetype == SF_FORMAT_RAW)
+ { sfinfo_read.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo_read.channels = 1 ;
+ sfinfo_read.samplerate = 44100 ;
+ } ;
+
+ useek_pipe_rw_short (ext, &sfinfo_write, &sfinfo_read) ;
+
+ sfinfo_read.format = sfinfo_write.format = filetype | SF_FORMAT_FLOAT ;
+ if (sf_format_check (&sfinfo_read) != 0)
+ useek_pipe_rw_float (ext, &sfinfo_write, &sfinfo_read) ;
+
+ sfinfo_read.format = sfinfo_write.format = filetype | SF_FORMAT_DOUBLE ;
+ if (sf_format_check (&sfinfo_read) != 0)
+ useek_pipe_rw_double (ext, &sfinfo_write, &sfinfo_read) ;
+
+ puts ("ok") ;
+ return ;
+} /* useek_pipe_rw_test */
+
+
+
+static void
+pipe_test_others (FILETYPE* list1, FILETYPE* list2)
+{ SF_FORMAT_INFO info ;
+ int k, m, major_count, in_list ;
+
+ print_test_name ("pipe_test_others", "") ;
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)) ;
+
+ for (k = 0 ; k < major_count ; k++)
+ { info.format = k ;
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof (info)) ;
+
+ in_list = SF_FALSE ;
+ for (m = 0 ; list1 [m].format ; m++)
+ if (info.format == list1 [m].format)
+ in_list = SF_TRUE ;
+
+ for (m = 0 ; list2 [m].format ; m++)
+ if (info.format == list2 [m].format)
+ in_list = SF_TRUE ;
+
+ if (in_list)
+ continue ;
+
+ printf ("%s %x\n", info.name, info.format) ;
+
+ if (1)
+ { static short data [PIPE_TEST_LEN] ;
+ static char buffer [256] ;
+ static const char *filename = "pipe_in.dat" ;
+
+ SNDFILE *outfile ;
+ SF_INFO sfinfo ;
+ int retval ;
+
+ sfinfo.format = info.format | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = 44100 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ sf_close (outfile) ;
+
+ snprintf (buffer, sizeof (buffer), "cat %s | ./stdin_test %s %d ", filename, info.extension, PIPE_TEST_LEN) ;
+ if ((retval = system (buffer)) == 0)
+ { retval = WEXITSTATUS (retval) ;
+ printf ("\n\n Line %d : pipe test should have returned error file type \"%s\" but didn't.\n\n", __LINE__, info.name) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ } ;
+ } ;
+
+
+ puts ("ok") ;
+
+ return ;
+} /* pipe_test_others */
+
+
+/*==============================================================================
+*/
+
+static int
+file_exists (const char *filename)
+{ struct stat buf ;
+
+ if (stat (filename, &buf))
+ return 0 ;
+
+ return 1 ;
+} /* file_exists */
+
+#endif
+
diff --git a/tests/pipe_test.def b/tests/pipe_test.def
new file mode 100644
index 0000000..6469cca
--- /dev/null
+++ b/tests/pipe_test.def
@@ -0,0 +1,14 @@
+autogen definitions pipe_test.tpl;
+
+data_type = {
+ type_name = short ;
+ };
+
+data_type = {
+ type_name = float ;
+ };
+
+data_type = {
+ type_name = double ;
+ };
+
diff --git a/tests/pipe_test.tpl b/tests/pipe_test.tpl
new file mode 100644
index 0000000..5215556
--- /dev/null
+++ b/tests/pipe_test.tpl
@@ -0,0 +1,374 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU 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 is a test program which tests reading from and writing to pipes.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if (OS_IS_WIN32 || HAVE_PIPE == 0 || HAVE_WAITPID == 0)
+
+int
+main (void)
+{
+ puts (" pipe_test : this test doesn't work on this OS.") ;
+ return 0 ;
+} /* main */
+
+#else
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+typedef struct
+{ int format ;
+ const char *ext ;
+} FILETYPE ;
+
+static int file_exists (const char *filename) ;
+static void useek_pipe_rw_test (int filetype, const char *ext) ;
+static void pipe_read_test (int filetype, const char *ext) ;
+static void pipe_write_test (const char *ext) ;
+static void pipe_test_others (FILETYPE*, FILETYPE*) ;
+
+static FILETYPE read_write_types [] =
+{ { SF_FORMAT_RAW , "raw" },
+ { SF_FORMAT_AU , "au" },
+ /* Lite remove start */
+ { SF_FORMAT_PAF , "paf" },
+ { SF_FORMAT_IRCAM , "ircam" },
+ { SF_FORMAT_PVF , "pvf" },
+ /* Lite remove end */
+ { 0 , NULL }
+} ;
+
+static FILETYPE read_only_types [] =
+{ { SF_FORMAT_RAW , "raw" },
+ { SF_FORMAT_AU , "au" },
+ { SF_FORMAT_AIFF , "aiff" },
+ { SF_FORMAT_WAV , "wav" },
+ { SF_FORMAT_W64 , "w64" },
+ /* Lite remove start */
+ { SF_FORMAT_PAF , "paf" },
+ { SF_FORMAT_NIST , "nist" },
+ { SF_FORMAT_IRCAM , "ircam" },
+ { SF_FORMAT_MAT4 , "mat4" },
+ { SF_FORMAT_MAT5 , "mat5" },
+ { SF_FORMAT_SVX , "svx" },
+ { SF_FORMAT_PVF , "pvf" },
+ /* Lite remove end */
+ { 0 , NULL }
+} ;
+
+int
+main (void)
+{ int k ;
+
+ if (file_exists ("libsndfile.spec.in"))
+ exit_if_true (chdir ("tests") != 0, "\n Error : chdir ('tests') failed.\n") ;
+
+ for (k = 0 ; read_only_types [k].format ; k++)
+ pipe_read_test (read_only_types [k].format, read_only_types [k].ext) ;
+
+ for (k = 0 ; read_write_types [k].format ; k++)
+ pipe_write_test (read_write_types [k].ext) ;
+
+ for (k = 0 ; read_write_types [k].format ; k++)
+ useek_pipe_rw_test (read_write_types [k].format, read_write_types [k].ext) ;
+
+ if (0)
+ pipe_test_others (read_write_types, read_only_types) ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static void
+pipe_read_test (int filetype, const char *ext)
+{ static short data [PIPE_TEST_LEN] ;
+ static char buffer [256] ;
+ static char filename [256] ;
+
+ SNDFILE *outfile ;
+ SF_INFO sfinfo ;
+ int k, retval ;
+
+ snprintf (filename, sizeof (filename), "pipe_in.%s", ext) ;
+ print_test_name ("pipe_read_test", filename) ;
+
+ sfinfo.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = 44100 ;
+
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ sf_close (outfile) ;
+
+ snprintf (buffer, sizeof (buffer), "cat %s | ./stdin_test %s ", filename, ext) ;
+ if ((retval = system (buffer)) != 0)
+ { retval = WEXITSTATUS (retval) ;
+ printf ("\n\n Line %d : pipe test returned error for file type \"%s\".\n\n", __LINE__, ext) ;
+ exit (retval) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+
+ return ;
+} /* pipe_read_test */
+
+static void
+pipe_write_test (const char *ext)
+{ static char buffer [256] ;
+
+ int retval ;
+
+ print_test_name ("pipe_write_test", ext) ;
+
+ snprintf (buffer, sizeof (buffer), "./stdout_test %s | ./stdin_test %s ", ext, ext) ;
+ if ((retval = system (buffer)))
+ { retval = WEXITSTATUS (retval) ;
+ printf ("\n\n Line %d : pipe test returned error file type \"%s\".\n\n", __LINE__, ext) ;
+ exit (retval) ;
+ } ;
+
+ puts ("ok") ;
+
+ return ;
+} /* pipe_write_test */
+
+/*==============================================================================
+*/
+
+[+ FOR data_type +]
+static void
+useek_pipe_rw_[+ (get "type_name") +] (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
+{ static [+ (get "type_name") +] buffer [PIPE_TEST_LEN] ;
+ static [+ (get "type_name") +] data [PIPE_TEST_LEN] ;
+ SNDFILE *outfile ;
+ SNDFILE *infile_piped ;
+
+ int k, status = 0 ;
+ int pipefd [2] ;
+ pid_t pida ;
+
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ /*
+ ** Create the pipe.
+ */
+ exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
+
+ /*
+ ** Attach the write end of the pipe to be written to.
+ */
+ if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
+ printf ("\t%s\n\n", sf_strerror (outfile)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (outfile) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /*
+ ** Attach the read end of the pipe to be read from.
+ */
+ if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
+ { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
+ { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Fork a child process that will write directly into the pipe. */
+ if ((pida = fork ()) == 0) /* child process */
+ { test_writef_[+ (get "type_name") +]_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ exit (0) ;
+ } ;
+
+ /* In the parent process, read from the pipe and compare what is read
+ ** to what is written, if they match everything went as planned.
+ */
+ test_readf_[+ (get "type_name") +]_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
+ if (memcmp (buffer, data, sizeof (buffer)) != 0)
+ { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
+ exit (1) ;
+ } ;
+
+ /* Wait for the child process to return. */
+ waitpid (pida, &status, 0) ;
+ status = WEXITSTATUS (status) ;
+ sf_close (outfile) ;
+ sf_close (infile_piped) ;
+
+ if (status != 0)
+ { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* useek_pipe_rw_[+ (get "type_name") +] */
+
+[+ ENDFOR data_type +]
+
+
+static void
+useek_pipe_rw_test (int filetype, const char *ext)
+{ SF_INFO sfinfo_write ;
+ SF_INFO sfinfo_read ;
+
+ print_test_name ("useek_pipe_rw_test", ext) ;
+
+ /*
+ ** Setup the INFO structures for the filetype we will be
+ ** working with.
+ */
+ sfinfo_write.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo_write.channels = 1 ;
+ sfinfo_write.samplerate = 44100 ;
+
+
+ sfinfo_read.format = 0 ;
+ if (filetype == SF_FORMAT_RAW)
+ { sfinfo_read.format = filetype | SF_FORMAT_PCM_16 ;
+ sfinfo_read.channels = 1 ;
+ sfinfo_read.samplerate = 44100 ;
+ } ;
+
+ useek_pipe_rw_short (ext, &sfinfo_write, &sfinfo_read) ;
+
+ sfinfo_read.format = sfinfo_write.format = filetype | SF_FORMAT_FLOAT ;
+ if (sf_format_check (&sfinfo_read) != 0)
+ useek_pipe_rw_float (ext, &sfinfo_write, &sfinfo_read) ;
+
+ sfinfo_read.format = sfinfo_write.format = filetype | SF_FORMAT_DOUBLE ;
+ if (sf_format_check (&sfinfo_read) != 0)
+ useek_pipe_rw_double (ext, &sfinfo_write, &sfinfo_read) ;
+
+ puts ("ok") ;
+ return ;
+} /* useek_pipe_rw_test */
+
+
+
+static void
+pipe_test_others (FILETYPE* list1, FILETYPE* list2)
+{ SF_FORMAT_INFO info ;
+ int k, m, major_count, in_list ;
+
+ print_test_name ("pipe_test_others", "") ;
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)) ;
+
+ for (k = 0 ; k < major_count ; k++)
+ { info.format = k ;
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof (info)) ;
+
+ in_list = SF_FALSE ;
+ for (m = 0 ; list1 [m].format ; m++)
+ if (info.format == list1 [m].format)
+ in_list = SF_TRUE ;
+
+ for (m = 0 ; list2 [m].format ; m++)
+ if (info.format == list2 [m].format)
+ in_list = SF_TRUE ;
+
+ if (in_list)
+ continue ;
+
+ printf ("%s %x\n", info.name, info.format) ;
+
+ if (1)
+ { static short data [PIPE_TEST_LEN] ;
+ static char buffer [256] ;
+ static const char *filename = "pipe_in.dat" ;
+
+ SNDFILE *outfile ;
+ SF_INFO sfinfo ;
+ int retval ;
+
+ sfinfo.format = info.format | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = 44100 ;
+
+ outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
+ sf_close (outfile) ;
+
+ snprintf (buffer, sizeof (buffer), "cat %s | ./stdin_test %s %d ", filename, info.extension, PIPE_TEST_LEN) ;
+ if ((retval = system (buffer)) == 0)
+ { retval = WEXITSTATUS (retval) ;
+ printf ("\n\n Line %d : pipe test should have returned error file type \"%s\" but didn't.\n\n", __LINE__, info.name) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+ } ;
+ } ;
+
+
+ puts ("ok") ;
+
+ return ;
+} /* pipe_test_others */
+
+
+/*==============================================================================
+*/
+
+static int
+file_exists (const char *filename)
+{ struct stat buf ;
+
+ if (stat (filename, &buf))
+ return 0 ;
+
+ return 1 ;
+} /* file_exists */
+
+#endif
+
diff --git a/tests/raw_test.c b/tests/raw_test.c
new file mode 100644
index 0000000..96fd926
--- /dev/null
+++ b/tests/raw_test.c
@@ -0,0 +1,186 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<10)
+#define LOG_BUFFER_SIZE 1024
+
+static void raw_offset_test (const char *filename, int typeminor) ;
+static void bad_raw_test (void) ;
+
+/* Force the start of this buffer to be double aligned. Sparc-solaris will
+** choke if its not.
+*/
+static short data [BUFFER_LEN] ;
+
+int
+main (void)
+{
+ raw_offset_test ("offset.raw", SF_FORMAT_PCM_16) ;
+ bad_raw_test () ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+raw_offset_test (const char *filename, int typeminor)
+{ SNDFILE *sndfile ;
+ SF_INFO sfinfo ;
+ sf_count_t start ;
+ int k ;
+
+ print_test_name ("raw_offset_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = SF_FORMAT_RAW | typeminor ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ sndfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ start = 0 ;
+ sf_command (sndfile, SFC_FILE_TRUNCATE, &start, sizeof (start)) ;
+
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ data [k] = k ;
+ test_write_short_or_die (sndfile, 0, data, BUFFER_LEN, __LINE__) ;
+
+ sf_close (sndfile) ;
+
+ sndfile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ check_log_buffer_or_die (sndfile, __LINE__) ;
+
+ if (abs (BUFFER_LEN - sfinfo.frames) > 1)
+ { printf ("\n\nLine %d : Incorrect sample count (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), BUFFER_LEN) ;
+ dump_log_buffer (sndfile) ;
+ exit (1) ;
+ } ;
+
+ memset (data, 0 , sizeof (data)) ;
+ test_read_short_or_die (sndfile, 0, data, BUFFER_LEN, __LINE__) ;
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (data [k] != k)
+ printf ("Error : line %d\n", __LINE__) ;
+
+ /* Set dataoffset to 2 bytes from beginning of file. */
+ start = 2 ;
+ sf_command (sndfile, SFC_SET_RAW_START_OFFSET, &start, sizeof (start)) ;
+
+ /* Seek to new start */
+ test_seek_or_die (sndfile, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ memset (data, 0 , sizeof (data)) ;
+ test_read_short_or_die (sndfile, 0, data, BUFFER_LEN - 1, __LINE__) ;
+ for (k = 0 ; k < BUFFER_LEN - 1 ; k++)
+ if (data [k] != k + 1)
+ { printf ("Error : line %d\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Set dataoffset to 4 bytes from beginning of file. */
+ start = 4 ;
+ sf_command (sndfile, SFC_SET_RAW_START_OFFSET, &start, sizeof (start)) ;
+
+ /* Seek to new start */
+ test_seek_or_die (sndfile, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ memset (data, 0 , sizeof (data)) ;
+ test_read_short_or_die (sndfile, 0, data, BUFFER_LEN - 2, __LINE__) ;
+ for (k = 0 ; k < BUFFER_LEN - 2 ; k++)
+ if (data [k] != k + 2)
+ { printf ("Error : line %d\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Set dataoffset back to 0 bytes from beginning of file. */
+ start = 0 ;
+ sf_command (sndfile, SFC_SET_RAW_START_OFFSET, &start, sizeof (start)) ;
+
+ /* Seek to new start */
+ test_seek_or_die (sndfile, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ memset (data, 0 , sizeof (data)) ;
+ test_read_short_or_die (sndfile, 0, data, BUFFER_LEN, __LINE__) ;
+ for (k = 0 ; k < BUFFER_LEN ; k++)
+ if (data [k] != k)
+ { printf ("Error : line %d\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ sf_close (sndfile) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* raw_offset_test */
+
+static void
+bad_raw_test (void)
+{ FILE *textfile ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ const char *errorstr, *filename = "bad.raw" ;
+
+ print_test_name ("bad_raw_test", filename) ;
+
+ if ((textfile = fopen (filename, "w")) == NULL)
+ { printf ("\n\nLine %d : not able to open text file for write.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ fprintf (textfile, "This is not a valid file.\n") ;
+ fclose (textfile) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = SF_FORMAT_RAW | 0xABCD ;
+ sfinfo.channels = 1 ;
+
+ if ((file = sf_open (filename, SFM_READ, &sfinfo)) != NULL)
+ { printf ("\n\nLine %d : Error, file should not have opened.\n", __LINE__ - 1) ;
+ exit (1) ;
+ } ;
+
+ errorstr = sf_strerror (file) ;
+
+ if (strstr (errorstr, "Bad format field in SF_INFO struct") == NULL)
+ { printf ("\n\nLine %d : Error bad error string : %s.\n", __LINE__ - 1, errorstr) ;
+ exit (1) ;
+ } ;
+
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* bad_raw_test */
+
diff --git a/tests/rdwr_test.c b/tests/rdwr_test.c
new file mode 100644
index 0000000..d6f1222
--- /dev/null
+++ b/tests/rdwr_test.c
@@ -0,0 +1,240 @@
+/*
+** Copyright (C) 2010-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation ; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <io.h>
+#include <direct.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+static void rdwr_short_test (const char *filename) ;
+static void rdwr_int_test (const char *filename) ;
+static void rdwr_float_test (const char *filename) ;
+static void rdwr_double_test (const char *filename) ;
+static void rdwr_raw_test (const char *filename) ;
+
+
+int
+main (void)
+{
+ rdwr_short_test ("rdwr_short.wav") ;
+ rdwr_int_test ("rdwr_int.wav") ;
+ rdwr_float_test ("rdwr_float.wav") ;
+ rdwr_double_test ("rdwr_double.wav") ;
+ rdwr_raw_test ("rdwr_raw.wav") ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static void
+rdwr_short_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ short buffer [160] ;
+
+ print_test_name ("rdwr_short_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound file with no data. */
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
+ sfinfo.samplerate = 16000 ;
+ sfinfo.channels = 1 ;
+
+ unlink (filename) ;
+
+ frames = ARRAY_LEN (buffer) ;
+
+ /* Open again for read/write. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_short_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ test_read_short_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* rdwr_short_test */
+
+static void
+rdwr_int_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ int buffer [160] ;
+
+ print_test_name ("rdwr_int_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound file with no data. */
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_32 ;
+ sfinfo.samplerate = 16000 ;
+ sfinfo.channels = 1 ;
+
+ unlink (filename) ;
+
+ frames = ARRAY_LEN (buffer) ;
+
+ /* Open again for read/write. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_int_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ test_read_int_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* rdwr_int_test */
+
+static void
+rdwr_float_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ float buffer [160] ;
+
+ print_test_name ("rdwr_float_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound file with no data. */
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT ;
+ sfinfo.samplerate = 16000 ;
+ sfinfo.channels = 1 ;
+
+ unlink (filename) ;
+
+ frames = ARRAY_LEN (buffer) ;
+
+ /* Open again for read/write. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_float_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ test_read_float_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* rdwr_float_test */
+
+static void
+rdwr_double_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ double buffer [160] ;
+
+ print_test_name ("rdwr_double_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound file with no data. */
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_DOUBLE ;
+ sfinfo.samplerate = 16000 ;
+ sfinfo.channels = 1 ;
+
+ unlink (filename) ;
+
+ frames = ARRAY_LEN (buffer) ;
+
+ /* Open again for read/write. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_double_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ test_read_double_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* rdwr_double_test */
+
+static void
+rdwr_raw_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ unsigned char buffer [160] ;
+
+ print_test_name ("rdwr_raw_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound file with no data. */
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8 ;
+ sfinfo.samplerate = 16000 ;
+ sfinfo.channels = 1 ;
+
+ unlink (filename) ;
+
+ frames = ARRAY_LEN (buffer) ;
+
+ /* Open again for read/write. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_raw_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ test_read_raw_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* rdwr_raw_test */
+
+
+
diff --git a/tests/rdwr_test.def b/tests/rdwr_test.def
new file mode 100644
index 0000000..43c1089
--- /dev/null
+++ b/tests/rdwr_test.def
@@ -0,0 +1,32 @@
+autogen definitions rdwr_test.tpl;
+
+data_type = {
+ name = "short" ;
+ type = "short" ;
+ format = "SF_FORMAT_PCM_16" ;
+ } ;
+
+data_type = {
+ name = "int" ;
+ type = "int" ;
+ format = "SF_FORMAT_PCM_32" ;
+ } ;
+
+data_type = {
+ name = "float" ;
+ type = "float" ;
+ format = "SF_FORMAT_FLOAT" ;
+ } ;
+
+data_type = {
+ name = "double" ;
+ type = "double" ;
+ format = "SF_FORMAT_DOUBLE" ;
+ } ;
+
+data_type = {
+ name = "raw" ;
+ type = "unsigned char" ;
+ format = "SF_FORMAT_PCM_U8" ;
+ } ;
+
diff --git a/tests/rdwr_test.tpl b/tests/rdwr_test.tpl
new file mode 100644
index 0000000..dc862e2
--- /dev/null
+++ b/tests/rdwr_test.tpl
@@ -0,0 +1,105 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 2010-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation ; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <io.h>
+#include <direct.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+[+ FOR data_type
++]static void rdwr_[+ (get "name") +]_test (const char *filename) ;
+[+ ENDFOR data_type
++]
+
+int
+main (void)
+{
+ rdwr_short_test ("rdwr_short.wav") ;
+ rdwr_int_test ("rdwr_int.wav") ;
+ rdwr_float_test ("rdwr_float.wav") ;
+ rdwr_double_test ("rdwr_double.wav") ;
+ rdwr_raw_test ("rdwr_raw.wav") ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+[+ FOR data_type
++]static void
+rdwr_[+ (get "name") +]_test (const char *filename)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ [+ (get "type") +] buffer [160] ;
+
+ print_test_name ("rdwr_[+ (get "name") +]_test", filename) ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Create sound file with no data. */
+ sfinfo.format = SF_FORMAT_WAV | [+ (get "format") +] ;
+ sfinfo.samplerate = 16000 ;
+ sfinfo.channels = 1 ;
+
+ unlink (filename) ;
+
+ frames = ARRAY_LEN (buffer) ;
+
+ /* Open again for read/write. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
+
+ test_write_[+ (get "name") +]_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ test_read_[+ (get "name") +]_or_die (file, 0, buffer, frames, __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* rdwr_[+ (get "name") +]_test */
+
+[+ ENDFOR data_type
++]
+
diff --git a/tests/scale_clip_test.c b/tests/scale_clip_test.c
new file mode 100644
index 0000000..57b0b96
--- /dev/null
+++ b/tests/scale_clip_test.c
@@ -0,0 +1,1853 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+#define HALF_BUFFER_SIZE (1 << 12)
+#define BUFFER_SIZE (2 * HALF_BUFFER_SIZE)
+
+#define SINE_AMP 1.1
+#define MAX_ERROR 0.0202
+
+
+static void flt_scale_clip_test_16 (const char *filename, int filetype, float maxval) ;
+static void flt_scale_clip_test_24 (const char *filename, int filetype, float maxval) ;
+static void flt_scale_clip_test_32 (const char *filename, int filetype, float maxval) ;
+static void flt_scale_clip_test_08 (const char *filename, int filetype, float maxval) ;
+
+static void dbl_scale_clip_test_16 (const char *filename, int filetype, float maxval) ;
+static void dbl_scale_clip_test_24 (const char *filename, int filetype, float maxval) ;
+static void dbl_scale_clip_test_32 (const char *filename, int filetype, float maxval) ;
+static void dbl_scale_clip_test_08 (const char *filename, int filetype, float maxval) ;
+
+
+
+static void flt_short_clip_read_test (const char *filename, int filetype) ;
+static void flt_int_clip_read_test (const char *filename, int filetype) ;
+
+static void dbl_short_clip_read_test (const char *filename, int filetype) ;
+static void dbl_int_clip_read_test (const char *filename, int filetype) ;
+
+
+
+static void short_flt_scale_write_test (const char *filename, int filetype) ;
+static void short_dbl_scale_write_test (const char *filename, int filetype) ;
+
+static void int_flt_scale_write_test (const char *filename, int filetype) ;
+static void int_dbl_scale_write_test (const char *filename, int filetype) ;
+
+
+typedef union
+{ double dbl [BUFFER_SIZE] ;
+ float flt [BUFFER_SIZE] ;
+ int i [BUFFER_SIZE] ;
+ short s [BUFFER_SIZE] ;
+} BUFFER ;
+
+/* Data buffer. */
+static BUFFER buffer_out ;
+static BUFFER buffer_in ;
+
+int
+main (void)
+{
+ flt_scale_clip_test_08 ("scale_clip_s8.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8, 1.0 * 0x80) ;
+ flt_scale_clip_test_08 ("scale_clip_u8.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 1.0 * 0x80) ;
+
+ dbl_scale_clip_test_08 ("scale_clip_s8.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8, 1.0 * 0x80) ;
+ dbl_scale_clip_test_08 ("scale_clip_u8.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 1.0 * 0x80) ;
+
+ /*
+ ** Now use SF_FORMAT_AU where possible because it allows both
+ ** big and little endian files.
+ */
+
+ flt_scale_clip_test_16 ("scale_clip_be16.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ flt_scale_clip_test_16 ("scale_clip_le16.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ flt_scale_clip_test_24 ("scale_clip_be24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ flt_scale_clip_test_24 ("scale_clip_le24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ flt_scale_clip_test_32 ("scale_clip_be32.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+ flt_scale_clip_test_32 ("scale_clip_le32.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+
+ dbl_scale_clip_test_16 ("scale_clip_be16.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ dbl_scale_clip_test_16 ("scale_clip_le16.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ dbl_scale_clip_test_24 ("scale_clip_be24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ dbl_scale_clip_test_24 ("scale_clip_le24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ dbl_scale_clip_test_32 ("scale_clip_be32.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+ dbl_scale_clip_test_32 ("scale_clip_le32.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+
+ flt_short_clip_read_test ("flt_short.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ flt_int_clip_read_test ("flt_int.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ dbl_short_clip_read_test ("dbl_short.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+ dbl_int_clip_read_test ("dbl_int.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+
+ short_flt_scale_write_test ("short_flt.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ int_flt_scale_write_test ("int_flt.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ short_dbl_scale_write_test ("short_dbl.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+ int_dbl_scale_write_test ("int_dbl.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+
+static void
+flt_scale_clip_test_16 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ float *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("flt_scale_clip_test_16", filename) ;
+
+ data_out = buffer_out.flt ;
+ data_in = buffer_in.flt ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_float_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_write_float_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_read_float_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x8000)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* flt_scale_clip_test_16 */
+
+static void
+flt_scale_clip_test_24 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ float *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("flt_scale_clip_test_24", filename) ;
+
+ data_out = buffer_out.flt ;
+ data_in = buffer_in.flt ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_float_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_write_float_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_read_float_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x800000)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* flt_scale_clip_test_24 */
+
+static void
+flt_scale_clip_test_32 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ float *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("flt_scale_clip_test_32", filename) ;
+
+ data_out = buffer_out.flt ;
+ data_in = buffer_in.flt ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_float_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_write_float_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_read_float_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x80000000)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* flt_scale_clip_test_32 */
+
+static void
+flt_scale_clip_test_08 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ float *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("flt_scale_clip_test_08", filename) ;
+
+ data_out = buffer_out.flt ;
+ data_in = buffer_in.flt ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_float_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_write_float_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+ test_read_float_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x80)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* flt_scale_clip_test_08 */
+
+
+
+static void
+dbl_scale_clip_test_16 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ double *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("dbl_scale_clip_test_16", filename) ;
+
+ data_out = buffer_out.dbl ;
+ data_in = buffer_in.dbl ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_double_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_write_double_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_read_double_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x8000)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* dbl_scale_clip_test_16 */
+
+static void
+dbl_scale_clip_test_24 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ double *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("dbl_scale_clip_test_24", filename) ;
+
+ data_out = buffer_out.dbl ;
+ data_in = buffer_in.dbl ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_double_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_write_double_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_read_double_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x800000)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* dbl_scale_clip_test_24 */
+
+static void
+dbl_scale_clip_test_32 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ double *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("dbl_scale_clip_test_32", filename) ;
+
+ data_out = buffer_out.dbl ;
+ data_in = buffer_in.dbl ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_double_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_write_double_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_read_double_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x80000000)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* dbl_scale_clip_test_32 */
+
+static void
+dbl_scale_clip_test_08 (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ double *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("dbl_scale_clip_test_08", filename) ;
+
+ data_out = buffer_out.dbl ;
+ data_in = buffer_in.dbl ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_double_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_write_double_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+ test_read_double_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0 / 0x80)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* dbl_scale_clip_test_08 */
+
+
+
+
+/*==============================================================================
+*/
+
+
+static void flt_short_clip_read_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ float *data_out ;
+ short *data_in, max_value ;
+ int k ;
+
+ print_test_name ("flt_short_clip_read_test", filename) ;
+
+ data_out = buffer_out.flt ;
+ data_in = buffer_in.s ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = 0.995 * sin (4 * M_PI * k / BUFFER_SIZE) ;
+ data_out [BUFFER_SIZE / 8] = 1.0 ;
+ data_out [3 * BUFFER_SIZE / 8] = -1.000000001 ;
+ data_out [5 * BUFFER_SIZE / 8] = 1.0 ;
+ data_out [7 * BUFFER_SIZE / 8] = -1.000000001 ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /* Save unclipped data to the file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_float_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_read_short_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+ /*-sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;-*/
+ sf_close (file) ;
+
+ /* Check the first half. */
+ max_value = 0 ;
+ for (k = 0 ; k < sfinfo.frames ; k++)
+ { /* Check if data_out has different sign from data_in. */
+ if ((data_out [k] < 0.0 && data_in [k] > 0) || (data_out [k] > 0.0 && data_in [k] < 0))
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d (%f -> %d).\n\n", __LINE__, k, BUFFER_SIZE, data_out [k], data_in [k]) ;
+ exit (1) ;
+ } ;
+ max_value = (max_value > abs (data_in [k])) ? max_value : abs (data_in [k]) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* flt_short_clip_read_test */
+static void flt_int_clip_read_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ float *data_out ;
+ int *data_in, max_value ;
+ int k ;
+
+ print_test_name ("flt_int_clip_read_test", filename) ;
+
+ data_out = buffer_out.flt ;
+ data_in = buffer_in.i ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = 0.995 * sin (4 * M_PI * k / BUFFER_SIZE) ;
+ data_out [BUFFER_SIZE / 8] = 1.0 ;
+ data_out [3 * BUFFER_SIZE / 8] = -1.000000001 ;
+ data_out [5 * BUFFER_SIZE / 8] = 1.0 ;
+ data_out [7 * BUFFER_SIZE / 8] = -1.000000001 ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /* Save unclipped data to the file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_float_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_read_int_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+ /*-sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;-*/
+ sf_close (file) ;
+
+ /* Check the first half. */
+ max_value = 0 ;
+ for (k = 0 ; k < sfinfo.frames ; k++)
+ { /* Check if data_out has different sign from data_in. */
+ if ((data_out [k] < 0.0 && data_in [k] > 0) || (data_out [k] > 0.0 && data_in [k] < 0))
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d (%f -> %d).\n\n", __LINE__, k, BUFFER_SIZE, data_out [k], data_in [k]) ;
+ exit (1) ;
+ } ;
+ max_value = (max_value > abs (data_in [k])) ? max_value : abs (data_in [k]) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* flt_int_clip_read_test */
+
+static void dbl_short_clip_read_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double *data_out ;
+ short *data_in, max_value ;
+ int k ;
+
+ print_test_name ("dbl_short_clip_read_test", filename) ;
+
+ data_out = buffer_out.dbl ;
+ data_in = buffer_in.s ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = 0.995 * sin (4 * M_PI * k / BUFFER_SIZE) ;
+ data_out [BUFFER_SIZE / 8] = 1.0 ;
+ data_out [3 * BUFFER_SIZE / 8] = -1.000000001 ;
+ data_out [5 * BUFFER_SIZE / 8] = 1.0 ;
+ data_out [7 * BUFFER_SIZE / 8] = -1.000000001 ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /* Save unclipped data to the file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_read_short_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+ /*-sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;-*/
+ sf_close (file) ;
+
+ /* Check the first half. */
+ max_value = 0 ;
+ for (k = 0 ; k < sfinfo.frames ; k++)
+ { /* Check if data_out has different sign from data_in. */
+ if ((data_out [k] < 0.0 && data_in [k] > 0) || (data_out [k] > 0.0 && data_in [k] < 0))
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d (%f -> %d).\n\n", __LINE__, k, BUFFER_SIZE, data_out [k], data_in [k]) ;
+ exit (1) ;
+ } ;
+ max_value = (max_value > abs (data_in [k])) ? max_value : abs (data_in [k]) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* dbl_short_clip_read_test */
+static void dbl_int_clip_read_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double *data_out ;
+ int *data_in, max_value ;
+ int k ;
+
+ print_test_name ("dbl_int_clip_read_test", filename) ;
+
+ data_out = buffer_out.dbl ;
+ data_in = buffer_in.i ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = 0.995 * sin (4 * M_PI * k / BUFFER_SIZE) ;
+ data_out [BUFFER_SIZE / 8] = 1.0 ;
+ data_out [3 * BUFFER_SIZE / 8] = -1.000000001 ;
+ data_out [5 * BUFFER_SIZE / 8] = 1.0 ;
+ data_out [7 * BUFFER_SIZE / 8] = -1.000000001 ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /* Save unclipped data to the file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_double_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_read_int_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+ /*-sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;-*/
+ sf_close (file) ;
+
+ /* Check the first half. */
+ max_value = 0 ;
+ for (k = 0 ; k < sfinfo.frames ; k++)
+ { /* Check if data_out has different sign from data_in. */
+ if ((data_out [k] < 0.0 && data_in [k] > 0) || (data_out [k] > 0.0 && data_in [k] < 0))
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d (%f -> %d).\n\n", __LINE__, k, BUFFER_SIZE, data_out [k], data_in [k]) ;
+ exit (1) ;
+ } ;
+ max_value = (max_value > abs (data_in [k])) ? max_value : abs (data_in [k]) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* dbl_int_clip_read_test */
+
+
+/*==============================================================================
+*/
+
+
+static void short_flt_scale_write_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *data_out ;
+ float *data_in, max_value ;
+ int k ;
+
+ print_test_name ("short_flt_clip_write_test", filename) ;
+
+ data_out = buffer_out.s ;
+ data_in = buffer_in.flt ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = lrintf (0x7FFFF * 0.995 * sin (4 * M_PI * k / BUFFER_SIZE)) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_short_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
+ test_write_short_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_FALSE) ;
+ test_write_short_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != 3 * BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, 3 * BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ /* Check the first section. */
+ test_read_float_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the second section. */
+ test_read_float_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value > 1.0)
+ { printf ("\n\nLine %d: Max value (%f) > 1.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the third section. */
+ test_read_float_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* short_flt_scale_write_test */
+static void short_dbl_scale_write_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *data_out ;
+ double *data_in, max_value ;
+ int k ;
+
+ print_test_name ("short_dbl_clip_write_test", filename) ;
+
+ data_out = buffer_out.s ;
+ data_in = buffer_in.dbl ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = lrint (0x7FFFF * 0.995 * sin (4 * M_PI * k / BUFFER_SIZE)) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_short_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
+ test_write_short_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_FALSE) ;
+ test_write_short_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != 3 * BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, 3 * BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ /* Check the first section. */
+ test_read_double_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the second section. */
+ test_read_double_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value > 1.0)
+ { printf ("\n\nLine %d: Max value (%f) > 1.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the third section. */
+ test_read_double_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* short_dbl_scale_write_test */
+
+static void int_flt_scale_write_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *data_out ;
+ float *data_in, max_value ;
+ int k ;
+
+ print_test_name ("int_flt_clip_write_test", filename) ;
+
+ data_out = buffer_out.i ;
+ data_in = buffer_in.flt ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = lrintf (0x7FFFFFFF * 0.995 * sin (4 * M_PI * k / BUFFER_SIZE)) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_int_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
+ test_write_int_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_FALSE) ;
+ test_write_int_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != 3 * BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, 3 * BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ /* Check the first section. */
+ test_read_float_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the second section. */
+ test_read_float_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value > 1.0)
+ { printf ("\n\nLine %d: Max value (%f) > 1.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the third section. */
+ test_read_float_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* int_flt_scale_write_test */
+static void int_dbl_scale_write_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *data_out ;
+ double *data_in, max_value ;
+ int k ;
+
+ print_test_name ("int_dbl_clip_write_test", filename) ;
+
+ data_out = buffer_out.i ;
+ data_in = buffer_in.dbl ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = lrint (0x7FFFFFFF * 0.995 * sin (4 * M_PI * k / BUFFER_SIZE)) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_int_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
+ test_write_int_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_FALSE) ;
+ test_write_int_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != 3 * BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, 3 * BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ /* Check the first section. */
+ test_read_double_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the second section. */
+ test_read_double_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value > 1.0)
+ { printf ("\n\nLine %d: Max value (%f) > 1.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the third section. */
+ test_read_double_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* int_dbl_scale_write_test */
+
+
+
diff --git a/tests/scale_clip_test.def b/tests/scale_clip_test.def
new file mode 100644
index 0000000..3459819
--- /dev/null
+++ b/tests/scale_clip_test.def
@@ -0,0 +1,56 @@
+autogen definitions scale_clip_test.tpl;
+
+float_type = {
+ float_type_name = "float" ;
+ float_short_name = "flt" ;
+ float_upper_name = "FLOAT" ;
+ float_to_int = "lrintf" ;
+ } ;
+
+float_type = {
+ float_type_name = "double" ;
+ float_short_name = "dbl" ;
+ float_upper_name = "DOUBLE" ;
+ float_to_int = "lrint" ;
+ } ;
+
+
+
+int_type = {
+ int_type_name = "short" ;
+ int_short_name = "s" ;
+ int_max_value = 0x7FFFF ;
+ } ;
+
+int_type = {
+ int_type_name = "int" ;
+ int_short_name = "i" ;
+ int_max_value = 0x7FFFFFFF ;
+ } ;
+
+
+
+data_type = {
+ name = "16" ;
+ bit_count = 16 ;
+ error_val = "1.0 / 0x8000" ;
+ } ;
+
+data_type = {
+ name = "24" ;
+ bit_count = 24 ;
+ error_val = "1.0 / 0x800000" ;
+ } ;
+
+data_type = {
+ name = "32" ;
+ bit_count = 32 ;
+ error_val = "1.0 / 0x80000000" ;
+ } ;
+
+data_type = {
+ name = "08" ;
+ bit_count = 8 ;
+ error_val = "1.0 / 0x80" ;
+ } ;
+
diff --git a/tests/scale_clip_test.tpl b/tests/scale_clip_test.tpl
new file mode 100644
index 0000000..d8a8b32
--- /dev/null
+++ b/tests/scale_clip_test.tpl
@@ -0,0 +1,438 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+#define HALF_BUFFER_SIZE (1 << 12)
+#define BUFFER_SIZE (2 * HALF_BUFFER_SIZE)
+
+#define SINE_AMP 1.1
+#define MAX_ERROR 0.0202
+
+[+ FOR float_type +]
+[+ FOR data_type
++]static void [+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +] (const char *filename, int filetype, float maxval) ;
+[+ ENDFOR data_type
++][+ ENDFOR float_type +]
+
+[+ FOR float_type +]
+[+ FOR int_type
++]static void [+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test (const char *filename, int filetype) ;
+[+ ENDFOR int_type
++][+ ENDFOR float_type +]
+
+[+ FOR int_type +]
+[+ FOR float_type
++]static void [+ (get "int_type_name") +]_[+ (get "float_short_name") +]_scale_write_test (const char *filename, int filetype) ;
+[+ ENDFOR float_type
++][+ ENDFOR int_type +]
+
+typedef union
+{ double dbl [BUFFER_SIZE] ;
+ float flt [BUFFER_SIZE] ;
+ int i [BUFFER_SIZE] ;
+ short s [BUFFER_SIZE] ;
+} BUFFER ;
+
+/* Data buffer. */
+static BUFFER buffer_out ;
+static BUFFER buffer_in ;
+
+int
+main (void)
+{
+ flt_scale_clip_test_08 ("scale_clip_s8.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8, 1.0 * 0x80) ;
+ flt_scale_clip_test_08 ("scale_clip_u8.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 1.0 * 0x80) ;
+
+ dbl_scale_clip_test_08 ("scale_clip_s8.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8, 1.0 * 0x80) ;
+ dbl_scale_clip_test_08 ("scale_clip_u8.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 1.0 * 0x80) ;
+
+ /*
+ ** Now use SF_FORMAT_AU where possible because it allows both
+ ** big and little endian files.
+ */
+
+ flt_scale_clip_test_16 ("scale_clip_be16.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ flt_scale_clip_test_16 ("scale_clip_le16.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ flt_scale_clip_test_24 ("scale_clip_be24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ flt_scale_clip_test_24 ("scale_clip_le24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ flt_scale_clip_test_32 ("scale_clip_be32.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+ flt_scale_clip_test_32 ("scale_clip_le32.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+
+ dbl_scale_clip_test_16 ("scale_clip_be16.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ dbl_scale_clip_test_16 ("scale_clip_le16.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ;
+ dbl_scale_clip_test_24 ("scale_clip_be24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ dbl_scale_clip_test_24 ("scale_clip_le24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ;
+ dbl_scale_clip_test_32 ("scale_clip_be32.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+ dbl_scale_clip_test_32 ("scale_clip_le32.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ;
+
+ flt_short_clip_read_test ("flt_short.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ flt_int_clip_read_test ("flt_int.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ dbl_short_clip_read_test ("dbl_short.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+ dbl_int_clip_read_test ("dbl_int.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+
+ short_flt_scale_write_test ("short_flt.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ int_flt_scale_write_test ("int_flt.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ short_dbl_scale_write_test ("short_dbl.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+ int_dbl_scale_write_test ("int_dbl.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+[+ FOR float_type +]
+[+ FOR data_type
++]static void
+[+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +] (const char *filename, int filetype, float maxval)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k ;
+ [+ (get "float_type_name") +] *data_out, *data_in ;
+ double diff, clip_max_diff ;
+
+ print_test_name ("[+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +]", filename) ;
+
+ data_out = buffer_out.[+ (get "float_short_name") +] ;
+ data_in = buffer_in.[+ (get "float_short_name") +] ;
+
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ;
+ data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ;
+ } ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /*
+ ** Write two versions of the data:
+ ** normalized and clipped
+ ** un-normalized and clipped.
+ */
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_write_[+ (get "float_type_name") +]_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_[+ (get "float_upper_name") +], NULL, SF_FALSE) ;
+ test_write_[+ (get "float_type_name") +]_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&buffer_in, 0, sizeof (buffer_in)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_NORM_[+ (get "float_upper_name") +], NULL, SF_FALSE) ;
+ test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ /* Check normalized version. */
+ clip_max_diff = 0.0 ;
+ for (k = 0 ; k < HALF_BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > 1.0)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > 1.0)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > [+ (get "error_val") +])
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ /* Check the un-normalized data. */
+ clip_max_diff = 0.0 ;
+ for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++)
+ { if (fabs (data_in [k]) > maxval)
+ { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ;
+ exit (1) ;
+ } ;
+
+ if (data_out [k] * data_in [k] < 0.0)
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ;
+ exit (1) ;
+ } ;
+
+ if (fabs (data_out [k]) > maxval)
+ continue ;
+
+ diff = fabs (data_out [k] - data_in [k]) ;
+ if (diff > clip_max_diff)
+ clip_max_diff = diff ;
+ } ;
+
+ if (clip_max_diff < 1e-20)
+ { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ if (clip_max_diff > 1.0)
+ { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ;
+ exit (1) ;
+ } ;
+
+ printf ("ok\n") ;
+ unlink (filename) ;
+} /* [+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +] */
+
+[+ ENDFOR data_type
++]
+[+ ENDFOR float_type +]
+
+/*==============================================================================
+*/
+
+[+ FOR float_type +]
+[+ FOR int_type
++]static void [+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ [+ (get "float_type_name") +] *data_out ;
+ [+ (get "int_type_name") +] *data_in, max_value ;
+ int k ;
+
+ print_test_name ("[+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test", filename) ;
+
+ data_out = buffer_out.[+ (get "float_short_name") +] ;
+ data_in = buffer_in.[+ (get "int_short_name") +] ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = 0.995 * sin (4 * M_PI * k / BUFFER_SIZE) ;
+ data_out [BUFFER_SIZE / 8] = 1.0 ;
+ data_out [3 * BUFFER_SIZE / 8] = -1.000000001 ;
+ data_out [5 * BUFFER_SIZE / 8] = 1.0 ;
+ data_out [7 * BUFFER_SIZE / 8] = -1.000000001 ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ /* Save unclipped data to the file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_[+ (get "float_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+ test_read_[+ (get "int_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+ /*-sf_command (file, SFC_SET_NORM_[+ (get "float_upper_name") +], NULL, SF_FALSE) ;-*/
+ sf_close (file) ;
+
+ /* Check the first half. */
+ max_value = 0 ;
+ for (k = 0 ; k < sfinfo.frames ; k++)
+ { /* Check if data_out has different sign from data_in. */
+ if ((data_out [k] < 0.0 && data_in [k] > 0) || (data_out [k] > 0.0 && data_in [k] < 0))
+ { printf ("\n\nLine %d: Data wrap around at index %d/%d (%f -> %d).\n\n", __LINE__, k, BUFFER_SIZE, data_out [k], data_in [k]) ;
+ exit (1) ;
+ } ;
+ max_value = (max_value > abs (data_in [k])) ? max_value : abs (data_in [k]) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* [+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test */
+[+ ENDFOR int_type
++][+ ENDFOR float_type +]
+
+/*==============================================================================
+*/
+
+[+ FOR int_type +]
+[+ FOR float_type
++]static void [+ (get "int_type_name") +]_[+ (get "float_short_name") +]_scale_write_test (const char *filename, int filetype)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ [+ (get "int_type_name") +] *data_out ;
+ [+ (get "float_type_name") +] *data_in, max_value ;
+ int k ;
+
+ print_test_name ("[+ (get "int_type_name") +]_[+ (get "float_short_name") +]_clip_write_test", filename) ;
+
+ data_out = buffer_out.[+ (get "int_short_name") +] ;
+ data_in = buffer_in.[+ (get "float_short_name") +] ;
+
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ data_out [k] = [+ (get "float_to_int") +] ([+ (get "int_max_value") +] * 0.995 * sin (4 * M_PI * k / BUFFER_SIZE)) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = filetype ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ test_write_[+ (get "int_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
+ test_write_[+ (get "int_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_FALSE) ;
+ test_write_[+ (get "int_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ;
+ sf_close (file) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
+
+ if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
+ { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames != 3 * BUFFER_SIZE)
+ { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %ld).\n\n", __LINE__, 3 * BUFFER_SIZE, SF_COUNT_TO_LONG (sfinfo.frames)) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ /* Check the first section. */
+ test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the second section. */
+ test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value > 1.0)
+ { printf ("\n\nLine %d: Max value (%f) > 1.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ /* Check the third section. */
+ test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ;
+
+ max_value = 0.0 ;
+ for (k = 0 ; k < BUFFER_SIZE ; k++)
+ max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ;
+
+ if (max_value < 1000.0)
+ { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* [+ (get "int_type_name") +]_[+ (get "float_short_name") +]_scale_write_test */
+[+ ENDFOR float_type
++][+ ENDFOR int_type +]
+
+
diff --git a/tests/sfversion.c b/tests/sfversion.c
new file mode 100644
index 0000000..c464f08
--- /dev/null
+++ b/tests/sfversion.c
@@ -0,0 +1,45 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sndfile.h>
+
+#define BUFFER_SIZE (256)
+
+
+int
+main (void)
+{ static char strbuffer [BUFFER_SIZE] ;
+ const char * ver ;
+
+ sf_command (NULL, SFC_GET_LIB_VERSION, strbuffer, sizeof (strbuffer)) ;
+ ver = sf_version_string () ;
+
+ if (strcmp (ver, strbuffer) != 0)
+ { printf ("Version mismatch : '%s' != '%s'\n\n", ver, strbuffer) ;
+ exit (1) ;
+ } ;
+
+ printf ("%s", strbuffer) ;
+
+ return 0 ;
+} /* main */
+
diff --git a/tests/stdin_test.c b/tests/stdin_test.c
new file mode 100644
index 0000000..1d941bd
--- /dev/null
+++ b/tests/stdin_test.c
@@ -0,0 +1,204 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1<<16)
+
+static void stdin_test (int typemajor, int count) ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0, test_count = 0 ;
+
+ if (BUFFER_LEN < PIPE_TEST_LEN)
+ { fprintf (stderr, "Error : BUFFER_LEN < PIPE_TEST_LEN.\n\n") ;
+ exit (1) ;
+ } ;
+
+ if (argc != 2)
+ { fprintf (stderr, "This program cannot be run by itself. It needs\n") ;
+ fprintf (stderr, "to be run from the stdio_test program.\n") ;
+ exit (1) ;
+ } ;
+
+ do_all = ! strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "raw"))
+ { stdin_test (SF_FORMAT_RAW, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { stdin_test (SF_FORMAT_WAV, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { stdin_test (SF_FORMAT_AIFF, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { stdin_test (SF_FORMAT_AU, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { stdin_test (SF_FORMAT_PAF, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { stdin_test (SF_FORMAT_SVX, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { stdin_test (SF_FORMAT_NIST, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { stdin_test (SF_FORMAT_IRCAM, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { stdin_test (SF_FORMAT_VOC, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { stdin_test (SF_FORMAT_W64, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { stdin_test (SF_FORMAT_MAT4, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { stdin_test (SF_FORMAT_MAT5, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { stdin_test (SF_FORMAT_PVF, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "htk"))
+ { stdin_test (SF_FORMAT_HTK, PIPE_TEST_LEN) ;
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { fprintf (stderr, "************************************\n") ;
+ fprintf (stderr, "* No '%s' test defined.\n", argv [1]) ;
+ fprintf (stderr, "************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+static void
+stdin_test (int typemajor, int count)
+{ static short data [BUFFER_LEN] ;
+
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, total, err ;
+
+ if (typemajor == SF_FORMAT_RAW)
+ { sfinfo.samplerate = 44100 ;
+ sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+ }
+ else
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ if ((file = sf_open_fd (STDIN_FILENO, SFM_READ, &sfinfo, SF_TRUE)) == NULL)
+ { fprintf (stderr, "sf_open_fd failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ dump_log_buffer (NULL) ;
+ exit (1) ;
+ } ;
+
+ err = sf_error (file) ;
+ if (err != SF_ERR_NO_ERROR)
+ { printf ("Line %d : unexpected error : %s\n", __LINE__, sf_error_number (err)) ;
+ exit (1) ;
+ } ;
+
+ if ((sfinfo.format & SF_FORMAT_TYPEMASK) != typemajor)
+ { fprintf (stderr, "\n\nError : File type doesn't match.\n") ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.samplerate != 44100)
+ { fprintf (stderr, "\n\nError : Sample rate (%d) should be 44100\n", sfinfo.samplerate) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { fprintf (stderr, "\n\nError : Channels (%d) should be 1\n", sfinfo.channels) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < count)
+ { fprintf (stderr, "\n\nError : Sample count (%ld) should be %d\n", (long) sfinfo.frames, count) ;
+ exit (1) ;
+ } ;
+
+ total = 0 ;
+ while ((k = sf_read_short (file, data + total, BUFFER_LEN - total)) > 0)
+ total += k ;
+
+ if (total != count)
+ { fprintf (stderr, "\n\nError : Expected %d frames, read %d.\n", count, total) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < total ; k++)
+ if (data [k] != PIPE_INDEX (k))
+ { printf ("\n\nError : data [%d] == %d, should have been %d.\n\n", k, data [k], k) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ return ;
+} /* stdin_test */
+
diff --git a/tests/stdio_test.c b/tests/stdio_test.c
new file mode 100644
index 0000000..80a696c
--- /dev/null
+++ b/tests/stdio_test.c
@@ -0,0 +1,153 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU 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 is a test program which tests reading from stdin and writing to
+** stdout.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#include "utils.h"
+
+/* EMX is OS/2. */
+#if (OS_IS_WIN32) || defined (__EMX__)
+
+int
+main (void)
+{
+ puts (" stdio_test : this test doesn't work on win32.") ;
+ return 0 ;
+} /* main */
+
+#else
+
+#ifndef WIFEXITED
+#define WIFEXITED(s) (((s) & 0xff) == 0)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(s) (((s) & 0xff00) >> 8)
+#endif
+
+
+static size_t file_length (const char *filename) ;
+static int file_exists (const char *filename) ;
+static void stdio_test (const char *filetype) ;
+
+static const char *filetypes [] =
+{ "raw", "wav", "aiff", "au", "paf", "svx", "nist", "ircam",
+ "voc", "w64", "mat4", "mat5", "pvf",
+ NULL
+} ;
+
+int
+main (void)
+{ int k ;
+
+ if (file_exists ("libsndfile.spec.in"))
+ exit_if_true (chdir ("tests") != 0, "\n Error : chdir ('tests') failed.\n") ;
+
+ for (k = 0 ; filetypes [k] ; k++)
+ stdio_test (filetypes [k]) ;
+
+ return 0 ;
+} /* main */
+
+
+static void
+stdio_test (const char *filetype)
+{ static char buffer [256] ;
+
+ int file_size, retval ;
+
+ print_test_name ("stdio_test", filetype) ;
+
+ snprintf (buffer, sizeof (buffer), "./stdout_test %s > stdio.%s", filetype, filetype) ;
+ if ((retval = system (buffer)))
+ { retval = WIFEXITED (retval) ? WEXITSTATUS (retval) : 1 ;
+ printf ("%s : %s", buffer, (strerror (retval))) ;
+ exit (1) ;
+ } ;
+
+ snprintf (buffer, sizeof (buffer), "stdio.%s", filetype) ;
+ if ((file_size = file_length (buffer)) < PIPE_TEST_LEN)
+ { printf ("\n Error : test file '%s' too small (%d).\n\n", buffer, file_size) ;
+ exit (1) ;
+ } ;
+
+ snprintf (buffer, sizeof (buffer), "./stdin_test %s < stdio.%s", filetype, filetype) ;
+ if ((retval = system (buffer)))
+ { retval = WIFEXITED (retval) ? WEXITSTATUS (retval) : 1 ;
+ printf ("%s : %s", buffer, (strerror (retval))) ;
+ exit (1) ;
+ } ;
+
+ snprintf (buffer, sizeof (buffer), "rm stdio.%s", filetype) ;
+ if ((retval = system (buffer)))
+ { retval = WIFEXITED (retval) ? WEXITSTATUS (retval) : 1 ;
+ printf ("%s : %s", buffer, (strerror (retval))) ;
+ exit (1) ;
+ } ;
+
+ puts ("ok") ;
+
+ return ;
+} /* stdio_test */
+
+
+
+
+static size_t
+file_length (const char *filename)
+{ struct stat buf ;
+
+ if (stat (filename, &buf))
+ { perror (filename) ;
+ exit (1) ;
+ } ;
+
+ return buf.st_size ;
+} /* file_length */
+
+static int
+file_exists (const char *filename)
+{ struct stat buf ;
+
+ if (stat (filename, &buf))
+ return 0 ;
+
+ return 1 ;
+} /* file_exists */
+
+#endif
+
diff --git a/tests/stdout_test.c b/tests/stdout_test.c
new file mode 100644
index 0000000..042a59a
--- /dev/null
+++ b/tests/stdout_test.c
@@ -0,0 +1,161 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+static void stdout_test (int typemajor, int count) ;
+
+int
+main (int argc, char *argv [])
+{ int do_all, test_count = 0 ;
+
+ if (argc != 2)
+ { fprintf (stderr, "This program cannot be run by itself. It needs\n") ;
+ fprintf (stderr, "to be run from the stdio_test program.\n") ;
+ exit (1) ;
+ } ;
+
+ do_all =! strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "raw"))
+ { stdout_test (SF_FORMAT_RAW, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { stdout_test (SF_FORMAT_WAV, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { stdout_test (SF_FORMAT_AIFF, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { stdout_test (SF_FORMAT_AU, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { stdout_test (SF_FORMAT_PAF, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { stdout_test (SF_FORMAT_SVX, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { stdout_test (SF_FORMAT_NIST, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { stdout_test (SF_FORMAT_IRCAM, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { stdout_test (SF_FORMAT_VOC, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { stdout_test (SF_FORMAT_W64, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { stdout_test (SF_FORMAT_MAT4, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { stdout_test (SF_FORMAT_MAT5, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { stdout_test (SF_FORMAT_PVF, PIPE_TEST_LEN) ;
+ test_count ++ ;
+ } ;
+
+ if (test_count == 0)
+ { fprintf (stderr, "************************************\n") ;
+ fprintf (stderr, "* No '%s' test defined.\n", argv [1]) ;
+ fprintf (stderr, "************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+static void
+stdout_test (int typemajor, int count)
+{ static short data [PIPE_TEST_LEN] ;
+
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int k, total, this_write ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ /* Create some random data. */
+ for (k = 0 ; k < PIPE_TEST_LEN ; k++)
+ data [k] = PIPE_INDEX (k) ;
+
+ if ((file = sf_open ("-", SFM_WRITE, &sfinfo)) == NULL)
+ { fprintf (stderr, "sf_open_write failed with error : ") ;
+ fprintf (stderr, "%s\n", sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ total = 0 ;
+
+ while (total < count)
+ { this_write = (count - total > 1024) ? 1024 : count - total ;
+ if ((k = sf_write_short (file, data + total, this_write)) != this_write)
+ { fprintf (stderr, "sf_write_short # %d failed with short write (%d -> %d)\n", count, this_write, k) ;
+ exit (1) ;
+ } ;
+ total += k ;
+ } ;
+
+ sf_close (file) ;
+
+ return ;
+} /* stdout_test */
+
diff --git a/tests/string_test.c b/tests/string_test.c
new file mode 100644
index 0000000..758612e
--- /dev/null
+++ b/tests/string_test.c
@@ -0,0 +1,663 @@
+/*
+** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_LEN (1 << 10)
+#define LOG_BUFFER_SIZE 1024
+
+static void string_start_test (const char *filename, int typemajor) ;
+static void string_start_end_test (const char *filename, int typemajor) ;
+static void string_multi_set_test (const char *filename, int typemajor) ;
+static void string_rdwr_test (const char *filename, int typemajor) ;
+static void string_short_rdwr_test (const char *filename, int typemajor) ;
+
+static void software_string_test (const char *filename) ;
+
+static int str_count (const char * haystack, const char * needle) ;
+
+int
+main (int argc, char *argv [])
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test adding strings to WAV files\n") ;
+ printf (" aiff - test adding strings to AIFF files\n") ;
+ printf (" flac - test adding strings to FLAC files\n") ;
+ printf (" ogg - test adding strings to OGG files\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all =! strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { string_start_end_test ("strings.wav", SF_FORMAT_WAV) ;
+ string_multi_set_test ("multi.wav", SF_FORMAT_WAV) ;
+ string_rdwr_test ("rdwr.wav", SF_FORMAT_WAV) ;
+ string_short_rdwr_test ("short_rdwr.wav", SF_FORMAT_WAV) ;
+
+ string_start_end_test ("strings.wavex", SF_FORMAT_WAVEX) ;
+ string_multi_set_test ("multi.wavex", SF_FORMAT_WAVEX) ;
+ string_rdwr_test ("rdwr.wavex", SF_FORMAT_WAVEX) ;
+ string_short_rdwr_test ("short_rdwr.wavex", SF_FORMAT_WAVEX) ;
+
+ string_start_end_test ("strings.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
+ string_multi_set_test ("multi.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
+ string_rdwr_test ("rdwr.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
+ string_short_rdwr_test ("short_rdwr.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
+
+ software_string_test ("software_string.wav") ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { string_start_end_test ("strings.aiff", SF_FORMAT_AIFF) ;
+ /*
+ string_multi_set_test ("multi.aiff", SF_FORMAT_AIFF) ;
+ string_rdwr_test ("rdwr.aiff", SF_FORMAT_AIFF) ;
+ string_short_rdwr_test ("short_rdwr.aiff", SF_FORMAT_AIFF) ;
+ */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "flac"))
+ { if (HAVE_EXTERNAL_LIBS)
+ string_start_test ("strings.flac", SF_FORMAT_FLAC) ;
+ else
+ puts (" No FLAC tests because FLAC support was not compiled in.") ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ogg"))
+ { if (HAVE_EXTERNAL_LIBS)
+ string_start_test ("vorbis.oga", SF_FORMAT_OGG) ;
+ else
+ puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "rf64"))
+ { puts ("\n\n **** String test not working yet for RF64 format. ****\n") ;
+ /*
+ string_start_end_test ("strings.rf64", SF_FORMAT_RF64) ;
+ string_multi_set_test ("multi.rf64", SF_FORMAT_RF64) ;
+ string_rdwr_test ("rdwr.rf64", SF_FORMAT_RF64) ;
+ string_short_rdwr_test ("short_rdwr.rf64", SF_FORMAT_RF64) ;
+ */
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ return 0 ;
+} /* main */
+
+
+/*============================================================================================
+** Here are the test functions.
+*/
+
+static const char
+ software [] = "software (libsndfile-X.Y.Z)",
+ artist [] = "The Artist",
+ copyright [] = "Copyright (c) 2001 Artist",
+ comment [] = "Comment goes here!!!",
+ date [] = "2001/01/27",
+ album [] = "The Album",
+ license [] = "The license",
+ title [] = "This is the title",
+ long_title [] = "This is a very long and very boring title for this file",
+ long_artist [] = "The artist who kept on changing its name",
+ genre [] = "The genre",
+ trackno [] = "Track three" ;
+
+
+static short data_out [BUFFER_LEN] ;
+
+static void
+string_start_end_test (const char *filename, int typemajor)
+{ const char *cptr ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int errors = 0 ;
+
+ typemajor = typemajor ;
+
+ print_test_name ("string_start_end_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+ sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /* Write stuff at start of file. */
+ sf_set_string (file, SF_STR_TITLE, filename) ;
+ sf_set_string (file, SF_STR_SOFTWARE, software) ;
+ sf_set_string (file, SF_STR_ARTIST, artist) ;
+ sf_set_string (file, SF_STR_GENRE, genre) ;
+ sf_set_string (file, SF_STR_TRACKNUMBER, trackno) ;
+
+ /* Write data to file. */
+ test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ /* Write more stuff at end of file. */
+ sf_set_string (file, SF_STR_COPYRIGHT, copyright) ;
+ sf_set_string (file, SF_STR_COMMENT, comment) ;
+ sf_set_string (file, SF_STR_DATE, date) ;
+ sf_set_string (file, SF_STR_ALBUM, album) ;
+ sf_set_string (file, SF_STR_LICENSE, license) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("***** Bad frame count %d (should be %d)\n\n", (int) sfinfo.frames, BUFFER_LEN) ;
+ errors ++ ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_TITLE) ;
+ if (cptr == NULL || strcmp (filename, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad filename : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_COPYRIGHT) ;
+ if (cptr == NULL || strcmp (copyright, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad copyright : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_SOFTWARE) ;
+ if (cptr == NULL || strstr (cptr, software) != cptr)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad software : %s\n", cptr) ;
+ } ;
+
+ if (str_count (cptr, "libsndfile") != 1)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad software : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_ARTIST) ;
+ if (cptr == NULL || strcmp (artist, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad artist : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_COMMENT) ;
+ if (cptr == NULL || strcmp (comment, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad comment : %s\n", cptr) ;
+ } ;
+
+ if (typemajor != SF_FORMAT_AIFF)
+ { cptr = sf_get_string (file, SF_STR_DATE) ;
+ if (cptr == NULL || strcmp (date, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad date : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_GENRE) ;
+ if (cptr == NULL || strcmp (genre, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad genre : %s\n", cptr) ;
+ } ;
+ } ;
+
+ switch (typemajor)
+ { case SF_FORMAT_AIFF :
+ case SF_FORMAT_WAV :
+ case SF_FORMAT_WAVEX :
+ case SF_ENDIAN_BIG | SF_FORMAT_WAV :
+ break ;
+
+ default :
+ cptr = sf_get_string (file, SF_STR_ALBUM) ;
+ if (cptr == NULL || strcmp (album, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad album : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_LICENSE) ;
+ if (cptr == NULL || strcmp (license, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad license : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_TRACKNUMBER) ;
+ if (cptr == NULL || strcmp (genre, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad track no. : %s\n", cptr) ;
+ } ;
+ break ;
+ } ;
+
+ if (errors > 0)
+ { printf ("\n*** Error count : %d ***\n\n", errors) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* string_start_end_test */
+
+static void
+string_start_test (const char *filename, int typemajor)
+{ const char *cptr ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int errors = 0 ;
+
+ print_test_name ("string_start_test", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ switch (typemajor)
+ { case SF_FORMAT_OGG :
+ sfinfo.format = typemajor | SF_FORMAT_VORBIS ;
+ break ;
+
+ default :
+ sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
+ break ;
+ } ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /* Write stuff at start of file. */
+ sf_set_string (file, SF_STR_TITLE, filename) ;
+ sf_set_string (file, SF_STR_SOFTWARE, software) ;
+ sf_set_string (file, SF_STR_ARTIST, artist) ;
+ sf_set_string (file, SF_STR_COPYRIGHT, copyright) ;
+ sf_set_string (file, SF_STR_COMMENT, comment) ;
+ sf_set_string (file, SF_STR_DATE, date) ;
+ sf_set_string (file, SF_STR_ALBUM, album) ;
+ sf_set_string (file, SF_STR_LICENSE, license) ;
+
+ /* Write data to file. */
+ test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if (sfinfo.frames != BUFFER_LEN)
+ { printf ("***** Bad frame count %d (should be %d)\n\n", (int) sfinfo.frames, BUFFER_LEN) ;
+ errors ++ ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_TITLE) ;
+ if (cptr == NULL || strcmp (filename, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad filename : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_COPYRIGHT) ;
+ if (cptr == NULL || strcmp (copyright, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad copyright : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_SOFTWARE) ;
+ if (cptr == NULL || strstr (cptr, software) != cptr)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad software : %s\n", cptr) ;
+ } ;
+
+ if (str_count (cptr, "libsndfile") != 1)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad software : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_ARTIST) ;
+ if (cptr == NULL || strcmp (artist, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad artist : %s\n", cptr) ;
+ } ;
+
+ cptr = sf_get_string (file, SF_STR_COMMENT) ;
+ if (cptr == NULL || strcmp (comment, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad comment : %s\n", cptr) ;
+ } ;
+
+ if (typemajor != SF_FORMAT_AIFF)
+ { cptr = sf_get_string (file, SF_STR_DATE) ;
+ if (cptr == NULL || strcmp (date, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad date : %s\n", cptr) ;
+ } ;
+ } ;
+
+ if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF)
+ { cptr = sf_get_string (file, SF_STR_ALBUM) ;
+ if (cptr == NULL || strcmp (album, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad album : %s\n", cptr) ;
+ } ;
+ } ;
+
+ if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF)
+ { cptr = sf_get_string (file, SF_STR_LICENSE) ;
+ if (cptr == NULL || strcmp (license, cptr) != 0)
+ { if (errors++ == 0)
+ puts ("\n") ;
+ printf (" Bad license : %s\n", cptr) ;
+ } ;
+ } ;
+
+ if (errors > 0)
+ { printf ("\n*** Error count : %d ***\n\n", errors) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* string_start_test */
+
+static void
+string_multi_set_test (const char *filename, int typemajor)
+{ static const char
+ new_software [] = "new software (libsndfile-X.Y.Z)",
+ new_copyright [] = "Copyright (c) 2001 New Artist",
+ new_artist [] = "The New Artist",
+ new_title [] = "This is the new title" ;
+
+ static char buffer [2048] ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int count ;
+
+ print_test_name (__func__, filename) ;
+
+ sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+ /* Write stuff at start of file. */
+ sf_set_string (file, SF_STR_TITLE, title) ;
+ sf_set_string (file, SF_STR_SOFTWARE, software) ;
+ sf_set_string (file, SF_STR_ARTIST, artist) ;
+
+ /* Write data to file. */
+ test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ /* Write it all again. */
+
+ sf_set_string (file, SF_STR_TITLE, new_title) ;
+ sf_set_string (file, SF_STR_SOFTWARE, new_software) ;
+ sf_set_string (file, SF_STR_ARTIST, new_artist) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, copyright) ;
+ sf_set_string (file, SF_STR_COMMENT, comment) ;
+ sf_set_string (file, SF_STR_DATE, date) ;
+ sf_set_string (file, SF_STR_ALBUM, album) ;
+ sf_set_string (file, SF_STR_LICENSE, license) ;
+ sf_set_string (file, SF_STR_COPYRIGHT, new_copyright) ;
+ sf_set_string (file, SF_STR_COMMENT, comment) ;
+ sf_set_string (file, SF_STR_DATE, date) ;
+ sf_set_string (file, SF_STR_ALBUM, album) ;
+ sf_set_string (file, SF_STR_LICENSE, license) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+ sf_command (file, SFC_GET_LOG_INFO, buffer, sizeof (buffer)) ;
+ sf_close (file) ;
+
+ count = str_count (buffer, new_title) ;
+ exit_if_true (count < 1, "\n\nLine %d : Could not find new_title in :\n%s\n", __LINE__, buffer) ;
+ exit_if_true (count > 1, "\n\nLine %d : new_title appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
+
+ count = str_count (buffer, software) ;
+ exit_if_true (count < 1, "\n\nLine %d : Could not find new_software in :\n%s\n", __LINE__, buffer) ;
+ exit_if_true (count > 1, "\n\nLine %d : new_software appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
+
+ count = str_count (buffer, new_artist) ;
+ exit_if_true (count < 1, "\n\nLine %d : Could not find new_artist in :\n%s\n", __LINE__, buffer) ;
+ exit_if_true (count > 1, "\n\nLine %d : new_artist appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
+
+ count = str_count (buffer, new_copyright) ;
+ exit_if_true (count < 1, "\n\nLine %d : Could not find new_copyright in :\n%s\n", __LINE__, buffer) ;
+ exit_if_true (count > 1, "\n\nLine %d : new_copyright appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
+
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* string_multi_set_test */
+
+static void
+string_rdwr_test (const char *filename, int typemajor)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames ;
+ const char * str ;
+
+ print_test_name (__func__, filename) ;
+ create_short_sndfile (filename, typemajor | SF_FORMAT_PCM_16, 2) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
+ frames = sfinfo.frames ;
+ sf_set_string (file, SF_STR_TITLE, title) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+ exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %lld should be %lld.\n", __LINE__, sfinfo.frames, frames) ;
+ str = sf_get_string (file, SF_STR_TITLE) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
+ frames = sfinfo.frames ;
+ sf_set_string (file, SF_STR_TITLE, title) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
+ str = sf_get_string (file, SF_STR_TITLE) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
+ sf_set_string (file, SF_STR_ARTIST, artist) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ str = sf_get_string (file, SF_STR_ARTIST) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_ARTIST string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, artist) != 0, "\n\nLine %d : SF_STR_ARTIST doesn't match what was written.\n", __LINE__) ;
+
+ str = sf_get_string (file, SF_STR_TITLE) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
+
+ exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %lld should be %lld.\n", __LINE__, sfinfo.frames, frames) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* string_rdwr_test */
+
+static void
+string_short_rdwr_test (const char *filename, int typemajor)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ sf_count_t frames = BUFFER_LEN ;
+ const char * str ;
+
+ print_test_name (__func__, filename) ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = 1 ;
+ sfinfo.frames = 0 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+
+ /* Write data to file. */
+ test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+ sf_set_string (file, SF_STR_TITLE, long_title) ;
+ sf_set_string (file, SF_STR_ARTIST, long_artist) ;
+ sf_close (file) ;
+
+ /* Open the file RDWR. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
+ exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %lld should be %lld.\n", __LINE__, sfinfo.frames, frames) ;
+ str = sf_get_string (file, SF_STR_TITLE) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, long_title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
+ str = sf_get_string (file, SF_STR_ARTIST) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, long_artist) != 0, "\n\nLine %d : SF_STR_ARTIST doesn't match what was written.\n", __LINE__) ;
+
+ /* Change title and artist. */
+ sf_set_string (file, SF_STR_TITLE, title) ;
+ sf_set_string (file, SF_STR_ARTIST, artist) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ str = sf_get_string (file, SF_STR_TITLE) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
+
+ str = sf_get_string (file, SF_STR_ARTIST) ;
+ exit_if_true (str == NULL, "\n\nLine %d : SF_STR_ARTIST string is NULL.\n", __LINE__) ;
+ exit_if_true (strcmp (str, artist) != 0, "\n\nLine %d : SF_STR_ARTIST doesn't match what was written.\n", __LINE__) ;
+
+ sf_close (file) ;
+ unlink (filename) ;
+
+ puts ("ok") ;
+} /* string_short_rdwr_test */
+
+static int
+str_count (const char * haystack, const char * needle)
+{ int count = 0 ;
+
+ while ((haystack = strstr (haystack, needle)) != NULL)
+ { count ++ ;
+ haystack ++ ;
+ } ;
+
+ return count ;
+} /* str_count */
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+static void
+software_string_test (const char *filename)
+{ size_t k ;
+
+ print_test_name (__func__, filename) ;
+
+ for (k = 0 ; k < 50 ; k++)
+ { const char *result ;
+ char sfname [64] ;
+ SNDFILE *file ;
+ SF_INFO info ;
+
+ sf_info_setup (&info, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 44100, 1) ;
+ file = test_open_file_or_die (filename, SFM_WRITE, &info, SF_TRUE, __LINE__) ;
+
+ snprintf (sfname, MIN (k, sizeof (sfname)), "%s", "abcdefghijklmnopqrestvwxyz0123456789abcdefghijklmnopqrestvwxyz") ;
+
+ exit_if_true (sf_set_string (file, SF_STR_SOFTWARE, sfname),
+ "\n\nLine %d : sf_set_string (f, SF_STR_SOFTWARE, '%s') failed : %s\n", __LINE__, sfname, sf_strerror (file)) ;
+
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &info, SF_TRUE, __LINE__) ;
+ result = sf_get_string (file, SF_STR_SOFTWARE) ;
+
+ exit_if_true (result == NULL, "\n\nLine %d : sf_get_string (file, SF_STR_SOFTWARE) returned NULL.\n\n", __LINE__) ;
+
+ exit_if_true (strstr (result, sfname) != result,
+ "\n\nLine %d : String '%s''%s' -> '%s'\n\n", sfname, result) ;
+ sf_close (file) ;
+ } ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+} /* new_test_test */
diff --git a/tests/test_wrapper.sh.in b/tests/test_wrapper.sh.in
new file mode 100644
index 0000000..1595246
--- /dev/null
+++ b/tests/test_wrapper.sh.in
@@ -0,0 +1,359 @@
+#!/bin/sh
+
+# Copyright (C) 2008-2011 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:
+#
+# * 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.
+# * Neither the author nor the names of any contributors may be used
+# to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# 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 OWNER 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.
+
+
+HOST_TRIPLET=@HOST_TRIPLET@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+LIB_VERSION=`echo $PACKAGE_VERSION | sed "s/[a-z].*//"`
+
+if test -f tests/sfversion@EXEEXT@ ; then
+ cd tests
+ fi
+
+if test ! -f sfversion@EXEEXT@ ; then
+ echo "Not able to find test executables."
+ exit 1
+ fi
+
+if test -f libsndfile.so.$LIB_VERSION ; then
+ # This will work on Linux, but not on Mac.
+ # Windows is already sorted out.
+ export LD_LIBRARY_PATH=`pwd`
+ if test ! -f libsndfile.so.1 ; then
+ ln -s libsndfile.so.$LIB_VERSION libsndfile.so.1
+ fi
+ fi
+
+sfversion=`./sfversion@EXEEXT@ | sed "s/-exp$//"`
+
+if test $sfversion != libsndfile-$PACKAGE_VERSION ; then
+ echo "Error : sfversion ($sfversion) and PACKAGE_VERSION ($PACKAGE_VERSION) don't match."
+ exit 1
+ fi
+
+# Force exit on errors.
+set -e
+
+# Generic-tests
+uname -a
+
+# Check the header file.
+sh pedantic-header-test.sh
+
+# Need this for when we're running from files collected into the
+# libsndfile-testsuite-@PACKAGE_VERSION@ tarball.
+if test -x test_main@EXEEXT@ ; then
+ echo "Running unit tests from src/ directory of source code tree."
+ ./test_main@EXEEXT@
+ echo
+ echo "Running end-to-end tests from tests/ directory."
+ fi
+
+./error_test@EXEEXT@
+./pcm_test@EXEEXT@
+./ulaw_test@EXEEXT@
+./alaw_test@EXEEXT@
+./dwvw_test@EXEEXT@
+./command_test@EXEEXT@ ver
+./command_test@EXEEXT@ norm
+./command_test@EXEEXT@ format
+./command_test@EXEEXT@ peak
+./command_test@EXEEXT@ trunc
+./command_test@EXEEXT@ inst
+./command_test@EXEEXT@ current_sf_info
+./command_test@EXEEXT@ bext
+./command_test@EXEEXT@ bextch
+./command_test@EXEEXT@ chanmap
+./floating_point_test@EXEEXT@
+./checksum_test@EXEEXT@
+./scale_clip_test@EXEEXT@
+./headerless_test@EXEEXT@
+./rdwr_test@EXEEXT@
+./locale_test@EXEEXT@
+./win32_ordinal_test@EXEEXT@
+./external_libs_test@EXEEXT@
+./format_check_test@EXEEXT@
+
+# The w64 G++ compiler requires an extra runtime DLL which we don't have,
+# so skip this test.
+case "$HOST_TRIPLET" in
+ x86_64-w64-mingw32)
+ ;;
+ i686-w64-mingw32)
+ ;;
+ *)
+ ./cpp_test@EXEEXT@
+ ;;
+ esac
+
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed common tests."
+echo "----------------------------------------------------------------------"
+
+# aiff-tests
+./write_read_test@EXEEXT@ aiff
+./lossy_comp_test@EXEEXT@ aiff_ulaw
+./lossy_comp_test@EXEEXT@ aiff_alaw
+./lossy_comp_test@EXEEXT@ aiff_gsm610
+echo "=========================="
+echo "./lossy_comp_test@EXEEXT@ aiff_ima"
+echo "=========================="
+./peak_chunk_test@EXEEXT@ aiff
+./header_test@EXEEXT@ aiff
+./misc_test@EXEEXT@ aiff
+./string_test@EXEEXT@ aiff
+./multi_file_test@EXEEXT@ aiff
+./aiff_rw_test@EXEEXT@
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on AIFF files."
+echo "----------------------------------------------------------------------"
+
+# au-tests
+./write_read_test@EXEEXT@ au
+./lossy_comp_test@EXEEXT@ au_ulaw
+./lossy_comp_test@EXEEXT@ au_alaw
+./lossy_comp_test@EXEEXT@ au_g721
+./lossy_comp_test@EXEEXT@ au_g723
+./header_test@EXEEXT@ au
+./misc_test@EXEEXT@ au
+./multi_file_test@EXEEXT@ au
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on AU files."
+echo "----------------------------------------------------------------------"
+
+# caf-tests
+./write_read_test@EXEEXT@ caf
+./lossy_comp_test@EXEEXT@ caf_ulaw
+./lossy_comp_test@EXEEXT@ caf_alaw
+./header_test@EXEEXT@ caf
+./peak_chunk_test@EXEEXT@ caf
+./misc_test@EXEEXT@ caf
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on CAF files."
+echo "----------------------------------------------------------------------"
+
+# wav-tests
+./write_read_test@EXEEXT@ wav
+./lossy_comp_test@EXEEXT@ wav_pcm
+./lossy_comp_test@EXEEXT@ wav_ima
+./lossy_comp_test@EXEEXT@ wav_msadpcm
+./lossy_comp_test@EXEEXT@ wav_ulaw
+./lossy_comp_test@EXEEXT@ wav_alaw
+./lossy_comp_test@EXEEXT@ wav_gsm610
+./lossy_comp_test@EXEEXT@ wav_g721
+./peak_chunk_test@EXEEXT@ wav
+./header_test@EXEEXT@ wav
+./misc_test@EXEEXT@ wav
+./string_test@EXEEXT@ wav
+./multi_file_test@EXEEXT@ wav
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on WAV files."
+echo "----------------------------------------------------------------------"
+
+# w64-tests
+./write_read_test@EXEEXT@ w64
+./lossy_comp_test@EXEEXT@ w64_ima
+./lossy_comp_test@EXEEXT@ w64_msadpcm
+./lossy_comp_test@EXEEXT@ w64_ulaw
+./lossy_comp_test@EXEEXT@ w64_alaw
+./lossy_comp_test@EXEEXT@ w64_gsm610
+./header_test@EXEEXT@ w64
+./misc_test@EXEEXT@ w64
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on W64 files."
+echo "----------------------------------------------------------------------"
+
+# rf64-tests
+./write_read_test@EXEEXT@ rf64
+./header_test@EXEEXT@ rf64
+./misc_test@EXEEXT@ rf64
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on RF64 files."
+echo "----------------------------------------------------------------------"
+
+# raw-tests
+./write_read_test@EXEEXT@ raw
+./lossy_comp_test@EXEEXT@ raw_ulaw
+./lossy_comp_test@EXEEXT@ raw_alaw
+./lossy_comp_test@EXEEXT@ raw_gsm610
+./lossy_comp_test@EXEEXT@ vox_adpcm
+./raw_test@EXEEXT@
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on RAW (header-less) files."
+echo "----------------------------------------------------------------------"
+
+# paf-tests
+./write_read_test@EXEEXT@ paf
+./header_test@EXEEXT@ paf
+./misc_test@EXEEXT@ paf
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on PAF files."
+echo "----------------------------------------------------------------------"
+
+# svx-tests
+./write_read_test@EXEEXT@ svx
+./header_test@EXEEXT@ svx
+./misc_test@EXEEXT@ svx
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on SVX files."
+echo "----------------------------------------------------------------------"
+
+# nist-tests
+./write_read_test@EXEEXT@ nist
+./lossy_comp_test@EXEEXT@ nist_ulaw
+./lossy_comp_test@EXEEXT@ nist_alaw
+./header_test@EXEEXT@ nist
+./misc_test@EXEEXT@ nist
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on NIST files."
+echo "----------------------------------------------------------------------"
+
+# ircam-tests
+./write_read_test@EXEEXT@ ircam
+./lossy_comp_test@EXEEXT@ ircam_ulaw
+./lossy_comp_test@EXEEXT@ ircam_alaw
+./header_test@EXEEXT@ ircam
+./misc_test@EXEEXT@ ircam
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on IRCAM files."
+echo "----------------------------------------------------------------------"
+
+# voc-tests
+./write_read_test@EXEEXT@ voc
+./lossy_comp_test@EXEEXT@ voc_ulaw
+./lossy_comp_test@EXEEXT@ voc_alaw
+./header_test@EXEEXT@ voc
+./misc_test@EXEEXT@ voc
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on VOC files."
+echo "----------------------------------------------------------------------"
+
+# mat4-tests
+./write_read_test@EXEEXT@ mat4
+./header_test@EXEEXT@ mat4
+./misc_test@EXEEXT@ mat4
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on MAT4 files."
+echo "----------------------------------------------------------------------"
+
+# mat5-tests
+./write_read_test@EXEEXT@ mat5
+./header_test@EXEEXT@ mat5
+./misc_test@EXEEXT@ mat5
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on MAT5 files."
+echo "----------------------------------------------------------------------"
+
+# pvf-tests
+./write_read_test@EXEEXT@ pvf
+./header_test@EXEEXT@ pvf
+./misc_test@EXEEXT@ pvf
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on PVF files."
+echo "----------------------------------------------------------------------"
+
+# xi-tests
+./lossy_comp_test@EXEEXT@ xi_dpcm
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on XI files."
+echo "----------------------------------------------------------------------"
+
+# htk-tests
+./write_read_test@EXEEXT@ htk
+./header_test@EXEEXT@ htk
+./misc_test@EXEEXT@ htk
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on HTK files."
+echo "----------------------------------------------------------------------"
+
+# avr-tests
+./write_read_test@EXEEXT@ avr
+./header_test@EXEEXT@ avr
+./misc_test@EXEEXT@ avr
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on AVR files."
+echo "----------------------------------------------------------------------"
+
+# sds-tests
+./write_read_test@EXEEXT@ sds
+./header_test@EXEEXT@ sds
+./misc_test@EXEEXT@ sds
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on SDS files."
+echo "----------------------------------------------------------------------"
+
+# sd2-tests
+./write_read_test@EXEEXT@ sd2
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on SD2 files."
+echo "----------------------------------------------------------------------"
+
+# wve-tests
+./lossy_comp_test@EXEEXT@ wve
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on WVE files."
+echo "----------------------------------------------------------------------"
+
+# mpc2k-tests
+./write_read_test@EXEEXT@ mpc2k
+./header_test@EXEEXT@ mpc2k
+./misc_test@EXEEXT@ mpc2k
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on MPC 2000 files."
+echo "----------------------------------------------------------------------"
+
+# flac-tests
+./write_read_test@EXEEXT@ flac
+./string_test@EXEEXT@ flac
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on FLAC files."
+echo "----------------------------------------------------------------------"
+
+# vorbis-tests
+./ogg_test@EXEEXT@
+./vorbis_test@EXEEXT@
+./lossy_comp_test@EXEEXT@ ogg_vorbis
+./string_test@EXEEXT@ ogg
+./misc_test@EXEEXT@ ogg
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed tests on OGG/VORBIS files."
+echo "----------------------------------------------------------------------"
+
+# io-tests
+./stdio_test@EXEEXT@
+./pipe_test@EXEEXT@
+./virtual_io_test@EXEEXT@
+echo "----------------------------------------------------------------------"
+echo " $sfversion passed stdio/pipe/vio tests."
+echo "----------------------------------------------------------------------"
+
+
diff --git a/tests/ulaw_test.c b/tests/ulaw_test.c
new file mode 100644
index 0000000..c2644f1
--- /dev/null
+++ b/tests/ulaw_test.c
@@ -0,0 +1,257 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE (65536)
+
+static unsigned char ulaw_encode (int sample) ;
+static int ulaw_decode (unsigned int ulawbyte) ;
+
+static short short_buffer [BUFFER_SIZE] ;
+static unsigned char ulaw_buffer [BUFFER_SIZE] ;
+
+int
+main (void)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ const char *filename ;
+ int k ;
+
+ print_test_name ("ulaw_test", "encoder") ;
+
+ filename = "test.raw" ;
+
+ sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ULAW, 44100, 1) ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { printf ("sf_open_write failed with error : ") ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ /* Generate a file containing all possible 16 bit sample values
+ ** and write it to disk as ulaw encoded.frames.
+ */
+
+ for (k = 0 ; k < 0x10000 ; k++)
+ short_buffer [k] = k & 0xFFFF ;
+
+ sf_write_short (file, short_buffer, BUFFER_SIZE) ;
+ sf_close (file) ;
+
+ /* Now open that file and compare the ulaw encoded sample values
+ ** with what they should be.
+ */
+
+ if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if (sf_read_raw (file, ulaw_buffer, BUFFER_SIZE) != BUFFER_SIZE)
+ { printf ("sf_read_raw : ") ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < 0x10000 ; k++)
+ if (ulaw_encode (short_buffer [k]) != ulaw_buffer [k])
+ { printf ("Encoder error : sample #%d (0x%02X should be 0x%02X)\n", k, ulaw_buffer [k], ulaw_encode (short_buffer [k])) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ print_test_name ("ulaw_test", "decoder") ;
+
+ /* Now generate a file containing all possible 8 bit encoded
+ ** sample values and write it to disk as ulaw encoded.frames.
+ */
+
+ if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; k < 256 ; k++)
+ ulaw_buffer [k] = k & 0xFF ;
+
+ sf_write_raw (file, ulaw_buffer, 256) ;
+ sf_close (file) ;
+
+ /* Now open that file and compare the ulaw decoded sample values
+ ** with what they should be.
+ */
+
+ if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
+ { printf ("sf_open_write failed with error : ") ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ if (sf_read_short (file, short_buffer, 256) != 256)
+ { printf ("sf_read_short : ") ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+
+ for (k = 0 ; k < 256 ; k++)
+ if (short_buffer [k] != ulaw_decode (ulaw_buffer [k]))
+ { printf ("Decoder error : sample #%d (0x%04X should be 0x%04X)\n", k, short_buffer [k], ulaw_decode (ulaw_buffer [k])) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+
+ unlink (filename) ;
+
+ return 0 ;
+} /* main */
+
+
+/*=================================================================================
+** The following routines came from the sox-12.15 (Sound eXcahcnge) distribution.
+**
+** This code is not compiled into libsndfile. It is only used to test the
+** libsndfile lookup tables for correctness.
+**
+** I have included the original authors comments.
+*/
+
+/*
+** This routine converts from linear to ulaw.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** Joe Campbell: Department of Defense
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711 (very difficult to follow)
+** 2) "A New Digital Technique for Implementation of Any
+** Continuous PCM Companding Law," Villeret, Michel,
+** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
+** 1973, pg. 11.12-11.17
+** 3) MIL-STD-188-113,"Interoperability and Performance Standards
+** for Analog-to_Digital Conversion Techniques,"
+** 17 February 1987
+**
+** Input: Signed 16 bit linear sample
+** Output: 8 bit ulaw sample
+*/
+
+#define uBIAS 0x84 /* define the add-in bias for 16 bit.frames */
+#define uCLIP 32635
+
+static
+unsigned char ulaw_encode (int sample)
+{ static int exp_lut [256] =
+ { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ } ;
+
+ int sign, exponent, mantissa ;
+ unsigned char ulawbyte ;
+
+ /* Get the sample into sign-magnitude. */
+ sign = (sample >> 8) & 0x80 ; /* set aside the sign */
+ if ( sign != 0 )
+ sample = -sample ; /* get magnitude */
+ if ( sample > uCLIP )
+ sample = uCLIP ; /* clip the magnitude */
+
+ /* Convert from 16 bit linear to ulaw. */
+ sample = sample + uBIAS ;
+ exponent = exp_lut [( sample >> 7 ) & 0xFF] ;
+ mantissa = (sample >> ( exponent + 3 ) ) & 0x0F ;
+ ulawbyte = ~ (sign | ( exponent << 4 ) | mantissa) ;
+
+ return ulawbyte ;
+} /* ulaw_encode */
+
+
+/*
+** This routine converts from ulaw to 16 bit linear.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711 (very difficult to follow)
+** 2) MIL-STD-188-113,"Interoperability and Performance Standards
+** for Analog-to_Digital Conversion Techniques,"
+** 17 February 1987
+**
+** Input: 8 bit ulaw sample
+** Output: signed 16 bit linear sample
+*/
+
+static
+int ulaw_decode (unsigned int ulawbyte)
+{ static int exp_lut [8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 } ;
+ int sign, exponent, mantissa, sample ;
+
+ ulawbyte = ~ ulawbyte ;
+ sign = (ulawbyte & 0x80) ;
+ exponent = (ulawbyte >> 4) & 0x07 ;
+ mantissa = ulawbyte & 0x0F ;
+ sample = exp_lut [exponent] + (mantissa << (exponent + 3)) ;
+ if (sign != 0)
+ sample = -sample ;
+
+ return sample ;
+} /* ulaw_decode */
+
diff --git a/tests/utils.c b/tests/utils.c
new file mode 100644
index 0000000..882c969
--- /dev/null
+++ b/tests/utils.c
@@ -0,0 +1,1162 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+** Utility functions to make writing the test suite easier.
+**
+** The .c and .h files were generated automagically with Autogen from
+** the files utils.def and utils.tpl.
+*/
+
+
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+#define LOG_BUFFER_SIZE 2048
+
+/*
+** Neat solution to the Win32/OS2 binary file flage requirement.
+** If O_BINARY isn't already defined by the inclusion of the system
+** headers, set it to zero.
+*/
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+
+void
+gen_windowed_sine_float (float *data, int len, double maximum)
+{ int k ;
+
+ memset (data, 0, len * sizeof (float)) ;
+ /*
+ ** Choose a frequency of 1/32 so that it aligns perfectly with a DFT
+ ** bucket to minimise spreading of energy over more than one bucket.
+ ** Also do not want to make the frequency too high as some of the
+ ** codecs (ie gsm610) have a quite severe high frequency roll off.
+ */
+ len /= 2 ;
+
+ for (k = 0 ; k < len ; k++)
+ { data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;
+
+ /* Apply Hanning Window. */
+ data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
+ }
+
+ return ;
+} /* gen_windowed_sine_float */
+
+void
+gen_windowed_sine_double (double *data, int len, double maximum)
+{ int k ;
+
+ memset (data, 0, len * sizeof (double)) ;
+ /*
+ ** Choose a frequency of 1/32 so that it aligns perfectly with a DFT
+ ** bucket to minimise spreading of energy over more than one bucket.
+ ** Also do not want to make the frequency too high as some of the
+ ** codecs (ie gsm610) have a quite severe high frequency roll off.
+ */
+ len /= 2 ;
+
+ for (k = 0 ; k < len ; k++)
+ { data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;
+
+ /* Apply Hanning Window. */
+ data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
+ }
+
+ return ;
+} /* gen_windowed_sine_double */
+
+
+void
+create_short_sndfile (const char *filename, int format, int channels)
+{ short data [2 * 3 * 4 * 5 * 6 * 7] = { 0, } ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = channels ;
+ sfinfo.format = format ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { printf ("Error (%s, %d) : sf_open failed : %s\n", __FILE__, __LINE__, sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ sf_write_short (file, data, ARRAY_LEN (data)) ;
+
+ sf_close (file) ;
+} /* create_short_sndfile */
+
+void
+check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num)
+{ static unsigned char buf [4096] ;
+ uint64_t cksum ;
+ FILE *file ;
+ int k, read_count ;
+
+ memset (buf, 0, sizeof (buf)) ;
+
+ /* The 'b' in the mode string means binary for Win32. */
+ if ((file = fopen (filename, "rb")) == NULL)
+ { printf ("\n\nLine %d: could not open file '%s'\n\n", line_num, filename) ;
+ exit (1) ;
+ } ;
+
+ cksum = 0 ;
+
+ while ((read_count = fread (buf, 1, sizeof (buf), file)))
+ for (k = 0 ; k < read_count ; k++)
+ cksum = cksum * 511 + buf [k] ;
+
+ fclose (file) ;
+
+ if (target_hash == 0)
+ { printf (" 0x%016" PRIx64 "\n", cksum) ;
+ return ;
+ } ;
+
+ if (cksum != target_hash)
+ { printf ("\n\nLine %d: incorrect hash value 0x%016" PRIx64 " should be 0x%016" PRIx64 ".\n\n", line_num, cksum, target_hash) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* check_file_hash_or_die */
+
+void
+print_test_name (const char *test, const char *filename)
+{ int count ;
+
+ if (test == NULL)
+ { printf (__FILE__ ": bad test of filename parameter.\n") ;
+ exit (1) ;
+ } ;
+
+ if (filename == NULL || strlen (filename) == 0)
+ { printf (" %-30s : ", test) ;
+ count = 25 ;
+ }
+ else
+ { printf (" %-30s : %s ", test, filename) ;
+ count = 24 - strlen (filename) ;
+ } ;
+
+ while (count -- > 0)
+ putchar ('.') ;
+ putchar (' ') ;
+
+ fflush (stdout) ;
+} /* print_test_name */
+
+void
+dump_data_to_file (const char *filename, const void *data, unsigned int datalen)
+{ FILE *file ;
+
+ if ((file = fopen (filename, "wb")) == NULL)
+ { printf ("\n\nLine %d : could not open file : %s\n\n", __LINE__, filename) ;
+ exit (1) ;
+ } ;
+
+ if (fwrite (data, 1, datalen, file) != datalen)
+ { printf ("\n\nLine %d : fwrite failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ fclose (file) ;
+
+} /* dump_data_to_file */
+
+/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+*/
+
+static char octfilename [] = "error.dat" ;
+
+int
+oct_save_short (const short *a, const short *b, int len)
+{ FILE *file ;
+ int k ;
+
+ if (! (file = fopen (octfilename, "w")))
+ return 1 ;
+
+ fprintf (file, "# Not created by Octave\n") ;
+
+ fprintf (file, "# name: a\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% d" "\n", a [k]) ;
+
+ fprintf (file, "# name: b\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% d" "\n", b [k]) ;
+
+ fclose (file) ;
+ return 0 ;
+} /* oct_save_short */
+int
+oct_save_int (const int *a, const int *b, int len)
+{ FILE *file ;
+ int k ;
+
+ if (! (file = fopen (octfilename, "w")))
+ return 1 ;
+
+ fprintf (file, "# Not created by Octave\n") ;
+
+ fprintf (file, "# name: a\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% d" "\n", a [k]) ;
+
+ fprintf (file, "# name: b\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% d" "\n", b [k]) ;
+
+ fclose (file) ;
+ return 0 ;
+} /* oct_save_int */
+int
+oct_save_float (const float *a, const float *b, int len)
+{ FILE *file ;
+ int k ;
+
+ if (! (file = fopen (octfilename, "w")))
+ return 1 ;
+
+ fprintf (file, "# Not created by Octave\n") ;
+
+ fprintf (file, "# name: a\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% g" "\n", a [k]) ;
+
+ fprintf (file, "# name: b\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% g" "\n", b [k]) ;
+
+ fclose (file) ;
+ return 0 ;
+} /* oct_save_float */
+int
+oct_save_double (const double *a, const double *b, int len)
+{ FILE *file ;
+ int k ;
+
+ if (! (file = fopen (octfilename, "w")))
+ return 1 ;
+
+ fprintf (file, "# Not created by Octave\n") ;
+
+ fprintf (file, "# name: a\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% g" "\n", a [k]) ;
+
+ fprintf (file, "# name: b\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, "% g" "\n", b [k]) ;
+
+ fclose (file) ;
+ return 0 ;
+} /* oct_save_double */
+
+
+void
+check_log_buffer_or_die (SNDFILE *file, int line_num)
+{ static char buffer [LOG_BUFFER_SIZE] ;
+ int count ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Get the log buffer data. */
+ count = sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
+
+ if (LOG_BUFFER_SIZE - count < 2)
+ { printf ("\n\nLine %d : Possible long log buffer.\n", line_num) ;
+ exit (1) ;
+ }
+
+ /* Look for "Should" */
+ if (strstr (buffer, "ould"))
+ { printf ("\n\nLine %d : Log buffer contains `ould'. Dumping.\n", line_num) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ /* Look for "**" */
+ if (strstr (buffer, "*"))
+ { printf ("\n\nLine %d : Log buffer contains `*'. Dumping.\n", line_num) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ /* Look for "Should" */
+ if (strstr (buffer, "nknown marker"))
+ { printf ("\n\nLine %d : Log buffer contains `nknown marker'. Dumping.\n", line_num) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* check_log_buffer_or_die */
+
+int
+string_in_log_buffer (SNDFILE *file, const char *s)
+{ static char buffer [LOG_BUFFER_SIZE] ;
+ int count ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Get the log buffer data. */
+ count = sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
+
+ if (LOG_BUFFER_SIZE - count < 2)
+ { printf ("Possible long log buffer.\n") ;
+ exit (1) ;
+ }
+
+ /* Look for string */
+ return strstr (buffer, s) ? SF_TRUE : SF_FALSE ;
+} /* string_in_log_buffer */
+
+void
+hexdump_file (const char * filename, sf_count_t offset, sf_count_t length)
+{
+ FILE * file ;
+ char buffer [16] ;
+ int k, m, ch, readcount ;
+
+ if (length > 1000000)
+ { printf ("\n\nError : length (%ld) too long.\n\n", SF_COUNT_TO_LONG (offset)) ;
+ exit (1) ;
+ } ;
+
+ if ((file = fopen (filename, "r")) == NULL)
+ { printf ("\n\nError : hexdump_file (%s) could not open file for read.\n\n", filename) ;
+ exit (1) ;
+ } ;
+
+ if (fseek (file, offset, SEEK_SET) != 0)
+ { printf ("\n\nError : fseek(file, %ld, SEEK_SET) failed : %s\n\n", SF_COUNT_TO_LONG (offset), strerror (errno)) ;
+ exit (1) ;
+ } ;
+
+ puts ("\n\n") ;
+
+ for (k = 0 ; k < length ; k+= sizeof (buffer))
+ { readcount = fread (buffer, 1, sizeof (buffer), file) ;
+
+ printf ("%08lx : ", SF_COUNT_TO_LONG (offset + k)) ;
+
+ for (m = 0 ; m < readcount ; m++)
+ printf ("%02x ", buffer [m] & 0xFF) ;
+
+ for (m = readcount ; m < SIGNED_SIZEOF (buffer) ; m++)
+ printf (" ") ;
+
+ printf (" ") ;
+ for (m = 0 ; m < readcount ; m++)
+ { ch = isprint (buffer [m]) ? buffer [m] : '.' ;
+ putchar (ch) ;
+ } ;
+
+ if (readcount < SIGNED_SIZEOF (buffer))
+ break ;
+
+ putchar ('\n') ;
+ } ;
+
+ puts ("\n") ;
+
+ fclose (file) ;
+} /* hexdump_file */
+
+void
+dump_log_buffer (SNDFILE *file)
+{ static char buffer [LOG_BUFFER_SIZE] ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Get the log buffer data. */
+ sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
+
+ if (strlen (buffer) < 1)
+ puts ("Log buffer empty.\n") ;
+ else
+ puts (buffer) ;
+
+ return ;
+} /* dump_log_buffer */
+
+SNDFILE *
+test_open_file_or_die (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num)
+{ static int count = 0 ;
+
+ SNDFILE *file ;
+ const char *modestr, *func_name ;
+ int oflags = 0, omode = 0, err ;
+
+ /*
+ ** Need to test both sf_open() and sf_open_fd().
+ ** Do so alternately.
+ */
+ switch (mode)
+ { case SFM_READ :
+ modestr = "SFM_READ" ;
+ oflags = O_RDONLY | O_BINARY ;
+ omode = 0 ;
+ break ;
+
+ case SFM_WRITE :
+ modestr = "SFM_WRITE" ;
+ oflags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
+ omode = S_IRUSR | S_IWUSR | S_IRGRP ;
+ break ;
+
+ case SFM_RDWR :
+ modestr = "SFM_RDWR" ;
+ oflags = O_RDWR | O_CREAT | O_BINARY ;
+ omode = S_IRUSR | S_IWUSR | S_IRGRP ;
+ break ;
+ default :
+ printf ("\n\nLine %d: Bad mode.\n", line_num) ;
+ fflush (stdout) ;
+ exit (1) ;
+ } ;
+
+ if (OS_IS_WIN32)
+ { /* Windows does not understand and ignores the S_IRGRP flag, but Wine
+ ** gives a run time warning message, so just clear it.
+ */
+ omode &= ~S_IRGRP ;
+ } ;
+
+ if (allow_fd && ((++count) & 1) == 1)
+ { int fd ;
+
+ /* Only use the three argument open() function if omode != 0. */
+ fd = (omode == 0) ? open (filename, oflags) : open (filename, oflags, omode) ;
+
+ if (fd < 0)
+ { printf ("\n\n%s : open failed : %s\n", __func__, strerror (errno)) ;
+ exit (1) ;
+ } ;
+
+ func_name = "sf_open_fd" ;
+ file = sf_open_fd (fd, mode, sfinfo, SF_TRUE) ;
+ }
+ else
+ { func_name = "sf_open" ;
+ file = sf_open (filename, mode, sfinfo) ;
+ } ;
+
+ if (file == NULL)
+ { printf ("\n\nLine %d: %s (%s) failed : %s\n\n", line_num, func_name, modestr, sf_strerror (NULL)) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ err = sf_error (file) ;
+ if (err != SF_ERR_NO_ERROR)
+ { printf ("\n\nLine %d : sf_error : %s\n\n", line_num, sf_error_number (err)) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ return file ;
+} /* test_open_file_or_die */
+
+void
+test_read_write_position_or_die (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos)
+{ sf_count_t pos ;
+
+ /* Check the current read position. */
+ if (read_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_READ)) != read_pos)
+ { printf ("\n\nLine %d ", line_num) ;
+ if (pass > 0)
+ printf ("(pass %d): ", pass) ;
+ printf ("Read position (%ld) should be %ld.\n", SF_COUNT_TO_LONG (pos), SF_COUNT_TO_LONG (read_pos)) ;
+ exit (1) ;
+ } ;
+
+ /* Check the current write position. */
+ if (write_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_WRITE)) != write_pos)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : Write position (%ld) should be %ld.\n",
+ SF_COUNT_TO_LONG (pos), SF_COUNT_TO_LONG (write_pos)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_write_position */
+
+void
+test_seek_or_die (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num)
+{ sf_count_t position ;
+ const char *channel_name, *whence_name ;
+
+ switch (whence)
+ { case SEEK_SET :
+ whence_name = "SEEK_SET" ;
+ break ;
+ case SEEK_CUR :
+ whence_name = "SEEK_CUR" ;
+ break ;
+ case SEEK_END :
+ whence_name = "SEEK_END" ;
+ break ;
+
+ /* SFM_READ */
+ case SEEK_SET | SFM_READ :
+ whence_name = "SFM_READ | SEEK_SET" ;
+ break ;
+ case SEEK_CUR | SFM_READ :
+ whence_name = "SFM_READ | SEEK_CUR" ;
+ break ;
+ case SEEK_END | SFM_READ :
+ whence_name = "SFM_READ | SEEK_END" ;
+ break ;
+
+ /* SFM_WRITE */
+ case SEEK_SET | SFM_WRITE :
+ whence_name = "SFM_WRITE | SEEK_SET" ;
+ break ;
+ case SEEK_CUR | SFM_WRITE :
+ whence_name = "SFM_WRITE | SEEK_CUR" ;
+ break ;
+ case SEEK_END | SFM_WRITE :
+ whence_name = "SFM_WRITE | SEEK_END" ;
+ break ;
+
+ default :
+ printf ("\n\nLine %d: bad whence parameter.\n", line_num) ;
+ exit (1) ;
+ } ;
+
+ channel_name = (channels == 1) ? "Mono" : "Stereo" ;
+
+ if ((position = sf_seek (file, offset, whence)) != new_pos)
+ { printf ("\n\nLine %d : %s : sf_seek (file, %ld, %s) returned %ld (should be %ld).\n\n",
+ line_num, channel_name, SF_COUNT_TO_LONG (offset), whence_name,
+ SF_COUNT_TO_LONG (position), SF_COUNT_TO_LONG (new_pos)) ;
+ exit (1) ;
+ } ;
+
+} /* test_seek_or_die */
+
+
+
+void
+test_read_short_or_die (SNDFILE *file, int pass, short *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_read_short (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_read_short failed with short read (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_short_or_die */
+
+void
+test_read_int_or_die (SNDFILE *file, int pass, int *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_read_int (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_read_int failed with short read (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_int_or_die */
+
+void
+test_read_float_or_die (SNDFILE *file, int pass, float *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_read_float (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_read_float failed with short read (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_float_or_die */
+
+void
+test_read_double_or_die (SNDFILE *file, int pass, double *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_read_double (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_read_double failed with short read (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_double_or_die */
+
+
+void
+test_readf_short_or_die (SNDFILE *file, int pass, short *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_readf_short (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_readf_short failed with short readf (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_readf_short_or_die */
+
+void
+test_readf_int_or_die (SNDFILE *file, int pass, int *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_readf_int (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_readf_int failed with short readf (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_readf_int_or_die */
+
+void
+test_readf_float_or_die (SNDFILE *file, int pass, float *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_readf_float (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_readf_float failed with short readf (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_readf_float_or_die */
+
+void
+test_readf_double_or_die (SNDFILE *file, int pass, double *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_readf_double (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_readf_double failed with short readf (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_readf_double_or_die */
+
+
+void
+test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_read_raw (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_read_raw failed with short read (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_raw_or_die */
+
+
+
+void
+test_write_short_or_die (SNDFILE *file, int pass, const short *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_write_short (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_write_short failed with short write (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_write_short_or_die */
+
+void
+test_write_int_or_die (SNDFILE *file, int pass, const int *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_write_int (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_write_int failed with short write (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_write_int_or_die */
+
+void
+test_write_float_or_die (SNDFILE *file, int pass, const float *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_write_float (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_write_float failed with short write (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_write_float_or_die */
+
+void
+test_write_double_or_die (SNDFILE *file, int pass, const double *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_write_double (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_write_double failed with short write (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_write_double_or_die */
+
+
+void
+test_writef_short_or_die (SNDFILE *file, int pass, const short *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_writef_short (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_writef_short failed with short writef (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_writef_short_or_die */
+
+void
+test_writef_int_or_die (SNDFILE *file, int pass, const int *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_writef_int (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_writef_int failed with short writef (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_writef_int_or_die */
+
+void
+test_writef_float_or_die (SNDFILE *file, int pass, const float *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_writef_float (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_writef_float failed with short writef (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_writef_float_or_die */
+
+void
+test_writef_double_or_die (SNDFILE *file, int pass, const double *test, sf_count_t frames, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_writef_double (file, test, frames)) != frames)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_writef_double failed with short writef (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (frames), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_writef_double_or_die */
+
+
+void
+test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_write_raw (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_write_raw failed with short write (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_write_raw_or_die */
+
+
+void
+compare_short_or_die (const short *left, const short *right, unsigned count, int line_num)
+{
+ unsigned k ;
+
+ for (k = 0 ; k < count ;k++)
+ if (left [k] != right [k])
+ { printf ("\n\nLine %d : Error at index %d, " "% d" " should be " "% d" ".\n\n", line_num, k, left [k], right [k]) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* compare_short_or_die */
+void
+compare_int_or_die (const int *left, const int *right, unsigned count, int line_num)
+{
+ unsigned k ;
+
+ for (k = 0 ; k < count ;k++)
+ if (left [k] != right [k])
+ { printf ("\n\nLine %d : Error at index %d, " "% d" " should be " "% d" ".\n\n", line_num, k, left [k], right [k]) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* compare_int_or_die */
+void
+compare_float_or_die (const float *left, const float *right, unsigned count, int line_num)
+{
+ unsigned k ;
+
+ for (k = 0 ; k < count ;k++)
+ if (left [k] != right [k])
+ { printf ("\n\nLine %d : Error at index %d, " "% g" " should be " "% g" ".\n\n", line_num, k, left [k], right [k]) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* compare_float_or_die */
+void
+compare_double_or_die (const double *left, const double *right, unsigned count, int line_num)
+{
+ unsigned k ;
+
+ for (k = 0 ; k < count ;k++)
+ if (left [k] != right [k])
+ { printf ("\n\nLine %d : Error at index %d, " "% g" " should be " "% g" ".\n\n", line_num, k, left [k], right [k]) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* compare_double_or_die */
+
+
+
+void
+delete_file (int format, const char *filename)
+{ char rsrc_name [512], *fname ;
+
+ unlink (filename) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2)
+ return ;
+
+ /*
+ ** Now try for a resource fork stored as a separate file.
+ ** Grab the un-adulterated filename again.
+ */
+ snprintf (rsrc_name, sizeof (rsrc_name), "%s", filename) ;
+
+ if ((fname = strrchr (rsrc_name, '/')) != NULL)
+ fname ++ ;
+ else if ((fname = strrchr (rsrc_name, '\\')) != NULL)
+ fname ++ ;
+ else
+ fname = rsrc_name ;
+
+ memmove (fname + 2, fname, strlen (fname) + 1) ;
+ fname [0] = '.' ;
+ fname [1] = '_' ;
+
+ unlink (rsrc_name) ;
+} /* delete_file */
+
+static int allowed_open_files = -1 ;
+
+void
+count_open_files (void)
+{
+#if OS_IS_WIN32
+ return ;
+#else
+ int k, count = 0 ;
+ struct stat statbuf ;
+
+ if (allowed_open_files > 0)
+ return ;
+
+ for (k = 0 ; k < 1024 ; k++)
+ if (fstat (k, &statbuf) == 0)
+ count ++ ;
+
+ allowed_open_files = count ;
+#endif
+} /* count_open_files */
+
+void
+increment_open_file_count (void)
+{ allowed_open_files ++ ;
+} /* increment_open_file_count */
+
+void
+check_open_file_count_or_die (int lineno)
+{
+#if OS_IS_WIN32
+ lineno = 0 ;
+ return ;
+#else
+ int k, count = 0 ;
+ struct stat statbuf ;
+
+ if (allowed_open_files < 0)
+ count_open_files () ;
+
+ for (k = 0 ; k < 1024 ; k++)
+ if (fstat (k, &statbuf) == 0)
+ count ++ ;
+
+ if (count > allowed_open_files)
+ { printf ("\nLine %d : number of open files (%d) > allowed (%d).\n\n", lineno, count, allowed_open_files) ;
+ exit (1) ;
+ } ;
+#endif
+} /* check_open_file_count_or_die */
+
+void
+write_mono_file (const char * filename, int format, int srate, float * output, int len)
+{ SNDFILE * file ;
+ SF_INFO sfinfo ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ sfinfo.samplerate = srate ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { printf ("sf_open (%s) : %s\n", filename, sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ sf_write_float (file, output, len) ;
+
+ sf_close (file) ;
+} /* write_mono_file */
+
+void
+gen_lowpass_noise_float (float *data, int len)
+{ int32_t value = 0x1243456 ;
+ double sample, last_val = 0.0 ;
+ int k ;
+
+ for (k = 0 ; k < len ; k++)
+ { /* Not a crypto quality RNG. */
+ value = 11117 * value + 211231 ;
+ value = 11117 * value + 211231 ;
+ value = 11117 * value + 211231 ;
+
+ sample = value / (0x7fffffff * 1.000001) ;
+ sample = 0.2 * sample - 0.9 * last_val ;
+
+ data [k] = last_val = sample ;
+ } ;
+
+} /* gen_lowpass_noise_float */
+
+
+/*
+** Windows is fucked.
+** If a file is opened R/W and data is written to it, then fstat will return
+** the correct file length, but stat will return zero.
+*/
+
+sf_count_t
+file_length (const char * fname)
+{ struct stat data ;
+
+ if (stat (fname, &data) != 0)
+ return 0 ;
+
+ return (sf_count_t) data.st_size ;
+} /* file_length */
+
+sf_count_t
+file_length_fd (int fd)
+{ struct stat data ;
+
+ memset (&data, 0, sizeof (data)) ;
+ if (fstat (fd, &data) != 0)
+ return 0 ;
+
+ return (sf_count_t) data.st_size ;
+} /* file_length_fd */
+
+
+
+
diff --git a/tests/utils.def b/tests/utils.def
new file mode 100644
index 0000000..0d94183
--- /dev/null
+++ b/tests/utils.def
@@ -0,0 +1,52 @@
+autogen definitions utils.tpl;
+
+float_type = {
+ name = float ;
+ };
+
+float_type = {
+ name = double ;
+ };
+
+/*----------------------------------*/
+
+io_type = {
+ io_element = short ;
+ format_str = "\"% d\"" ;
+ };
+
+io_type = {
+ io_element = int ;
+ format_str = "\"% d\"" ;
+ };
+
+io_type = {
+ io_element = float ;
+ format_str = "\"% g\"" ;
+ };
+
+io_type = {
+ io_element = double ;
+ format_str = "\"% g\"" ;
+ };
+
+read_op = {
+ op_element = read ;
+ count_name = items ;
+ };
+
+read_op = {
+ op_element = readf ;
+ count_name = frames ;
+ };
+
+write_op = {
+ op_element = write ;
+ count_name = items ;
+ };
+
+write_op = {
+ op_element = writef ;
+ count_name = frames ;
+ };
+
diff --git a/tests/utils.h b/tests/utils.h
new file mode 100644
index 0000000..79da286
--- /dev/null
+++ b/tests/utils.h
@@ -0,0 +1,183 @@
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+** Utility functions to make writing the test suite easier.
+**
+** The .c and .h files were generated automagically with Autogen from
+** the files utils.def and utils.tpl.
+*/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#define SF_COUNT_TO_LONG(x) ((long) (x))
+#define ARRAY_LEN(x) ((int) (sizeof (x)) / (sizeof ((x) [0])))
+#define SIGNED_SIZEOF(x) ((int64_t) (sizeof (x)))
+#define NOT(x) (! (x))
+
+#define PIPE_INDEX(x) ((x) + 500)
+#define PIPE_TEST_LEN 12345
+
+
+void gen_windowed_sine_float (float *data, int len, double maximum) ;
+void gen_windowed_sine_double (double *data, int len, double maximum) ;
+
+
+void create_short_sndfile (const char *filename, int format, int channels) ;
+
+void check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num) ;
+
+void print_test_name (const char *test, const char *filename) ;
+
+void dump_data_to_file (const char *filename, const void *data, unsigned int datalen) ;
+
+void write_mono_file (const char * filename, int format, int srate, float * output, int len) ;
+
+static inline void
+exit_if_true (int test, const char *format, ...)
+{ if (test)
+ { va_list argptr ;
+ va_start (argptr, format) ;
+ vprintf (format, argptr) ;
+ va_end (argptr) ;
+ exit (1) ;
+ } ;
+} /* exit_if_true */
+
+/*
+** Functions for saving two vectors of data in an ascii text file which
+** can then be loaded into GNU octave for comparison.
+*/
+
+int oct_save_short (const short *a, const short *b, int len) ;
+int oct_save_int (const int *a, const int *b, int len) ;
+int oct_save_float (const float *a, const float *b, int len) ;
+int oct_save_double (const double *a, const double *b, int len) ;
+
+
+void delete_file (int format, const char *filename) ;
+
+void count_open_files (void) ;
+void increment_open_file_count (void) ;
+void check_open_file_count_or_die (int lineno) ;
+
+#ifdef SNDFILE_H
+
+static inline void
+sf_info_clear (SF_INFO * info)
+{ memset (info, 0, sizeof (SF_INFO)) ;
+} /* sf_info_clear */
+
+static inline void
+sf_info_setup (SF_INFO * info, int format, int samplerate, int channels)
+{ sf_info_clear (info) ;
+
+ info->format = format ;
+ info->samplerate = samplerate ;
+ info->channels = channels ;
+} /* sf_info_setup */
+
+
+void dump_log_buffer (SNDFILE *file) ;
+void check_log_buffer_or_die (SNDFILE *file, int line_num) ;
+int string_in_log_buffer (SNDFILE *file, const char *s) ;
+void hexdump_file (const char * filename, sf_count_t offset, sf_count_t length) ;
+
+
+SNDFILE *test_open_file_or_die
+ (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num) ;
+
+void test_read_write_position_or_die
+ (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos) ;
+
+void test_seek_or_die
+ (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num) ;
+
+
+void test_read_short_or_die
+ (SNDFILE *file, int pass, short *test, sf_count_t items, int line_num) ;
+void test_read_int_or_die
+ (SNDFILE *file, int pass, int *test, sf_count_t items, int line_num) ;
+void test_read_float_or_die
+ (SNDFILE *file, int pass, float *test, sf_count_t items, int line_num) ;
+void test_read_double_or_die
+ (SNDFILE *file, int pass, double *test, sf_count_t items, int line_num) ;
+
+void test_readf_short_or_die
+ (SNDFILE *file, int pass, short *test, sf_count_t frames, int line_num) ;
+void test_readf_int_or_die
+ (SNDFILE *file, int pass, int *test, sf_count_t frames, int line_num) ;
+void test_readf_float_or_die
+ (SNDFILE *file, int pass, float *test, sf_count_t frames, int line_num) ;
+void test_readf_double_or_die
+ (SNDFILE *file, int pass, double *test, sf_count_t frames, int line_num) ;
+
+
+void
+test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num) ;
+
+
+void test_write_short_or_die
+ (SNDFILE *file, int pass, const short *test, sf_count_t items, int line_num) ;
+void test_write_int_or_die
+ (SNDFILE *file, int pass, const int *test, sf_count_t items, int line_num) ;
+void test_write_float_or_die
+ (SNDFILE *file, int pass, const float *test, sf_count_t items, int line_num) ;
+void test_write_double_or_die
+ (SNDFILE *file, int pass, const double *test, sf_count_t items, int line_num) ;
+
+void test_writef_short_or_die
+ (SNDFILE *file, int pass, const short *test, sf_count_t frames, int line_num) ;
+void test_writef_int_or_die
+ (SNDFILE *file, int pass, const int *test, sf_count_t frames, int line_num) ;
+void test_writef_float_or_die
+ (SNDFILE *file, int pass, const float *test, sf_count_t frames, int line_num) ;
+void test_writef_double_or_die
+ (SNDFILE *file, int pass, const double *test, sf_count_t frames, int line_num) ;
+
+
+void
+test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num) ;
+
+void compare_short_or_die (const short *left, const short *right, unsigned count, int line_num) ;
+void compare_int_or_die (const int *left, const int *right, unsigned count, int line_num) ;
+void compare_float_or_die (const float *left, const float *right, unsigned count, int line_num) ;
+void compare_double_or_die (const double *left, const double *right, unsigned count, int line_num) ;
+
+
+
+void gen_lowpass_noise_float (float *data, int len) ;
+
+sf_count_t file_length (const char * fname) ;
+sf_count_t file_length_fd (int fd) ;
+
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+
+
diff --git a/tests/utils.tpl b/tests/utils.tpl
new file mode 100644
index 0000000..f517e23
--- /dev/null
+++ b/tests/utils.tpl
@@ -0,0 +1,890 @@
+[+ AutoGen5 template h c +]
+/*
+** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+** Utility functions to make writing the test suite easier.
+**
+** The .c and .h files were generated automagically with Autogen from
+** the files utils.def and utils.tpl.
+*/
+
+[+ CASE (suffix) +]
+[+ == h +]
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#define SF_COUNT_TO_LONG(x) ((long) (x))
+#define ARRAY_LEN(x) ((int) (sizeof (x)) / (sizeof ((x) [0])))
+#define SIGNED_SIZEOF(x) ((int64_t) (sizeof (x)))
+#define NOT(x) (! (x))
+
+#define PIPE_INDEX(x) ((x) + 500)
+#define PIPE_TEST_LEN 12345
+
+
+[+ FOR float_type
++]void gen_windowed_sine_[+ (get "name") +] ([+ (get "name") +] *data, int len, double maximum) ;
+[+ ENDFOR float_type
++]
+
+void create_short_sndfile (const char *filename, int format, int channels) ;
+
+void check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num) ;
+
+void print_test_name (const char *test, const char *filename) ;
+
+void dump_data_to_file (const char *filename, const void *data, unsigned int datalen) ;
+
+void write_mono_file (const char * filename, int format, int srate, float * output, int len) ;
+
+static inline void
+exit_if_true (int test, const char *format, ...)
+{ if (test)
+ { va_list argptr ;
+ va_start (argptr, format) ;
+ vprintf (format, argptr) ;
+ va_end (argptr) ;
+ exit (1) ;
+ } ;
+} /* exit_if_true */
+
+/*
+** Functions for saving two vectors of data in an ascii text file which
+** can then be loaded into GNU octave for comparison.
+*/
+
+[+ FOR io_type
++]int oct_save_[+ (get "io_element") +] (const [+ (get "io_element") +] *a, const [+ (get "io_element") +] *b, int len) ;
+[+ ENDFOR io_type
++]
+
+void delete_file (int format, const char *filename) ;
+
+void count_open_files (void) ;
+void increment_open_file_count (void) ;
+void check_open_file_count_or_die (int lineno) ;
+
+#ifdef SNDFILE_H
+
+static inline void
+sf_info_clear (SF_INFO * info)
+{ memset (info, 0, sizeof (SF_INFO)) ;
+} /* sf_info_clear */
+
+static inline void
+sf_info_setup (SF_INFO * info, int format, int samplerate, int channels)
+{ sf_info_clear (info) ;
+
+ info->format = format ;
+ info->samplerate = samplerate ;
+ info->channels = channels ;
+} /* sf_info_setup */
+
+
+void dump_log_buffer (SNDFILE *file) ;
+void check_log_buffer_or_die (SNDFILE *file, int line_num) ;
+int string_in_log_buffer (SNDFILE *file, const char *s) ;
+void hexdump_file (const char * filename, sf_count_t offset, sf_count_t length) ;
+
+
+SNDFILE *test_open_file_or_die
+ (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num) ;
+
+void test_read_write_position_or_die
+ (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos) ;
+
+void test_seek_or_die
+ (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num) ;
+
+[+ FOR read_op +]
+[+ FOR io_type
++]void test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die
+ (SNDFILE *file, int pass, [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num) ;
+[+ ENDFOR io_type +][+ ENDFOR read_op +]
+
+void
+test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num) ;
+
+[+ FOR write_op +]
+[+ FOR io_type
++]void test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die
+ (SNDFILE *file, int pass, const [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num) ;
+[+ ENDFOR io_type +][+ ENDFOR write_op +]
+
+void
+test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num) ;
+
+[+ FOR io_type
++]void compare_[+ (get "io_element") +]_or_die (const [+ (get "io_element") +] *left, const [+ (get "io_element") +] *right, unsigned count, int line_num) ;
+[+ ENDFOR io_type +]
+
+
+void gen_lowpass_noise_float (float *data, int len) ;
+
+sf_count_t file_length (const char * fname) ;
+sf_count_t file_length_fd (int fd) ;
+
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+[+ == c +]
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338
+#endif
+
+#define LOG_BUFFER_SIZE 2048
+
+/*
+** Neat solution to the Win32/OS2 binary file flage requirement.
+** If O_BINARY isn't already defined by the inclusion of the system
+** headers, set it to zero.
+*/
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+[+ FOR float_type +]
+void
+gen_windowed_sine_[+ (get "name") +] ([+ (get "name") +] *data, int len, double maximum)
+{ int k ;
+
+ memset (data, 0, len * sizeof ([+ (get "name") +])) ;
+ /*
+ ** Choose a frequency of 1/32 so that it aligns perfectly with a DFT
+ ** bucket to minimise spreading of energy over more than one bucket.
+ ** Also do not want to make the frequency too high as some of the
+ ** codecs (ie gsm610) have a quite severe high frequency roll off.
+ */
+ len /= 2 ;
+
+ for (k = 0 ; k < len ; k++)
+ { data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;
+
+ /* Apply Hanning Window. */
+ data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
+ }
+
+ return ;
+} /* gen_windowed_sine_[+ (get "name") +] */
+[+ ENDFOR float_type +]
+
+void
+create_short_sndfile (const char *filename, int format, int channels)
+{ short data [2 * 3 * 4 * 5 * 6 * 7] = { 0, } ;
+ SNDFILE *file ;
+ SF_INFO sfinfo ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.channels = channels ;
+ sfinfo.format = format ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { printf ("Error (%s, %d) : sf_open failed : %s\n", __FILE__, __LINE__, sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ sf_write_short (file, data, ARRAY_LEN (data)) ;
+
+ sf_close (file) ;
+} /* create_short_sndfile */
+
+void
+check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num)
+{ static unsigned char buf [4096] ;
+ uint64_t cksum ;
+ FILE *file ;
+ int k, read_count ;
+
+ memset (buf, 0, sizeof (buf)) ;
+
+ /* The 'b' in the mode string means binary for Win32. */
+ if ((file = fopen (filename, "rb")) == NULL)
+ { printf ("\n\nLine %d: could not open file '%s'\n\n", line_num, filename) ;
+ exit (1) ;
+ } ;
+
+ cksum = 0 ;
+
+ while ((read_count = fread (buf, 1, sizeof (buf), file)))
+ for (k = 0 ; k < read_count ; k++)
+ cksum = cksum * 511 + buf [k] ;
+
+ fclose (file) ;
+
+ if (target_hash == 0)
+ { printf (" 0x%016" PRIx64 "\n", cksum) ;
+ return ;
+ } ;
+
+ if (cksum != target_hash)
+ { printf ("\n\nLine %d: incorrect hash value 0x%016" PRIx64 " should be 0x%016" PRIx64 ".\n\n", line_num, cksum, target_hash) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* check_file_hash_or_die */
+
+void
+print_test_name (const char *test, const char *filename)
+{ int count ;
+
+ if (test == NULL)
+ { printf (__FILE__ ": bad test of filename parameter.\n") ;
+ exit (1) ;
+ } ;
+
+ if (filename == NULL || strlen (filename) == 0)
+ { printf (" %-30s : ", test) ;
+ count = 25 ;
+ }
+ else
+ { printf (" %-30s : %s ", test, filename) ;
+ count = 24 - strlen (filename) ;
+ } ;
+
+ while (count -- > 0)
+ putchar ('.') ;
+ putchar (' ') ;
+
+ fflush (stdout) ;
+} /* print_test_name */
+
+void
+dump_data_to_file (const char *filename, const void *data, unsigned int datalen)
+{ FILE *file ;
+
+ if ((file = fopen (filename, "wb")) == NULL)
+ { printf ("\n\nLine %d : could not open file : %s\n\n", __LINE__, filename) ;
+ exit (1) ;
+ } ;
+
+ if (fwrite (data, 1, datalen, file) != datalen)
+ { printf ("\n\nLine %d : fwrite failed.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ fclose (file) ;
+
+} /* dump_data_to_file */
+
+/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+*/
+
+static char octfilename [] = "error.dat" ;
+
+[+ FOR io_type
++]int
+oct_save_[+ (get "io_element") +] (const [+ (get "io_element") +] *a, const [+ (get "io_element") +] *b, int len)
+{ FILE *file ;
+ int k ;
+
+ if (! (file = fopen (octfilename, "w")))
+ return 1 ;
+
+ fprintf (file, "# Not created by Octave\n") ;
+
+ fprintf (file, "# name: a\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, [+ (get "format_str") +] "\n", a [k]) ;
+
+ fprintf (file, "# name: b\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < len ; k++)
+ fprintf (file, [+ (get "format_str") +] "\n", b [k]) ;
+
+ fclose (file) ;
+ return 0 ;
+} /* oct_save_[+ (get "io_element") +] */
+[+ ENDFOR io_type
++]
+
+void
+check_log_buffer_or_die (SNDFILE *file, int line_num)
+{ static char buffer [LOG_BUFFER_SIZE] ;
+ int count ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Get the log buffer data. */
+ count = sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
+
+ if (LOG_BUFFER_SIZE - count < 2)
+ { printf ("\n\nLine %d : Possible long log buffer.\n", line_num) ;
+ exit (1) ;
+ }
+
+ /* Look for "Should" */
+ if (strstr (buffer, "ould"))
+ { printf ("\n\nLine %d : Log buffer contains `ould'. Dumping.\n", line_num) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ /* Look for "**" */
+ if (strstr (buffer, "*"))
+ { printf ("\n\nLine %d : Log buffer contains `*'. Dumping.\n", line_num) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ /* Look for "Should" */
+ if (strstr (buffer, "nknown marker"))
+ { printf ("\n\nLine %d : Log buffer contains `nknown marker'. Dumping.\n", line_num) ;
+ puts (buffer) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* check_log_buffer_or_die */
+
+int
+string_in_log_buffer (SNDFILE *file, const char *s)
+{ static char buffer [LOG_BUFFER_SIZE] ;
+ int count ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Get the log buffer data. */
+ count = sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
+
+ if (LOG_BUFFER_SIZE - count < 2)
+ { printf ("Possible long log buffer.\n") ;
+ exit (1) ;
+ }
+
+ /* Look for string */
+ return strstr (buffer, s) ? SF_TRUE : SF_FALSE ;
+} /* string_in_log_buffer */
+
+void
+hexdump_file (const char * filename, sf_count_t offset, sf_count_t length)
+{
+ FILE * file ;
+ char buffer [16] ;
+ int k, m, ch, readcount ;
+
+ if (length > 1000000)
+ { printf ("\n\nError : length (%ld) too long.\n\n", SF_COUNT_TO_LONG (offset)) ;
+ exit (1) ;
+ } ;
+
+ if ((file = fopen (filename, "r")) == NULL)
+ { printf ("\n\nError : hexdump_file (%s) could not open file for read.\n\n", filename) ;
+ exit (1) ;
+ } ;
+
+ if (fseek (file, offset, SEEK_SET) != 0)
+ { printf ("\n\nError : fseek(file, %ld, SEEK_SET) failed : %s\n\n", SF_COUNT_TO_LONG (offset), strerror (errno)) ;
+ exit (1) ;
+ } ;
+
+ puts ("\n\n") ;
+
+ for (k = 0 ; k < length ; k+= sizeof (buffer))
+ { readcount = fread (buffer, 1, sizeof (buffer), file) ;
+
+ printf ("%08lx : ", SF_COUNT_TO_LONG (offset + k)) ;
+
+ for (m = 0 ; m < readcount ; m++)
+ printf ("%02x ", buffer [m] & 0xFF) ;
+
+ for (m = readcount ; m < SIGNED_SIZEOF (buffer) ; m++)
+ printf (" ") ;
+
+ printf (" ") ;
+ for (m = 0 ; m < readcount ; m++)
+ { ch = isprint (buffer [m]) ? buffer [m] : '.' ;
+ putchar (ch) ;
+ } ;
+
+ if (readcount < SIGNED_SIZEOF (buffer))
+ break ;
+
+ putchar ('\n') ;
+ } ;
+
+ puts ("\n") ;
+
+ fclose (file) ;
+} /* hexdump_file */
+
+void
+dump_log_buffer (SNDFILE *file)
+{ static char buffer [LOG_BUFFER_SIZE] ;
+
+ memset (buffer, 0, sizeof (buffer)) ;
+
+ /* Get the log buffer data. */
+ sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
+
+ if (strlen (buffer) < 1)
+ puts ("Log buffer empty.\n") ;
+ else
+ puts (buffer) ;
+
+ return ;
+} /* dump_log_buffer */
+
+SNDFILE *
+test_open_file_or_die (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num)
+{ static int count = 0 ;
+
+ SNDFILE *file ;
+ const char *modestr, *func_name ;
+ int oflags = 0, omode = 0, err ;
+
+ /*
+ ** Need to test both sf_open() and sf_open_fd().
+ ** Do so alternately.
+ */
+ switch (mode)
+ { case SFM_READ :
+ modestr = "SFM_READ" ;
+ oflags = O_RDONLY | O_BINARY ;
+ omode = 0 ;
+ break ;
+
+ case SFM_WRITE :
+ modestr = "SFM_WRITE" ;
+ oflags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
+ omode = S_IRUSR | S_IWUSR | S_IRGRP ;
+ break ;
+
+ case SFM_RDWR :
+ modestr = "SFM_RDWR" ;
+ oflags = O_RDWR | O_CREAT | O_BINARY ;
+ omode = S_IRUSR | S_IWUSR | S_IRGRP ;
+ break ;
+ default :
+ printf ("\n\nLine %d: Bad mode.\n", line_num) ;
+ fflush (stdout) ;
+ exit (1) ;
+ } ;
+
+ if (OS_IS_WIN32)
+ { /* Windows does not understand and ignores the S_IRGRP flag, but Wine
+ ** gives a run time warning message, so just clear it.
+ */
+ omode &= ~S_IRGRP ;
+ } ;
+
+ if (allow_fd && ((++count) & 1) == 1)
+ { int fd ;
+
+ /* Only use the three argument open() function if omode != 0. */
+ fd = (omode == 0) ? open (filename, oflags) : open (filename, oflags, omode) ;
+
+ if (fd < 0)
+ { printf ("\n\n%s : open failed : %s\n", __func__, strerror (errno)) ;
+ exit (1) ;
+ } ;
+
+ func_name = "sf_open_fd" ;
+ file = sf_open_fd (fd, mode, sfinfo, SF_TRUE) ;
+ }
+ else
+ { func_name = "sf_open" ;
+ file = sf_open (filename, mode, sfinfo) ;
+ } ;
+
+ if (file == NULL)
+ { printf ("\n\nLine %d: %s (%s) failed : %s\n\n", line_num, func_name, modestr, sf_strerror (NULL)) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ err = sf_error (file) ;
+ if (err != SF_ERR_NO_ERROR)
+ { printf ("\n\nLine %d : sf_error : %s\n\n", line_num, sf_error_number (err)) ;
+ dump_log_buffer (file) ;
+ exit (1) ;
+ } ;
+
+ return file ;
+} /* test_open_file_or_die */
+
+void
+test_read_write_position_or_die (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos)
+{ sf_count_t pos ;
+
+ /* Check the current read position. */
+ if (read_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_READ)) != read_pos)
+ { printf ("\n\nLine %d ", line_num) ;
+ if (pass > 0)
+ printf ("(pass %d): ", pass) ;
+ printf ("Read position (%ld) should be %ld.\n", SF_COUNT_TO_LONG (pos), SF_COUNT_TO_LONG (read_pos)) ;
+ exit (1) ;
+ } ;
+
+ /* Check the current write position. */
+ if (write_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_WRITE)) != write_pos)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : Write position (%ld) should be %ld.\n",
+ SF_COUNT_TO_LONG (pos), SF_COUNT_TO_LONG (write_pos)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_write_position */
+
+void
+test_seek_or_die (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num)
+{ sf_count_t position ;
+ const char *channel_name, *whence_name ;
+
+ switch (whence)
+ { case SEEK_SET :
+ whence_name = "SEEK_SET" ;
+ break ;
+ case SEEK_CUR :
+ whence_name = "SEEK_CUR" ;
+ break ;
+ case SEEK_END :
+ whence_name = "SEEK_END" ;
+ break ;
+
+ /* SFM_READ */
+ case SEEK_SET | SFM_READ :
+ whence_name = "SFM_READ | SEEK_SET" ;
+ break ;
+ case SEEK_CUR | SFM_READ :
+ whence_name = "SFM_READ | SEEK_CUR" ;
+ break ;
+ case SEEK_END | SFM_READ :
+ whence_name = "SFM_READ | SEEK_END" ;
+ break ;
+
+ /* SFM_WRITE */
+ case SEEK_SET | SFM_WRITE :
+ whence_name = "SFM_WRITE | SEEK_SET" ;
+ break ;
+ case SEEK_CUR | SFM_WRITE :
+ whence_name = "SFM_WRITE | SEEK_CUR" ;
+ break ;
+ case SEEK_END | SFM_WRITE :
+ whence_name = "SFM_WRITE | SEEK_END" ;
+ break ;
+
+ default :
+ printf ("\n\nLine %d: bad whence parameter.\n", line_num) ;
+ exit (1) ;
+ } ;
+
+ channel_name = (channels == 1) ? "Mono" : "Stereo" ;
+
+ if ((position = sf_seek (file, offset, whence)) != new_pos)
+ { printf ("\n\nLine %d : %s : sf_seek (file, %ld, %s) returned %ld (should be %ld).\n\n",
+ line_num, channel_name, SF_COUNT_TO_LONG (offset), whence_name,
+ SF_COUNT_TO_LONG (position), SF_COUNT_TO_LONG (new_pos)) ;
+ exit (1) ;
+ } ;
+
+} /* test_seek_or_die */
+
+[+ FOR read_op +]
+[+ FOR io_type +]
+void
+test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die (SNDFILE *file, int pass, [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_[+ (get "op_element") +]_[+ (get "io_element") +] (file, test, [+ (get "count_name") +])) != [+ (get "count_name") +])
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_[+ (get "op_element") +]_[+ (get "io_element") +] failed with short [+ (get "op_element") +] (%ld => %ld).\n",
+ SF_COUNT_TO_LONG ([+ (get "count_name") +]), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die */
+[+ ENDFOR io_type +][+ ENDFOR read_op +]
+
+void
+test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_read_raw (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_read_raw failed with short read (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_read_raw_or_die */
+
+[+ FOR write_op +]
+[+ FOR io_type +]
+void
+test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die (SNDFILE *file, int pass, const [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_[+ (get "op_element") +]_[+ (get "io_element") +] (file, test, [+ (get "count_name") +])) != [+ (get "count_name") +])
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_[+ (get "op_element") +]_[+ (get "io_element") +] failed with short [+ (get "op_element") +] (%ld => %ld).\n",
+ SF_COUNT_TO_LONG ([+ (get "count_name") +]), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die */
+[+ ENDFOR io_type +][+ ENDFOR write_op +]
+
+void
+test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num)
+{ sf_count_t count ;
+
+ if ((count = sf_write_raw (file, test, items)) != items)
+ { printf ("\n\nLine %d", line_num) ;
+ if (pass > 0)
+ printf (" (pass %d)", pass) ;
+ printf (" : sf_write_raw failed with short write (%ld => %ld).\n",
+ SF_COUNT_TO_LONG (items), SF_COUNT_TO_LONG (count)) ;
+ fflush (stdout) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* test_write_raw_or_die */
+
+
+[+ FOR io_type
++]void
+compare_[+ (get "io_element") +]_or_die (const [+ (get "io_element") +] *left, const [+ (get "io_element") +] *right, unsigned count, int line_num)
+{
+ unsigned k ;
+
+ for (k = 0 ; k < count ;k++)
+ if (left [k] != right [k])
+ { printf ("\n\nLine %d : Error at index %d, " [+ (get "format_str") +] " should be " [+ (get "format_str") +] ".\n\n", line_num, k, left [k], right [k]) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* compare_[+ (get "io_element") +]_or_die */
+[+ ENDFOR io_type +]
+
+
+void
+delete_file (int format, const char *filename)
+{ char rsrc_name [512], *fname ;
+
+ unlink (filename) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2)
+ return ;
+
+ /*
+ ** Now try for a resource fork stored as a separate file.
+ ** Grab the un-adulterated filename again.
+ */
+ snprintf (rsrc_name, sizeof (rsrc_name), "%s", filename) ;
+
+ if ((fname = strrchr (rsrc_name, '/')) != NULL)
+ fname ++ ;
+ else if ((fname = strrchr (rsrc_name, '\\')) != NULL)
+ fname ++ ;
+ else
+ fname = rsrc_name ;
+
+ memmove (fname + 2, fname, strlen (fname) + 1) ;
+ fname [0] = '.' ;
+ fname [1] = '_' ;
+
+ unlink (rsrc_name) ;
+} /* delete_file */
+
+static int allowed_open_files = -1 ;
+
+void
+count_open_files (void)
+{
+#if OS_IS_WIN32
+ return ;
+#else
+ int k, count = 0 ;
+ struct stat statbuf ;
+
+ if (allowed_open_files > 0)
+ return ;
+
+ for (k = 0 ; k < 1024 ; k++)
+ if (fstat (k, &statbuf) == 0)
+ count ++ ;
+
+ allowed_open_files = count ;
+#endif
+} /* count_open_files */
+
+void
+increment_open_file_count (void)
+{ allowed_open_files ++ ;
+} /* increment_open_file_count */
+
+void
+check_open_file_count_or_die (int lineno)
+{
+#if OS_IS_WIN32
+ lineno = 0 ;
+ return ;
+#else
+ int k, count = 0 ;
+ struct stat statbuf ;
+
+ if (allowed_open_files < 0)
+ count_open_files () ;
+
+ for (k = 0 ; k < 1024 ; k++)
+ if (fstat (k, &statbuf) == 0)
+ count ++ ;
+
+ if (count > allowed_open_files)
+ { printf ("\nLine %d : number of open files (%d) > allowed (%d).\n\n", lineno, count, allowed_open_files) ;
+ exit (1) ;
+ } ;
+#endif
+} /* check_open_file_count_or_die */
+
+void
+write_mono_file (const char * filename, int format, int srate, float * output, int len)
+{ SNDFILE * file ;
+ SF_INFO sfinfo ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ sfinfo.samplerate = srate ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { printf ("sf_open (%s) : %s\n", filename, sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ sf_write_float (file, output, len) ;
+
+ sf_close (file) ;
+} /* write_mono_file */
+
+void
+gen_lowpass_noise_float (float *data, int len)
+{ int32_t value = 0x1243456 ;
+ double sample, last_val = 0.0 ;
+ int k ;
+
+ for (k = 0 ; k < len ; k++)
+ { /* Not a crypto quality RNG. */
+ value = 11117 * value + 211231 ;
+ value = 11117 * value + 211231 ;
+ value = 11117 * value + 211231 ;
+
+ sample = value / (0x7fffffff * 1.000001) ;
+ sample = 0.2 * sample - 0.9 * last_val ;
+
+ data [k] = last_val = sample ;
+ } ;
+
+} /* gen_lowpass_noise_float */
+
+
+/*
+** Windows is fucked.
+** If a file is opened R/W and data is written to it, then fstat will return
+** the correct file length, but stat will return zero.
+*/
+
+sf_count_t
+file_length (const char * fname)
+{ struct stat data ;
+
+ if (stat (fname, &data) != 0)
+ return 0 ;
+
+ return (sf_count_t) data.st_size ;
+} /* file_length */
+
+sf_count_t
+file_length_fd (int fd)
+{ struct stat data ;
+
+ memset (&data, 0, sizeof (data)) ;
+ if (fstat (fd, &data) != 0)
+ return 0 ;
+
+ return (sf_count_t) data.st_size ;
+} /* file_length_fd */
+
+
+[+ ESAC +]
+
diff --git a/tests/virtual_io_test.c b/tests/virtual_io_test.c
new file mode 100644
index 0000000..1aae063
--- /dev/null
+++ b/tests/virtual_io_test.c
@@ -0,0 +1,237 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <fcntl.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+
+static void vio_test (const char *fname, int format) ;
+
+int
+main (void)
+{
+ vio_test ("vio_pcm16.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ vio_test ("vio_pcm24.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_24) ;
+ vio_test ("vio_float.au", SF_FORMAT_AU | SF_FORMAT_FLOAT) ;
+ vio_test ("vio_pcm24.paf", SF_FORMAT_PAF | SF_FORMAT_PCM_24) ;
+
+ return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+typedef struct
+{ sf_count_t offset, length ;
+ unsigned char data [16 * 1024] ;
+} VIO_DATA ;
+
+static sf_count_t
+vfget_filelen (void *user_data)
+{ VIO_DATA *vf = (VIO_DATA *) user_data ;
+
+ return vf->length ;
+} /* vfget_filelen */
+
+static sf_count_t
+vfseek (sf_count_t offset, int whence, void *user_data)
+{ VIO_DATA *vf = (VIO_DATA *) user_data ;
+
+ switch (whence)
+ { case SEEK_SET :
+ vf->offset = offset ;
+ break ;
+
+ case SEEK_CUR :
+ vf->offset = vf->offset + offset ;
+ break ;
+
+ case SEEK_END :
+ vf->offset = vf->length + offset ;
+ break ;
+ default :
+ break ;
+ } ;
+
+ return vf->offset ;
+} /* vfseek */
+
+static sf_count_t
+vfread (void *ptr, sf_count_t count, void *user_data)
+{ VIO_DATA *vf = (VIO_DATA *) user_data ;
+
+ /*
+ ** This will brack badly for files over 2Gig in length, but
+ ** is sufficient for testing.
+ */
+ if (vf->offset + count > vf->length)
+ count = vf->length - vf->offset ;
+
+ memcpy (ptr, vf->data + vf->offset, count) ;
+ vf->offset += count ;
+
+ return count ;
+} /* vfread */
+
+static sf_count_t
+vfwrite (const void *ptr, sf_count_t count, void *user_data)
+{ VIO_DATA *vf = (VIO_DATA *) user_data ;
+
+ /*
+ ** This will break badly for files over 2Gig in length, but
+ ** is sufficient for testing.
+ */
+ if (vf->offset >= SIGNED_SIZEOF (vf->data))
+ return 0 ;
+
+ if (vf->offset + count > SIGNED_SIZEOF (vf->data))
+ count = sizeof (vf->data) - vf->offset ;
+
+ memcpy (vf->data + vf->offset, ptr, (size_t) count) ;
+ vf->offset += count ;
+
+ if (vf->offset > vf->length)
+ vf->length = vf->offset ;
+
+ return count ;
+} /* vfwrite */
+
+static sf_count_t
+vftell (void *user_data)
+{ VIO_DATA *vf = (VIO_DATA *) user_data ;
+
+ return vf->offset ;
+} /* vftell */
+
+
+/*==============================================================================
+*/
+
+static void
+gen_short_data (short * data, int len, int start)
+{ int k ;
+
+ for (k = 0 ; k < len ; k++)
+ data [k] = start + k ;
+} /* gen_short_data */
+
+
+static void
+check_short_data (short * data, int len, int start, int line)
+{ int k ;
+
+ for (k = 0 ; k < len ; k++)
+ if (data [k] != start + k)
+ { printf ("\n\nLine %d : data [%d] = %d (should be %d).\n\n", line, k, data [k], start + k) ;
+ exit (1) ;
+ } ;
+} /* gen_short_data */
+
+/*------------------------------------------------------------------------------
+*/
+
+static void
+vio_test (const char *fname, int format)
+{ static VIO_DATA vio_data ;
+ static short data [256] ;
+
+ SF_VIRTUAL_IO vio ;
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+
+ print_test_name ("virtual i/o test", fname) ;
+
+ /* Set up pointers to the locally defined functions. */
+ vio.get_filelen = vfget_filelen ;
+ vio.seek = vfseek ;
+ vio.read = vfread ;
+ vio.write = vfwrite ;
+ vio.tell = vftell ;
+
+ /* Set virtual file offset and length to zero. */
+ vio_data.offset = 0 ;
+ vio_data.length = 0 ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.format = format ;
+ sfinfo.channels = 2 ;
+ sfinfo.samplerate = 44100 ;
+
+ if ((file = sf_open_virtual (&vio, SFM_WRITE, &sfinfo, &vio_data)) == NULL)
+ { printf ("\n\nLine %d : sf_open_write failed with error : ", __LINE__) ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+ exit (1) ;
+ } ;
+
+ if (vfget_filelen (&vio_data) < 0)
+ { printf ("\n\nLine %d : vfget_filelen returned negative length.\n\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ gen_short_data (data, ARRAY_LEN (data), 0) ;
+ sf_write_short (file, data, ARRAY_LEN (data)) ;
+
+ gen_short_data (data, ARRAY_LEN (data), 1) ;
+ sf_write_short (file, data, ARRAY_LEN (data)) ;
+
+ gen_short_data (data, ARRAY_LEN (data), 2) ;
+ sf_write_short (file, data, ARRAY_LEN (data)) ;
+
+ sf_close (file) ;
+
+ /* Now test read. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ vio_data.offset = 0 ;
+
+ if ((file = sf_open_virtual (&vio, SFM_READ, &sfinfo, &vio_data)) == NULL)
+ { printf ("\n\nLine %d : sf_open_write failed with error : ", __LINE__) ;
+ fflush (stdout) ;
+ puts (sf_strerror (NULL)) ;
+
+ dump_data_to_file (fname, vio_data.data, vio_data.length) ;
+ exit (1) ;
+ } ;
+
+
+ sf_read_short (file, data, ARRAY_LEN (data)) ;
+ check_short_data (data, ARRAY_LEN (data), 0, __LINE__) ;
+
+ sf_read_short (file, data, ARRAY_LEN (data)) ;
+ check_short_data (data, ARRAY_LEN (data), 1, __LINE__) ;
+
+ sf_read_short (file, data, ARRAY_LEN (data)) ;
+ check_short_data (data, ARRAY_LEN (data), 2, __LINE__) ;
+
+ sf_close (file) ;
+
+ puts ("ok") ;
+} /* vio_test */
+
diff --git a/tests/vorbis_test.c b/tests/vorbis_test.c
new file mode 100644
index 0000000..9f5797f
--- /dev/null
+++ b/tests/vorbis_test.c
@@ -0,0 +1,176 @@
+/*
+** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <math.h>
+
+#include <sndfile.h>
+
+#include "utils.h"
+#include "dft_cmp.h"
+
+#define SAMPLE_RATE 16000
+#define DATA_LENGTH (SAMPLE_RATE / 8)
+
+static float data_out [DATA_LENGTH] ;
+
+static inline float
+max_float (float a, float b)
+{ return a > b ? a : b ;
+} /* max_float */
+
+static void
+vorbis_test (void)
+{ static float float_data [DFT_DATA_LENGTH] ;
+ const char * filename = "vorbis_test.oga" ;
+ SNDFILE * file ;
+ SF_INFO sfinfo ;
+ float max_abs = 0.0 ;
+ unsigned k ;
+
+ print_test_name ("vorbis_test", filename) ;
+
+ /* Generate float data. */
+ gen_windowed_sine_float (float_data, ARRAY_LEN (float_data), 1.0) ;
+
+ /* Set up output file type. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+
+ /* The Vorbis encoder has a bug on PowerPC and X86-64 with sample rates
+ ** <= 22050. Increasing the sample rate to 32000 avoids triggering it.
+ ** See https://trac.xiph.org/ticket/1229
+ */
+ if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
+ { const char * errstr ;
+
+ errstr = sf_strerror (NULL) ;
+ if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") == NULL)
+ { printf ("Line %d: sf_open (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
+ dump_log_buffer (NULL) ;
+ exit (1) ;
+ } ;
+
+ printf ("\n Sample rate -> 32kHz ") ;
+ sfinfo.samplerate = 32000 ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+ } ;
+
+ test_write_float_or_die (file, 0, float_data, ARRAY_LEN (float_data), __LINE__) ;
+ sf_close (file) ;
+
+ memset (float_data, 0, sizeof (float_data)) ;
+
+ /* Read the file back in again. */
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+ test_read_float_or_die (file, 0, float_data, ARRAY_LEN (float_data), __LINE__) ;
+ sf_close (file) ;
+
+ for (k = 0 ; k < ARRAY_LEN (float_data) ; k ++)
+ max_abs = max_float (max_abs, fabs (float_data [k])) ;
+
+ if (max_abs > 1.021)
+ { printf ("\n\n Error : max_abs %f should be < 1.021.\n\n", max_abs) ;
+ exit (1) ;
+ } ;
+
+ puts ("ok") ;
+ unlink (filename) ;
+} /* vorbis_test */
+
+static void
+vorbis_quality_test (void)
+{ /*
+ ** Encode two files, one at quality 0.3 and one at quality 0.5 and then
+ ** make sure that the quality 0.3 files is the smaller of the two.
+ */
+ const char * q3_fname = "q3_vorbis.oga" ;
+ const char * q5_fname = "q5_vorbis.oga" ;
+
+ SNDFILE *q3_file, *q5_file ;
+ SF_INFO sfinfo ;
+ int q3_size, q5_size ;
+ double quality ;
+ int k ;
+
+ print_test_name (__func__, "q[35]_vorbis.oga") ;
+
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ /* Set up output file type. */
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+ sfinfo.channels = 1 ;
+ sfinfo.samplerate = SAMPLE_RATE ;
+
+ /* Write the output file. */
+ q3_file = test_open_file_or_die (q3_fname, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+ q5_file = test_open_file_or_die (q5_fname, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+
+ quality = 0.3 ;
+ sf_command (q3_file, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof (quality)) ;
+ quality = 0.5 ;
+ sf_command (q5_file, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof (quality)) ;
+
+ for (k = 0 ; k < 5 ; k++)
+ { gen_lowpass_noise_float (data_out, ARRAY_LEN (data_out)) ;
+ test_write_float_or_die (q3_file, 0, data_out, ARRAY_LEN (data_out), __LINE__) ;
+ test_write_float_or_die (q5_file, 0, data_out, ARRAY_LEN (data_out), __LINE__) ;
+ } ;
+
+ sf_close (q3_file) ;
+ sf_close (q5_file) ;
+
+ q3_size = file_length (q3_fname) ;
+ q5_size = file_length (q5_fname) ;
+
+ if (q3_size >= q5_size)
+ { printf ("\n\nLine %d : q3 size (%d) >= q5 size (%d)\n\n", __LINE__, q3_size, q5_size) ;
+ exit (1) ;
+ } ;
+
+ puts ("ok") ;
+ unlink (q3_fname) ;
+ unlink (q5_fname) ;
+} /* vorbis_quality_test */
+
+
+
+int
+main (void)
+{
+ if (HAVE_EXTERNAL_LIBS)
+ { vorbis_test () ;
+ vorbis_quality_test () ;
+ }
+ else
+ puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
+
+ return 0 ;
+} /* main */
diff --git a/tests/win32_ordinal_test.c b/tests/win32_ordinal_test.c
new file mode 100644
index 0000000..ce8723f
--- /dev/null
+++ b/tests/win32_ordinal_test.c
@@ -0,0 +1,146 @@
+/*
+** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+#include "sndfile.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include "utils.h"
+
+#if (defined (WIN32) || defined (_WIN32) || defined (__CYGWIN__))
+#define TEST_WIN32 1
+#else
+#define TEST_WIN32 0
+#endif
+
+#if TEST_WIN32
+#include <windows.h>
+
+
+static const char * locations [] =
+{ ".", "../src/", "src/", "../src/.libs/", "src/.libs/",
+ NULL
+} ; /* locations. */
+
+static int
+test_ordinal (HMODULE hmod, const char * func_name, int ordinal)
+{ char *lpmsg ;
+ void *name, *ord ;
+
+ print_test_name ("win32_ordinal_test", func_name) ;
+
+#if SIZEOF_VOIDP == 8
+#define LPCSTR_OF_ORDINAL(x) ((LPCSTR) ((int64_t) (x)))
+#else
+#define LPCSTR_OF_ORDINAL(x) ((LPCSTR) (x))
+#endif
+
+ ord = GetProcAddress (hmod, LPCSTR_OF_ORDINAL (ordinal)) ;
+ if ((name = GetProcAddress (hmod, func_name)) == NULL)
+ { FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (),
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpmsg, 0, NULL) ;
+ /*-puts (lpmsg) ;-*/
+ } ;
+
+ if (name != NULL && ord != NULL && name == ord)
+ { puts ("ok") ;
+ return 0 ;
+ } ;
+
+ puts ("fail") ;
+ return 1 ;
+} /* test_ordinal */
+
+static void
+win32_ordinal_test (void)
+{ static char buffer [1024] ;
+ static char func_name [1024] ;
+ HMODULE hmod = NULL ;
+ FILE * file = NULL ;
+ int k, ordinal, errors = 0 ;
+
+ for (k = 0 ; locations [k] != NULL ; k++)
+ { snprintf (buffer, sizeof (buffer), "%s/libsndfile-1.def", locations [k]) ;
+ if ((file = fopen (buffer, "r")) != NULL)
+ break ;
+ } ;
+
+ if (file == NULL)
+ { puts ("\n\nError : cannot open DEF file.\n") ;
+ exit (1) ;
+ } ;
+
+ for (k = 0 ; locations [k] != NULL ; k++)
+ { snprintf (buffer, sizeof (buffer), "%s/libsndfile-1.dll", locations [k]) ;
+ if ((hmod = (HMODULE) LoadLibrary (buffer)) != NULL)
+ break ;
+ } ;
+
+ if (hmod == NULL)
+ { puts ("\n\nError : cannot load DLL.\n") ;
+ exit (1) ;
+ } ;
+
+ while (fgets (buffer, sizeof (buffer), file) != NULL)
+ { func_name [0] = 0 ;
+ ordinal = 0 ;
+
+ if (sscanf (buffer, "%s @%d", func_name, &ordinal) != 2)
+ continue ;
+
+ errors += test_ordinal (hmod, func_name, ordinal) ;
+ } ;
+
+ FreeLibrary (hmod) ;
+
+ fclose (file) ;
+
+ if (errors > 0)
+ { printf ("\n\nErrors : %d\n\n", errors) ;
+ exit (1) ;
+ } ;
+
+ return ;
+} /* win32_ordinal_test */
+
+#endif
+
+int
+main (void)
+{
+#if (TEST_WIN32 && WIN32_TARGET_DLL)
+ win32_ordinal_test () ;
+#endif
+
+ return 0 ;
+} /* main */
+
diff --git a/tests/win32_test.c b/tests/win32_test.c
new file mode 100644
index 0000000..d0dc6d8
--- /dev/null
+++ b/tests/win32_test.c
@@ -0,0 +1,318 @@
+/*
+** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+#include "sndfile.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if (HAVE_DECL_S_IRGRP == 0)
+#include <sf_unistd.h>
+#endif
+
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define SIGNED_SIZEOF(x) ((int) sizeof (x))
+
+/* EMX is OS/2. */
+#if defined (__CYGWIN__) || defined (__EMX__)
+
+ #define LSEEK lseek
+ #define FSTAT fstat
+
+ typedef struct stat STATBUF ;
+ typedef off_t INT64 ;
+
+ static char dir_cmd [] = "ls -l" ;
+
+#elif (defined (WIN32) || defined (_WIN32))
+
+ #define LSEEK _lseeki64
+ #define FSTAT _fstati64
+
+ typedef struct _stati64 STATBUF ;
+ typedef __int64 INT64 ;
+
+ static char dir_cmd [] = "dir" ;
+
+#else
+
+ #define LSEEK lseek
+ #define FSTAT fstat
+
+ typedef struct stat STATBUF ;
+ typedef sf_count_t INT64 ;
+
+ #define O_BINARY 0
+ static char dir_cmd [] = "ls -l" ;
+
+#endif
+
+static void show_fstat_error (void) ;
+static void show_lseek_error (void) ;
+static void show_stat_fstat_error (void) ;
+static void write_to_closed_file (void) ;
+
+int
+main (void)
+{
+ puts ("\n\n\n\n"
+ "This program shows up errors in the Win32 implementation of\n"
+ "a couple of POSIX API functions on some versions of windoze.\n"
+ "It can also be compiled on Linux (which works correctly) and\n"
+ "other OSes just to provide a sanity check.\n"
+ ) ;
+
+ show_fstat_error () ;
+ show_lseek_error () ;
+ show_stat_fstat_error () ;
+ write_to_closed_file () ;
+
+ puts ("\n\n") ;
+
+ return 0 ;
+} /* main */
+
+static void
+show_fstat_error (void)
+{ static const char *filename = "fstat.dat" ;
+ static char data [256] ;
+
+ STATBUF statbuf ;
+ int fd, mode, flags ;
+
+ if (sizeof (statbuf.st_size) != sizeof (INT64))
+ { printf ("\n\nLine %d: Error, sizeof (statbuf.st_size) != 8.\n\n", __LINE__) ;
+ return ;
+ } ;
+
+ puts ("\n64 bit fstat() test.\n--------------------") ;
+
+ printf ("0) Create a file, write %d bytes and close it.\n", SIGNED_SIZEOF (data)) ;
+ mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
+ flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
+ if ((fd = open (filename, mode, flags)) < 0)
+ { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+ assert (write (fd, data, sizeof (data)) > 0) ;
+ close (fd) ;
+
+ printf ("1) Re-open file in read/write mode and write another %d bytes at the end.\n", SIGNED_SIZEOF (data)) ;
+ mode = O_RDWR | O_BINARY ;
+ flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
+ if ((fd = open (filename, mode, flags)) < 0)
+ { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+ LSEEK (fd, 0, SEEK_END) ;
+ assert (write (fd, data, sizeof (data)) > 0) ;
+
+ printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd, filename) ;
+
+ /* Would use snprintf, but thats not really available on windows. */
+ memset (data, 0, sizeof (data)) ;
+ strncpy (data, dir_cmd, sizeof (data) - 1) ;
+ strncat (data, " ", sizeof (data) - 1 - strlen (data)) ;
+ strncat (data, filename, sizeof (data) - 1 - strlen (data)) ;
+
+ assert (system (data) >= 0) ;
+ puts ("") ;
+
+ printf ("3) Now use fstat() to get the file length.\n") ;
+ if (FSTAT (fd, &statbuf) != 0)
+ { printf ("\n\nLine %d: fstat() returned error : %s\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+
+ printf ("4) According to fstat(), the file length is %ld, ", (long) statbuf.st_size) ;
+
+ close (fd) ;
+
+ if (statbuf.st_size != 2 * sizeof (data))
+ printf ("but thats just plain ***WRONG***.\n\n") ;
+ else
+ { printf ("which is correct.\n\n") ;
+ unlink (filename) ;
+ } ;
+
+} /* show_fstat_error */
+
+static void
+show_lseek_error (void)
+{ static const char *filename = "fstat.dat" ;
+ static char data [256] ;
+
+ INT64 retval ;
+ int fd, mode, flags ;
+
+ puts ("\n64 bit lseek() test.\n--------------------") ;
+
+ printf ("0) Create a file, write %d bytes and close it.\n", SIGNED_SIZEOF (data)) ;
+ mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
+ flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
+ if ((fd = open (filename, mode, flags)) < 0)
+ { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+ assert (write (fd, data, sizeof (data)) > 0) ;
+ close (fd) ;
+
+ printf ("1) Re-open file in read/write mode and write another %d bytes at the end.\n", SIGNED_SIZEOF (data)) ;
+ mode = O_RDWR | O_BINARY ;
+ flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
+ if ((fd = open (filename, mode, flags)) < 0)
+ { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+
+ LSEEK (fd, 0, SEEK_END) ;
+ assert (write (fd, data, sizeof (data)) > 0) ;
+
+ printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd, filename) ;
+
+ /* Would use snprintf, but thats not really available on windows. */
+ memset (data, 0, sizeof (data)) ;
+ strncpy (data, dir_cmd, sizeof (data) - 1) ;
+ strncat (data, " ", sizeof (data) - 1 - strlen (data)) ;
+ strncat (data, filename, sizeof (data) - 1 - strlen (data)) ;
+
+ assert (system (data) >= 0) ;
+ puts ("") ;
+
+ printf ("3) Now use lseek() to go to the end of the file.\n") ;
+ retval = LSEEK (fd, 0, SEEK_END) ;
+
+ printf ("4) We are now at position %ld, ", (long) retval) ;
+
+ close (fd) ;
+
+ if (retval != 2 * sizeof (data))
+ printf ("but thats just plain ***WRONG***.\n\n") ;
+ else
+ { printf ("which is correct.\n\n") ;
+ unlink (filename) ;
+ } ;
+
+} /* show_lseek_error */
+
+static void
+show_stat_fstat_error (void)
+{ static const char *filename = "stat_fstat.dat" ;
+ static char data [256] ;
+
+ int fd, mode, flags ;
+ int stat_size, fstat_size ;
+ struct stat buf ;
+
+ /* Known to fail on WinXP. */
+ puts ("\nstat/fstat test.\n----------------") ;
+
+ printf ("0) Create a file and write %d bytes.\n", SIGNED_SIZEOF (data)) ;
+
+ mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
+ flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
+ if ((fd = open (filename, mode, flags)) < 0)
+ { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+
+ assert (write (fd, data, sizeof (data)) > 0) ;
+
+ printf ("1) Now call stat and fstat on the file and retreive the file lengths.\n") ;
+
+ if (stat (filename, &buf) != 0)
+ { printf ("\n\nLine %d: stat() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ goto error_exit ;
+ } ;
+ stat_size = buf.st_size ;
+
+ if (fstat (fd, &buf) != 0)
+ { printf ("\n\nLine %d: fstat() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ goto error_exit ;
+ } ;
+ fstat_size = buf.st_size ;
+
+ printf ("2) Size returned by stat and fstat is %d and %d, ", stat_size, fstat_size) ;
+
+
+ if (stat_size == 0 || stat_size != fstat_size)
+ printf ("but thats just plain ***WRONG***.\n\n") ;
+ else
+ printf ("which is correct.\n\n") ;
+
+error_exit :
+
+ close (fd) ;
+ unlink (filename) ;
+
+ return ;
+} /* show_stat_fstat_error */
+
+
+static void
+write_to_closed_file (void)
+{ const char * filename = "closed_write_test.txt" ;
+ struct stat buf ;
+ FILE * file ;
+ int fd ;
+
+ puts ("\nWrite to closed file test.\n--------------------------") ;
+
+ printf ("0) First we open file for write using fopen().\n") ;
+ if ((file = fopen (filename, "w")) == NULL)
+ { printf ("\n\nLine %d: fopen() failed : %s\n\n", __LINE__, strerror (errno)) ;
+ return ;
+ } ;
+
+ printf ("1) Now we grab the file descriptor fileno().\n") ;
+ fd = fileno (file) ;
+
+ printf ("2) Write some text via the file descriptor.\n") ;
+ assert (write (fd, "a\n", 2) > 0) ;
+
+ printf ("3) Now we close the file using fclose().\n") ;
+ fclose (file) ;
+
+ stat (filename, &buf) ;
+ printf (" File size is %d bytes.\n", (int) buf.st_size) ;
+
+ printf ("4) Now write more data to the file descriptor which should fail.\n") ;
+ if (write (fd, "b\n", 2) < 0)
+ printf ("5) Good, write returned an error code as it should have.\n") ;
+ else
+ { printf ("5) Attempting to write to a closed file should have failed but didn't! *** WRONG ***\n") ;
+
+ stat (filename, &buf) ;
+ printf (" File size is %d bytes.\n", (int) buf.st_size) ;
+ } ;
+
+ unlink (filename) ;
+
+ return ;
+} /* write_to_closed_file */
diff --git a/tests/write_read_test.c b/tests/write_read_test.c
new file mode 100644
index 0000000..9f8a8f5
--- /dev/null
+++ b/tests/write_read_test.c
@@ -0,0 +1,3731 @@
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <math.h>
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <fcntl.h>
+static int truncate (const char *filename, int ignored) ;
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+#include "generate.h"
+
+#define SAMPLE_RATE 11025
+#define DATA_LENGTH (1<<12)
+
+#define SILLY_WRITE_COUNT (234)
+
+static void pcm_test_char (const char *str, int format, int long_file_okz) ;
+static void pcm_test_short (const char *str, int format, int long_file_okz) ;
+static void pcm_test_24bit (const char *str, int format, int long_file_okz) ;
+static void pcm_test_int (const char *str, int format, int long_file_okz) ;
+static void pcm_test_float (const char *str, int format, int long_file_okz) ;
+static void pcm_test_double (const char *str, int format, int long_file_okz) ;
+
+static void empty_file_test (const char *filename, int format) ;
+
+typedef union
+{ double d [DATA_LENGTH] ;
+ float f [DATA_LENGTH] ;
+ int i [DATA_LENGTH] ;
+ short s [DATA_LENGTH] ;
+ char c [DATA_LENGTH] ;
+} BUFFER ;
+
+static BUFFER orig_data ;
+static BUFFER test_data ;
+
+int
+main (int argc, char **argv)
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ count_open_files () ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file functions (little endian)\n") ;
+ printf (" aiff - test AIFF file functions (big endian)\n") ;
+ printf (" au - test AU file functions\n") ;
+ printf (" avr - test AVR file functions\n") ;
+ printf (" caf - test CAF file functions\n") ;
+ printf (" raw - test RAW header-less PCM file functions\n") ;
+ printf (" paf - test PAF file functions\n") ;
+ printf (" svx - test 8SVX/16SV file functions\n") ;
+ printf (" nist - test NIST Sphere file functions\n") ;
+ printf (" ircam - test IRCAM file functions\n") ;
+ printf (" voc - Create Voice file functions\n") ;
+ printf (" w64 - Sonic Foundry's W64 file functions\n") ;
+ printf (" flac - test FLAC file functions\n") ;
+ printf (" mpc2k - test MPC 2000 file functions\n") ;
+ printf (" rf64 - test RF64 file functions\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all = !strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { pcm_test_char ("char.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_char ("char.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_24bit ("24bit.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_float ("float.wav" , SF_FORMAT_WAV | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.wav" , SF_FORMAT_WAV | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ pcm_test_float ("float.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ pcm_test_float ("float.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ empty_file_test ("empty_char.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { pcm_test_char ("char_u8.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_char ("char_s8.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_short ("short_sowt.aifc" , SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_sowt.aifc" , SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_sowt.aifc" , SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_short ("short_twos.aifc" , SF_ENDIAN_BIG | SF_FORMAT_AIFF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_twos.aifc" , SF_ENDIAN_BIG | SF_FORMAT_AIFF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_twos.aifc" , SF_ENDIAN_BIG | SF_FORMAT_AIFF | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_short ("dwvw16.aifc", SF_FORMAT_AIFF | SF_FORMAT_DWVW_16, SF_TRUE) ;
+ pcm_test_24bit ("dwvw24.aifc", SF_FORMAT_AIFF | SF_FORMAT_DWVW_24, SF_TRUE) ;
+
+ pcm_test_float ("float.aifc" , SF_FORMAT_AIFF | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.aifc" , SF_FORMAT_AIFF | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ empty_file_test ("empty_char.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { pcm_test_char ("char.au" , SF_FORMAT_AU | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.au" , SF_FORMAT_AU | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.au" , SF_FORMAT_AU | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.au" , SF_FORMAT_AU | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float.au" , SF_FORMAT_AU | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.au", SF_FORMAT_AU | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ pcm_test_char ("char_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "caf"))
+ { pcm_test_char ("char.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float.caf" , SF_FORMAT_CAF | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.caf" , SF_FORMAT_CAF | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ pcm_test_short ("short_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_le.caf", SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "raw"))
+ { pcm_test_char ("char_s8.raw" , SF_FORMAT_RAW | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_char ("char_u8.raw" , SF_FORMAT_RAW | SF_FORMAT_PCM_U8, SF_FALSE) ;
+
+ pcm_test_short ("short_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_24bit ("24bit_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_float ("float_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_FLOAT , SF_FALSE) ;
+
+ pcm_test_double ("double_le.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ pcm_test_double ("double_be.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ /* Lite remove start */
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { pcm_test_char ("char_le.paf", SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_char ("char_be.paf", SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short_le.paf", SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_be.paf", SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.paf", SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_24, SF_TRUE) ;
+ pcm_test_24bit ("24bit_be.paf", SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_24, SF_TRUE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { pcm_test_char ("char.svx" , SF_FORMAT_SVX | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_16, SF_FALSE) ;
+
+ empty_file_test ("empty_char.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_S8) ;
+ empty_file_test ("empty_short.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_16) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { pcm_test_short ("short_le.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_be.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_24bit ("24bit_be.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.nist" , SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_be.nist" , SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { pcm_test_short ("short_be.ircam" , SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_le.ircam" , SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int_be.ircam" , SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_le.ircam" , SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_float ("float_be.ircam" , SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_le.ircam" , SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_FLOAT , SF_FALSE) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { pcm_test_char ("char.voc" , SF_FORMAT_VOC | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.voc", SF_FORMAT_VOC | SF_FORMAT_PCM_16, SF_FALSE) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { pcm_test_short ("short_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_float ("float_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ pcm_test_double ("double_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ empty_file_test ("empty_short.mat4", SF_FORMAT_MAT4 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.mat4", SF_FORMAT_MAT4 | SF_FORMAT_FLOAT) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { pcm_test_char ("char_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_char ("char_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_float ("float_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ pcm_test_double ("double_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ increment_open_file_count () ;
+
+ empty_file_test ("empty_char.mat5", SF_FORMAT_MAT5 | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.mat5", SF_FORMAT_MAT5 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.mat5", SF_FORMAT_MAT5 | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { pcm_test_char ("char.pvf" , SF_FORMAT_PVF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.pvf", SF_FORMAT_PVF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int.pvf" , SF_FORMAT_PVF | SF_FORMAT_PCM_32, SF_FALSE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "htk"))
+ { pcm_test_short ("short.htk", SF_FORMAT_HTK | SF_FORMAT_PCM_16, SF_FALSE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mpc2k"))
+ { pcm_test_short ("short.mpc", SF_FORMAT_MPC2K | SF_FORMAT_PCM_16, SF_FALSE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "avr"))
+ { pcm_test_char ("char_u8.avr" , SF_FORMAT_AVR | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_char ("char_s8.avr" , SF_FORMAT_AVR | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.avr" , SF_FORMAT_AVR | SF_FORMAT_PCM_16, SF_FALSE) ;
+ test_count++ ;
+ } ;
+ /* Lite remove end */
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { pcm_test_char ("char.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float.w64" , SF_FORMAT_W64 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.w64" , SF_FORMAT_W64 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ empty_file_test ("empty_char.w64", SF_FORMAT_W64 | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.w64", SF_FORMAT_W64 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.w64", SF_FORMAT_W64 | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sds"))
+ { pcm_test_char ("char.sds" , SF_FORMAT_SDS | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.sds" , SF_FORMAT_SDS | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.sds" , SF_FORMAT_SDS | SF_FORMAT_PCM_24, SF_FALSE) ;
+
+ empty_file_test ("empty_char.sds", SF_FORMAT_SDS | SF_FORMAT_PCM_S8) ;
+ empty_file_test ("empty_short.sds", SF_FORMAT_SDS | SF_FORMAT_PCM_16) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sd2"))
+ { pcm_test_char ("char.sd2" , SF_FORMAT_SD2 | SF_FORMAT_PCM_S8, SF_TRUE) ;
+ pcm_test_short ("short.sd2" , SF_FORMAT_SD2 | SF_FORMAT_PCM_16, SF_TRUE) ;
+ pcm_test_24bit ("24bit.sd2" , SF_FORMAT_SD2 | SF_FORMAT_PCM_24, SF_TRUE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "flac"))
+ { if (HAVE_EXTERNAL_LIBS)
+ { pcm_test_char ("char.flac" , SF_FORMAT_FLAC | SF_FORMAT_PCM_S8, SF_TRUE) ;
+ pcm_test_short ("short.flac" , SF_FORMAT_FLAC | SF_FORMAT_PCM_16, SF_TRUE) ;
+ pcm_test_24bit ("24bit.flac" , SF_FORMAT_FLAC | SF_FORMAT_PCM_24, SF_TRUE) ;
+ }
+ else
+ puts (" No FLAC tests because FLAC support was not compiled in.") ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "rf64"))
+ { pcm_test_char ("char.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_float ("float.rf64" , SF_FORMAT_RF64 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.rf64" , SF_FORMAT_RF64 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ empty_file_test ("empty_char.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.rf64", SF_FORMAT_RF64 | SF_FORMAT_FLOAT) ;
+ /* Lite remove end */
+
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ /* Only open file descriptors should be stdin, stdout and stderr. */
+ check_open_file_count_or_die (__LINE__) ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Helper functions and macros.
+*/
+
+static void create_short_file (const char *filename) ;
+
+#define CHAR_ERROR(x,y) (abs ((x) - (y)) > 255)
+#define INT_ERROR(x,y) (((x) - (y)) != 0)
+#define TRIBYTE_ERROR(x,y) (abs ((x) - (y)) > 255)
+#define FLOAT_ERROR(x,y) (fabs ((x) - (y)) > 1e-5)
+
+#define CONVERT_DATA(k,len,new,orig) \
+ { for ((k) = 0 ; (k) < (len) ; (k) ++) \
+ (new) [k] = (orig) [k] ; \
+ }
+
+
+/*======================================================================================
+*/
+
+static void mono_char_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_char_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_char_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_char_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_char (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ short *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_char", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 32000.0) ;
+
+ orig = orig_data.s ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_char_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_char_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_char_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_char_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_char */
+
+static void
+mono_char_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_short_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_short_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (short)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_short (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_short (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_char_test */
+
+static void
+stereo_char_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 32000.0) ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_short_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (short)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (CHAR_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (CHAR_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_short (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_short_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (CHAR_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if (CHAR_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (CHAR_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_char_test */
+
+static void
+mono_rdwr_char_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_short_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_short_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_short (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_short_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (CHAR_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_short (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_short_test */
+
+static void
+new_rdwr_char_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_short_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_short_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_short_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_short_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_short_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_char_test */
+
+
+/*======================================================================================
+*/
+
+static void mono_short_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_short_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_short_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_short_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_short (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ short *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_short", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 32000.0) ;
+
+ orig = orig_data.s ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_short_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_short_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_short_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_short_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_short */
+
+static void
+mono_short_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_short_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_short_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (short)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_short (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_short_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_short (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_short_test */
+
+static void
+stereo_short_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 32000.0) ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_short_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (short)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_short (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_short_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_short_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_short_test */
+
+static void
+mono_rdwr_short_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_short_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_short_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_short (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_short_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_short (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_short_test */
+
+static void
+new_rdwr_short_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ short *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_short_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_short_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_short_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_short_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_short_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_short_test */
+
+
+/*======================================================================================
+*/
+
+static void mono_24bit_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_24bit_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_24bit_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_24bit_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_24bit (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ int *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_24bit", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, (1.0 * 0x7F000000)) ;
+
+ orig = orig_data.i ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_24bit_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_24bit_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_24bit_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_24bit_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_24bit */
+
+static void
+mono_24bit_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_int_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_int_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (int)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_int (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_int (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_24bit_test */
+
+static void
+stereo_24bit_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, (1.0 * 0x7F000000)) ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_int_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (int)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (TRIBYTE_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (TRIBYTE_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_int (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_int_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (TRIBYTE_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if (TRIBYTE_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (TRIBYTE_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_24bit_test */
+
+static void
+mono_rdwr_24bit_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_int_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_int_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_int (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_int_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (TRIBYTE_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_int (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_int_test */
+
+static void
+new_rdwr_24bit_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_int_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_int_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_int_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_int_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_int_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_24bit_test */
+
+
+/*======================================================================================
+*/
+
+static void mono_int_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_int_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_int_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_int_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_int (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ int *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_int", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, (1.0 * 0x7F000000)) ;
+
+ orig = orig_data.i ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_int_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_int_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_int_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_int_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_int */
+
+static void
+mono_int_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_int_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_int_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (int)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_int (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_int_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : 0x%X => 0x%X).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_int (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_int_test */
+
+static void
+stereo_int_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, (1.0 * 0x7F000000)) ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_int_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (int)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_int (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_int_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_int_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (INT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : 0x%X => 0x%X).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_int_test */
+
+static void
+mono_rdwr_int_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_int_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_int_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_int (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_int_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (INT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d (0x%X => 0x%X).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_int (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_int_test */
+
+static void
+new_rdwr_int_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ int *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.i ;
+ test = test_data.i ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_int_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_int_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_int_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_int_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_int_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_int_test */
+
+
+/*======================================================================================
+*/
+
+static void mono_float_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_float_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_float_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_float_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_float (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ float *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_float", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 1.0) ;
+
+ orig = orig_data.f ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_float_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_float_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_float_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_float_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_float */
+
+static void
+mono_float_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ float *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.f ;
+ test = test_data.f ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_float_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_float_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (float)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_float_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_float (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_float_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_float_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_float_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_float_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : %g => %g).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_float (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_float_test */
+
+static void
+stereo_float_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ float *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 1.0) ;
+
+ orig = orig_data.f ;
+ test = test_data.f ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_float_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (float)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_float_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_float_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_float (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_float_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_float_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_float_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_float_test */
+
+static void
+mono_rdwr_float_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ float *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.f ;
+ test = test_data.f ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_float_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_float_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d (%g => %g).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_float (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_float_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d (%g => %g).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_float (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_float_test */
+
+static void
+new_rdwr_float_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ float *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.f ;
+ test = test_data.f ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_float_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_float_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_float_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_float_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_float_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_float_test */
+
+
+/*======================================================================================
+*/
+
+static void mono_double_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_double_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_double_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_double_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_double (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ double *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_double", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 1.0) ;
+
+ orig = orig_data.d ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_double_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_double_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_double_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_double_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_double */
+
+static void
+mono_double_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.d ;
+ test = test_data.d ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_double_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_double_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (double)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_double_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_double (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : %g => %g).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_double_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : %g => %g).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_double (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_double_test */
+
+static void
+stereo_double_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, 1.0) ;
+
+ orig = orig_data.d ;
+ test = test_data.d ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_double_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof (double)) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_double (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_double_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_double_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if (FLOAT_ERROR (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : %g => %g).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_double_test */
+
+static void
+mono_rdwr_double_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ double *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.d ;
+ test = test_data.d ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_double_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_double_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d (%g => %g).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_double (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_double_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if (FLOAT_ERROR (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d (%g => %g).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_double (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_double_test */
+
+static void
+new_rdwr_double_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ double *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.d ;
+ test = test_data.d ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_double_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_double_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_double_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_double_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_double_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_double_test */
+
+
+
+/*----------------------------------------------------------------------------------------
+*/
+
+static void
+empty_file_test (const char *filename, int format)
+{ SNDFILE *file ;
+ SF_INFO info ;
+ int allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("empty_file_test", filename) ;
+
+ unlink (filename) ;
+
+ info.samplerate = 48000 ;
+ info.channels = 2 ;
+ info.format = format ;
+
+ if (sf_format_check (&info) == SF_FALSE)
+ { info.channels = 1 ;
+ if (sf_format_check (&info) == SF_FALSE)
+ { puts ("invalid file format") ;
+ return ;
+ } ;
+ } ;
+
+ /* Create an empty file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &info, allow_fd, __LINE__) ;
+ sf_close (file) ;
+
+ /* Open for read and check the length. */
+ file = test_open_file_or_die (filename, SFM_READ, &info, allow_fd, __LINE__) ;
+
+ if (SF_COUNT_TO_LONG (info.frames) != 0)
+ { printf ("\n\nError : frame count (%ld) should be zero.\n", SF_COUNT_TO_LONG (info.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Open for read/write and check the length. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &info, allow_fd, __LINE__) ;
+
+ if (SF_COUNT_TO_LONG (info.frames) != 0)
+ { printf ("\n\nError : frame count (%ld) should be zero.\n", SF_COUNT_TO_LONG (info.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Open for read and check the length. */
+ file = test_open_file_or_die (filename, SFM_READ, &info, allow_fd, __LINE__) ;
+
+ if (SF_COUNT_TO_LONG (info.frames) != 0)
+ { printf ("\n\nError : frame count (%ld) should be zero.\n", SF_COUNT_TO_LONG (info.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ check_open_file_count_or_die (__LINE__) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+
+ return ;
+} /* empty_file_test */
+
+
+/*----------------------------------------------------------------------------------------
+*/
+
+static void
+create_short_file (const char *filename)
+{ FILE *file ;
+
+ if (! (file = fopen (filename, "w")))
+ { printf ("create_short_file : fopen (%s, \"w\") failed.", filename) ;
+ fflush (stdout) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+
+ fprintf (file, "This is the file data.\n") ;
+
+ fclose (file) ;
+} /* create_short_file */
+
+#if (defined (WIN32) || defined (__WIN32))
+
+/* Win32 does not have truncate (nor does it have the POSIX function ftruncate).
+** Hack somethng up here to over come this. This function can only truncate to a
+** length of zero.
+*/
+
+static int
+truncate (const char *filename, int ignored)
+{ int fd ;
+
+ ignored = 0 ;
+
+ if ((fd = open (filename, O_RDWR | O_TRUNC | O_BINARY)) < 0)
+ return 0 ;
+
+ close (fd) ;
+
+ return 0 ;
+} /* truncate */
+
+#endif
+
+static void
+multi_seek_test (const char * filename, int format)
+{ SNDFILE * file ;
+ SF_INFO info ;
+ sf_count_t pos ;
+ int k ;
+
+ /* This test doesn't work on the following. */
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_RAW :
+ return ;
+
+ default :
+ break ;
+ } ;
+
+ memset (&info, 0, sizeof (info)) ;
+
+ generate_file (filename, format, 88200) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &info, SF_FALSE, __LINE__) ;
+
+ for (k = 0 ; k < 10 ; k++)
+ { pos = info.frames / (k + 2) ;
+ test_seek_or_die (file, pos, SEEK_SET, pos, info.channels, __LINE__) ;
+ } ;
+
+ sf_close (file) ;
+} /* multi_seek_test */
+
+static void
+write_seek_extend_test (const char * filename, int format)
+{ SNDFILE * file ;
+ SF_INFO info ;
+ short *orig, *test ;
+ unsigned items, k ;
+
+ /* This test doesn't work on the following. */
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_FLAC :
+ case SF_FORMAT_HTK :
+ case SF_FORMAT_PAF :
+ case SF_FORMAT_SDS :
+ case SF_FORMAT_SVX :
+ return ;
+
+ default :
+ break ;
+ } ;
+
+ memset (&info, 0, sizeof (info)) ;
+
+ info.samplerate = 48000 ;
+ info.channels = 1 ;
+ info.format = format ;
+
+ items = 512 ;
+ exit_if_true (items > ARRAY_LEN (orig_data.s), "Line %d : Bad assumption.\n", __LINE__) ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ for (k = 0 ; k < ARRAY_LEN (orig_data.s) ; k++)
+ orig [k] = 0x3fff ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &info, SF_FALSE, __LINE__) ;
+ test_write_short_or_die (file, 0, orig, items, __LINE__) ;
+
+ /* Extend the file using a seek. */
+ test_seek_or_die (file, 2 * items, SEEK_SET, 2 * items, info.channels, __LINE__) ;
+
+ test_writef_short_or_die (file, 0, orig, items, __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &info, SF_FALSE, __LINE__) ;
+ test_read_short_or_die (file, 0, test, 3 * items, __LINE__) ;
+ sf_close (file) ;
+
+ /* Can't do these formats due to scaling. */
+ switch (format & SF_FORMAT_SUBMASK)
+ { case SF_FORMAT_PCM_S8 :
+ case SF_FORMAT_PCM_U8 :
+ return ;
+ default :
+ break ;
+ } ;
+
+ for (k = 0 ; k < items ; k++)
+ { exit_if_true (test [k] != 0x3fff, "Line %d : test [%d] == %d, should be 0x3fff.\n", __LINE__, k, test [k]) ;
+ exit_if_true (test [items + k] != 0, "Line %d : test [%d] == %d, should be 0.\n", __LINE__, items + k, test [items + k]) ;
+ exit_if_true (test [2 * items + k] != 0x3fff, "Line %d : test [%d] == %d, should be 0x3fff.\n", __LINE__, 2 * items + k, test [2 * items + k]) ;
+ } ;
+
+ return ;
+} /* write_seek_extend_test */
+
+
diff --git a/tests/write_read_test.def b/tests/write_read_test.def
new file mode 100644
index 0000000..cfc7ce5
--- /dev/null
+++ b/tests/write_read_test.def
@@ -0,0 +1,65 @@
+autogen definitions write_read_test.tpl;
+
+data_type = {
+ type_name = char ;
+ data_type = short ;
+ data_field = s ;
+ error_func = CHAR_ERROR ;
+ format_char = "0x%X" ;
+ max_val = "32000.0" ;
+ max_error = "255" ;
+ } ;
+
+data_type = {
+ type_name = short ;
+ data_type = short ;
+ data_field = s ;
+ error_func = INT_ERROR ;
+ format_char = "0x%X" ;
+ max_val = "32000.0" ;
+ max_error = "0" ;
+ } ;
+
+data_type = {
+ type_name = "24bit" ;
+ data_type = int ;
+ data_field = i ;
+ error_func = TRIBYTE_ERROR ;
+ format_char = "0x%X" ;
+ max_val = "(1.0 * 0x7F000000)" ;
+ max_error = "256" ;
+ } ;
+
+data_type = {
+ type_name = int ;
+ data_type = int ;
+ data_field = i ;
+ error_func = INT_ERROR ;
+ format_char = "0x%X" ;
+ max_val = "(1.0 * 0x7F000000)" ;
+ max_error = "0" ;
+ } ;
+
+/* Lite remove start */
+
+data_type = {
+ type_name = float ;
+ data_type = float ;
+ data_field = f ;
+ error_func = FLOAT_ERROR ;
+ format_char = "%g" ;
+ max_val = "1.0" ;
+ max_error = "0" ;
+ } ;
+
+data_type = {
+ type_name = double ;
+ data_type = double ;
+ data_field = d ;
+ error_func = FLOAT_ERROR ;
+ format_char = "%g" ;
+ max_val = "1.0" ;
+ max_error = "0" ;
+ } ;
+
+/* Lite remove end */
diff --git a/tests/write_read_test.tpl b/tests/write_read_test.tpl
new file mode 100644
index 0000000..4f288f5
--- /dev/null
+++ b/tests/write_read_test.tpl
@@ -0,0 +1,1150 @@
+[+ AutoGen5 template c +]
+/*
+** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <math.h>
+
+#if (defined (WIN32) || defined (_WIN32))
+#include <fcntl.h>
+static int truncate (const char *filename, int ignored) ;
+#endif
+
+#include <sndfile.h>
+
+#include "utils.h"
+#include "generate.h"
+
+#define SAMPLE_RATE 11025
+#define DATA_LENGTH (1<<12)
+
+#define SILLY_WRITE_COUNT (234)
+
+[+ FOR data_type
++]static void pcm_test_[+ (get "type_name") +] (const char *str, int format, int long_file_okz) ;
+[+ ENDFOR data_type
++]
+static void empty_file_test (const char *filename, int format) ;
+
+typedef union
+{ double d [DATA_LENGTH] ;
+ float f [DATA_LENGTH] ;
+ int i [DATA_LENGTH] ;
+ short s [DATA_LENGTH] ;
+ char c [DATA_LENGTH] ;
+} BUFFER ;
+
+static BUFFER orig_data ;
+static BUFFER test_data ;
+
+int
+main (int argc, char **argv)
+{ int do_all = 0 ;
+ int test_count = 0 ;
+
+ count_open_files () ;
+
+ if (argc != 2)
+ { printf ("Usage : %s <test>\n", argv [0]) ;
+ printf (" Where <test> is one of the following:\n") ;
+ printf (" wav - test WAV file functions (little endian)\n") ;
+ printf (" aiff - test AIFF file functions (big endian)\n") ;
+ printf (" au - test AU file functions\n") ;
+ printf (" avr - test AVR file functions\n") ;
+ printf (" caf - test CAF file functions\n") ;
+ printf (" raw - test RAW header-less PCM file functions\n") ;
+ printf (" paf - test PAF file functions\n") ;
+ printf (" svx - test 8SVX/16SV file functions\n") ;
+ printf (" nist - test NIST Sphere file functions\n") ;
+ printf (" ircam - test IRCAM file functions\n") ;
+ printf (" voc - Create Voice file functions\n") ;
+ printf (" w64 - Sonic Foundry's W64 file functions\n") ;
+ printf (" flac - test FLAC file functions\n") ;
+ printf (" mpc2k - test MPC 2000 file functions\n") ;
+ printf (" rf64 - test RF64 file functions\n") ;
+ printf (" all - perform all tests\n") ;
+ exit (1) ;
+ } ;
+
+ do_all = !strcmp (argv [1], "all") ;
+
+ if (do_all || ! strcmp (argv [1], "wav"))
+ { pcm_test_char ("char.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.wav" , SF_FORMAT_WAV | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_char ("char.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_24bit ("24bit.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_float ("float.wav" , SF_FORMAT_WAV | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.wav" , SF_FORMAT_WAV | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ pcm_test_float ("float.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.rifx" , SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ pcm_test_float ("float.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.wavex" , SF_FORMAT_WAVEX | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ empty_file_test ("empty_char.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "aiff"))
+ { pcm_test_char ("char_u8.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_char ("char_s8.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_short ("short_sowt.aifc" , SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_sowt.aifc" , SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_sowt.aifc" , SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ pcm_test_short ("short_twos.aifc" , SF_ENDIAN_BIG | SF_FORMAT_AIFF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_twos.aifc" , SF_ENDIAN_BIG | SF_FORMAT_AIFF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_twos.aifc" , SF_ENDIAN_BIG | SF_FORMAT_AIFF | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_short ("dwvw16.aifc", SF_FORMAT_AIFF | SF_FORMAT_DWVW_16, SF_TRUE) ;
+ pcm_test_24bit ("dwvw24.aifc", SF_FORMAT_AIFF | SF_FORMAT_DWVW_24, SF_TRUE) ;
+
+ pcm_test_float ("float.aifc" , SF_FORMAT_AIFF | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.aifc" , SF_FORMAT_AIFF | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ empty_file_test ("empty_char.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "au"))
+ { pcm_test_char ("char.au" , SF_FORMAT_AU | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.au" , SF_FORMAT_AU | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.au" , SF_FORMAT_AU | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.au" , SF_FORMAT_AU | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float.au" , SF_FORMAT_AU | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.au", SF_FORMAT_AU | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ pcm_test_char ("char_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_le.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "caf"))
+ { pcm_test_char ("char.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float.caf" , SF_FORMAT_CAF | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.caf" , SF_FORMAT_CAF | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ pcm_test_short ("short_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float_le.caf" , SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_le.caf", SF_ENDIAN_LITTLE | SF_FORMAT_CAF | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "raw"))
+ { pcm_test_char ("char_s8.raw" , SF_FORMAT_RAW | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_char ("char_u8.raw" , SF_FORMAT_RAW | SF_FORMAT_PCM_U8, SF_FALSE) ;
+
+ pcm_test_short ("short_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_24bit ("24bit_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_float ("float_le.raw" , SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_be.raw" , SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_FLOAT , SF_FALSE) ;
+
+ pcm_test_double ("double_le.raw", SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ pcm_test_double ("double_be.raw", SF_ENDIAN_BIG | SF_FORMAT_RAW | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+ test_count++ ;
+ } ;
+
+ /* Lite remove start */
+ if (do_all || ! strcmp (argv [1], "paf"))
+ { pcm_test_char ("char_le.paf", SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_char ("char_be.paf", SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short_le.paf", SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_be.paf", SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.paf", SF_ENDIAN_LITTLE | SF_FORMAT_PAF | SF_FORMAT_PCM_24, SF_TRUE) ;
+ pcm_test_24bit ("24bit_be.paf", SF_ENDIAN_BIG | SF_FORMAT_PAF | SF_FORMAT_PCM_24, SF_TRUE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "svx"))
+ { pcm_test_char ("char.svx" , SF_FORMAT_SVX | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_16, SF_FALSE) ;
+
+ empty_file_test ("empty_char.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_S8) ;
+ empty_file_test ("empty_short.svx", SF_FORMAT_SVX | SF_FORMAT_PCM_16) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "nist"))
+ { pcm_test_short ("short_le.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_be.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit_le.nist", SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_24bit ("24bit_be.nist", SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int_le.nist" , SF_ENDIAN_LITTLE | SF_FORMAT_NIST | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_be.nist" , SF_ENDIAN_BIG | SF_FORMAT_NIST | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "ircam"))
+ { pcm_test_short ("short_be.ircam" , SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_le.ircam" , SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int_be.ircam" , SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_le.ircam" , SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_float ("float_be.ircam" , SF_ENDIAN_BIG | SF_FORMAT_IRCAM | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_le.ircam" , SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_FLOAT , SF_FALSE) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "voc"))
+ { pcm_test_char ("char.voc" , SF_FORMAT_VOC | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.voc", SF_FORMAT_VOC | SF_FORMAT_PCM_16, SF_FALSE) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat4"))
+ { pcm_test_short ("short_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_float ("float_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_be.mat4" , SF_ENDIAN_BIG | SF_FORMAT_MAT4 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ pcm_test_double ("double_le.mat4" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT4 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ empty_file_test ("empty_short.mat4", SF_FORMAT_MAT4 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.mat4", SF_FORMAT_MAT4 | SF_FORMAT_FLOAT) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mat5"))
+ { pcm_test_char ("char_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_char ("char_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_short ("short_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_int ("int_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ pcm_test_float ("float_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_float ("float_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double_be.mat5" , SF_ENDIAN_BIG | SF_FORMAT_MAT5 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ pcm_test_double ("double_le.mat5" , SF_ENDIAN_LITTLE | SF_FORMAT_MAT5 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+
+ increment_open_file_count () ;
+
+ empty_file_test ("empty_char.mat5", SF_FORMAT_MAT5 | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.mat5", SF_FORMAT_MAT5 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.mat5", SF_FORMAT_MAT5 | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "pvf"))
+ { pcm_test_char ("char.pvf" , SF_FORMAT_PVF | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.pvf", SF_FORMAT_PVF | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_int ("int.pvf" , SF_FORMAT_PVF | SF_FORMAT_PCM_32, SF_FALSE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "htk"))
+ { pcm_test_short ("short.htk", SF_FORMAT_HTK | SF_FORMAT_PCM_16, SF_FALSE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "mpc2k"))
+ { pcm_test_short ("short.mpc", SF_FORMAT_MPC2K | SF_FORMAT_PCM_16, SF_FALSE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "avr"))
+ { pcm_test_char ("char_u8.avr" , SF_FORMAT_AVR | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_char ("char_s8.avr" , SF_FORMAT_AVR | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.avr" , SF_FORMAT_AVR | SF_FORMAT_PCM_16, SF_FALSE) ;
+ test_count++ ;
+ } ;
+ /* Lite remove end */
+
+ if (do_all || ! strcmp (argv [1], "w64"))
+ { pcm_test_char ("char.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.w64" , SF_FORMAT_W64 | SF_FORMAT_PCM_32, SF_FALSE) ;
+ /* Lite remove start */
+ pcm_test_float ("float.w64" , SF_FORMAT_W64 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.w64" , SF_FORMAT_W64 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ /* Lite remove end */
+
+ empty_file_test ("empty_char.w64", SF_FORMAT_W64 | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.w64", SF_FORMAT_W64 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.w64", SF_FORMAT_W64 | SF_FORMAT_FLOAT) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sds"))
+ { pcm_test_char ("char.sds" , SF_FORMAT_SDS | SF_FORMAT_PCM_S8, SF_FALSE) ;
+ pcm_test_short ("short.sds" , SF_FORMAT_SDS | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.sds" , SF_FORMAT_SDS | SF_FORMAT_PCM_24, SF_FALSE) ;
+
+ empty_file_test ("empty_char.sds", SF_FORMAT_SDS | SF_FORMAT_PCM_S8) ;
+ empty_file_test ("empty_short.sds", SF_FORMAT_SDS | SF_FORMAT_PCM_16) ;
+
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "sd2"))
+ { pcm_test_char ("char.sd2" , SF_FORMAT_SD2 | SF_FORMAT_PCM_S8, SF_TRUE) ;
+ pcm_test_short ("short.sd2" , SF_FORMAT_SD2 | SF_FORMAT_PCM_16, SF_TRUE) ;
+ pcm_test_24bit ("24bit.sd2" , SF_FORMAT_SD2 | SF_FORMAT_PCM_24, SF_TRUE) ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "flac"))
+ { if (HAVE_EXTERNAL_LIBS)
+ { pcm_test_char ("char.flac" , SF_FORMAT_FLAC | SF_FORMAT_PCM_S8, SF_TRUE) ;
+ pcm_test_short ("short.flac" , SF_FORMAT_FLAC | SF_FORMAT_PCM_16, SF_TRUE) ;
+ pcm_test_24bit ("24bit.flac" , SF_FORMAT_FLAC | SF_FORMAT_PCM_24, SF_TRUE) ;
+ }
+ else
+ puts (" No FLAC tests because FLAC support was not compiled in.") ;
+ test_count++ ;
+ } ;
+
+ if (do_all || ! strcmp (argv [1], "rf64"))
+ { pcm_test_char ("char.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_U8, SF_FALSE) ;
+ pcm_test_short ("short.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_16, SF_FALSE) ;
+ pcm_test_24bit ("24bit.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_24, SF_FALSE) ;
+ pcm_test_int ("int.rf64" , SF_FORMAT_RF64 | SF_FORMAT_PCM_32, SF_FALSE) ;
+
+ /* Lite remove start */
+ pcm_test_float ("float.rf64" , SF_FORMAT_RF64 | SF_FORMAT_FLOAT , SF_FALSE) ;
+ pcm_test_double ("double.rf64" , SF_FORMAT_RF64 | SF_FORMAT_DOUBLE, SF_FALSE) ;
+ empty_file_test ("empty_char.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_U8) ;
+ empty_file_test ("empty_short.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
+ empty_file_test ("empty_float.rf64", SF_FORMAT_RF64 | SF_FORMAT_FLOAT) ;
+ /* Lite remove end */
+
+ test_count++ ;
+ } ;
+
+ if (test_count == 0)
+ { printf ("Mono : ************************************\n") ;
+ printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
+ printf ("Mono : ************************************\n") ;
+ return 1 ;
+ } ;
+
+ /* Only open file descriptors should be stdin, stdout and stderr. */
+ check_open_file_count_or_die (__LINE__) ;
+
+ return 0 ;
+} /* main */
+
+/*============================================================================================
+** Helper functions and macros.
+*/
+
+static void create_short_file (const char *filename) ;
+
+#define CHAR_ERROR(x,y) (abs ((x) - (y)) > 255)
+#define INT_ERROR(x,y) (((x) - (y)) != 0)
+#define TRIBYTE_ERROR(x,y) (abs ((x) - (y)) > 255)
+#define FLOAT_ERROR(x,y) (fabs ((x) - (y)) > 1e-5)
+
+#define CONVERT_DATA(k,len,new,orig) \
+ { for ((k) = 0 ; (k) < (len) ; (k) ++) \
+ (new) [k] = (orig) [k] ; \
+ }
+
+[+ FOR data_type
++]
+/*======================================================================================
+*/
+
+static void mono_[+ (get "type_name") +]_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void stereo_[+ (get "type_name") +]_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void mono_rdwr_[+ (get "type_name") +]_test (const char *filename, int format, int long_file_ok, int allow_fd) ;
+static void new_rdwr_[+ (get "type_name") +]_test (const char *filename, int format, int allow_fd) ;
+static void multi_seek_test (const char * filename, int format) ;
+static void write_seek_extend_test (const char * filename, int format) ;
+
+static void
+pcm_test_[+ (get "type_name") +] (const char *filename, int format, int long_file_ok)
+{ SF_INFO sfinfo ;
+ [+ (get "data_type") +] *orig ;
+ int k, allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("pcm_test_[+ (get "type_name") +]", filename) ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, [+ (get "max_val") +]) ;
+
+ orig = orig_data.[+ (get "data_field") +] ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ /* Some test broken out here. */
+
+ mono_[+ (get "type_name") +]_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* Sub format DWVW does not allow seeking. */
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { unlink (filename) ;
+ printf ("no seek : ok\n") ;
+ return ;
+ } ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ mono_rdwr_[+ (get "type_name") +]_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* If the format doesn't support stereo we're done. */
+ sfinfo.channels = 2 ;
+ if (sf_format_check (&sfinfo) == 0)
+ { unlink (filename) ;
+ puts ("no stereo : ok") ;
+ return ;
+ } ;
+
+ stereo_[+ (get "type_name") +]_test (filename, format, long_file_ok, allow_fd) ;
+
+ /* New read/write test. Not sure if this is needed yet. */
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC &&
+ (format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC)
+ new_rdwr_[+ (get "type_name") +]_test (filename, format, allow_fd) ;
+
+ delete_file (format, filename) ;
+
+ puts ("ok") ;
+ return ;
+} /* pcm_test_[+ (get "type_name") +] */
+
+static void
+mono_[+ (get "type_name") +]_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ [+ (get "data_type") +] *orig, *test ;
+ sf_count_t count ;
+ int k, items ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ orig = orig_data.[+ (get "data_field") +] ;
+ test = test_data.[+ (get "data_field") +] ;
+
+ items = DATA_LENGTH ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_write_[+ (get "data_type") +]_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+ test_write_[+ (get "data_type") +]_or_die (file, 0, orig, items, __LINE__) ;
+ sf_write_sync (file) ;
+
+ /* Add non-audio data after the audio. */
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof ([+ (get "data_type") +])) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too short). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > 2 * items)
+ { printf ("\n\nLine %d : Mono : Incorrect number of frames in file (too long). (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), items) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Mono : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_read_[+ (get "data_type") +]_or_die (file, 0, test, items, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d: Mono : Incorrect sample A (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ oct_save_[+ (get "data_type") +] (orig, test, items) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_read_[+ (get "data_type") +]_or_die (file, 0, test, 4, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ if ((format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_16 ||
+ (format & SF_FORMAT_SUBMASK) == SF_FORMAT_DWVW_24)
+ { sf_close (file) ;
+ unlink (filename) ;
+ printf ("no seek : ") ;
+ return ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, items + 10, SEEK_SET, items + 10, sfinfo.channels, __LINE__) ;
+
+ test_read_[+ (get "data_type") +]_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 6, SEEK_CUR, items + 20, sfinfo.channels, __LINE__) ;
+
+ test_read_[+ (get "data_type") +]_or_die (file, 0, test + 20, 4, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample A (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_read_[+ (get "data_type") +]_or_die (file, 0, test + 10, 4, __LINE__) ;
+ for (k = 10 ; k < 14 ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d : Mono : Incorrect sample D (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, test [k], orig [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Check read past end of file followed by sf_seek (sndfile, 0, SEEK_CUR). */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ count = 0 ;
+ while (count < sfinfo.frames)
+ count += sf_read_[+ (get "data_type") +] (file, test, 311) ;
+
+ /* Check that no error has occurred. */
+ if (sf_error (file))
+ { printf ("\n\nLine %d : Mono : error where there shouldn't have been one.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ /* Check that we haven't read beyond EOF. */
+ if (count > sfinfo.frames)
+ { printf ("\n\nLines %d : read past end of file (%ld should be %ld)\n", __LINE__, (long) count, (long) sfinfo.frames) ;
+ exit (1) ;
+ } ;
+
+ test_seek_or_die (file, 0, SEEK_CUR, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+ sf_close (file) ;
+
+ multi_seek_test (filename, format) ;
+ write_seek_extend_test (filename, format) ;
+
+} /* mono_[+ (get "type_name") +]_test */
+
+static void
+stereo_[+ (get "type_name") +]_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ [+ (get "data_type") +] *orig, *test ;
+ int k, items, frames ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ gen_windowed_sine_double (orig_data.d, DATA_LENGTH, [+ (get "max_val") +]) ;
+
+ orig = orig_data.[+ (get "data_field") +] ;
+ test = test_data.[+ (get "data_field") +] ;
+
+ /* Make this a macro so gdb steps over it in one go. */
+ CONVERT_DATA (k, DATA_LENGTH, orig, orig_data.d) ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+
+ sf_set_string (file, SF_STR_ARTIST, "Your name here") ;
+
+ test_writef_[+ (get "data_type") +]_or_die (file, 0, orig, frames, __LINE__) ;
+
+ sf_set_string (file, SF_STR_COPYRIGHT, "Copyright (c) 2003") ;
+
+ sf_close (file) ;
+
+ memset (test, 0, items * sizeof ([+ (get "data_type") +])) ;
+
+ if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
+ memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Stereo : Returned format incorrect (0x%08X => 0x%08X).\n",
+ __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too short). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok && sfinfo.frames > frames)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of frames in file (too long). (%ld should be %d)\n",
+ __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), frames) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 2)
+ { printf ("\n\nLine %d : Stereo : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ check_log_buffer_or_die (file, __LINE__) ;
+
+ test_readf_[+ (get "data_type") +]_or_die (file, 0, test, frames, __LINE__) ;
+ for (k = 0 ; k < items ; k++)
+ if ([+ (get "error_func") +] (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to start of file. */
+ test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
+
+ test_readf_[+ (get "data_type") +]_or_die (file, 0, test, 2, __LINE__) ;
+ for (k = 0 ; k < 4 ; k++)
+ if ([+ (get "error_func") +] (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from start of file. */
+ test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
+
+ /* Check for errors here. */
+ if (sf_error (file))
+ { printf ("Line %d: Should NOT return an error.\n", __LINE__) ;
+ puts (sf_strerror (file)) ;
+ exit (1) ;
+ } ;
+
+ if (sf_read_[+ (get "data_type") +] (file, test, 1) > 0)
+ { printf ("Line %d: Should return 0.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! sf_error (file))
+ { printf ("Line %d: Should return an error.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+ /*-----------------------*/
+
+ test_readf_[+ (get "data_type") +]_or_die (file, 0, test + 10, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if ([+ (get "error_func") +] (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from current position. */
+ test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
+
+ test_readf_[+ (get "data_type") +]_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 40 ; k < 44 ; k++)
+ if ([+ (get "error_func") +] (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ /* Seek to offset from end of file. */
+ test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
+
+ test_readf_[+ (get "data_type") +]_or_die (file, 0, test + 20, 2, __LINE__) ;
+ for (k = 20 ; k < 24 ; k++)
+ if ([+ (get "error_func") +] (test [k], orig [k]))
+ { printf ("\n\nLine %d : Stereo : Incorrect sample (#%d : [+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, k, orig [k], test [k]) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+} /* stereo_[+ (get "type_name") +]_test */
+
+static void
+mono_rdwr_[+ (get "type_name") +]_test (const char *filename, int format, int long_file_ok, int allow_fd)
+{ SNDFILE *file ;
+ SF_INFO sfinfo ;
+ [+ (get "data_type") +] *orig, *test ;
+ int k, pass ;
+
+ orig = orig_data.[+ (get "data_field") +] ;
+ test = test_data.[+ (get "data_field") +] ;
+
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AU
+ || (format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2)
+ unlink (filename) ;
+ else
+ { /* Create a short file. */
+ create_short_file (filename) ;
+
+ /* Opening a already existing short file (ie invalid header) RDWR is disallowed.
+ ** If this returns a valif pointer sf_open() screwed up.
+ */
+ if ((file = sf_open (filename, SFM_RDWR, &sfinfo)))
+ { printf ("\n\nLine %d: sf_open should (SFM_RDWR) have failed but didn't.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ /* Truncate the file to zero bytes. */
+ if (truncate (filename, 0) < 0)
+ { printf ("\n\nLine %d: truncate (%s) failed", __LINE__, filename) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+ } ;
+
+ /* Opening a zero length file RDWR is allowed, but the SF_INFO struct must contain
+ ** all the usual data required when opening the file in WRITE mode.
+ */
+ sfinfo.samplerate = SAMPLE_RATE ;
+ sfinfo.frames = DATA_LENGTH ;
+ sfinfo.channels = 1 ;
+ sfinfo.format = format ;
+
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ /* Do 3 writes followed by reads. After each, check the data and the current
+ ** read and write offsets.
+ */
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ /* Write some data. */
+ test_write_[+ (get "data_type") +]_or_die (file, pass, orig, DATA_LENGTH, __LINE__) ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, pass * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_[+ (get "data_type") +]_or_die (file, 0, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) A : Error at sample %d ([+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_[+ (get "data_type") +] (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, pass * DATA_LENGTH, pass * DATA_LENGTH) ;
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+
+ /* Open the file again to check the data. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+
+ if (sfinfo.format != format)
+ { printf ("\n\nLine %d : Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.frames < 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Not enough frames in file. (%ld < %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ }
+
+ if (! long_file_ok && sfinfo.frames != 3 * DATA_LENGTH)
+ { printf ("\n\nLine %d : Incorrect number of frames in file. (%ld should be %d)\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 3 * DATA_LENGTH ) ;
+ exit (1) ;
+ } ;
+
+ if (sfinfo.channels != 1)
+ { printf ("\n\nLine %d : Incorrect number of channels in file.\n", __LINE__) ;
+ exit (1) ;
+ } ;
+
+ if (! long_file_ok)
+ test_read_write_position_or_die (file, __LINE__, 0, 0, 3 * DATA_LENGTH) ;
+ else
+ test_seek_or_die (file, 3 * DATA_LENGTH, SFM_WRITE | SEEK_SET, 3 * DATA_LENGTH, sfinfo.channels, __LINE__) ;
+
+ for (pass = 1 ; pass <= 3 ; pass ++)
+ { orig [20] = pass * 2 ;
+
+ test_read_write_position_or_die (file, __LINE__, pass, (pass - 1) * DATA_LENGTH, 3 * DATA_LENGTH) ;
+
+ /* Read what we just wrote. */
+ test_read_[+ (get "data_type") +]_or_die (file, pass, test, DATA_LENGTH, __LINE__) ;
+
+ /* Check the data. */
+ for (k = 0 ; k < DATA_LENGTH ; k++)
+ if ([+ (get "error_func") +] (orig [k], test [k]))
+ { printf ("\n\nLine %d (pass %d) B : Error at sample %d ([+ (get "format_char") +] => [+ (get "format_char") +]).\n", __LINE__, pass, k, orig [k], test [k]) ;
+ oct_save_[+ (get "data_type") +] (orig, test, DATA_LENGTH) ;
+ exit (1) ;
+ } ;
+
+ } ; /* for (pass ...) */
+
+ sf_close (file) ;
+} /* mono_rdwr_[+ (get "data_type") +]_test */
+
+static void
+new_rdwr_[+ (get "type_name") +]_test (const char *filename, int format, int allow_fd)
+{ SNDFILE *wfile, *rwfile ;
+ SF_INFO sfinfo ;
+ [+ (get "data_type") +] *orig, *test ;
+ int items, frames ;
+
+ orig = orig_data.[+ (get "data_field") +] ;
+ test = test_data.[+ (get "data_field") +] ;
+
+ sfinfo.samplerate = 44100 ;
+ sfinfo.frames = SILLY_WRITE_COUNT ; /* Wrong length. Library should correct this on sf_close. */
+ sfinfo.channels = 2 ;
+ sfinfo.format = format ;
+
+ items = DATA_LENGTH ;
+ frames = items / sfinfo.channels ;
+
+ wfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
+ sf_command (wfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+ test_writef_[+ (get "data_type") +]_or_die (wfile, 1, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+ test_writef_[+ (get "data_type") +]_or_die (wfile, 2, orig, frames, __LINE__) ;
+ sf_write_sync (wfile) ;
+
+ rwfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, allow_fd, __LINE__) ;
+ if (sfinfo.frames != 2 * frames)
+ { printf ("\n\nLine %d : incorrect number of frames in file (%ld should be %d)\n\n", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * frames) ;
+ exit (1) ;
+ } ;
+
+ test_writef_[+ (get "data_type") +]_or_die (wfile, 3, orig, frames, __LINE__) ;
+
+ test_readf_[+ (get "data_type") +]_or_die (rwfile, 1, test, frames, __LINE__) ;
+ test_readf_[+ (get "data_type") +]_or_die (rwfile, 2, test, frames, __LINE__) ;
+
+ sf_close (wfile) ;
+ sf_close (rwfile) ;
+} /* new_rdwr_[+ (get "type_name") +]_test */
+
+[+ ENDFOR data_type +]
+
+/*----------------------------------------------------------------------------------------
+*/
+
+static void
+empty_file_test (const char *filename, int format)
+{ SNDFILE *file ;
+ SF_INFO info ;
+ int allow_fd ;
+
+ /* Sd2 files cannot be opened from an existing file descriptor. */
+ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ;
+
+ print_test_name ("empty_file_test", filename) ;
+
+ unlink (filename) ;
+
+ info.samplerate = 48000 ;
+ info.channels = 2 ;
+ info.format = format ;
+
+ if (sf_format_check (&info) == SF_FALSE)
+ { info.channels = 1 ;
+ if (sf_format_check (&info) == SF_FALSE)
+ { puts ("invalid file format") ;
+ return ;
+ } ;
+ } ;
+
+ /* Create an empty file. */
+ file = test_open_file_or_die (filename, SFM_WRITE, &info, allow_fd, __LINE__) ;
+ sf_close (file) ;
+
+ /* Open for read and check the length. */
+ file = test_open_file_or_die (filename, SFM_READ, &info, allow_fd, __LINE__) ;
+
+ if (SF_COUNT_TO_LONG (info.frames) != 0)
+ { printf ("\n\nError : frame count (%ld) should be zero.\n", SF_COUNT_TO_LONG (info.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Open for read/write and check the length. */
+ file = test_open_file_or_die (filename, SFM_RDWR, &info, allow_fd, __LINE__) ;
+
+ if (SF_COUNT_TO_LONG (info.frames) != 0)
+ { printf ("\n\nError : frame count (%ld) should be zero.\n", SF_COUNT_TO_LONG (info.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ /* Open for read and check the length. */
+ file = test_open_file_or_die (filename, SFM_READ, &info, allow_fd, __LINE__) ;
+
+ if (SF_COUNT_TO_LONG (info.frames) != 0)
+ { printf ("\n\nError : frame count (%ld) should be zero.\n", SF_COUNT_TO_LONG (info.frames)) ;
+ exit (1) ;
+ } ;
+
+ sf_close (file) ;
+
+ check_open_file_count_or_die (__LINE__) ;
+
+ unlink (filename) ;
+ puts ("ok") ;
+
+ return ;
+} /* empty_file_test */
+
+
+/*----------------------------------------------------------------------------------------
+*/
+
+static void
+create_short_file (const char *filename)
+{ FILE *file ;
+
+ if (! (file = fopen (filename, "w")))
+ { printf ("create_short_file : fopen (%s, \"w\") failed.", filename) ;
+ fflush (stdout) ;
+ perror (NULL) ;
+ exit (1) ;
+ } ;
+
+ fprintf (file, "This is the file data.\n") ;
+
+ fclose (file) ;
+} /* create_short_file */
+
+#if (defined (WIN32) || defined (__WIN32))
+
+/* Win32 does not have truncate (nor does it have the POSIX function ftruncate).
+** Hack somethng up here to over come this. This function can only truncate to a
+** length of zero.
+*/
+
+static int
+truncate (const char *filename, int ignored)
+{ int fd ;
+
+ ignored = 0 ;
+
+ if ((fd = open (filename, O_RDWR | O_TRUNC | O_BINARY)) < 0)
+ return 0 ;
+
+ close (fd) ;
+
+ return 0 ;
+} /* truncate */
+
+#endif
+
+static void
+multi_seek_test (const char * filename, int format)
+{ SNDFILE * file ;
+ SF_INFO info ;
+ sf_count_t pos ;
+ int k ;
+
+ /* This test doesn't work on the following. */
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_RAW :
+ return ;
+
+ default :
+ break ;
+ } ;
+
+ memset (&info, 0, sizeof (info)) ;
+
+ generate_file (filename, format, 88200) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &info, SF_FALSE, __LINE__) ;
+
+ for (k = 0 ; k < 10 ; k++)
+ { pos = info.frames / (k + 2) ;
+ test_seek_or_die (file, pos, SEEK_SET, pos, info.channels, __LINE__) ;
+ } ;
+
+ sf_close (file) ;
+} /* multi_seek_test */
+
+static void
+write_seek_extend_test (const char * filename, int format)
+{ SNDFILE * file ;
+ SF_INFO info ;
+ short *orig, *test ;
+ unsigned items, k ;
+
+ /* This test doesn't work on the following. */
+ switch (format & SF_FORMAT_TYPEMASK)
+ { case SF_FORMAT_FLAC :
+ case SF_FORMAT_HTK :
+ case SF_FORMAT_PAF :
+ case SF_FORMAT_SDS :
+ case SF_FORMAT_SVX :
+ return ;
+
+ default :
+ break ;
+ } ;
+
+ memset (&info, 0, sizeof (info)) ;
+
+ info.samplerate = 48000 ;
+ info.channels = 1 ;
+ info.format = format ;
+
+ items = 512 ;
+ exit_if_true (items > ARRAY_LEN (orig_data.s), "Line %d : Bad assumption.\n", __LINE__) ;
+
+ orig = orig_data.s ;
+ test = test_data.s ;
+
+ for (k = 0 ; k < ARRAY_LEN (orig_data.s) ; k++)
+ orig [k] = 0x3fff ;
+
+ file = test_open_file_or_die (filename, SFM_WRITE, &info, SF_FALSE, __LINE__) ;
+ test_write_short_or_die (file, 0, orig, items, __LINE__) ;
+
+ /* Extend the file using a seek. */
+ test_seek_or_die (file, 2 * items, SEEK_SET, 2 * items, info.channels, __LINE__) ;
+
+ test_writef_short_or_die (file, 0, orig, items, __LINE__) ;
+ sf_close (file) ;
+
+ file = test_open_file_or_die (filename, SFM_READ, &info, SF_FALSE, __LINE__) ;
+ test_read_short_or_die (file, 0, test, 3 * items, __LINE__) ;
+ sf_close (file) ;
+
+ /* Can't do these formats due to scaling. */
+ switch (format & SF_FORMAT_SUBMASK)
+ { case SF_FORMAT_PCM_S8 :
+ case SF_FORMAT_PCM_U8 :
+ return ;
+ default :
+ break ;
+ } ;
+
+ for (k = 0 ; k < items ; k++)
+ { exit_if_true (test [k] != 0x3fff, "Line %d : test [%d] == %d, should be 0x3fff.\n", __LINE__, k, test [k]) ;
+ exit_if_true (test [items + k] != 0, "Line %d : test [%d] == %d, should be 0.\n", __LINE__, items + k, test [items + k]) ;
+ exit_if_true (test [2 * items + k] != 0x3fff, "Line %d : test [%d] == %d, should be 0x3fff.\n", __LINE__, 2 * items + k, test [2 * items + k]) ;
+ } ;
+
+ return ;
+} /* write_seek_extend_test */
+
+