Imported Upstream version 1.0.31 90/267490/1 upstream/1.0.31
authorSeungbae Shin <seungbae.shin@samsung.com>
Mon, 13 Sep 2021 02:58:53 +0000 (11:58 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Mon, 6 Dec 2021 07:13:21 +0000 (16:13 +0900)
Change-Id: I76108a64afc8b24ece185fda3b49b65a38a58dbf

269 files changed:
.editorconfig [new file with mode: 0644]
.gitattributes [deleted file]
.gitignore [deleted file]
.travis.yml [deleted file]
AUTHORS
CMake/autogen.cmake [deleted file]
CMake/build.cmake [deleted file]
CMake/check.cmake [deleted file]
CMake/compiler_is_gcc.c [deleted file]
CMake/external_libs.cmake [deleted file]
CMake/file.cmake [deleted file]
CMake/have_decl_s_irgrp.c [deleted file]
CMake/libsndfile.cmake [deleted file]
CMakeLists.txt
CODEOWNERS [new file with mode: 0644]
CONTRIBUTING.md
ChangeLog
M4/Makefile.am [deleted file]
M4/add_cflags.m4 [deleted file]
M4/add_cxxflags.m4 [deleted file]
M4/clang.m4 [deleted file]
M4/endian.m4 [deleted file]
M4/gcc_version.m4 [deleted file]
M4/llrint.m4 [deleted file]
M4/lrint.m4 [deleted file]
M4/lrintf.m4 [deleted file]
M4/really_gcc.m4 [deleted file]
M4/visibility.m4 [deleted file]
Makefile.am
NEWS
README
README.md
Scripts/asan-configure.sh [new file with mode: 0755]
Scripts/build-test-tarball.mk.in
Scripts/cmake-build.sh
Scripts/cstyle.py
Scripts/git-pre-commit-hook
Scripts/static-deps-build.mk
Win32/Makefile.am [deleted file]
autogen.sh
cmake/CMakeAutoGen.cmake [new file with mode: 0644]
cmake/CMakeAutoGenScript.cmake [new file with mode: 0644]
cmake/CheckCPUArch.c.in [new file with mode: 0644]
cmake/CheckCPUArch.cmake [new file with mode: 0644]
cmake/ClipMode.cmake [new file with mode: 0644]
cmake/FindFLAC.cmake [new file with mode: 0644]
cmake/FindOgg.cmake [new file with mode: 0644]
cmake/FindOpus.cmake [new file with mode: 0644]
cmake/FindSndio.cmake [new file with mode: 0644]
cmake/FindSpeex.cmake [new file with mode: 0644]
cmake/FindVorbis.cmake [new file with mode: 0644]
cmake/SndFileChecks.cmake [new file with mode: 0644]
cmake/SndFileConfig.cmake.in [new file with mode: 0644]
cmake/TestInline.c.in [new file with mode: 0644]
cmake/TestInline.cmake [new file with mode: 0644]
cmake/TestLargeFiles.cmake [new file with mode: 0644]
cmake/sqlite/FindSQLite3.cmake [new file with mode: 0644]
configure.ac
doc/FAQ.html [deleted file]
doc/Makefile.am [deleted file]
doc/api.html [deleted file]
doc/bugs.html [deleted file]
doc/command.html [deleted file]
doc/development.html [deleted file]
doc/donate.html [deleted file]
doc/embedded_files.html [deleted file]
doc/index.html [deleted file]
doc/lists.html [deleted file]
doc/octave.html [deleted file]
doc/sndfile_info.html [deleted file]
doc/tutorial.html [deleted file]
doc/win32.html [deleted file]
docs/FAQ.md [new file with mode: 0644]
docs/_config.yml [new file with mode: 0644]
docs/_includes/logo.html [new file with mode: 0644]
docs/_layouts/default.html [new file with mode: 0644]
docs/_layouts/home.html [new file with mode: 0644]
docs/_layouts/page.html [new file with mode: 0644]
docs/api.md [new file with mode: 0644]
docs/bugs.md [new file with mode: 0644]
docs/command.md [new file with mode: 0644]
docs/development.md [new file with mode: 0644]
docs/donate.md [new file with mode: 0644]
docs/embedded_files.md [new file with mode: 0644]
docs/formats.md [new file with mode: 0644]
docs/index.md [new file with mode: 0644]
docs/libsndfile.css [moved from doc/libsndfile.css.in with 63% similarity]
docs/libsndfile.jpg [moved from doc/libsndfile.jpg with 100% similarity]
docs/linux_games_programming.txt [moved from doc/linux_games_programming.txt with 100% similarity]
docs/lists.md [new file with mode: 0644]
docs/new_file_type_howto.md [moved from doc/new_file_type.HOWTO with 72% similarity]
docs/octave.md [new file with mode: 0644]
docs/print.css [moved from doc/print.css with 100% similarity]
docs/sndfile_info.md [new file with mode: 0644]
docs/tutorial.md [new file with mode: 0644]
docs/win32.md [new file with mode: 0644]
echo-install-dirs.in [deleted file]
examples/Makefile.am [deleted file]
examples/generate.c
examples/make_sine.c
examples/sndfile-loopify.c
include/sndfile.h.in [moved from src/sndfile.h.in with 96% similarity]
include/sndfile.hh [moved from src/sndfile.hh with 93% similarity]
m4/ax_add_fortify_source.m4 [moved from M4/ax_add_fortify_source.m4 with 100% similarity]
m4/ax_append_compile_flags.m4 [new file with mode: 0644]
m4/ax_append_flag.m4 [new file with mode: 0644]
m4/ax_append_link_flags.m4 [new file with mode: 0644]
m4/ax_check_compile_flag.m4 [new file with mode: 0644]
m4/ax_check_link_flag.m4 [new file with mode: 0644]
m4/ax_compiler_vendor.m4 [new file with mode: 0644]
m4/ax_compiler_version.m4 [new file with mode: 0644]
m4/ax_recursive_eval.m4 [new file with mode: 0644]
m4/ax_require_defined.m4 [new file with mode: 0644]
m4/clip_mode.m4 [moved from M4/clip_mode.m4 with 100% similarity]
m4/extra_pkg.m4 [moved from M4/extra_pkg.m4 with 97% similarity]
m4/flexible_array.m4 [moved from M4/flexible_array.m4 with 100% similarity]
m4/mkoctfile_version.m4 [moved from M4/mkoctfile_version.m4 with 100% similarity]
m4/octave.m4 [moved from M4/octave.m4 with 100% similarity]
m4/stack_protect.m4 [moved from M4/stack_protect.m4 with 100% similarity]
man/Makefile.am [deleted file]
man/sndfile-cmp.1
man/sndfile-concat.1
man/sndfile-convert.1
man/sndfile-info.1
man/sndfile-interleave.1
man/sndfile-metadata-get.1
man/sndfile-play.1
man/sndfile-salvage.1
ossfuzz/ci_oss.sh [new file with mode: 0755]
ossfuzz/ossfuzz.sh [new file with mode: 0755]
ossfuzz/sndfile_fuzzer.cc [new file with mode: 0644]
ossfuzz/standaloneengine.cc [new file with mode: 0644]
ossfuzz/testinput.h [new file with mode: 0644]
programs/Makefile.am [deleted file]
programs/common.c
programs/common.h
programs/sndfile-convert.c
programs/sndfile-deinterleave.c
programs/sndfile-info.c
programs/sndfile-metadata-get.c
programs/sndfile-metadata-set.c
programs/sndfile-play-beos.cpp [deleted file]
programs/sndfile-play.c
programs/sndfile-salvage.c
regtest/Makefile.am [deleted file]
regtest/checksum.c
regtest/database.c
sndfile.pc.in
src/G72x/g72x_test.c
src/GSM610/gsm610_priv.h
src/GSM610/lpc.c
src/GSM610/rpe.c
src/Makefile.am [deleted file]
src/aiff.c
src/alaw.c
src/au.c
src/audio_detect.c
src/avr.c
src/binheader_writef_check.py
src/broadcast.c
src/caf.c
src/chunk.c
src/command.c
src/common.c
src/common.h
src/config.h.cmake [new file with mode: 0644]
src/create_symbols_file.c [deleted file]
src/create_symbols_file.py [changed mode: 0755->0644]
src/dither.c
src/double64.c
src/dwvw.c
src/file_io.c
src/flac.c
src/float32.c
src/g72x.c
src/gsm610.c
src/htk.c
src/id3.c
src/ima_adpcm.c
src/ircam.c
src/mat4.c
src/mat5.c
src/mpc2k.c
src/ms_adpcm.c
src/nist.c
src/nms_adpcm.c [new file with mode: 0644]
src/ogg.c
src/ogg.h
src/ogg_opus.c
src/ogg_pcm.c
src/ogg_speex.c
src/ogg_vcomment.c [new file with mode: 0644]
src/ogg_vcomment.h [new file with mode: 0644]
src/ogg_vorbis.c
src/paf.c
src/pcm.c
src/raw.c
src/rf64.c
src/sd2.c
src/sds.c
src/sf_unistd.h
src/sfconfig.h
src/sfendian.h
src/sndfile.c
src/svx.c
src/test_audio_detect.c
src/test_binheader_writef.c
src/test_endswap.tpl
src/test_file_io.c
src/test_main.c
src/test_main.h
src/test_nms_adpcm.c [new file with mode: 0644]
src/ulaw.c
src/version-metadata.rc.in
src/voc.c
src/vox_adpcm.c
src/w64.c
src/wav.c
src/wavlike.c
src/wavlike.h
src/windows.c
src/wve.c
src/xi.c
tests/Makefile.am [deleted file]
tests/aiff_rw_test.c
tests/alaw_test.c
tests/channel_test.c
tests/checksum_test.c
tests/chunk_test.c
tests/command_test.c
tests/compression_size_test.c
tests/cpp_test.cc
tests/cue_test.c [new file with mode: 0644]
tests/dft_cmp.c
tests/dither_test.c
tests/dwvw_test.c
tests/error_test.c
tests/external_libs_test.c
tests/fix_this.c
tests/floating_point_test.tpl
tests/format_check_test.c
tests/generate.c
tests/header_test.tpl
tests/headerless_test.c
tests/largefile_test.c
tests/locale_test.c
tests/long_read_write_test.c
tests/lossy_comp_test.c
tests/misc_test.c
tests/ogg_opus_test.c [new file with mode: 0644]
tests/ogg_test.c
tests/pcm_test.tpl
tests/peak_chunk_test.c
tests/pedantic-header-test.sh.in
tests/pipe_test.tpl
tests/raw_test.c
tests/scale_clip_test.tpl
tests/sftest.c
tests/sfversion.c
tests/stdin_test.c
tests/stdio_test.c
tests/stdout_test.c
tests/string_test.c
tests/test_wrapper.sh.in
tests/ulaw_test.c
tests/utils.tpl
tests/virtual_io_test.c
tests/win32_ordinal_test.c
tests/write_read_test.tpl

diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..f891142
--- /dev/null
@@ -0,0 +1,16 @@
+root = true
+
+[*]
+insert_final_newline = true
+
+[*.{h,hpp,c,tpl,def}]
+indent_style = tab
+tab_width = 4
+
+[*.py]
+indent_style = space
+indent_size = 4
+
+[*.yml]
+indent_style = space
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644 (file)
index cbedc73..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# Set the default behavior, in case people don't have core.autocrlf set.
-* text=auto
-
-# Declare files that will always have CRLF line endings on checkout.
-*.ac text eol=lf
-*.am text eol=lf
-*.m4 text eol=lf
-*.pc text eol=lf
-*.spec text eol=lf
-*.sh text eol=lf
-
-# Explicitly declare text files you want to always be normalized and converted
-# to native line endings on checkout.
-*.c text
-*.h text
diff --git a/.gitignore b/.gitignore
deleted file mode 100644 (file)
index 856aa66..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-*.8svx
-*.aif
-*.aifc
-*.aiff
-*.au
-*.bin
-*.caf
-*.cm*
-*.exe
-*.flac
-*.la
-*.lo
-*.loT
-*.o
-*.oct
-*.oga
-*.ogg
-*.paf
-*.raw
-*.rifx
-*.sd2
-*.sds
-*.svx
-*.w64
-*.wav
-*.wavex
-.DS_Store
-.deps
-.dirstamp
-.libs
-Build/
-CMake/config.h.in
-CMakeFiles
-CMakeCache.txt
-Cfg
-Hack
-Hack/sndfile-fuzzbomb
-INSTALL
-M4/libtool.m4
-M4/ltoptions.m4
-M4/ltsugar.m4
-M4/ltversion.m4
-M4/lt~obsolete.m4
-Makefile
-Makefile.in
-aclocal.m4
-autom4te.cache
-build-test-tarball.mk
-config.log
-config.status
-configure
-doc/AUTHORS
-doc/ChangeLog
-doc/NEWS
-doc/README
-doc/libsndfile.css
-echo-install-dirs
-examples/generate
-examples/list_formats
-examples/make_sine
-examples/sfprocess
-examples/sndfile-loopify
-examples/sndfile-to-text
-examples/sndfilehandle
-libsndfile-1.0.*
-libsndfile-testsuite-*
-libsndfile.spec
-libtool
-man/sndfile-deinterleave.1
-man/sndfile-metadata-set.1
-programs/sndfile-cmp
-programs/sndfile-concat
-programs/sndfile-convert
-programs/sndfile-data-trim
-programs/sndfile-deinterleave
-programs/sndfile-info
-programs/sndfile-interleave
-programs/sndfile-jackplay
-programs/sndfile-metadata-get
-programs/sndfile-metadata-set
-programs/sndfile-play
-programs/sndfile-salvage
-regtest/sndfile-regtest
-sndfile.pc
-src/Ext
-src/G72x/g72x_test
-src/Symbols.darwin
-src/Symbols.gnu-binutils
-src/Symbols.os2
-src/Symbols.static
-src/config.h
-src/config.h.in
-src/libsndfile.so*
-src/libsndfile-1.def
-src/sndfile.h
-src/stamp-h1
-src/test_endswap.c
-src/test_main
-src/version-metadata.rc
-tests/*_test
-tests/benchmark
-tests/benchmark.c
-tests/fix_this
-tests/floating_point_test.c
-tests/header_test.c
-tests/libsndfile-1.dll
-tests/pcm_test.c
-tests/pedantic-header-test.sh
-tests/pipe_test.c
-tests/rdwr_test.c
-tests/scale_clip_test.c
-tests/sfversion
-tests/test_wrapper.sh
-tests/utils.c
-tests/utils.h
-tests/write_read_test.c
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644 (file)
index c9cf431..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-language: c
-
-sudo: required
-dist: trusty
-
-before_install:
-  - sudo apt-get update
-  - sudo apt-get install -y libogg-dev libflac-dev libvorbis-dev
-
-script:
-  - ./autogen.sh
-  - ./configure
-  - make distcheck
diff --git a/AUTHORS b/AUTHORS
index b91ec92..9ef64da 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,5 @@
+Original author:
+
 The main author of libsndfile is Erik de Castro Lopo <erikd@mega-nerd.com>
 apart from code in the following directories:
 
@@ -12,6 +14,182 @@ apart from code in the following directories:
    modifications were required to integrate these files into libsndfile. The
    changes are listed in src/G72x/ChangeLog.
 
+Current maintainers:
+
+After the release of version 1.0.30, @erikd transferred the project to
+[the libsndfile team](https://github.com/libsndfile) consisting of:
+
+* Erik de Castro Lopo aka @erikd
+* David Seifert aka @SoapGentoo
+* Arthur Taylor aka @arthurt
+* @evpobr
+
+Current releaser is David Seifert:
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQINBFppABgBEAC42ZiNvV7BTIgR6TQy0YnF54fx3mVRP1u8Mq00UZa7reAsNKh7
+1H60j0W4s6+4pVVIKGfpVGxLwUdJe+KVCYw1Cd3YW6uMf5zZrC/ZWqnJiH/n6S6o
+1l4INII2o6YbGBnzIWBPRo7PlOL+mvgKTLpBSJPnhD8XDGN5wRiV8rL2+6Dptg0F
+nJt7oxECGF3OD3gk6HMel0o82CVkIqMtNaX1L/bhcdF7K0Rp2MXPZMmpn1izW5sI
+asN1G9+w+Zwj7kMJzq1Aw3ac+rsX4SEYdvXjS2QhDHQUIr6LXri3D2WbcEqIZj2R
+JVoVwblsrG11dYXFDBbgrq4NhgTBsxHYDlkr/qF2W+kbPC/nhSqTVZeCYvTBZbOQ
++RqyN/I0izukglnWmV1jGijFA8snyP8efx732hw/24zRYmtXOtnEITUpw8WOeZCq
+6uiHaQ+eopnY2ojBg9BI7WZm0AFn58xxT9soMsyFOUFgXTqaWFZWlJ3fhZE8/0v8
+JEu/kPGE5aJReT3b34B+Bojkj74XR+h2u7iJJBHMTE8RwGoUOZHer/XsL9xlcdks
+I+7TCjiq++ShaSSt2XsJmw2BhREohrjW/2KkwmvT3b44RMpKPB4WTH+++aqJQNeM
+IqmswOMoZvzEZezInj7WVY/r0WEei1Y6wt1tBrJ/cFf1oQBM1UmphxcrfQARAQAB
+tB9EYXZpZCBTZWlmZXJ0IDxzb2FwQGdlbnRvby5vcmc+iQJUBBMBCgA+BQsJCAcD
+BRUKCQgLBRYCAwEAAh4BAheAAhsBFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/V
+CvoFCQkuceIACgkQpHYg6AHkfpXYxA//aiJW1NwunpmzEc62id8lRMnoLHWVjISZ
+b+xSlm+hk4LYq+ZbthJDzKcT86/3DJOSE1zQw9wLuCao9IW2UfFJQBtR+TAfbagG
+0Yyk/kMcLoFJxnG1ywdJWypCAauuIhia52Z7PmmjsBbFwr6LygDwSQmZAyACMAs7
+TLQe+yERc2RNDsIEsquLSxxRF0Spk9gagWtKgrPc2XBjuNtQDwW7JgsOUoEeHyxC
+29fRUjC3o/pG2I6iAZp17OROZI5yl4TSORrSBDGIi2sayxyxP0x+IPKtrCUcBGNx
+wGp+56bP/V0hA6sgCPh/iwvqLoeibso6l/Kd4ltVAEQnHTd6fr8g+wLEUXfbJVTR
+7aeFUoaFmWjSPlQrNr6HlxSLV/kRx9kVJp1Pn16vkfVBF7fG7iDLiqphwEeQg5ND
+nmGeKAbRRNxFHyBHf0XRsaYiFZQckguO+71XSRtVx8/YP5nyNbtl9y1h/4JlT6Gy
+t7hb5twYFQyQrKss83E/Bo1sRdHpj0ibtqb4ZbYANbh482E6yFhAkuo8YjVTJipI
+1Ve8EBKnX3R+pDt147uyysNvtPVXML+sWpGSMVSm4NA8uT3F5nqxVwj+SeXy3Wq/
+CHQ2VBKGBC655G+wFD5C6O7cTx2MwH+2H8tzhWm+gFlI3MFKEXa/PC+YUC/diYcb
+BrApavriTRa5Ag0EWmkAZgEQAPXMD3mZI+ChvBysXZWksC88/uSEwFeb3XkcRm7v
+04GN7hcz+bfrmnUTB3tuE/ZQgv+u7ZjetvH1aEKieznn/GjnWoOBoJusOYvfAQeF
+0mQVi118QiOZRCnEZpkz+RY9TiXVgrZJg+AGqHZ3Ol4GkInEV2NWgH37Xal+HkFl
+rwI2U7mL0kZRG+LAVCQHKzqU0R0HE1XyJ4qf0awtG5Qi/TZvgXBdZPDXgr8i9Vlf
+UUu10c2XnXM0Av/YAlZmBFjVYrSOUCFenqSVqL+s9sTCVdWlJrGjrr3Ja4uT3kl2
+rLva0AR4oSQoxt8adKohmFz0vzOkQtCoRzhrCwoo3JvNjKdSNoOP1nSsxlO5ji8r
+ih5d+ajPgi580XyHLnrvG7vobR48qqscv1hizKuCgTacOTe6Db2Gqc8xF6v8HhJa
+KwWJtmFllIfN/tIvZ6BbbgHQn0IGf4CYnWf0SksPZqpBmTRpD2jfBxcj2UEg+AR3
+LARjuyUVpFJScyu6ExQG+6O+ByLL31iWP5MgUrza1rIpriPa3NT3rZ3DG2pvQrS3
+ySsrPzH7VRX8L1ThSMSzjwF96aMsd14s7XzR4EzNuWwZDukfs0yavZk6l4o1M0mb
+tbJi7hE4cz13KRHYvIkKMdZGYUnzRzZUDlsj2imakk3BR6GXnxZ1ST6062g+QxiL
+AJFLABEBAAGJBHIEGAEKACYCGwIWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9UL
+DQUJCS5xpwJAwXQgBBkBCgAdFiEEuNUxXaAAcsCoYIifzjbhFyAuOEIFAlppAGYA
+CgkQzjbhFyAuOELmrQ/9H9wrWsWa21STZdxUmyU2sh9VXAWEHl1Ey0fVTznDM0Fl
+zx5YSR/TmmnE36rpaz31Ttkx8SP914oV+mMgseecdya9Bf6uZL9Cv7V3KEsJBRL/
+ncrOWQBHP/Xy1X+mLD6A19xq7H4RihSLj0LeK2YVjrJzJ7wMf4mKXuBayQeAHImU
+WRCRTbmK3umh2nB5V0iPd/XZEIiYtiTPe+7E/va6+0bBvOumF3a+Z0iui7eU4hFC
+7Jk71D0dcg09SlIaNoMOrw7cMC3j2pMdKtsj8+0I6WBv14PhhqPAsnjdf7I/4NfK
+L7Jav8T/gDS01uA2Jxm72d+wr+eSjOBXa6x8CEbTqfkjAGxsWENThCp6zDkaXSDd
+JsV0va47vjzG8+wTDAvPy5IxIM/KZZdl4uWM+mF5K+q+eSTOHe7aLF2OdcussoBA
+A18zm994dAkG1COX/qpxanxx2bv/2IvCGPg+x6JtAN8ji2kncWu3dWGQdE5XbVjc
+fDwgsUPpp04G27Mr/x+HpEbgZ5SdA0dAqJktlNvCcHALhlblCWrsh/1QNjT/2iG8
+wsjcpEy/s4tWAuV4PTa4xvZ1JPS7Z7Eo5aBy9ZGOWG9SrHEiHnhkUsiswbHBOEjd
+pBSkmNElDcv9fRUahVCTPfvWBATFDrQyMjJBSm+cV8c/iFQM7isVSu8W7E0eetsJ
+EKR2IOgB5H6Vv9sP/1dxTvH0N0UoEoxIG/hnirEkbRpljdvqy4/uikYBKyQgSbo8
+VITTjea7gIhDztil9WZYt35jbOmoaGM2Z6TP2LEDOWgljYUNq9pl9Sc2GS8cNtEO
+WxExzGOc1Flo730dX3A85Ks3+0WPXZjLDcRRcPVkFd5WLQQDV1YVYopWkuQBC+Br
+4q3uv+sk+bw6gDa9+zFBbDuegdsYuTXrFHoxHz2GRv9Yb7ULCMgpFeNKDgtQq91u
+RqewoTwQp9tlp91LH/hh7R0Q4DRgeFDkLnVRXwSKjVvCrT5cBgImGwtFTGS4egoy
+MDKd/KKjZllp1ahRCln1XfmFQyQVMVvuF/JTtt31n6KwXwK2yxIlXB01xvRH+Ees
+AWeRYWKWXydaAY/9Ve0/PLFlgsr/XUGvt0GoEKe7odD3nZgg6015+/8JTroKw19L
+NZkhdfFMl11Zi0j5k3UbyzjYVpFSd8K2o0VoOG1LFsPp8tlRxNoVzpId0CX1au/p
+y1H7Wy/39mzriRG3rw+mJAQbBjN09putCltXFXpOEWk08n/N3vufCVQUoSu/2Bqw
+2HYj8VtToQp+O5dG3XxvDHINtInP1yr2Wcw2plna0KoXLwv/lZgDm3LN+eCWpG6d
+N/xk25DTSqTHArUQIEkhcHYK6GnyxUcvoKtG88hXtqEPYXiK08FZYAUPTnDYuQIN
+BFppAIkBEADDjvQZUs1NoqJpxkD2QDBudU1DBCaeI1D6CancMtb5FebPUxgFlDMd
+CBGOun48dY5i87gDhT/qS3gP/Mv9rjKJmcG9JHfhpXdW73owxrcsQ96nxxVJNEVl
+UHJw00z8C9eGWqr0SzSoE33K/PkzSkgtsaotF6+3uCerWulweulmGa5dpVfV0mbS
+aVw8VmrhZ5NmCeodyy/lR85rPik5pb32NT6v7xBkgkfS0VYtPB2E5gW1pXX/jEOi
+Mfq9idOEP9lxrNXV9j49Lr0JQCwAcrYbQ2+VPe6eacJEjzJ/6HiUqhPrYdnvydmb
+hU+xmv2NjGp2UnDZDEhzQfwm6fMx+8Nx2uPzCnXQGoyRBwiC/KcdW0F1ZPKdSXqH
+NKoOF62pLvIMSmfI3ZVOrTohArfr1kFEYVDv9Nl7oY+qg2rZEc2srOF74a9Z46bR
+TDPsEQzE2UMCvu3+rofhSD7aRotlKeDCvbe2s0yE4Man457Xc3LXh8Gva8CzCOLE
+2eMhNTsHIZk68WgXp3/uvE4Xy42myrk1AV8XXDdlWgx0Kc/I6tE59O5NVPSfuGvH
+1a15KKx0F6euEnYDKKpQ5PDR6dSn61po0tfbt96m044G/xQFjrfhHei4jji9Ogd9
+vlXVAi2vn3+NCSHFP5l3igLByBHy9iLIdmz7yQuus/1nwRmxOHOf2QARAQABiQI8
+BBgBCgAmAhsMFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/VCxkFCQkucZAACgkQ
+pHYg6AHkfpVPSRAAmheYkYJmtDbkzPBBnj5mbCIQN1/G5PI9eixc/TXWFOXtcjU1
+mJlJpSidHJyLRrx7r0c+N+s8vnY/JuUBsNoMJMER+Mv/CFW4iFi59V534SyAb2S0
+7NINJnFNkXBY62CDz9KsMuv/MdSv2yLhPH2Tfrm/eDRQesj1PanE4U1cgjWyJRc/
+IOlaRHvTasWDLgwbQi8ykt+4xUWzL/YKHzB+KyyzBK7vPBXqySX8ka4BOw7SDwG5
+lX2gtmhk4AGBwVChLXKflqVx1WXj4DPOt0kmOKVnKFyvUijK58M0A2FMgFMXDTIS
+DRtoZPdx/rkODXxgS+W+27NcYAnxJiM0cQqizEnQh7PQ1KzgdChPejYXMKe9lwdn
+ssMUxrBpbuAuagEf+pebNjD2eaNR4p8kfaDdGn53q55ysDvoyxKvnVQGSk1FAR9Q
+s4N5a4f02U7dzlyEhEfIcuUlRCfnlpn4n725YIhHheDig5zKWoEZCkNIfiRcGzDl
+8Drj+tlZiUR+gDkIoWSBaCkKbIQlc8qCYy6Hm7oZBaol6xKlUnTMK2rjK8fR4i8r
+bVDWBAaWj3jcDHJ0Jg3fS/qBpeya/JXMp89TR8NK5Ys7PZpWbor+puXBYyXDAVx3
+rXQ7JBA5klHPxrgjso1S/LqwscKLENtrVjdjhryLBmPifrmofJRnrpiHIEa5Ag0E
+WmkAswEQAL0hKwsRybQzkNGpJP+ElLSwFHd7XQhr+qIwLllpumWtnIK/DHmv8SpW
+FqAYajmRTXipFcBHH25x2jIIliZidn0a9826l+sMzrFadMC6/W4pitP71TeqZzwn
+pAuHs14YL7Wiy0aJQnfbCpRzPq3kYyOXmhmY7lPWO0WdUpR6W8wUbleK5XOVDDRx
+aIC/M3hhDOxZOMzQ+pdn4BaOFQQ0ygsRkqOudbuc0R1giYRt1i6gMeT8gfzL9jlw
+HcJ+aVnxdUQQ4uC47oKo/+lg7qh7LsiW79pQC1Bcdm8lhRmqtxe6ub60ecjax3XU
+1ILIEfIFCv6M7LRUAwz0bqk35spgkJqrGGKkdeWEKAFHg2QWR2F0zy+HdlPLfKxO
+uhaccpwc9EJtf744GS0SXa2AXr32j56n7CFcEjFcIQPBC6OJn6eA3hOVUYGZ7SrT
+4fsmZiFAdGEkvLKFuNhju1Hj2EJQUY1pm4GSBco7BR8x+QqoYrt5clU3WxRMNfTR
+0Rtuzsh4xskXNVMMgvKOahAtxENv2M2Cx6zJPVL5dmaysP7d6QRVeOQA5PwkcZ5Q
+qK6JtDZj2jpaKQH4Za715kiIcdqMDSkwxa6avc0kARHvfFcBR4hwDm1GAlaKG7eH
+8TOGGQIk8x2F3s4l8mTJVLWTP/uJYnkYBdqANYo5t1NIQLvwLFV3ABEBAAGJAjwE
+GAEKACYCGyAWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9ULIwUJCS5xcAAKCRCk
+diDoAeR+leekD/sF7aHH0W35ckWrXZlfSp0qHPWrBUaLBI9OAUHenRhgs4SbK0D4
+wqEiu0C5iDQojpXAeALQ8g/1pUsZ1yuFqYbGYWrHkA0Pm+P3tAGB4LMZ41YfvROP
+uaiW/+IMJbWllgRtaDt8/NtCgs30WI9I+az5M29HcGfvEwEUykrBx3dE9T+1ui3O
+capdd+GMvdAAsX5PyVkjWgZ7GrZeH8mG7UysYfT4qthxEtQfZ/u8ceSduKA46ugh
+C2eafIDNvluqn7BU4oKxME61u6C8BN2yHLI6LV0Tr4z5H8joVbM4BSFMwLVGlsXf
+HhB8kLiErN6bXolxsjARlmYiD9S9H2AcYidr6RYXf2EVFSpBG59xn1WTDN+DsHQf
+7btNPEPl/OPxa3OQjG+xn8USddiP0N0B4xsyzMNCCKDgvXXcIhX55KG9eh3Tc98S
+fEyhxu8ybZBIGmTJysPKxijfvSgQF+RPNTsz9lvXqkoK7RTgeYMschpjJEznCLbt
+M6eTDb5z0G5uLXh6+dYxtDOlPogI5OHd+G51LwCjvrQ+AtIUCgafuemwA9mpFT2b
+svb/qcxSVUb44bVaNHn1JHebX2YbokGtBOm1x2PI5fT8n6YIIYz3jKYOZAYdUT7x
+6qURyNjOfG4aPJIATwuh4GSNuxUG40+yuT+XfQF24mu1esS1J3wzRloJ7w==
+=K3x+
+-----END PGP PUBLIC KEY BLOCK-----
+
+Previous releasers:
+
+Version 1.0.29-1.0.30 - @evpobr.
+
+The public GPG key:
+
+-----BEGIN PGP MESSAGE-----
+
+yMMwAnicrVJ7UFRVHF50SdiJ2AknHmYM19IhFrmPva91hnBKHMkcSyAyY7nn3nN3
+L7AP9qVoO5Lja1YUycgJ4iUFWYluTlE4Oi6PxdhpCkesIWiAQIbXqlSs1Ex1l7H/
+6r/OP2fOd77vm+/3za8nZqVCFVEfk/xkgPyrMiLgO+FUFIze8R5AgEUoR3QHkBK4
+fMFSAdod+hJJQHQIiqEYBzECYByBs4AnGBYDGIYDjqEYHMc4nKB5ntICkQSAxCke
+RTEaJ3AthWJaWccItIhyiAYRJbMB2qw2yeyQbVmA8aKAQxbHCZbXApxhIIqTIiug
+AiZiPA8IUhQZXhYaLfawQg4HODvcKFlkTH7ol+P9C/9/zu1cthMJlJG5NM+RFEUC
+nsIomiJIBhMIUmAwNky0Q5uZM0GZDV1WC7Ahbg0iYy6Jh+FaH/4ZJIfRCf6L7yi3
+hoG9EOgfSvVAMgtyd7LCBW12yWJGdJjM5B1SWItpWQwjtBjOahC4zyrZoF4KM0ia
+YlD5aBCrDbpkSxrwIkpwUO6YIHCUAjwOKEIUBFaAIsWKAJfrF7XyoJAGkIaUPD9g
+aSBwIkUIOIqEhykzWxAdKcfkDLKlXTKYOYfTBhF3l2+PUhGhUjwSuSK8UwpVtPqf
+TTv+gVoRyKt70PuZxj6oi7ZkZP481vcc2vJ6cV774dld3s3n3+3w+cXdW9YaVvc9
+ni8Nv6aOUqx5b/+Lexria1wn7c1DOxVnikYSV50eY0o7Lwatz3qqg6RHWVOVF3zm
+lai7u7ud7r7vh5Lrm+95j06OeWN+29SbkNVeW9X1Vs651NsF9K1jV7xzkRdz6N4f
+Vy+5B37qTr18Lclk9lx7o3cmP/+6Jbbl3qvj7w/PvTnVDyYiuxtSZlvtCZ2JT6yv
+21rw8tLXnDHhwv0/7kfnpgSNXxKLA/tyPRsunLxp8tw4e6zx6PGbwsxKsTopg9u1
+dkdzBxWf+VVb/tbUzZNtUzUpj0l1fiSUtu1UaHxwdOnj2JlI4fdfdyAh/5GqvbY5
+7YKy0hgabi89Ffen+qUNtZ+f90258OevKhf6S+p+qelSRh/64ZOihg87D857slVZ
+5wqttfExWb7LymH/oVjTpcWFt4u/uP3pC8YrwfY+ad2NpDuW5oqPZrKOFCoGzqgb
+t1jSF1Vph1c0qtZUds+PaAqpp/Mqhjo0yavKiid91emBiPaeb3s2uW8d9J6YXZiu
+T8p7tK+8yHp3ov4dcCk3lNY28s13ZePrW8ceVGc3zOT01/ibotLjdFZn9tmd67a3
+iCrDaJM7Y/9TY8XzHdPbTZ2wPG7bxFBg2LSx6WootqI1dF2fGutPzE0bzJzW/w3x
+usYz
+=XFTp
+-----END PGP MESSAGE-----
+
+Versions before 1.0.29 - Erik de Castro Lopo.
+
+The public GPG key:
+
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCAAdFiEEapGlzyLCTJmjXgE/z9z5H7JCrO0FAljgv0wACgkQz9z5H7JC
+rO2RhxAAnIuHquhkhaY8CVsIOGImMxEF8RKDyFoioV9RnckNzBb592EYxU9hS0MM
+cT6xPZU0bJa8CvmCxEABMlkk60JP4VmmOtWxD8EEyktbHGyao80mDR82yVKYv78L
+zTRzz/JoTncgwWz/QataMbkAfy3KpxkwDW87az0kzkqGuSm3Jg3medt+t/iBe0Wm
+jcxIexxEZCmIhty6VyaVEkGWax0zdJHe7aD9FK2C/R3DU5Byp4e9pcp/a8v74G1n
+dgD4S3YlqvJGuU9S6QD4PzsoWD1X8f6pHzxpRP/OkqHAe11sSRo6sSYYCjsYi9Ca
+IJSlVC1nMx9OUxxAA8ZqtnztOo7GZcJ5NAL5X3GNV6YfQ7Bqxvtr6QG26F06MB6i
+p08UC7NC0bxFsD3f07wY22QnbnM052rniTn5sqQZv+GVls6t1b3u1iHzEjAjlgvi
+eOjVVt/A8iaOzMbKC/3+SZ9/GYqbSAQOCIoWAXmhV9IaMQyQeLCIC1YD5NMGBXal
+HPfSHV0hSUDbKjAYXFigJRzFU125bXTgg+v13Kd0KklIEjoaZYZLAYs0BupXdjBf
+jSPv8pwUaXJkv9/bGH0Ot1fvwDqPDOlGFINQbGAWdxwsdhiYBeXMFeFNTEfiqEMz
+BhhMxKa+Mfd9fkrX4NNigGW5QgRBS+FHNLf6ZfiXSnBGjjxMcbI=
+=UUA0
+-----END PGP SIGNATURE-----
 
 Others:
 
diff --git a/CMake/autogen.cmake b/CMake/autogen.cmake
deleted file mode 100644 (file)
index 9d06f92..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-function (lsf_autogen dir basefilename)
-       # Only generate the file if it does not already exist.
-       if (NOT (EXISTS "${CMAKE_SOURCE_DIR}/${dir}/${basefilename}.c"))
-
-               # If it doesn't exist, but we don't have autogen its an error.
-               if (NOT AUTOGEN)
-                       message (FATAL_ERROR "Need GNU autogen to generate '${dir}/${basefilename}.c'.")
-                       endif ()
-
-               execute_process (
-                               COMMAND ${AUTOGEN} --writable ${basefilename}.def
-                               WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${dir}
-                               )
-               endif ()
-
-       endfunction ()
diff --git a/CMake/build.cmake b/CMake/build.cmake
deleted file mode 100644 (file)
index ae1d663..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-# Build recipe for building programs in the programs/ directory.
-function (lsf_build_program prog_name)
-       add_executable (${prog_name}
-               programs/common.c
-               programs/${prog_name}.c
-               )
-       target_link_libraries (${prog_name} sndfile)
-       set_target_properties (${prog_name}
-               PROPERTIES
-               RUNTIME_OUTPUT_DIRECTORY programs
-               )
-       endfunction ()
-
-function (lsf_build_program_extra prog_name extra_libs)
-       add_executable (${prog_name}
-               programs/common.c
-               programs/${prog_name}.c
-               )
-       target_link_libraries (${prog_name} sndfile ${extra_libs})
-       set_target_properties (${prog_name}
-               PROPERTIES
-               RUNTIME_OUTPUT_DIRECTORY programs
-               )
-       endfunction ()
-
-# Build recipe for building C tests in the src/ directory.
-function (lsf_build_src_test_c test_name extra_files)
-       add_executable (${test_name}
-               src/${test_name}.c
-               ${extra_files}
-               )
-       target_link_libraries (${test_name} m)
-       set_target_properties (${test_name}
-               PROPERTIES
-               EXCLUDE_FROM_DEFAULT_BUILD TRUE
-               EXCLUDE_FROM_ALL TRUE
-               RUNTIME_OUTPUT_DIRECTORY src
-               )
-       add_dependencies (check ${test_name})
-       endfunction ()
-
-# Build recipe for building C tests in the tests/ directory.
-function (lsf_build_test_c test_name extra_files)
-       add_executable (${test_name}
-               tests/${test_name}.c
-               tests/utils.c
-               ${extra_files}
-               )
-       target_link_libraries (${test_name} sndfile)
-       set_target_properties (${test_name}
-               PROPERTIES
-               EXCLUDE_FROM_DEFAULT_BUILD TRUE
-               EXCLUDE_FROM_ALL TRUE
-               RUNTIME_OUTPUT_DIRECTORY tests
-               )
-       add_dependencies (check ${test_name})
-       endfunction ()
-
-# Build recipe for building C++ tests in the tests/ directory.
-function (lsf_build_test_cc test_name)
-       add_executable (${test_name}
-               tests/utils.c
-               tests/${test_name}.cc
-               )
-       target_link_libraries (${test_name} sndfile)
-       set_target_properties (${test_name}
-               PROPERTIES
-               EXCLUDE_FROM_DEFAULT_BUILD TRUE
-               EXCLUDE_FROM_ALL TRUE
-               RUNTIME_OUTPUT_DIRECTORY tests
-               )
-       add_dependencies (check ${test_name})
-       endfunction ()
diff --git a/CMake/check.cmake b/CMake/check.cmake
deleted file mode 100644 (file)
index ba5d1ab..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-include (CheckFunctionExists)
-include (CheckIncludeFile)
-include (CheckLibraryExists)
-include (CheckTypeSize)
-include (TestBigEndian)
-
-function (lsf_try_compile_c_result c_file result_name result_pass result_fail)
-       try_compile (compile_result
-               ${CMAKE_BINARY_DIR}
-               ${CMAKE_CURRENT_SOURCE_DIR}/${c_file}
-               OUTPUT_VARIABLE LOG2
-               )
-
-    if (${compile_result})
-               set (${result_name} ${result_pass} PARENT_SCOPE)
-       else (${compile_result})
-               set (${result_name} ${result_fail} PARENT_SCOPE)
-               endif (${compile_result})
-
-       endfunction ()
-
-function (lsf_check_include_file header_name result_name)
-       check_include_file (${header_name} header_${result_name})
-
-    if (header_${result_name})
-               set (${result_name} 1 PARENT_SCOPE)
-       else (header_${result_name})
-               set (${result_name} 0 PARENT_SCOPE)
-               endif (header_${result_name})
-
-       unset (header_${result_name})
-       endfunction ()
-
-function (lsf_check_type_size type_name result_size)
-       string (REPLACE "*" "_P"  tmp1 ${type_name})
-       string (REPLACE " " "_"  tmp2 ${tmp1})
-
-       check_type_size (${type_name} size_${tmp2})
-
-    if (size_${type_name})
-               set (${result_size} ${size_${type_name}} PARENT_SCOPE)
-       else (size_${type_name})
-               set (${result_size} 0 PARENT_SCOPE)
-               endif (size_${type_name})
-
-       unset (tmp1)
-       unset (tmp2)
-       unset (size_${tmp2})
-       endfunction ()
-
-function (lsf_check_function_exists func_name result_name)
-       check_function_exists (${func_name} func_${result_name})
-
-    if (func_${result_name})
-               set (${result_name} 1 PARENT_SCOPE)
-       else (func_${result_name})
-               set (${result_name} 0 PARENT_SCOPE)
-               endif (func_${result_name})
-
-       unset (func_${result_name})
-       endfunction ()
-
-# Unix does not link libm by default while windows does. We therefore have
-# a special function for testing math functions.
-function (lsf_check_math_function_exists func_name result_name)
-       if (${UNIX})
-               check_library_exists (m ${func_name} "" func_${result_name})
-       else (${UNIX})
-               check_function_exists (${func_name} func_${result_name})
-               endif (${UNIX})
-
-    if (func_${result_name})
-               set (${result_name} 1 PARENT_SCOPE)
-       else (func_${result_name})
-               set (${result_name} 0 PARENT_SCOPE)
-               endif (func_${result_name})
-
-       unset (func_${result_name})
-       endfunction ()
-
-function (lsf_check_library_exists lib_name lib_func location result_name)
-       check_library_exists (${lib_name} ${lib_func} "${location}" lib_${result_name})
-
-    if (lib_${result_name})
-               set (${result_name} 1 PARENT_SCOPE)
-       else (lib_${result_name})
-               set (${result_name} 0 PARENT_SCOPE)
-               endif (lib_${result_name})
-
-       unset (lib_${result_name})
-       endfunction ()
-
diff --git a/CMake/compiler_is_gcc.c b/CMake/compiler_is_gcc.c
deleted file mode 100644 (file)
index 784c884..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-int main (void)
-{
-#if __GNUC__
-       #if __clang__
-               This is clang
-#      endif
-#else
-       This is not GCC.
-#endif
-       return 0 ;
-}
diff --git a/CMake/external_libs.cmake b/CMake/external_libs.cmake
deleted file mode 100644 (file)
index 665a777..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-
-find_package (PkgConfig)
-include (FindPackageHandleStandardArgs)
-
-function (find_libogg return_name)
-       pkg_check_modules (PC_LIBOGG QUIET libogg)
-       set (LIBOGG_DEFINITIONS ${PC_LIBOGG_CFLAGS_OTHER})
-
-       find_path (LIBOGG_INCLUDE_DIR ogg/ogg.h
-                               HINTS ${PC_LIBOGG_INCLUDEDIR} ${PC_LIBOGG_INCLUDE_DIRS}
-                               PATH_SUFFIXES libogg)
-
-       find_library (LIBOGG_LIBRARY NAMES ogg libogg
-                                       HINTS ${PC_LIBOGG_LIBDIR} ${PC_LIBOGG_LIBRARY_DIRS})
-
-       find_package_handle_standard_args (LibOgg  DEFAULT_MSG
-                                                                               LIBOGG_LIBRARY LIBOGG_INCLUDE_DIR)
-
-       mark_as_advanced (LIBOGG_INCLUDE_DIR LIBOGG_LIBRARY)
-
-       set (LIBOGG_LIBRARIES ${LIBOGG_LIBRARY} PARENT_SCOPE)
-       set (LIBOGG_INCLUDE_DIRS ${LIBOGG_INCLUDE_DIR} PARENT_SCOPE)
-       set (${return_name} ${LIBOGG_FOUND} PARENT_SCOPE)
-       endfunction (find_libogg)
-
-
-function (find_libvorbis return_name)
-       pkg_check_modules (PC_LIBVORBIS QUIET libvorbis)
-       set (LIBVORBIS_DEFINITIONS ${PC_LIBVORBIS_CFLAGS_OTHER})
-
-       find_path (LIBVORBIS_INCLUDE_DIR vorbis/codec.h
-                               HINTS ${PC_LIBVORBIS_INCLUDEDIR} ${PC_LIBVORBIS_INCLUDE_DIRS}
-                               PATH_SUFFIXES libvorbis)
-
-       find_library (LIBVORBIS_LIBRARY NAMES vorbis libvorbis
-                                       HINTS ${PC_LIBVORBIS_LIBDIR} ${PC_LIBVORBIS_LIBRARY_DIRS})
-
-       find_package_handle_standard_args (LibVorbis  DEFAULT_MSG
-                                                                               LIBVORBIS_LIBRARY LIBVORBIS_INCLUDE_DIR)
-
-       mark_as_advanced (LIBVORBIS_INCLUDE_DIR LIBVORBIS_LIBRARY)
-
-       set (LIBVORBIS_LIBRARIES ${LIBVORBIS_LIBRARY} PARENT_SCOPE)
-       set (LIBVORBIS_INCLUDE_DIRS ${LIBVORBIS_INCLUDE_DIR} PARENT_SCOPE)
-       set (${return_name} ${LIBVORBIS_FOUND} PARENT_SCOPE)
-       endfunction (find_libvorbis)
-
-
-function (find_libflac return_name)
-       pkg_check_modules (PC_LIBFLAC QUIET libFLAC)
-       set (LIBFLAC_DEFINITIONS ${PC_LIBFLAC_CFLAGS_OTHER})
-
-       find_path (LIBFLAC_INCLUDE_DIR FLAC/all.h
-                               HINTS ${PC_LIBFLAC_INCLUDEDIR} ${PC_LIBFLAC_INCLUDE_DIRS}
-                               PATH_SUFFIXES libFLAC)
-
-       find_library (LIBFLAC_LIBRARY NAMES FLAC libFLAC
-                                       HINTS ${PC_LIBFLAC_LIBDIR} ${PC_LIBFLAC_LIBRARY_DIRS})
-
-       find_package_handle_standard_args (LibFlac  DEFAULT_MSG
-                                                                               LIBFLAC_LIBRARY LIBFLAC_INCLUDE_DIR)
-
-       mark_as_advanced (LIBFLAC_INCLUDE_DIR LIBFLAC_LIBRARY)
-
-       set (LIBFLAC_LIBRARIES ${LIBFLAC_LIBRARY} PARENT_SCOPE)
-       set (LIBFLAC_INCLUDE_DIRS ${LIBFLAC_INCLUDE_DIR} PARENT_SCOPE)
-       set (${return_name} ${LIBFLAC_FOUND} PARENT_SCOPE)
-       endfunction (find_libflac)
-
-
-function (find_external_xiph_libs return_name include_dirs external_libs)
-       find_libogg (LIBOGG_FOUND)
-       find_libvorbis (LIBVORBIS_FOUND)
-       find_libflac (LIBFLAC_FOUND)
-
-       set (name 1)
-       set (includes "")
-       set (libs "")
-
-       if (LIBOGG_FOUND AND LIBVORBIS_FOUND AND LIBFLAC_FOUND)
-               set (${name} 1)
-
-               if (NOT (LIBOGG_INCLUDE_DIR STREQUAL "/usr/include"))
-                       set (${includes} "${includes} ${LIBOGG_INCLUDE_DIR}")
-                       endif ()
-               if (NOT (LIBVORBIS_INCLUDE_DIR STREQUAL "/usr/include"))
-                       set (${includes} "${includes} ${LIBVORBIS_INCLUDE_DIR}")
-                       endif ()
-               if (NOT (LIBFLAC_INCLUDE_DIR STREQUAL "/usr/include"))
-                       set (${includes} "${includes} ${LIBFLAC_INCLUDE_DIR}")
-                       endif ()
-
-               set (libs "FLAC;vorbis;vorbisenc;ogg")
-               endif ()
-
-       set (${return_name} ${name} PARENT_SCOPE)
-       set (${include_dirs} "${includes}" PARENT_SCOPE)
-       set (${external_libs} "${libs}" PARENT_SCOPE)
-       endfunction (find_external_xiph_libs)
diff --git a/CMake/file.cmake b/CMake/file.cmake
deleted file mode 100644 (file)
index b9c8cf9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-
-function (file_line_count filename variable)
-       # Assume `find_progam (WC wc)` has already set this.
-       if (NOT WC)
-               message (FATAL_ERROR "Need the 'wc' program to find line coount.")
-               endif ()
-
-       if (NOT SED)
-               message (FATAL_ERROR "Need the 'sed' program to find line coount.")
-               endif ()
-
-       if (NOT (EXISTS "${filename}"))
-               message (FATAL_ERROR "File ${filename} does not exist.")
-               endif ()
-
-       execute_process (
-               COMMAND ${WC} -l ${filename}
-               COMMAND ${SED} "s/^[ ]*//"    # wc output on Mac has leading whitespace.
-               COMMAND ${SED} "s/ .*//"
-               OUTPUT_VARIABLE line_count
-               )
-
-       # Tedious!
-       string (STRIP ${line_count} line_count)
-
-       set (${variable} ${line_count} PARENT_SCOPE)
-       endfunction ()
-
-function (assert_line_count_non_zero filename)
-
-       file_line_count (${filename} line_count)
-
-       if (${line_count} LESS 1)
-               message (FATAL_ERROR "Line count of ${filename} is ${line_count}, which is less than expected.")
-               endif ()
-
-       endfunction ()
diff --git a/CMake/have_decl_s_irgrp.c b/CMake/have_decl_s_irgrp.c
deleted file mode 100644 (file)
index 854a460..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <sys/stat.h>
-int main (void)
-{
-       /* This will fail to compile if S_IRGRP doesn't exist. */
-       return S_IRGRP ;
-}
diff --git a/CMake/libsndfile.cmake b/CMake/libsndfile.cmake
deleted file mode 100644 (file)
index 080150d..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-
-include (CMake/check.cmake)
-
-lsf_check_include_file (alsa/asoundlib.h       HAVE_ALSA_ASOUNDLIB_H)
-lsf_check_include_file (byteswap.h                     HAVE_BYTESWAP_H)
-lsf_check_include_file (dlfcn.h                                HAVE_DLFCN_H)
-lsf_check_include_file (endian.h                       HAVE_ENDIAN_H)
-lsf_check_include_file (inttypes.h                     HAVE_INTTYPES_H)
-lsf_check_include_file (locale.h                       HAVE_LOCALE_H)
-lsf_check_include_file (memory.h                       HAVE_MEMORY_H)
-lsf_check_include_file (sndio.h                                HAVE_SNDIO_H)
-lsf_check_include_file (stdint.h                       HAVE_STDINT_H)
-lsf_check_include_file (stdlib.h                       HAVE_STDLIB_H)
-lsf_check_include_file (string.h                       HAVE_STRING_H)
-lsf_check_include_file (strings.h                      HAVE_STRINGS_H)
-lsf_check_include_file (sys/stat.h                     HAVE_SYS_STAT_H)
-lsf_check_include_file (sys/time.h                     HAVE_SYS_TIME_H)
-lsf_check_include_file (sys/types.h                    HAVE_SYS_TYPES_H)
-lsf_check_include_file (sys/wait.h                     HAVE_SYS_WAIT_H)
-lsf_check_include_file (unistd.h                       HAVE_UNISTD_H)
-
-
-lsf_check_type_size (double            SIZEOF_DOUBLE)
-lsf_check_type_size (float                     SIZEOF_FLOAT)
-lsf_check_type_size (int                       SIZEOF_INT)
-lsf_check_type_size (int64_t           SIZEOF_INT64_T)
-lsf_check_type_size (loff_t            SIZEOF_LOFF_T)
-lsf_check_type_size (long                      SIZEOF_LONG)
-lsf_check_type_size (long\ long        SIZEOF_LONG_LONG)
-lsf_check_type_size (offt64_t          SIZEOF_OFF64_T)
-lsf_check_type_size (off_t                     SIZEOF_OFF_T)
-lsf_check_type_size (short                     SIZEOF_SHORT)
-lsf_check_type_size (size_t            SIZEOF_SIZE_T)
-lsf_check_type_size (ssize_t           SIZEOF_SSIZE_T)
-lsf_check_type_size (void*                     SIZEOF_VOIDP)
-lsf_check_type_size (wchar_t           SIZEOF_WCHAR_T)
-
-set (SIZEOF_SF_COUNT_T ${SIZEOF_INT64_T})
-set (TYPEOF_SF_COUNT_T int64_t)
-set (SF_COUNT_MAX 0x7fffffffffffffffll)
-
-# Can't figure out how to make CMAKE_COMPILER_IS_GNUCC set something to either
-# 1 or 0 so we do this:
-lsf_try_compile_c_result (CMake/compiler_is_gcc.c COMPILER_IS_GCC 1 0)
-
-lsf_try_compile_c_result (CMake/have_decl_s_irgrp.c HAVE_DECL_S_IRGRP 1 0)
-
-TEST_BIG_ENDIAN (BIGENDIAN)
-if (${BIGENDIAN})
-       set (WORDS_BIGENDIAN 1)
-       set (CPU_IS_BIG_ENDIAN 1)
-       set (CPU_IS_LITTLE_ENDIAN 0)
-else (${BIGENDIAN})
-       set (WORDS_BIGENDIAN 0)
-       set (CPU_IS_LITTLE_ENDIAN 1)
-       set (CPU_IS_BIG_ENDIAN 0)
-       endif (${BIGENDIAN})
-
-if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
-       set (OS_IS_WIN32 1)
-       set (USE_WINDOWS_API 1)
-       set (USE_WINDOWS_API 1)
-       set (WIN32_TARGET_DLL 1)
-       set (__USE_MINGW_ANSI_STDIO 1)
-else (${WINDOWS})
-       set (OS_IS_WIN32 0)
-       set (USE_WINDOWS_API 0)
-       set (USE_WINDOWS_API 0)
-       set (WIN32_TARGET_DLL 0)
-       set (__USE_MINGW_ANSI_STDIO 0)
-       endif ()
-
-if (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
-       set (OS_IS_OPENBSD 1)
-else ()
-       set (OS_IS_OPENBSD 0)
-       endif ()
-
-lsf_check_library_exists (m floor "" HAVE_LIBM)
-lsf_check_library_exists (sqlite3 sqlite3_close "" HAVE_SQLITE3)
-
-lsf_check_function_exists (calloc              HAVE_CALLOC)
-lsf_check_function_exists (free                        HAVE_FREE)
-lsf_check_function_exists (fstat               HAVE_FSTAT)
-lsf_check_function_exists (fstat64             HAVE_FSTAT64)
-lsf_check_function_exists (fsync               HAVE_FSYNC)
-lsf_check_function_exists (ftruncate   HAVE_FTRUNCATE)
-lsf_check_function_exists (getpagesize HAVE_GETPAGESIZE)
-lsf_check_function_exists (gettimeofday        HAVE_GETTIMEOFDAY)
-lsf_check_function_exists (gmtime              HAVE_GMTIME)
-lsf_check_function_exists (gmtime_r            HAVE_GMTIME_R)
-lsf_check_function_exists (localtime   HAVE_LOCALTIME)
-lsf_check_function_exists (localtime_r HAVE_LOCALTIME_R)
-lsf_check_function_exists (lseek               HAVE_LSEEK)
-lsf_check_function_exists (lseek64             HAVE_LSEEK64)
-lsf_check_function_exists (malloc              HAVE_MALLOC)
-lsf_check_function_exists (mmap                        HAVE_MMAP)
-lsf_check_function_exists (open                        HAVE_OPEN)
-lsf_check_function_exists (pipe                        HAVE_PIPE)
-lsf_check_function_exists (read                        HAVE_READ)
-lsf_check_function_exists (realloc             HAVE_REALLOC)
-lsf_check_function_exists (setlocale   HAVE_SETLOCALE)
-lsf_check_function_exists (snprintf            HAVE_SNPRINTF)
-lsf_check_function_exists (vsnprintf   HAVE_VSNPRINTF)
-lsf_check_function_exists (waitpid             HAVE_WAITPID)
-lsf_check_function_exists (write               HAVE_WRITE)
-
-lsf_check_math_function_exists (ceil   HAVE_CEIL)
-lsf_check_math_function_exists (floor  HAVE_FLOOR)
-lsf_check_math_function_exists (fmod   HAVE_FMOD)
-lsf_check_math_function_exists (lrint  HAVE_LRINT)
-lsf_check_math_function_exists (lrintf HAVE_LRINTF)
-lsf_check_math_function_exists (lround HAVE_LROUND)
index 590429b..de98145 100644 (file)
-# CMakeLists.txt for libsndfile
+cmake_minimum_required (VERSION 3.1..3.18)
 
-cmake_minimum_required (VERSION 3.0.0)
+# MSVC runtime library flags are selected by an abstraction, CMake >= 3.15
+# This policy still need to be set even with cmake_minimum_required() command above.
+if (POLICY CMP0091)
+       if ((DEFINED ENABLE_STATIC_RUNTIME) AND (DEFINED CMAKE_MSVC_RUNTIME_LIBRARY))
+               message (FATAL_ERROR "Both ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY are set.")
+               return ()
+       endif ()
 
-project (libsndfile)
+       if (DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
+               cmake_policy (SET CMP0091 NEW)
+       else ()
+               cmake_policy (SET CMP0091 OLD)
+       endif ()
+endif ()
 
-# We may need these programs so detect them now.
-find_program (AUTOGEN autogen)
-find_program (AUTOHEADER autoheader)
-find_program (GREP grep)
-find_program (SED sed)
-find_program (WC wc)
+project(libsndfile VERSION 1.0.31)
 
-include (CMake/file.cmake)
+#
+# Variables
+#
 
-# Duplicate the autoconf/autoheader functionality.
+set (CMAKE_C_STANDARD 99)
+set (CMAKE_C_STANDARD_REQUIRED TRUE)
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
-# Get the version number from configure.ac.
-execute_process (
-       COMMAND ${GREP} ^AC_INIT configure.ac
-       COMMAND ${SED} "s/.*libsndfile[^0-9]*//;s/\\].*//"
-       OUTPUT_VARIABLE LIB_VERSION
-       )
+set (PACKAGE_NAME ${PROJECT_NAME})
+set (CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
+set (CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
+set (CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
+set (CPACK_PACKAGE_VERSION_STAGE "")
+set (CPACK_PACKAGE_VERSION_FULL "${PROJECT_VERSION}${CPACK_PACKAGE_VERSION_STAGE}")
 
-string (STRIP ${LIB_VERSION} LIB_VERSION)
-string (REGEX REPLACE "\\..*" "" LIB_VERSION_MAJOR ${LIB_VERSION})
+#
+# System-wide includes
+#
 
-message (STATUS "libsndfile version : ${LIB_VERSION}")
+include (GNUInstallDirs)
+include (FeatureSummary)
+include (CMakeDependentOption)
+include (CTest)
+include (CheckCCompilerFlag)
 
-# Generate config.h.in if it does not already exist.
-if (NOT (EXISTS "${CMAKE_SOURCE_DIR}/CMakeFiles/config.h.in"))
-       if (NOT AUTOHEADER)
-               message (FATAL_ERROR "Need autoheader (part of GNU autoconf) to proceed.")
-               endif ()
+#
+# Options
+#
 
-       message (STATUS "Running autoheader to create src/config.h.in")
-       execute_process (COMMAND ${AUTOHEADER} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+option (BUILD_SHARED_LIBS "Build shared libraries" OFF)
+if (BUILD_SHARED_LIBS AND BUILD_TESTING)
+       set (BUILD_TESTING OFF)
+       message ("Build testing required static libraries. To prevent build errors BUILD_TESTING disabled.")
+endif ()
+option (BUILD_PROGRAMS "Build programs" ON)
+option (BUILD_EXAMPLES "Build examples" ON)
+option (ENABLE_CPACK "Enable CPack support" ON)
+option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF)
+option (ENABLE_BOW_DOCS "Enable black-on-white html docs" OFF)
+if (MSVC AND (DEFINED ENABLE_STATIC_RUNTIME))
+       option (ENABLE_STATIC_RUNTIME "Enable static runtime" ${ENABLE_STATIC_RUNTIME})
+elseif (MINGW)
+       option (ENABLE_STATIC_RUNTIME "Enable static runtime" OFF)
+endif ()
+option (ENABLE_PACKAGE_CONFIG "Generate and install package config file" ON)
+option (INSTALL_PKGCONFIG_MODULE "Generate and install pkg-config module" ON)
 
-       assert_line_count_non_zero ("${CMAKE_SOURCE_DIR}/src/config.h.in")
+list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+if (CMAKE_VERSION VERSION_LESS 3.14)
+       list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/sqlite")
+endif ()
 
-       message (STATUS "Post processing src/config.h.in")
-       execute_process (
-               COMMAND ${SED} -E "s/undef([ \\t]+)([a-zA-Z0-8_]+)/define\\1\\2\\1@\\2@/" src/config.h.in
-               COMMAND ${SED} "s/.*_FILE_OFFSET_BITS.*//"
-               OUTPUT_FILE ${CMAKE_SOURCE_DIR}/CMakeFiles/config.h.in
-               WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-               )
+#
+# Setup definitions
+#
 
-       execute_process (
-               COMMAND ${GREP} -c undef ${CMAKE_SOURCE_DIR}/CMakeFiles/config.h.in
-               OUTPUT_VARIABLE undef_count
-               )
+include(SndFileChecks)
 
-       if (${undef_count} GREATER 0)
-               message (FATAL_ERROR "CMake processing of CMakeFIles/config.h.in has failed.")
-               endif ()
-       endif ()
 
-assert_line_count_non_zero ("${CMAKE_SOURCE_DIR}/CMakeFiles/config.h.in")
-
-# Use autogen to generate files if they don't already exist.
-include (CMake/autogen.cmake)
-lsf_autogen (src test_endswap)
-lsf_autogen (tests pcm_test)
-lsf_autogen (tests utils)
-lsf_autogen (tests floating_point_test)
-lsf_autogen (tests header_test)
-lsf_autogen (tests pipe_test)
-lsf_autogen (tests write_read_test)
-lsf_autogen (tests scale_clip_test)
-lsf_autogen (tests rdwr_test)
-lsf_autogen (tests benchmark)
-
-if (DEFINED ENV{CC})
-       set (CMAKE_C_COMPILER $ENV{CC})
-       endif()
+cmake_dependent_option (BUILD_REGTEST "Build regtest" ON "SQLITE3_FOUND" OFF)
+cmake_dependent_option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON "Vorbis_FOUND;FLAC_FOUND;OPUS_FOUND" OFF)
+cmake_dependent_option (ENABLE_CPU_CLIP "Enable tricky cpu specific clipper" ON "CPU_CLIPS_POSITIVE;CPU_CLIPS_NEGATIVE" OFF)
+if (NOT ENABLE_CPU_CLIP)
+       set (CPU_CLIPS_POSITIVE FALSE)
+       set (CPU_CLIPS_NEGATIVE FALSE)
+endif ()
+cmake_dependent_option (ENABLE_COMPATIBLE_LIBSNDFILE_NAME "Set DLL name to libsndfile-1.dll (canonical name), sndfile.dll otherwise" OFF "WIN32;BUILD_SHARED_LIBS" OFF)
+cmake_dependent_option (INSTALL_MANPAGES "Install man pages for programs" ON "BUILD_PROGRAMS" OFF)
 
-if (DEFINED ENV{CXX})
-       set (CMAKE_CXX_COMPILER $ENV{CXX})
-       endif()
+if (NOT MSVC)
+       if (CPU_IS_X86)
+               check_c_compiler_flag (-msse2 HAVE_MSSE2_COMPILER_FLAG)
+               if (HAVE_MSSE2_COMPILER_FLAG)
+                       cmake_dependent_option (ENABLE_SSE2 "Add SSE2 compiler flag" ON "HAVE_MSSE2_COMPILER_FLAG" OFF)
+               endif ()
+       endif ()
+endif ()
+if (ENABLE_SSE2)
+       add_compile_options (-msse2)
+endif ()
 
-message (STATUS "System       : ${CMAKE_SYSTEM_NAME}")
-message (STATUS "Processor    : ${CMAKE_SYSTEM_PROCESSOR}")
-message (STATUS "C compiler   : ${CMAKE_C_COMPILER_ID}")
-message (STATUS "C++ compiler : ${CMAKE_CXX_COMPILER_ID}")
+set (HAVE_EXTERNAL_XIPH_LIBS ${ENABLE_EXTERNAL_LIBS})
+set (HAVE_SQLITE3 ${BUILD_REGTEST})
+set (HAVE_ALSA_ASOUNDLIB_H ${ALSA_FOUND})
+set (HAVE_SNDIO_H ${SNDIO_FOUND})
 
-#-------------------------------------------------------------------------------
+set (ENABLE_EXPERIMENTAL_CODE ${ENABLE_EXPERIMENTAL})
+set (HAVE_SPEEX ${ENABLE_EXPERIMENTAL})
+set (HAVE_OPUS ${ENABLE_EXPERIMENTAL})
 
-set (PACKAGE \"libsndfile\")
-set (PACKAGE_NAME \"libsndfile\")
-set (VERSION \"${LIB_VERSION}\")
-set (PACKAGE_VERSION \"${LIB_VERSION}\")
+add_feature_info (BUILD_SHARED_LIBS BUILD_SHARED_LIBS "build shared libraries")
+add_feature_info (ENABLE_EXTERNAL_LIBS ENABLE_EXTERNAL_LIBS "enable FLAC, Vorbis, and Opus codecs")
+add_feature_info (ENABLE_EXPERIMENTAL ENABLE_EXPERIMENTAL "enable experimental code")
+add_feature_info (BUILD_TESTING BUILD_TESTING "build tests")
+add_feature_info (BUILD_REGTEST BUILD_REGTEST "build regtest")
+add_feature_info (ENABLE_CPACK ENABLE_CPACK "enable CPack support")
+add_feature_info (ENABLE_CPU_CLIP ENABLE_CPU_CLIP "Enable tricky cpu specific clipper")
+add_feature_info (ENABLE_BOW_DOCS ENABLE_BOW_DOCS "enable black-on-white html docs")
+add_feature_info (ENABLE_PACKAGE_CONFIG ENABLE_PACKAGE_CONFIG "generate and install package config file")
+add_feature_info (INSTALL_PKGCONFIG_MODULE INSTALL_PKGCONFIG_MODULE "generate and install pkg-config module")
+add_feature_info (INSTALL_MANPAGES INSTALL_MANPAGES "install man pages for programs")
+if (WIN32 AND BUILD_SHARED_LIBS)
+       add_feature_info (ENABLE_COMPATIBLE_LIBSNDFILE_NAME ENABLE_COMPATIBLE_LIBSNDFILE_NAME "Set DLL name to libsndfile-1.dll (canonical name), sndfile.dll otherwise")
+endif ()
 
-set (BASEPATH "${CMAKE_SOURCE_DIR}")
+if (HAVE_MSSE2_COMPILER_FLAG)
+       add_feature_info (ENABLE_SSE2 ENABLE_SSE2 "add SSE2 compiler flag")
+endif ()
 
-include (CMake/build.cmake)
-include (CMake/external_libs.cmake)
-include (CMake/libsndfile.cmake)
 
-if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
-       set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=gnu99 -Wall -Wextra" CACHE STRING "" FORCE)
-       set (CMAKE_CXX__FLAGS "${CMAKE_C_FLAGS} -O3 -std=gnu99 -Wall -Wextra" CACHE STRING "" FORCE)
 
-       set (COMPILER_IS_GCC 1)
-       set (_POSIX_SOURCE 1)
 
-       if (${Werror} MATCHES "on")
-               set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror" CACHE STRING "" FORCE)
-               endif ()
-       endif ()
+set_package_properties (Ogg PROPERTIES
+       TYPE RECOMMENDED
+       URL "www.xiph.org/ogg/"
+       DESCRIPTION "library for manipulating ogg bitstreams"
+       PURPOSE "Required to enable Vorbis, Speex, and Opus support"
+       )
+set_package_properties (Vorbis PROPERTIES
+       TYPE RECOMMENDED
+       URL "www.vorbis.com/"
+       DESCRIPTION "open source lossy audio codec"
+       PURPOSE "Enables Vorbis support"
+       )
+set_package_properties (FLAC PROPERTIES
+       TYPE RECOMMENDED
+       URL "www.xiph.org/flac/"
+       DESCRIPTION "Free Lossless Audio Codec Library"
+       PURPOSE "Enables FLAC support"
+       )
+set_package_properties(Opus PROPERTIES
+       TYPE RECOMMENDED
+       URL     "www.opus-codec.org/"
+       DESCRIPTION "Standardized open source low-latency fullband codec"
+       PURPOSE "Enables experimental Opus support"
+       )
+set_package_properties(Speex PROPERTIES TYPE OPTIONAL
+       URL "www.speex.org/"
+       DESCRIPTION "an audio codec tuned for speech"
+       PURPOSE "Enables experemental Speex support"
+       )
+set_package_properties (SQLite3 PROPERTIES
+       TYPE OPTIONAL
+       URL "www.sqlite.org/"
+       DESCRIPTION "light weight SQL database engine."
+       PURPOSE "Enables regtest"
+       )
+if (BUILD_SHARED_LIBS)
+       set_package_properties (PythonInterp PROPERTIES
+               TYPE REQUIRED
+               URL "www.python.org/"
+               DESCRIPTION "Python is a widely used high-level programming language."
+               PURPOSE "Required to build shared libraries"
+               )
+endif()
 
-if (CMAKE_C_COMPILER_ID STREQUAL "MSVC")
-       # Untested. Probably does not work. Patches accepted.
+feature_summary (WHAT ALL)
 
-       set (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4996" CACHE STRING "" FORCE)
-       add_definitions ("/wd4244 /wd4996")
-       endif ()
+#
+# Setup configuration
+#
 
+configure_file (src/config.h.cmake src/config.h)
 
-# Need to actually detect this.
-set (CPU_CLIPS_POSITIVE 0)
-set (CPU_CLIPS_NEGATIVE 0)
+configure_file (include/sndfile.h.in include/sndfile.h)
 
-set (ENABLE_EXPERIMENTAL_CODE 0)
+if (INSTALL_PKGCONFIG_MODULE)
 
-find_external_xiph_libs (HAVE_EXTERNAL_XIPH_LIBS EXTERNAL_XIPH_CFLAGS EXTERNAL_XIPH_LIBS)
+       set (prefix ${CMAKE_INSTALL_PREFIX})
+       set (exec_prefix "\$\{prefix\}")
+       set (libdir "\$\{prefix\}/${CMAKE_INSTALL_LIBDIR}")
+       set (includedir "\$\{prefix\}/${CMAKE_INSTALL_INCLUDEDIR}")
+       set (VERSION ${PROJECT_VERSION})
+       if (ENABLE_EXTERNAL_LIBS)
+               set (EXTERNAL_XIPH_REQUIRE "flac ogg vorbis vorbisenc opus")
+               if (ENABLE_EXPERIMENTAL)
+                       set (EXTERNAL_XIPH_REQUIRE "${EXTERNAL_XIPH_REQUIRE} speex")
+               endif ()
+       endif ()
 
-#-------------------------------------------------------------------------------
-# Project definitions follow.
+       configure_file (sndfile.pc.in sndfile.pc @ONLY)
 
-configure_file (${CMAKE_SOURCE_DIR}/src/sndfile.h.in ${CMAKE_SOURCE_DIR}/src/sndfile.h)
-configure_file (${CMAKE_SOURCE_DIR}/CMakeFiles/config.h.in ${CMAKE_SOURCE_DIR}/src/config.h)
+endif ()
 
-include_directories (src)
+#
+# libsndfile
+#
 
-set (libsndfile_sources
-       src/ALAC/ALACBitUtilities.c
-       src/ALAC/ag_dec.c
-       src/ALAC/ag_enc.c
-       src/ALAC/alac_decoder.c
-       src/ALAC/alac_encoder.c
-       src/ALAC/dp_dec.c
-       src/ALAC/dp_enc.c
-       src/ALAC/matrix_dec.c
-       src/ALAC/matrix_enc.c
-
-       src/G72x/g721.c
-       src/G72x/g723_16.c
-       src/G72x/g723_24.c
-       src/G72x/g723_40.c
-       src/G72x/g72x.c
-       src/G72x/g72x_test.c
+# Public libsndfile headers
+set (sndfile_HDRS
+       include/sndfile.hh
+       ${CMAKE_CURRENT_BINARY_DIR}/include/sndfile.h
+       )
 
-       src/GSM610/add.c
-       src/GSM610/code.c
-       src/GSM610/decode.c
-       src/GSM610/gsm_create.c
-       src/GSM610/gsm_decode.c
-       src/GSM610/gsm_destroy.c
-       src/GSM610/gsm_encode.c
-       src/GSM610/gsm_option.c
-       src/GSM610/long_term.c
-       src/GSM610/lpc.c
-       src/GSM610/preprocess.c
-       src/GSM610/rpe.c
-       src/GSM610/short_term.c
-       src/GSM610/table.c
+#
+# libsndfile static library
+#
 
-       src/aiff.c
-       src/alac.c
+add_library (sndfile
+       src/sfconfig.h
+       src/sfendian.h
+       src/sf_unistd.h
+       src/common.h
+       src/common.c
+       src/file_io.c
+       src/command.c
+       src/pcm.c
+       src/ulaw.c
        src/alaw.c
-       src/au.c
+       src/float32.c
+       src/double64.c
+       src/ima_adpcm.c
+       src/ms_adpcm.c
+       src/gsm610.c
+       src/dwvw.c
+       src/vox_adpcm.c
+       src/interleave.c
+       src/strings.c
+       src/dither.c
+       src/cart.c
+       src/broadcast.c
        src/audio_detect.c
+       src/ima_oki_adpcm.c
+       src/ima_oki_adpcm.h
+       src/alac.c
+       src/chunk.c
+       src/ogg.h
+       src/ogg.c
+       src/chanmap.h
+       src/chanmap.c
+       src/id3.c
+       $<$<BOOL:${WIN32}>:src/windows.c>
+       src/sndfile.c
+       src/aiff.c
+       src/au.c
        src/avr.c
-       src/broadcast.c
        src/caf.c
-       src/cart.c
-       src/chanmap.c
-       src/chunk.c
-       src/command.c
-       src/common.c
-       src/dither.c
-       src/double64.c
        src/dwd.c
-       src/dwvw.c
-       src/file_io.c
        src/flac.c
-       src/float32.c
        src/g72x.c
-       src/gsm610.c
        src/htk.c
-       src/id3.c
-       src/ima_adpcm.c
-       src/ima_oki_adpcm.c
-       src/interleave.c
        src/ircam.c
        src/macos.c
        src/mat4.c
        src/mat5.c
-       src/mpc2k.c
-       src/ms_adpcm.c
        src/nist.c
-       src/ogg.c
-       src/ogg_opus.c
-       src/ogg_pcm.c
-       src/ogg_speex.c
-       src/ogg_vorbis.c
        src/paf.c
-       src/pcm.c
        src/pvf.c
        src/raw.c
-       src/rf64.c
        src/rx2.c
        src/sd2.c
        src/sds.c
-       src/sndfile.c
-       src/strings.c
        src/svx.c
        src/txw.c
-       src/ulaw.c
        src/voc.c
-       src/vox_adpcm.c
+       src/wve.c
        src/w64.c
-       src/wav.c
+       src/wavlike.h
        src/wavlike.c
-       src/windows.c
-       src/wve.c
+       src/wav.c
        src/xi.c
+       src/mpc2k.c
+       src/rf64.c
+       src/ogg_vorbis.c
+       src/ogg_speex.c
+       src/ogg_pcm.c
+       src/ogg_opus.c
+       src/ogg_vcomment.c
+       src/nms_adpcm.c
+       src/GSM610/config.h
+       src/GSM610/gsm.h
+       src/GSM610/gsm610_priv.h
+       src/GSM610/add.c
+       src/GSM610/code.c
+       src/GSM610/decode.c
+       src/GSM610/gsm_create.c
+       src/GSM610/gsm_decode.c
+       src/GSM610/gsm_destroy.c
+       src/GSM610/gsm_encode.c
+       src/GSM610/gsm_option.c
+       src/GSM610/long_term.c
+       src/GSM610/lpc.c
+       src/GSM610/preprocess.c
+       src/GSM610/rpe.c
+       src/GSM610/short_term.c
+       src/GSM610/table.c
+       src/G72x/g72x.h
+       src/G72x/g72x_priv.h
+       src/G72x/g721.c
+       src/G72x/g723_16.c
+       src/G72x/g723_24.c
+       src/G72x/g723_40.c
+       src/G72x/g72x.c
+       src/ALAC/ALACAudioTypes.h
+       src/ALAC/ALACBitUtilities.h
+       src/ALAC/EndianPortable.h
+       src/ALAC/aglib.h
+       src/ALAC/dplib.h
+       src/ALAC/matrixlib.h
+       src/ALAC/alac_codec.h
+       src/ALAC/shift.h
+       src/ALAC/ALACBitUtilities.c
+       src/ALAC/ag_dec.c
+       src/ALAC/ag_enc.c
+       src/ALAC/dp_dec.c
+       src/ALAC/dp_enc.c
+       src/ALAC/matrix_dec.c
+       src/ALAC/matrix_enc.c
+       src/ALAC/alac_decoder.c
+       src/ALAC/alac_encoder.c
+       ${sndfile_HDRS}
+       ${CMAKE_CURRENT_BINARY_DIR}/src/config.h
        )
 
-add_library (sndfile SHARED
-       ${libsndfile_sources}
+add_library (SndFile::sndfile ALIAS sndfile)
+
+target_include_directories (sndfile
+       PUBLIC
+               $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+               $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
+               $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+       PRIVATE
+               src
+               $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/src>
+       )
+target_link_libraries (sndfile
+       PRIVATE
+               $<$<BOOL:${LIBM_REQUIRED}>:m>
+               $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Vorbis::vorbisenc>
+               $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:FLAC::FLAC>
+               $<$<AND:$<BOOL:${ENABLE_EXPERIMENTAL}>,$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>,$<BOOL:${HAVE_SPEEX}>>:Speex::Speex>
+               $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Opus::opus>
        )
+set_target_properties (sndfile PROPERTIES
+       PUBLIC_HEADER "${sndfile_HDRS}"
+       )
+
+if (ENABLE_COMPATIBLE_LIBSNDFILE_NAME)
+       if (MINGW OR CYGWIN)
+               set_target_properties (sndfile PROPERTIES
+                       RUNTIME_OUTPUT_NAME "sndfile-1"
+                       )
+       else ()
+               set_target_properties (sndfile PROPERTIES
+                       RUNTIME_OUTPUT_NAME "libsndfile-1"
+                       )
+       endif ()
+endif ()
+
+if (BUILD_SHARED_LIBS)
+
+       if (WIN32)
+               set (VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR})
+               set (GEN_TOOL cmake)
+               
+               set (WIN_RC_VERSION "${CPACK_PACKAGE_VERSION_MAJOR},${CPACK_PACKAGE_VERSION_MINOR},${CPACK_PACKAGE_VERSION_PATCH}")
+               set (CLEAN_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+               set (PACKAGE_VERSION ${CPACK_PACKAGE_VERSION})
+
+               configure_file (src/version-metadata.rc.in src/version-metadata.rc @ONLY)
+               target_sources (sndfile PRIVATE ${PROJECT_BINARY_DIR}/src/version-metadata.rc)
+       endif ()
+
+       set_target_properties (sndfile PROPERTIES
+               SOVERSION ${PROJECT_VERSION_MAJOR}
+               VERSION ${PROJECT_VERSION}
+               )
+
+       # Symbol files generation
+
+       if (WIN32)
+               set (SYMBOL_FILENAME "sndfile.def")
+               set (SYMBOL_OS "win32")
+       elseif ((CMAKE_SYSTEM_NAME MATCHES "Darwin") OR (CMAKE_SYSTEM_NAME MATCHES "Rhapsody"))
+               set (SYMBOL_FILENAME "Symbols.darwin")
+               set (SYMBOL_OS "darwin")
+       elseif (CMAKE_SYSTEM_NAME MATCHES "OS2")
+               set (SYMBOL_FILENAME "Symbols.os2")
+               set (SYMBOL_OS "os2")
+       elseif (UNIX)
+               set (SYMBOL_FILENAME "Symbols.gnu-binutils")
+               set (SYMBOL_OS "linux")
+       endif ()
+
+       if (DEFINED SYMBOL_OS)
+               add_custom_command (
+                       OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}
+                       COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${PROJECT_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}
+                       COMMENT "Generating ${SYMBOL_FILENAME}..."
+                       )
+
+               add_custom_target (GENFILES DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME})
+               if (SYMBOL_OS MATCHES "win32")
+                       target_sources (sndfile
+                               PRIVATE
+                                       ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}
+                               )
+               elseif (SYMBOL_OS MATCHES "darwin")
+                       add_dependencies (sndfile GENFILES)
+                       if (CMAKE_VERSION VERSION_LESS 3.13)
+                               set_property (TARGET sndfile APPEND_STRING PROPERTY
+                                       LINK_FLAGS "-Wl,-exported_symbols_list -Wl,${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}"
+                                       )
+                       else ()
+                               target_link_options (sndfile PRIVATE "LINKER:-exported_symbols_list,${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}")
+                       endif()
+               elseif (SYMBOL_OS MATCHES "os")
+                       add_dependencies (sndfile GENFILES)
+                       if (CMAKE_VERSION VERSION_LESS 3.13)
+                               set_property (TARGET sndfile APPEND_STRING PROPERTY
+                                       LINK_FLAGS "-Wl,-export-symbols ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}"
+                                       )
+                       else ()
+                               target_link_options (sndfile PRIVATE "LINKER:-export-symbols ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}")
+                       endif()
+               elseif (UNIX)
+                       add_dependencies (sndfile GENFILES)
+                       if (CMAKE_VERSION VERSION_LESS 3.13)
+                               set_property (TARGET sndfile APPEND_STRING PROPERTY
+                                       LINK_FLAGS "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}"
+                                       )
+                       else ()
+                               target_link_options (sndfile PRIVATE "LINKER:--version-script,${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}")
+                       endif()
+               endif()
+       endif()
+
+endif ()
+
+#
+# Programs
+#
+
+if (BUILD_PROGRAMS)
+
+# sndfile-info
+
+       add_executable (sndfile-info
+               programs/sndfile-info.c
+               programs/common.c
+               programs/common.h
+               )
+       target_link_libraries (sndfile-info
+               PRIVATE
+                       sndfile
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+# sndfile-play
+
+       add_executable (sndfile-play
+               $<$<NOT:$<BOOL:${BEOS}>>:programs/sndfile-play.c>
+               $<$<NOT:$<BOOL:${BEOS}>>:programs/common.c>
+               $<$<NOT:$<BOOL:${BEOS}>>:programs/sndfile-play.c>
+               $<$<BOOL:${BEOS}>:programs/sndfile-play-beos.cpp>
+               )
+       target_include_directories (sndfile-play
+               PRIVATE
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+               )
+       target_link_libraries (sndfile-play PRIVATE $<$<BOOL:${LIBM_REQUIRED}>:m>)
+       target_link_libraries (sndfile-play PRIVATE sndfile)
+       if (WIN32)
+               target_link_libraries(sndfile-play PRIVATE winmm)
+       # Maybe ALSA & Sndio are present in BeOS. They are not required
+       # so skip them anyway.
+       elseif ((NOT BEOS) AND ALSA_FOUND)
+               target_include_directories (sndfile-play PRIVATE ${ALSA_INCLUDE_DIRS})
+               target_link_libraries (sndfile-play PRIVATE ${ALSA_LIBRARIES})
+       elseif (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
+               target_link_libraries (sndfile-play PRIVATE Sndio::Sndio)
+       endif ()
+
+# sndfile-convert
+
+       add_executable (sndfile-convert
+               programs/sndfile-convert.c
+               programs/common.c
+               programs/common.h
+               )
+       target_link_libraries (sndfile-convert PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-cmp
+
+       add_executable (sndfile-cmp
+               programs/sndfile-cmp.c
+               programs/common.c
+               programs/common.h
+               )
+       target_include_directories (sndfile-cmp
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries (sndfile-cmp PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-metadata-set
+
+       add_executable (sndfile-metadata-set
+               programs/sndfile-metadata-set.c
+               programs/common.c
+               programs/common.h
+               )
+       target_include_directories (sndfile-metadata-set
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries (sndfile-metadata-set PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-metadata-get
+
+       add_executable (sndfile-metadata-get
+               programs/sndfile-metadata-get.c
+               programs/common.c
+               programs/common.h
+               )
+       target_include_directories (sndfile-metadata-get
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries (sndfile-metadata-get PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-interleave
+
+       add_executable (sndfile-interleave
+               programs/sndfile-interleave.c
+               programs/common.c
+               programs/common.h
+               )
+       target_link_libraries (sndfile-interleave PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-deinterleave
+
+       add_executable (sndfile-deinterleave
+               programs/sndfile-deinterleave.c
+               programs/common.c
+               programs/common.h
+               )
+       target_link_libraries (sndfile-deinterleave PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-concat
+
+       add_executable (sndfile-concat
+               programs/sndfile-concat.c
+               programs/common.c
+               programs/common.h
+               )
+       target_link_libraries (sndfile-concat PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+# sndfile-salvage
+
+       add_executable (sndfile-salvage
+               programs/sndfile-salvage.c
+               programs/common.c
+               programs/common.h
+               )
+       target_include_directories (sndfile-salvage
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries (sndfile-salvage PRIVATE sndfile $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+       set (SNDFILE_PROGRAM_TARGETS
+               sndfile-info
+               sndfile-play
+               sndfile-convert
+               sndfile-cmp
+               sndfile-metadata-set
+               sndfile-metadata-get
+               sndfile-interleave
+               sndfile-deinterleave
+               sndfile-concat
+               sndfile-salvage
+               )
+
+       set_target_properties(${SNDFILE_PROGRAM_TARGETS} PROPERTIES FOLDER Programs)
+
+endif ()
+
+#
+# Examples
+#
+
+if (BUILD_EXAMPLES)
+
+# sndfile-to-text
+
+       add_executable (sndfile-to-text examples/sndfile-to-text.c)
+       target_link_libraries (sndfile-to-text PRIVATE sndfile)
+
+# sndfile-loopify
+
+       add_executable (sndfile-loopify examples/sndfile-loopify.c)
+       target_link_libraries (sndfile-loopify PRIVATE sndfile)
+
+# make_sine
+
+       add_executable (make_sine examples/make_sine.c)
+       target_link_libraries (make_sine
+               PRIVATE
+                       sndfile
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+# sfprocess
+
+       add_executable (sfprocess examples/sfprocess.c)
+       target_link_libraries (sfprocess
+               PRIVATE
+                       sndfile
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+# list_formats
+
+       add_executable (list_formats examples/list_formats.c)
+       target_link_libraries (list_formats
+               PRIVATE
+                       sndfile
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+# sndfilehandle
+
+       add_executable (sndfilehandle examples/sndfilehandle.cc)
+       target_link_libraries (sndfilehandle PUBLIC sndfile)
+
+       set (SNDFILE_EXAMPLE_TARGETS
+               sndfile-to-text
+               sndfile-loopify
+               make_sine
+               sfprocess
+               list_formats
+               sndfilehandle
+               )
+
+       set_target_properties(${SNDFILE_EXAMPLE_TARGETS} PROPERTIES FOLDER Examples)
 
-target_link_libraries (sndfile LINK_PRIVATE ${EXTERNAL_XIPH_LIBS} LINK_PUBLIC m)
 
-set_target_properties (sndfile
-       PROPERTIES
-       VERSION ${LIB_VERSION}
-       SOVERSION ${LIB_VERSION_MAJOR}
-       LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src
+endif ()
+
+#
+# sndfile-regtest
+#
+
+if (BUILD_REGTEST)
+
+       add_executable (sndfile-regtest
+               regtest/sndfile-regtest.c
+               regtest/database.c
+               regtest/checksum.c
+               )
+       target_include_directories (sndfile-regtest
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries(sndfile-regtest
+               PRIVATE
+                       sndfile
+                       SQLite::SQLite3
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+endif ()
+
+#
+# Installation
+#
+
+if (ENABLE_PACKAGE_CONFIG)
+
+       if (WIN32 AND (NOT MINGW) AND (NOT CYGWIN))
+               set (CMAKE_INSTALL_PACKAGEDIR cmake) 
+        else ()
+               set (CMAKE_INSTALL_PACKAGEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/SndFile)
+        endif()
+
+        install (TARGETS ${SNDFILE_PROGRAM_TARGETS}
+               RUNTIME DESTINATION                     ${CMAKE_INSTALL_BINDIR}
+       )
+
+       install (TARGETS sndfile
+               EXPORT SndFileTargets
+               RUNTIME DESTINATION                     ${CMAKE_INSTALL_BINDIR}
+               ARCHIVE DESTINATION                     ${CMAKE_INSTALL_LIBDIR}
+               LIBRARY DESTINATION                     ${CMAKE_INSTALL_LIBDIR}
+               PUBLIC_HEADER DESTINATION       ${CMAKE_INSTALL_INCLUDEDIR}
        )
 
-#-------------------------------------------------------------------------------
-# Programs.
-
-lsf_build_program (sndfile-cmp)
-lsf_build_program (sndfile-concat)
-lsf_build_program (sndfile-convert)
-lsf_build_program (sndfile-deinterleave)
-lsf_build_program (sndfile-info)
-lsf_build_program (sndfile-interleave)
-lsf_build_program (sndfile-metadata-get)
-lsf_build_program (sndfile-metadata-set)
-lsf_build_program (sndfile-salvage)
-lsf_build_program_extra (sndfile-play asound)
-
-#-------------------------------------------------------------------------------
-# Tests.
-
-configure_file (${CMAKE_SOURCE_DIR}/tests/test_wrapper.sh.in ${CMAKE_SOURCE_DIR}/tests/test_wrapper.sh)
-configure_file (${CMAKE_SOURCE_DIR}/tests/pedantic-header-test.sh.in ${CMAKE_SOURCE_DIR}/tests/pedantic-header-test.sh)
-
-add_custom_target (check
-       COMMAND src/test_main && bash tests/test_wrapper.sh
-       DEPENDS src/test_main tests/test_wrapper.sh
+       include (CMakePackageConfigHelpers)
+
+       if (ENABLE_EXTERNAL_LIBS)
+               set (SndFile_WITH_EXTERNAL_LIBS 1)
+       else ()
+               set (SndFile_WITH_EXTERNAL_LIBS 0)
+       endif ()
+
+       set (INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
+       configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig.cmake
+               INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
+               PATH_VARS INCLUDE_INSTALL_DIR
+               )
+       write_basic_package_version_file (SndFileConfigVersion.cmake COMPATIBILITY SameMajorVersion)
+
+       install(EXPORT SndFileTargets
+               NAMESPACE SndFile::
+               DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
+               )
+       install(
+               FILES
+                       ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig.cmake
+                       ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfigVersion.cmake
+               DESTINATION     ${CMAKE_INSTALL_PACKAGEDIR}
+               )
+
+else ()
+
+       install (TARGETS sndfile ${sdnfile_PROGRAMS}
+               RUNTIME DESTINATION                     ${CMAKE_INSTALL_BINDIR}
+               ARCHIVE DESTINATION                     ${CMAKE_INSTALL_LIBDIR}
+               LIBRARY DESTINATION                     ${CMAKE_INSTALL_LIBDIR}
+               PUBLIC_HEADER DESTINATION       ${CMAKE_INSTALL_INCLUDEDIR})
+
+endif ()
+
+if (INSTALL_MANPAGES)
+
+       set (man_MANS
+               man/sndfile-info.1
+               man/sndfile-play.1
+               man/sndfile-convert.1
+               man/sndfile-cmp.1
+               man/sndfile-metadata-get.1
+               man/sndfile-concat.1
+               man/sndfile-interleave.1
+               man/sndfile-salvage.1
+               )
+       install (FILES ${man_MANS} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+       install (FILES man/sndfile-metadata-get.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 RENAME sndfile-metadata-set.1)
+       install (FILES man/sndfile-interleave.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 RENAME sndfile-deinterleave.1)
+endif ()
+
+if (ENABLE_BOW_DOCS)
+       set (HTML_BGCOLOUR "white")
+       set (HTML_FGCOLOUR "black")
+else ()
+       set (HTML_BGCOLOUR "black")
+       set (HTML_FGCOLOUR "white")
+endif ()
+set (dist_doc_DATA
+       docs/index.md
+       docs/libsndfile.jpg
+       docs/libsndfile.css
+       docs/print.css
+       docs/api.md
+       docs/command.md
+       docs/bugs.md
+       docs/formats.md
+       docs/sndfile_info.md
+       docs/new_file_type_howto.md
+       docs/win32.md
+       docs/FAQ.md
+       docs/lists.md
+       docs/embedded_files.md
+       docs/octave.md
+       docs/tutorial.md
        )
+install (FILES ${dist_doc_DATA} DESTINATION ${CMAKE_INSTALL_DOCDIR})
 
-# Tests from the src/ directory.
-set (src_test_sources
-       src/audio_detect.c
-       src/broadcast.c
-       src/cart.c
-       src/common.c
-       src/double64.c
-       src/file_io.c
-       src/float32.c
-       src/test_audio_detect.c
-       src/test_broadcast_var.c
-       src/test_cart_var.c
-       src/test_conversions.c
-       src/test_endswap.c
-       src/test_file_io.c
-       src/test_float.c
-       src/test_ima_oki_adpcm.c
-       src/test_log_printf.c
-       src/test_strncpy_crlf.c
+if (INSTALL_PKGCONFIG_MODULE)
+       install (FILES ${CMAKE_CURRENT_BINARY_DIR}/sndfile.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+endif ()
+
+#
+# Testing
+#
+
+if (BUILD_TESTING)
+
+       enable_testing ()
+
+       include (CMakeAutoGen)
+
+       # generate tests sources from autogen templates
+       lsf_autogen (tests benchmark c)
+       lsf_autogen (tests floating_point_test c)
+       lsf_autogen (tests header_test c)
+       lsf_autogen (tests pcm_test c)
+       lsf_autogen (tests pipe_test c)
+       lsf_autogen (tests rdwr_test c)
+       lsf_autogen (tests scale_clip_test c)
+       lsf_autogen (tests utils c h)
+       lsf_autogen (tests write_read_test c)
+       lsf_autogen (src test_endswap c)
+
+       # utils static library
+       add_library(test_utils STATIC tests/utils.c)
+       target_include_directories (test_utils
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries(test_utils PRIVATE sndfile)
+
+       ### test_main
+
+       add_executable (test_main
+               src/test_main.c
+               src/test_main.h
+               src/test_conversions.c
+               src/test_float.c
+               src/test_endswap.c
+               src/test_audio_detect.c
+               src/test_log_printf.c
+               src/test_file_io.c
+               src/test_ima_oki_adpcm.c
+               src/test_strncpy_crlf.c
+               src/test_broadcast_var.c
+               src/test_cart_var.c
+               src/test_binheader_writef.c
+               src/test_nms_adpcm.c
+               )
+       target_include_directories (test_main
+               PUBLIC
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+                       ${CMAKE_CURRENT_BINARY_DIR}/tests
+               )
+       target_link_libraries (test_main PRIVATE sndfile)
+       if (MSVC)
+               target_compile_definitions (test_main PRIVATE _USE_MATH_DEFINES)
+       endif ()
+       add_test (test_main test_main)
+
+       ### sfversion_test
+
+       add_executable (sfversion tests/sfversion.c)
+       target_include_directories (sfversion
+               PRIVATE
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+               )
+       target_link_libraries (sfversion sndfile)
+       add_test (sfversion sfversion)
+       set_tests_properties (sfversion PROPERTIES
+               PASS_REGULAR_EXPRESSION "${PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_FULL}"
+               )
+
+       ### error_test
+
+       add_executable (error_test tests/error_test.c)
+       target_link_libraries (error_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (error_test error_test)
+
+       ### ulaw_test
+       add_executable (ulaw_test tests/ulaw_test.c)
+       target_link_libraries (ulaw_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (ulaw_test ulaw_test)
+
+       ### alaw_test
+       add_executable (alaw_test tests/alaw_test.c)
+       target_link_libraries (alaw_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (alaw_test alaw_test)
+
+       ### dwvw_test
+
+       add_executable (dwvw_test tests/dwvw_test.c)
+       target_link_libraries (dwvw_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (dwvw_test dwvw_test)
+
+       ### command_test
+
+       add_executable (command_test tests/command_test.c)
+       target_link_libraries (command_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (command_test command_test all)
+
+       ### floating_point_test
+
+       add_executable (floating_point_test
+               tests/dft_cmp.c
+               tests/floating_point_test.c
+               )
+       target_link_libraries (floating_point_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       target_include_directories (floating_point_test PRIVATE tests)
+       add_test (floating_point_test floating_point_test)
+
+       ### checksum_test
+
+       add_executable (checksum_test tests/checksum_test.c)
+       target_link_libraries (checksum_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (checksum_test checksum_test)
+
+       ### scale_clip_test
+
+       add_executable (scale_clip_test tests/scale_clip_test.c)
+       target_link_libraries (scale_clip_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (scale_clip_test scale_clip_test)
+
+       ### headerless_test
+
+       add_executable (headerless_test tests/headerless_test.c)
+       target_link_libraries (headerless_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (headerless_test headerless_test)
+
+       ### rdwr_test
+
+       add_executable (rdwr_test tests/rdwr_test.c)
+       target_link_libraries (rdwr_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (rdwr_test rdwr_test)
+
+       ### locale_test
+
+       add_executable (locale_test tests/locale_test.c)
+       target_link_libraries (locale_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (locale_test locale_test)
+
+       ### win32_ordinal_test
+
+# Disabled because we cannot test with shared sndfile library
+#      if (WIN32 AND BUILD_SHARED_LIBS)
+#              add_executable (win32_ordinal_test tests/win32_ordinal_test.c)
+#              target_link_libraries (win32_ordinal_test PRIVATE sndfile test_utils)
+#              add_test (win32_ordinal_test win32_ordinal_test)
+#      endif ()
+
+       ### cpp_test
+
+       add_executable (cpp_test tests/cpp_test.cc)
+       target_link_libraries (cpp_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (cpp_test cpp_test)
+
+       ### external_libs_test
+
+       add_executable (external_libs_test tests/external_libs_test.c)
+       target_link_libraries (external_libs_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (external_libs_test external_libs_test)
+
+       ### format_check_test
+
+       add_executable (format_check_test tests/format_check_test.c)
+       target_link_libraries (format_check_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (format_check_test format_check_test)
+
+       ### channel_test
+
+       add_executable (channel_test tests/channel_test.c)
+       target_link_libraries (channel_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (channel_test channel_test)
+
+       ### pcm_test
+
+       add_executable (pcm_test tests/pcm_test.c)
+       target_link_libraries (pcm_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (pcm_test pcm_test)
+
+       ### common test executables
+
+       add_executable (write_read_test
+               tests/generate.c
+               tests/write_read_test.c
        )
+       target_link_libraries (write_read_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       target_include_directories (write_read_test PRIVATE tests)
+
+       add_executable (lossy_comp_test tests/lossy_comp_test.c)
+       target_link_libraries (lossy_comp_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (peak_chunk_test tests/peak_chunk_test.c)
+       target_link_libraries (peak_chunk_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (header_test tests/header_test.c)
+       target_link_libraries (header_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (misc_test tests/misc_test.c)
+       target_link_libraries (misc_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (string_test tests/string_test.c)
+       target_link_libraries (string_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (multi_file_test tests/multi_file_test.c)
+       target_link_libraries (multi_file_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (aiff_rw_test tests/aiff_rw_test.c)
+       target_link_libraries (aiff_rw_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (chunk_test tests/chunk_test.c)
+       target_link_libraries (chunk_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (long_read_write_test tests/long_read_write_test.c)
+       target_link_libraries (long_read_write_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (raw_test tests/raw_test.c)
+       target_link_libraries (raw_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (compression_size_test tests/compression_size_test.c)
+       target_link_libraries (compression_size_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (ogg_test tests/ogg_test.c)
+       target_link_libraries (ogg_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (ogg_opus_test tests/ogg_opus_test.c)
+       target_link_libraries (ogg_opus_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (stdin_test tests/stdin_test.c)
+       target_link_libraries (stdin_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       set_target_properties (stdin_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY "tests")
+
+       add_executable (stdout_test tests/stdout_test.c)
+       target_link_libraries (stdout_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       set_target_properties (stdout_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY "tests")
+
+       add_executable (stdio_test tests/stdio_test.c)
+       target_link_libraries (stdio_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (pipe_test tests/pipe_test.c)
+       target_link_libraries (pipe_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       add_executable (virtual_io_test tests/virtual_io_test.c)
+       target_link_libraries (virtual_io_test
+               PRIVATE
+                       sndfile
+                       test_utils
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+
+       ### g72x_test
+
+       add_executable (g72x_test src/G72x/g72x_test.c)
+       target_include_directories (g72x_test
+               PRIVATE
+                       src
+                       ${CMAKE_CURRENT_BINARY_DIR}/src
+               )
+       target_link_libraries (g72x_test
+               PRIVATE
+                       sndfile
+                       $<$<BOOL:${LIBM_REQUIRED}>:m>
+               )
+       add_test (g72x_test g72x_test all)
+
+       ### aiff-tests
+
+       add_test (write_read_test_aiff write_read_test aiff)
+       add_test (lossy_comp_test_aiff_ulaw lossy_comp_test aiff_ulaw)
+       add_test (lossy_comp_test_aiff_alaw lossy_comp_test aiff_alaw)
+       add_test (lossy_comp_test_aiff_gsm610 lossy_comp_test aiff_gsm610)
+       add_test (peak_chunk_test_aiff peak_chunk_test aiff)
+       add_test (header_test_aiff header_test aiff)
+       add_test (misc_test_aiff misc_test aiff)
+       add_test (string_test_aiff string_test aiff)
+       add_test (multi_file_test_aiff multi_file_test aiff)
+       add_test (aiff_rw_test aiff_rw_test)
+
+       ### au-tests
+
+       add_test (write_read_test_au write_read_test au)
+       add_test (lossy_comp_test_au_ulaw lossy_comp_test au_ulaw)
+       add_test (lossy_comp_test_au_alaw lossy_comp_test au_alaw)
+       add_test (lossy_comp_test_au_g721 lossy_comp_test au_g721)
+       add_test (lossy_comp_test_au_g723 lossy_comp_test au_g723)
+       add_test (header_test_au header_test au)
+       add_test (misc_test_au misc_test au)
+       add_test (multi_file_test_au multi_file_test au)
+
+       ### caf-tests
+
+       add_test (write_read_test_caf write_read_test caf)
+       add_test (lossy_comp_test_caf_ulaw lossy_comp_test caf_ulaw)
+       add_test (lossy_comp_test_caf_alaw lossy_comp_test caf_alaw)
+       add_test (header_test_caf header_test caf)
+       add_test (peak_chunk_test_caf peak_chunk_test caf)
+       add_test (misc_test_caf misc_test caf)
+       add_test (chunk_test_caf chunk_test caf)
+       add_test (string_test_caf string_test caf)
+       add_test (long_read_write_test_alac long_read_write_test alac)
+
+       # wav-tests
+       add_test (write_read_test_wav write_read_test wav)
+       add_test (lossy_comp_test_wav_pcm lossy_comp_test wav_pcm)
+       add_test (lossy_comp_test_wav_ima lossy_comp_test wav_ima)
+       add_test (lossy_comp_test_wav_msadpcm lossy_comp_test wav_msadpcm)
+       add_test (lossy_comp_test_wav_ulaw lossy_comp_test wav_ulaw)
+       add_test (lossy_comp_test_wav_alaw lossy_comp_test wav_alaw)
+       add_test (lossy_comp_test_wav_gsm610 lossy_comp_test wav_gsm610)
+       add_test (lossy_comp_test_wav_g721 lossy_comp_test wav_g721)
+       add_test (lossy_comp_test_wav_nmsadpcm lossy_comp_test wav_nmsadpcm)
+       add_test (peak_chunk_test_wav peak_chunk_test wav)
+       add_test (header_test_wav header_test wav)
+       add_test (misc_test_wav misc_test wav)
+       add_test (string_test_wav string_test wav)
+       add_test (multi_file_test_wav multi_file_test wav)
+       add_test (chunk_test_wav chunk_test wav)
+
+       ### w64-tests
+
+       add_test (write_read_test_w64 write_read_test w64)
+       add_test (lossy_comp_test_w64_ima lossy_comp_test w64_ima)
+       add_test (lossy_comp_test_w64_msadpcm lossy_comp_test w64_msadpcm)
+       add_test (lossy_comp_test_w64_ulaw lossy_comp_test w64_ulaw)
+       add_test (lossy_comp_test_w64_alaw lossy_comp_test w64_alaw)
+       add_test (lossy_comp_test_w64_gsm610 lossy_comp_test w64_gsm610)
+       add_test (header_test_w64 header_test w64)
+       add_test (misc_test_w64 misc_test w64)
+
+       ### rf64-tests
+
+       add_test (write_read_test_rf64 write_read_test rf64)
+       add_test (header_test_rf64 header_test rf64)
+       add_test (misc_test_rf64 misc_test rf64)
+       add_test (string_test_rf64 string_test rf64)
+       add_test (peak_chunk_test_rf64 peak_chunk_test rf64)
+       add_test (chunk_test_rf64 chunk_test rf64)
+
+       ### raw-tests
+       add_test (write_read_test_raw write_read_test raw)
+       add_test (lossy_comp_test_raw_ulaw lossy_comp_test raw_ulaw)
+       add_test (lossy_comp_test_raw_alaw lossy_comp_test raw_alaw)
+       add_test (lossy_comp_test_raw_gsm610 lossy_comp_test raw_gsm610)
+       add_test (lossy_comp_test_vox_adpcm lossy_comp_test vox_adpcm)
+       add_test (raw_test raw_test)
+
+       ### paf-tests
+       add_test (write_read_test_paf write_read_test paf)
+       add_test (header_test_paf header_test paf)
+       add_test (misc_test_paf misc_test paf)
+
+       ### svx-tests
+       add_test (write_read_test_svx write_read_test svx)
+       add_test (header_test_svx header_test svx)
+       add_test (misc_test_svx misc_test svx)
+
+       ### nist-tests
+       add_test (write_read_test_nist write_read_test nist)
+       add_test (lossy_comp_test_nist_ulaw lossy_comp_test nist_ulaw)
+       add_test (lossy_comp_test_nist_alaw lossy_comp_test nist_alaw)
+       add_test (header_test_nist header_test nist)
+       add_test (misc_test_nist misc_test nist)
+
+       ### ircam-tests
+       add_test (write_read_test_ircam write_read_test ircam)
+       add_test (lossy_comp_test_ircam_ulaw lossy_comp_test ircam_ulaw)
+       add_test (lossy_comp_test_ircam_alaw lossy_comp_test ircam_alaw)
+       add_test (header_test_ircam header_test ircam)
+       add_test (misc_test_ircam misc_test ircam)
+
+       ### voc-tests
+       add_test (write_read_test_voc write_read_test voc)
+       add_test (lossy_comp_test_voc_ulaw lossy_comp_test voc_ulaw)
+       add_test (lossy_comp_test_voc_alaw lossy_comp_test voc_alaw)
+       add_test (header_test_voc header_test voc)
+       add_test (misc_test_voc misc_test voc)
+
+       ### mat4-tests
+       add_test (write_read_test_mat4 write_read_test mat4)
+       add_test (header_test_mat4 header_test mat4)
+       add_test (misc_test_mat4 misc_test mat4)
+
+       ### mat5-tests
+       add_test (write_read_test_mat5 write_read_test mat5)
+       add_test (header_test_mat5 header_test mat5)
+       add_test (misc_test_mat5 misc_test mat5)
+
+       ### pvf-tests
+       add_test (write_read_test_pvf write_read_test pvf)
+       add_test (header_test_pvf header_test pvf)
+       add_test (misc_test_pvf misc_test pvf)
+
+       ### xi-tests
+       add_test (lossy_comp_test_xi_dpcm lossy_comp_test xi_dpcm)
+
+       ### htk-tests
+       add_test (write_read_test_htk write_read_test htk)
+       add_test (header_test_htk header_test htk)
+       add_test (misc_test_htk misc_test htk)
+
+       ### avr-tests
+       add_test (write_read_test_avr write_read_test avr)
+       add_test (header_test_avr header_test avr)
+       add_test (misc_test_avr misc_test avr)
+
+       ### sds-tests
+       add_test (write_read_test_sds write_read_test sds)
+       add_test (header_test_sds header_test sds)
+       add_test (misc_test_sds misc_test sds)
+
+       # sd2-tests
+       add_test (write_read_test_sd2 write_read_test sd2)
+
+       ### wve-tests
+       add_test (lossy_comp_test_wve lossy_comp_test wve)
+
+       ### mpc2k-tests
+       add_test (write_read_test_mpc2k write_read_test mpc2k)
+       add_test (header_test_mpc2k header_test mpc2k)
+       add_test (misc_test_mpc2k misc_test mpc2k)
+
+       ### flac-tests
+       add_test (write_read_test_flac write_read_test flac)
+       add_test (compression_size_test_flac compression_size_test flac)
+       add_test (string_test_flac string_test flac)
+
+       ### vorbis-tests
+       add_test (ogg_test ogg_test)
+       add_test (compression_size_test_vorbis compression_size_test vorbis)
+       add_test (lossy_comp_test_ogg_vorbis lossy_comp_test ogg_vorbis)
+       add_test (string_test_ogg string_test ogg)
+       add_test (misc_test_ogg misc_test ogg)
+
+       ### opus-tests ###
+       add_test (ogg_opus_test ogg_opus_test)
+       add_test (compression_size_test_opus compression_size_test opus)
+       add_test (lossy_comp_test_ogg_opus lossy_comp_test ogg_opus)
+       add_test (string_test_opus string_test opus)
+
+       ### io-tests
+       add_test (stdio_test stdio_test)
+       add_test (pipe_test pipe_test)
+       add_test (virtual_io_test virtual_io_test)
+
+       set (SNDFILE_TEST_TARGETS
+               test_utils
+               test_main
+               sfversion
+               error_test
+               ulaw_test
+               alaw_test
+               dwvw_test
+               command_test
+               floating_point_test
+               checksum_test
+               scale_clip_test
+               headerless_test
+               rdwr_test
+               locale_test
+               cpp_test
+               external_libs_test
+               format_check_test
+               channel_test
+               pcm_test
+               write_read_test
+               lossy_comp_test
+               peak_chunk_test
+               header_test
+               misc_test
+               string_test
+               multi_file_test
+               aiff_rw_test
+               chunk_test
+               long_read_write_test
+               raw_test
+               compression_size_test
+               ogg_test
+               stdin_test
+               stdout_test
+               stdio_test
+               pipe_test
+               virtual_io_test
+               g72x_test
+               )
+
+#      if (WIN32 AND BUILD_SHARED_LIBS)
+#              list (APPEND SNDFILE_TEST_TARGETS win32_ordinal_test)
+#      endif ()
+
+       set_target_properties(${SNDFILE_TEST_TARGETS} PROPERTIES FOLDER Tests)
+
+endif ()
 
-lsf_build_src_test_c (test_main "${src_test_sources}")
-
-# Tests from the tests/ directory.
-
-lsf_build_test_c (aiff_rw_test "")
-lsf_build_test_c (alaw_test "")
-lsf_build_test_c (benchmark "")
-lsf_build_test_c (channel_test "")
-lsf_build_test_c (checksum_test "")
-lsf_build_test_c (chunk_test "")
-lsf_build_test_c (command_test "")
-lsf_build_test_c (compression_size_test "")
-lsf_build_test_cc (cpp_test "")
-lsf_build_test_c (dither_test "")
-lsf_build_test_c (dwvw_test "")
-lsf_build_test_c (error_test "")
-lsf_build_test_c (external_libs_test "")
-lsf_build_test_c (fix_this "")
-lsf_build_test_c (floating_point_test "tests/dft_cmp.c")
-lsf_build_test_c (format_check_test "")
-lsf_build_test_c (headerless_test "")
-lsf_build_test_c (header_test "")
-lsf_build_test_c (largefile_test "")
-lsf_build_test_c (locale_test "")
-lsf_build_test_c (lossy_comp_test "")
-lsf_build_test_c (long_read_write_test "")
-lsf_build_test_c (misc_test "")
-lsf_build_test_c (multi_file_test "")
-lsf_build_test_c (ogg_test "")
-lsf_build_test_c (pcm_test "")
-lsf_build_test_c (peak_chunk_test "")
-lsf_build_test_c (pipe_test "")
-lsf_build_test_c (raw_test "")
-lsf_build_test_c (rdwr_test "")
-lsf_build_test_c (scale_clip_test "")
-lsf_build_test_c (sfversion "")
-lsf_build_test_c (stdin_test "")
-lsf_build_test_c (stdio_test "")
-lsf_build_test_c (stdout_test "")
-lsf_build_test_c (string_test "")
-lsf_build_test_c (ulaw_test "")
-lsf_build_test_c (virtual_io_test "")
-lsf_build_test_c (win32_ordinal_test "")
-lsf_build_test_c (win32_test "")
-lsf_build_test_c (write_read_test "tests/generate.c")
+if (ENABLE_CPACK)
+       include (CPack)
+endif ()
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644 (file)
index 0000000..d67616e
--- /dev/null
@@ -0,0 +1,14 @@
+# The owners of this repository. In order of suggestions as reviewers.
+*                           @evpobr @SoapGentoo @arthurt @erikd
+
+# Autotools
+configure.ac Makefile.am    @SoapGentoo @erikd
+
+# CMake
+CMakeLists.txt /cmake/      @evpobr
+
+# Ogg Opus format
+/src/ogg_opus.c             @arthurt
+
+# Documentation
+/doc/ /man/                 @evpobr
index 71f1226..afdcb55 100644 (file)
@@ -1,5 +1,19 @@
-## Submitting Patches.
+# Contributing
 
+## Submitting Issues
+
+* If your issue is that libsndfile is not able to or is incorrectly reading one
+  of your files, please include the output of the `sndfile-info` program run
+  against the file.
+* If you are writing a program that uses libsndfile and you think there is a bug
+  in libsndfile, reduce your program to the minimal example, make sure you compile
+  it with warnings on (for GCC I would recommend at least `-Wall -Wextra`) and that
+  your program is warning free, and that is is error free when run under Valgrind
+  or compiled with AddressSanitizer.
+
+## Submitting Patches
+
+* Patches should pass all existing tests
 * Patches should pass all pre-commit hook tests.
 * Patches should always be submitted via a either Github "pull request" or a
   via emailed patches created using "git format-patch".
index 6257617..3843688 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-2013-04-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
+For changes, please see the git commit history on github:
 
-    * Makefile.am
-    Make sure checkprograms are built as part of 'make test-tarball'.
-    Closes: https://github.com/erikd/libsndfile/issues/37
-
-2013-03-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/dft_cmp.c
-    Fix a buffer overflow detected using GCC 4.8's -fsantiize=address runtime
-    error checking functionality. This was a buffer overflow in libsndfile's
-    test suite, not in the actual library code.
-
-2013-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/gcc_version.m4
-    Fix to work with OpenBSD's sed.
-
-2013-03-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ALAC/alac_encoder.c
-    Patch from Michael Pruett (author of libaudiofile) to add correct byte
-    swapping for the mChannelLayoutTag field.
-
-2013-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/bugs.html
-    Bugs should bt reported on the github issue tracker.
-
-2013-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Improve sanitization of FLAC_CFLAGS value.
-
-2013-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/Makefile.am
-    Call python interpreter instead of using '#!' in script. Thanks to Jan
-    Stary for reporting this.
-
-    * doc/index.html doc/FAQ.html
-    Make internal links relative. Patch from Jan Stary.
-
-2013-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_endswap.def src/test_endswap.tpl
-    Add tests for psf_put_be32() and psf_put_be64().
-
-    * src/sfendian.h src/test_endswap.(def|tpl)
-    Add functions psf_get_be(16|32|64) with tests.
-    These are needed for platforms where un-aligned accesses cause bus faults.
-
-    * src/ALAC/ag_enc.c src/ALAC/alac_decoder.c
-    Replace all un-aligned accesses with safe alternatives.
-    Closes: https://github.com/erikd/libsndfile/issues/19
-
-2013-02-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.h
-    Add big endian versions of H2BE_16 and H2BE_32.
-
-2013-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ALAC/
-    Replace Apple endswap routines with ones from libsndfile.
-
-    * merge from libsndfile-cart repo
-    Add ability to set and get a cart chunk with WAV and RF64.
-    Orignal patch by Chris Roberts <c.roberts@csrfm.com> required a number of
-    tweaks.
-
-2013-02-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Bump SF_HEADER_LEN from 8192 to 12292, the value it was in the 1.0.25
-    release.
-
-2013-02-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alac.c
-    Fix segfault when encoding 8 channel files.
-    Closes: https://github.com/erikd/libsndfile/issues/30
-
-2013-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ALAC/EndianPortable.c
-    Fall back to compiler's __BYTE_ORDER__ for endian-ness detection.
-
-2013-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/common.h src/ima_adpcm.c src/ms_adpcm.c src/paf.c
-    Drop tests for and #ifdef hackery for C99 struct flexible array feature.
-    libsndfile assumes the compiler supports most of the ISO C99 standard.
-
-    * src/alac.c
-    Fix valgrind invalid realloc. Reported by nu774.
-    Closes: https://github.com/erikd/libsndfile/issues/31
-
-2013-02-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alac.c
-    The 'pakt' chunk header should now be written correctly.
-    Closes: https://github.com/erikd/libsndfile/issues/24
-
-    * configure.ac Makefile.am
-    Use PKG_INSTALLDIR when it exists. Suggestion from Christoph Thompson.
-    Closes: https://github.com/erikd/libsndfile/pull/28
-
-2013-02-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/caf.c
-    Read the ALAC 'pakt' header and stash the values.
-
-    * src/sfendian.h
-    Add functions psf_put_be64() and psf_put_be32().
-
-    * src/alac.c
-    Start work on filling on the 'pakt' chunk header.
-
-2013-02-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Add missing opening <P> tag.
-
-    * src/alac.c
-    Increase ALAC_BYTE_BUFFER_SIZE to 82000.
-
-2013-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Improve question #8.
-
-2013-01-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg_opus.c
-    Add skeleton implementation so someone else can run with it.
-
-2012-12-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/dwd.c src/rx2.c src/txw.c
-    Fix for compiling when configured with --enable-experimental. Thanks to
-    Eric Wong for reporting this.
-
-2012-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac programs/sndfile-play.c
-    OS X 10.8 uses a different audio API to previous versions.
-    Fix compile failure on by disabling sndfile-play on this version.
-    Someone needs to supply code for the new API.
-
-2012-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Octave/Makefile.am Octave/octave_test.sh
-    Fix 'make distcheck'.
-
-2012-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/octave.m4
-    Relax constraints on Octave version.
-
-2012-10-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl
-    Improve compare_*_or_die() functions.
-
-    * src/command.c
-    Fix bug reported by Keiler Florian. When reading short or int data from a
-    file containing float data, and setting SFC_SET_SCALE_FLOAT_INT_READ to
-    SF_TRUE would fail 3, 5, 7 and other channels counts. Problem was that
-    psf_calc_signal_max() was not calculating the signal max correctly.
-    Calculation of the signal max was failing because it was trying to read
-    a sample count that was not an integer multiple of the channel count.
-
-    * tests/channel_test.c tests/Makefile.am tests/test_wrapper.sh.in
-    Add test for the above.
-
-2012-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Added a constructor to allow the use of SF_VIRTUAL_IO. Patch from
-    DannyDaemonic : https://github.com/erikd/libsndfile/pull/20
-
-2012-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/octave.html
-    Fix link to octave.sourceforge.net. Thanks to IOhannes m zmoelnig.
-
-    * src/mat5.c
-    Allow reading of mat5 files without a specified sample rate (default to
-    44.1kHz). Thanks to IOhannes m zmoelnig.
-
-2012-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    Error out if channel count is zero. Bug report from William ELla via
-    launchpad:
-    https://bugs.launchpad.net/ubuntu/+source/libsndfile/+bug/1036831
-
-2012-08-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac programs/sndfile-play.c
-    Patch from Ricci Adams to use OSX's AudioQueues on OSX 10.7 and greater.
-
-2012-07-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/common.c
-    Accept "ogg" as a file extention for Ogg/Vorbis files.
-
-2012-06-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Make sure any previously allocated FLAC stream encoder and stream decoder
-    objects are deleted before a new one is allocated.
-
-2012-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl
-    Rename gen_lowpass_noise_float() to gen_lowpass_signal_float() and add a
-    sine wave component so that different FLAC compression levels can be
-    tested.
-
-    * src/sndfile.h.in doc/command.html
-    Add SFC_SET_COMPRESSION_LEVEL and document it.
-
-    * src/sndfile.c
-    Catch SFC_SET_VBR_ENCODING_QUALITY command and implement it as the inverse
-    of SFC_SET_COMPRESSION_LEVEL.
-
-    * src/ogg_vorbis.c src/flac.c
-    Implement SFC_SET_COMPRESSION_LEVEL command.
-
-    * tests/test_wrapper.sh.in tests/compression_size_test.c
-    Use the compression_size_test on FLAC as well.
-
-2012-06-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/
-    Rename vorbis_test.c -> compression_size_test.c so it can be extended to
-    test FLAC as well.
-
-2012-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c
-    Fix a bug where a file with a 'bext' chunk with a zero length coding
-    history field would get corrupted when the file was closed.
-    Reported by Paul Davis of the Ardour project.
-
-    * src/test_broadcast_var.c
-    Add a test for the above.
-
-2012-05-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    sf_format_check: For SF_FORMAT_AIFF, reject endian-ness setttings for
-    non-PCM formats.
-
-2012-04-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix regression in handling of odd length SSND chunks.
-    Thanks Olivier Tristan for the example file.
-
-    * src/aiff.c src/wav.c
-    Exit parser loop when marker == 0.
-
-2012-04-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Fix text. Thanks to Richard Collins.
-
-2012-03-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/caf.c
-    Exit parse loop if the marker is zero. Pass jump offsets as size_t instead
-    of int.
-
-2012-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alac.c
-    Fix segfault when decoding CAF/ALAC file with more than 4 channels.
-    Fixes github issue #8 reported by Charles Van Winkle.
-
-2012-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Change 'typedef SF_CHUNK_ITERATOR { ... } SF_CHUNK_ITERATOR' into 'struct
-    SF_CHUNK_ITERATOR { ... }' to prevent older compilers from complaining of
-    re-typedef-ing of SF_CHUNK_ITERATOR.
-
-    * configure.ac
-    Fix if test for empty $prefix.
-
-2012-03-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c tests/chunk_test.c
-    Reworking of custom chunk handling code.
-    - Memory for the iterator is now attached to the SF_PRIVATE struct and
-      freed one sf_close().
-    - Rename sf_create_chunk_iterator() ->  sf_get_chunk_iterator().
-    - Each SNDFILE handle never has more than one SF_CHUNK_ITERATOR handle.
-
-    * tests/string_test.c
-    Fix un-initialised char buffer.
-
-2012-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c tests/chunk_test.c
-    Add improved handling of custom chunk getting and settings. Set of patches
-    from IOhannes m zmoelnig submitted via github pull request #6.
-
-    * src/alac.c
-    Fix calculated frame count for files with zero block length.
-
-2012-03-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/avr.c
-    Remove double assignment to psf->endian. Thanks Kao Dome.
-
-    * src/gsm610.c
-    Fix clearing of buffers. Thanks Kao Dome.
-
-    * src/paf.c
-    Remove duplicate code. Thanks Kao Dome.
-
-    * src/test_strncpy_crlf.c
-    Fix minor error in test. Thanks Kao Dome.
-
-    * src/common.h src/*.c
-    Fix a bunch of valgrind errors.
-
-2012-03-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix typo in error string 'Uknown' -> 'Unknown'.
-
-    * tests/fix_this.c
-    Fix potential int overflow.
-
-2012-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alac.c
-    Fix decoding of last block so that the decode length is not a multiple of
-    the block length. Fixes github issue #4 reported by Charles Van Winkle.
-
-    * src/sfconfig.h src/sfendian.h
-    Fix for MinGW cross compiling. Use '#if (defined __*66__)' instead of
-    '#if __*86__' because the MinGW header use '#ifdef __x86_64__'.
-
-2012-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ALAC/ src/alac.c
-    Unify the interface between libsndfile and Apple ALAC codec. Regardless of
-    file bit width samples are now passed between the two as int32_t that are
-    justified towards the most significant bit. Without this modification, 16
-    conversion functions would have been needed between the libsndfile (short,
-    int, float, double) types and the ALAC types (16, 20, 24 and 32 bit). With
-    this mod, only 4 are needed.
-
-    * tests/floating_point_test.tpl tests/write_read_test.(def|tpl)
-    Add tests for 20 and 24 bit ALAC/CAF files.
-
-    * src/command.c
-    Add ALAC/CAF to the SFC_GET_FORMAT_* commands. Fixes github issue #5.
-
-    * configure.ac
-    Only use automake AM_SLIENT_RULES where supported. Thanks Dave Yeo.
-
-    * tests/pipe_test.tpl
-    Disable tests on OS/2. Thanks Dave Yeo.
-
-2012-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/sfconfig.h src/sfendian.h
-    For GCC, use inline assembler for endian swapping. This should work with
-    older versions of GCC like the one currently used in OS/2.
-
-2012-03-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alac.c
-    Make sure temp file gets opened in binary mode.
-
-    * src/alac.c src/common.c src/common.h
-    Fix function alac_write16_d().
-
-    * tests/floating_point_test.tpl
-    Add tests for 16 bit ALAC/CAF.
-
-    * src/alac.c src/common.c src/common.h
-    Add support for 32 bit ALAC/CAF files.
-
-    * tests/floating_point_test.tpl tests/write_read_test.tpl
-    Add tests for 32 bit ALAC/CAF files.
-
-2012-03-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/
-    Refactor chunk storage so it work on big as well as little endian CPUs.
-
-    * tests/chunk_test.c
-    Clean up error messages.
-
-    * src/sfendian.h src/*.c
-    Rename endian swapping macros and add ENDSWAP_64 and BE2H_64.
-
-    * configure.ac
-    Detect presence of <x86intrin.h> header file.
-
-    * src/sfendian.h
-    Use <x86intrin.h> intrinsics (ie for MinGW) when <byteswap.h> is not
-    present.
-    Make ENDSWAP_64() work with i686-w64-mingw32 compiler.
-
-    * src/ALAC/EndianPortable.c
-    Add support for __powerpc__.
-
-    * src/sfconfig.h
-    Make sure HAVE_X86INTRIN_H is either 1 or 0.
-
-2012-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ALAC/*
-    Big dump of code for Apple's ALAC file format. The copyyright to this code
-    is owned by Apple who have released it under an Apache style license. A few
-    small modifications were made to allow this to be integrated into libsndfile
-    but unfortunately the history of those changes were lost because they were
-    developed in a Bzr tree and during that time libsndfile moved to Git.
-
-    * src/alac.c src/caf.c src/common.[ch] src/Makefile.am src/sndfile.h.in
-        src/sndfile.c
-    Hook new ALAC codec in.
-
-    * programs/sndfile-convert.c
-    Add support for alac codec.
-
-    * tests/write_read_test.tpl
-    Expand tests to cover ALAC.
-
-2012-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/wav.c
-    Fix a couple of regressions from version 1.0.25.
-
-2012-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/strings.c
-    Minor refactoring. Make sure that the memory allocation size if always > 0
-    to avoid undefined behaviour.
-
-2012-02-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/chunk.c
-    Fix buffer overrun introduced in recently added chunk logging. This chunk
-    logging has not yet made it to a libsndfile release version. Thanks to
-    Olivier Tristan for providing an example file.
-
-    * src/wav.c
-    Fix handling of odd sized chunks which was causing the parser to lose some
-    chunks. Thanks to Olivier Tristan for providing an example file.
-
-2012-02-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/util.tpl
-    Used gnu_printf format checking with mingw-w64 compiler.
-
-    * tests/header_test.tpl
-    Printf format fixes.
-
-2012-02-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/extra_pkg.m4
-    Update PKG_CHECK_MOD_VERSION macro to add an AC_TRY_LINK step. This fix
-    allows the configure process to catch attempts to link incompatible
-    libraries. For example, linking 32 bit version of eg libFLAC to a 64 bit
-    version of libsndfile will now fail. Similarly, when cross compiling
-    libsndfile from Linux to Windows linking the Linux versions of a library
-    to the Windows version of libsndfile will now also fail.
-
-    * src/sndfile.h.in src/sndfile.c src/common.h src/create_symbols_file.py
-    Add API function sf_current_byterate().
-
-    * src/dwvw.c src/flac.c src/ogg_vorbis.c src/sds.c
-    Add codec specific handlers for current byterate.
-
-    * tests/floating_point_test.tpl
-    Add initial test for sf_current_byterate().
-
-2012-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.[ch]
-    Add function psf_decode_frame_count().
-
-    * src/dwvw.c
-    Fix a termnation bug that caused the decoder to go into an infinite loop.
-
-2012-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fix a regression in the WAV header parser. Thanks to Olivier Tristan for
-    bug report and the example file.
-
-2012-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Return error when SF_BROADCAST_INFO struct has bad coding_history_size.
-    Thanks to Alex Weiss for the report.
-
-2012-02-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c src/flac.c src/g72x.c src/ogg_vorbis.c src/wav_w64.c
-    Don't fake psf->bytewidth values.
-
-2012-02-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/string_test.c
-    Fix valgrind warnings.
-
-    * src/common.h src/sndfile.c src/strings.c
-    Make string storage dynamically allocated.
-
-    * src/sndfile.c
-    Add extra validation for custom chunk handling.
-
-2012-02-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Improve handlling unknown chunk types. Thanks to Olivier Tristan for sending
-    example files.
-
-    * src/utils.tpl
-    Add GCC specific testing for format string parameters for exit_if_true().
-
-    * tests/*.c tests/*.tpl
-    Fix all printf format warnings.
-
-    * programs/sndfile-play.c
-    Remove un-needed OSX include <Carbon.h>. Thanks jamesfmilne for github
-    issue #3.
-
-    * tests/chunk_test.c
-    Extend custom chunk test.
-
-2012-02-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Jump over some more chunk types while parsing.
-
-2012-02-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/strings.c
-    Change way strings are stored in SF_PRIVATE in preparation for dynamically
-    allocating the storage.
-
-2012-02-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src*.c
-    Improve encapsulation of string data in SF_PRIVATE.
-
-2012-02-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src*.c
-    Remove the buffer union from SF_PRIVATE. Most uses of this have been
-    replaced with a BUF_UNION that is allocated on the stack.
-
-2012-01-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src*.c
-    Rename logbuffer field of SF_PRIVATE to parselog and reduce its size.
-    Put the parselog buffer and the index inside a struct within SF_PRIVATE.
-
-2012-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fix typo, FLAC_CLFAGS -> FLAC_CFLAGS. Thanks to Jeremy Friesner.
-
-2012-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/ogg.c
-    Fix misleading error message when trying to create an SF_FORMAT_OGG file
-    with anything other than SF_FORMAT_FILE. Thanks to Charles Van Winkle for
-    the bug report. Github issue #1.
-
-2012-01-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/wav.c
-    Allow files opened in RDWR mode with string data in the tailer to be
-    extended. Thanks to Bodo for the patch.
-
-    * tests/string_test.c
-    Add tests for the above changes (patch from Bodo).
-
-2012-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Refactor reading of chunk size and use of psf_store_read_chunk().
-
-    * src/(caf|wav).c
-    Correct storing of chunk offset.
-
-2012-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/wav.c src/common.h
-    Refactor common code into src/common.h.
-
-    * src/caf.c
-    Make custom chunks work for CAF files.
-
-    * tests/chunk_test.c tests/test_wrapper.sh.in
-    Test CAF files with custom chunks.
-
-    * src/sndfile.c
-    Prevent psf->codec_close() being called more than once.
-
-2012-01-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-cmp.c
-    Catch the case where the second file has more frames than the first.
-
-2012-01-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/create_symbols_file.py
-    Add sf_set_chunk/sf_get_chunk_size/sf_get_chunk_data.
-
-2011-12-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/chunk_test.c tests/Makefile.am
-    New test for custom chunks.
-
-    * src/aiff.c src/chunk.c src/common.h src/sndfile.c
-    Make custom chunks work on AIFF files.
-
-    * src/wav.c
-    Make custom chunks work on WAV files (includes refactoring).
-
-2011-11-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/common.h src/sndfile.c
-    Start working on setting/getting chunks.
-
-2011-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/binheader_writef_check.py src/create_symbols_file.py
-    Make it work for Python 2 and 3. Thanks Michael.
-
-2011-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * libsndfile.spec.in
-    Change field name 'URL' to 'Url'.
-
-    * src/sndfile.h.in
-    Add SF_SEEK_SET/CUR/END.
-
-2011-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/id3.c
-    Fix a stack overflow that can occur when parsing a file with multiple
-    ID3 headers which would cause libsndfile to go into an infinite recursion
-    until it blew the stack. Thanks to Anders Svensson for supplying an example
-    file.
-
-2011-10-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/double64.c src/float32.c src/common.h
-    Make (float32|double_64)_(be|le)_read() functions const correct.
-
-2011-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.h
-    Minor tweaking of types. Cast to ptr to correct final type rather void*.
-
-    * programs/sndfile-play.c tests/utils.tpl
-    Fix compiler warnings with latest MinGW cross compiler.
-
-2011-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Use the non-deprecated resource fork name on OSX. Thanks to Olivier Tristan.
-
-2011-10-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Jump over the 'olym' chunks when parsing.
-
-2011-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Remove windows only truncate() implementation.
-
-2011-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c src/sndfile.c
-    Make sure 23 bit PCM SD2 files are readable/writeable.
-
-    * tests/write_read_test.tpl
-    Add tests for 32 bit PCM SD2 files.
-
-2011-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Use AC_SYS_LARGEFILE instead of AC_SYS_EXTRA_LARGEFILE as suggested by
-    Jan Willies.
-
-2011-08-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac Makefile.am
-    Move ACLOCAL_AMFLAGS setup to Makefile.am.
-
-2011-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Merge two separate blocks of SFC_SET_VBR_ENCODING_QUALITY documentation.
-
-    * src/paf.c
-    Replace ppaf24->samplesperblock with a compile time constant.
-
-2011-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg_vorbis.c
-    Fix return value of SFC_SET_VBR_ENCODING_QUALITY command.
-
-    * doc/command.html
-    Document SFC_SET_VBR_ENCODING_QUALITY, SFC_GET/SET_LOOP_INFO and
-    SFC_GET_INSTRUMENT.
-
-    * NEWS README configure.ac doc/*.html
-    Updates for 1.0.25.
-
-2011-07-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfconfig.h
-    Add handling for HAVE_SYS_WAIT_H.
-
-    * Makefile.am src/Makefile.am tests/Makefile.am
-    Add 'checkprograms' target.
-
-2011-07-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/sndfile.c
-    Purge SF_ASSERT macro. Use standard C assert instead.
-
-    * src/paf.c src/common.h src/sndfile.c
-    Fix for Secunia Advisory SA45125, heap overflow (heap gets overwritten with
-    byte value of 0) due to integer overflow if PAF file handler.
-
-    * src/ima_adpcm.c src/ms_adpcm.c src/paf.c
-    Use calloc instead of malloc followed by memset.
-
-    * tests/utils.tpl
-    Clean up use of memset.
-
-2011-07-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c
-    Fix log message.
-
-    * tests/format_check_test.c
-    Fix compiler warnings.
-
-2011-07-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix error message for erro code SFE_ZERO_MINOR_FORMAT.
-
-    * tests/format_check_test.c
-    Add a test to for SF_FINFO format field validation.
-
-    * src/ogg.c src/ogg_vorbis.c src/ogg.h src/ogg_pcm.c src/ogg_speex.c
-        src/common.h src/Makefile.am
-    Move vorbis specific code to ogg_vorbis.c, add new files for handling PCM
-    and Speex codecs in an Ogg container. The later two are only enabled with
-    ENABLE_EXPERIMENTAL_CODE config variable.
-
-2011-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/strings.c
-    Clean up and refactor storage of SF_STR_SOFTWARE.
-
-2011-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in doc/api.html
-    Fix definition of SF_STR_LAST and update SF_STR_* related docs. Thanks to
-    Tim van der Molen for the patch.
-
-2011-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-interleave.c
-    Fix handling of argc. Thanks to Marius Hennecke.
-
-    * src/wav_w64.c
-    Accept broken WAV files with blockalign == 0. Thanks to Olivier Tristan for
-    providing example files.
-
-    * src/wav.c
-    Jump over 'FLLR' chunks.
-
-2011-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Fix -Wundef warning due to ENABLE_SNDFILE_WINDOWS_PROTOTYPES.
-
-    * configure.ac
-    Add -Wundef to CFLAGS.
-
-    * src/ogg.c
-    Fix -Wunder warning.
-
-2011-05-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Use int64_t instead of off_t when they are the same size.
-
-    * src/Makefile.am tests/Makefile.am
-    Use check_PROGRAMS instead of noinst_PROGRAMS where appropriate.
-
-2011-05-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Don't allow unknown and/or un-editable chunks to prevent the file from being
-    opened in SFM_RDWR mode.
-
-2011-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/format_check_test.c
-    Fix segfault in test program.
-
-2011-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/format_check_test.c
-    New test program to check to make sure that sf_open() and sf_check_format()
-    agree as to what is a valid program.
-
-    * tests/Makefile.am tests/test_wrapper.sh.in
-    Hook into build and test runner.
-
-    * src/sndfile.c
-    Fix some sf_format_check() problems. Thanks to Charles Van Winkle for the
-    notification.
-
-2011-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/caf.c
-    Add validation to size of 'data' chunk and fix size of written 'data'
-    chunk. Thanks to Michael Pruett for reporting this.
-
-2011-03-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/* tests/* programs/*
-    Fix a bunch of compiler warnings with gcc-4.6.
-
-2011-03-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/util.tpl
-    Add NOT macro to util.h.
-
-    * src/strings.c
-    Fix handling of SF_STR_SOFTWARE that resulted in a segfault due to calling
-    strlen() on an unterminated string. Thanks to Francois Thibaud for reporting
-    this problem.
-
-    * tests/string_test.c
-    Add test for SF_STR_SOFTWARE segfault bug.
-
-    * configure.ac
-    Sanitize FLAC_CFLAGS value supplied by pkg-config which returns a value of
-    '-I${includedir}/FLAC'. However FLAC also provides an include file
-    <assert.h> which clashes with the Standard C header of the same name. The
-    solution is strip the 'FLAC' part off the end and include all FLAC headers
-    as <FLAC/header.h>.
-
-    * configure.ac src/Makefile.am
-    Use non-recursive make in src/ directory.
-
-2011-03-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * NEWS README docs/*.html
-    Updates for 1.0.24 release.
-
-2011-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fix up usage of sed (should not assume GNU sed).
-
-    * M4/add_(c|cxx)flags.m4
-    Test flags in isolation.
-
-    * tests/cpp_test.cc
-    Fix a broken test (test segfaults). Report by Dave Flogeras.
-
-2011-03-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/common.[ch]
-    Add function program_name() which returns the program name minus the path
-    from argv [0].
-
-    * programs/*.c programs/Makefile.am
-    Use program_name() where appropriate. Fix build.
-
-2011-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    For u-law and A-law files, write an 18 byte 'fmt ' chunk instead of a 16
-    byte one. Win98 accepts files with a 16 but not 18 byte 'fmt' chunk. Later
-    version accept 18 byte but not 16 byte.
-
-2011-03-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Add examples for question 12.
-
-    * doc/libsndfile.css.in
-    Add tweaks for h4 element.
-
-    * doc/api.html
-    Add documentation for virtual I/O functionality. Thanks to Uli Franke.
-
-    * tests/util.tpl
-    Add static inline functions sf_info_clear() and sf_info_setup().
-
-    * tests/(alaw|dwvw|ulaw)_test.c
-    Use functions sf_info_clear() and sf_info_setup().
-
-2011-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fail more gracefully if pkg-config is missing. Suggestion from Brian
-    Willoughby.
-
-2011-02-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Use size_t instead of int for size params with varargs.
-
-2011-02-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Update supported platforms with more Debian platforms and Android.
-
-2011-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add an LPCWSTR version of the SndfileHandle constructor to the SndfileHandle
-    class definition. Thanks to Eric Eizenman for pointing out this was missing.
-
-    * tests/cpp_test.cc
-    Add test for LPCWSTR version of the SndfileHandle constructor.
-
-2011-01-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-play.c
-    Remove cruft.
-
-2010-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add methods rawHandle() and takeOwnership(). Thanks to Tim Blechmann for
-    the patch.
-
-    * tests/cpp_test.cc
-    Add tests for above two methods. Also supplied by Tim Blechmann.
-
-2010-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Add mention of use of sf_strerror() when sf_open() fails.
-
-2010-11-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Make TYPEOF_SF_COUNT_T int64_t where possible. This may fix problems where
-    people are compiling on a 64 bit system with the GCC -m32 flag.
-
-    * src/sndfile.h.in
-    Fix comments on sf_count_t.
-
-2010-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Handle non-zero offset field in SSND chunk. Thanks to Michael Chinen.
-
-2010-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Sed fix for FreeBSD. Thanks Tony Theodore.
-
-2010-10-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * shave.in M4/shave.m4
-    Fix shave invocation of windres compiler. Thanks Damien Lespiau (upstream
-    shave author).
-
-    * configure.ac M4/shave.m4 shave-libtool.in shave.in
-    Switch from shave to automake-1.11's AM_SILENT_RULES.
-
-2010-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * shave-libtool.in shave.in
-    Sync to upstream version.
-
-    * src/rf64.c
-    More work to make the parser more robust and accepting of mal-formed files.
-
-2010-10-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add functions psf_strlcpy() and psf_strlcat().
-
-    * src/broadcast.c src/sndfile.c src/strings.c src/test_main.c
-        src/test_main.h src/test_strncpy_crlf.c
-    Use functions psf_strlcpy() and psf_strlcat() as appropriate.
-
-    * tests/string_test.c
-    Add tests for SF_STR_GENRE and SF_STR_TRACKNUMBER.
-
-    * src/rf64.c
-    Fix size of 'ds64' chunk when writing RF64.
-
-2010-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/*.c
-    Add the libsndfile version to the usage message of all programs.
-
-2010-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/version-metadata.rc.in src/Makefile.am
-    Add version string resources to the windows DLL.
-
-    * doc/api.html
-    Update to add missing SF_FORMAT_* values. Closed Debian bug #545257.
-
-    * NEWS README configure.ac doc/*.html
-    Updates for 1.0.23 release.
-
-2010-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pedantic-header-test.sh.in
-    Handle unusual values of CC environment variable.
-
-    * src/rf64.c
-    Minor tweaks and additional sanity checking.
-
-    * src/Makefile.am src/binheader_writef_check.py
-    Use python 2.6.
-
-2010-10-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add a missing 'inline' before a constructor defintion.
-
-2010-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add macro NOT.
-
-    * src/rf64.c
-    Minor tweaks.
-
-    * Makefile.am */Makefile.am
-    Add *~ to CLEANFILES.
-
-2010-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix a typo in the error string for SFE_OPEN_PIPE_RDWR. Thanks to Charles
-    Van Winkle for the report.
-
-2010-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c src/ogg.c src/sndfile.h.in src/strings.c src/wav.c
-    Add ability to read/write tracknumber and genre to flac/ogg/wav files.
-    Thanks to Matti Nykyri for the patch.
-
-    * src/common.h src/broadcast.c src/strings.c
-    Add function psf_safe_strncpy() and use where appropriate.
-
-2010-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * NEWS README configure.ac doc/*.html
-    Updates for 1.0.22 release.
-
-2010-10-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/broadcast.c src/rf64.c src/sndfile.c src/wav.c
-    Rewrite of SF_BROADCAST_INFO handling.
-
-    * src/test_broadcast_var.c tests/command_test.c
-    Tweak SF_BROADCAST_INFO tests.
-
-    * src/test_broadcast_var.c
-    Fix OSX stack check error.
-
-2010-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sds.c
-    Set sustain_loop_end to 0 as suggested by Brian Lewis.
-
-2010-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sds.c
-    Make sure the correct frame count gets written into the header.
-
-    * tests/write_read_test.tpl
-    Don't allow SDS files to have a long frame count.
-
-2010-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sds.c
-    Apply a pair of patches from Brian Lewis to fix the packet number location
-    and the checksum.
-
-2010-09-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    *  src/aiff.c src/file_io.c src/ogg.c src/rf64.c src/sndfile.c
-        src/strings.c src/test_audio_detect.c src/test_strncpy_crlf.c
-        src/wav.c tests/pcm_test.tpl
-   Fix a bunch of minor issues found using static analysis.
-
-2010-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_broadcast_var.c
-    New file containing tests for broadcast_set_var().
-
-    * src/Makefile.am src/test_main.[ch]
-    Hook test_broadcast_var.c into tests.
-
-2010-08-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c src/common.(c|h)
-    Move function strncpy_crlf() to src/common.c so the function can be tested
-    in isolation.
-
-    * src/test_strncpy_crlf.c
-    New file.
-
-    * src/Makefile.am src/test_main.[ch]
-    Hook test_strncpy_crlf.c into tests.
-
-2010-08-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Move code around to make comments make sense.
-
-    * src/broadcast.c
-    Add debugging code that is disabled by default.
-
-2010-08-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    When the file meta data says the file has zero frames set psf->sf.frames
-    to SF_COUNT_MAX. Fixes Debian bug #590752.
-
-    * programs/sndfile-info.c
-    Print 'unknown' if frame count == SF_COUNT_MAX.
-
-2010-06-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Only support writing mono SVX files. Multichannel SVX files are not
-    interleaved and there is no support infrastructure to cache and write
-    multiple channels to create a non-interleaved file.
-
-    * src/file_io.c
-    Don't call close() on a file descriptor of -1. Thanks to Jeremy Friesner
-    for the bug report.
-
-2010-06-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add macro SF_ASSERT.
-
-    * src/sndfile.c
-    Use SF_ASSERT to ensure sizeof (sf_count_t) == 8.
-
-    * src/svx.c
-    Add support for reading and writing stereo SVX files.
-
-2010-05-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    When compiling with x86_64-w64-mingw32-gcc link with -static-libgcc flags.
-
-    * programs/common.c programs/sndfile-metadata-set.c
-    Update metadata after the audio data is copied. Other minor fixes. Patch
-    from Marius Hennecke.
-
-2010-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    Fix a regression reported by Hugh Secker-Walker.
-
-    * src/api.html
-    Add comment about sf_open_fd() not working on Windows if the application
-    and the libsndfile DLL are linked to different versions of the Microsoft
-    C runtime DLL.
-
-2010-04-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pedantic-header-test.sh.in
-    Fix 'make distcheck'.
-
-2010-04-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pedantic-header-test.sh.in
-    New file to test whether sndfile.h can be compiled with gcc's -pedantic
-    flag.
-
-    * configure.ac tests/test_wrapper.sh.in
-    Hook pedantic-header-test into test suite.
-
-    * src/sndfile.h.in
-    Fix -pedantic warning.
-
-2010-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-salvage.c programs/Makefile.am
-    New program to salvage the audio data from WAV/WAVEX/AIFF files which are
-    greater than 4Gig in size.
-
-2010-04-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-convert.c
-    Fix valgrind warning.
-
-2010-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-cmp.c
-    When files differ in the PCM data, also print the difference offset.
-    Minor cleanup.
-
-2010-03-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Don't use the 'twos' marker for 24 and 32 bit PCM, use 'in24' and 'in32'
-    instead. Thanks to Paul Davis (Ardour) for this suggestion.
-
-2010-02-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Clean up configure report.
-
-    * tests/utils.tpl
-    Add functions test_read_raw_or_die and test_write_raw_or_die.
-
-    * tests/rdwr_test.(def|tpl) tests/Makefile.am
-    Add new test program and hook into build.
-
-    * src/sndfile.c
-    Fix minor issues with sf_read/write_raw(). Bug reported by Milan Křápek.
-
-    * tests/test_wrapper.sh.in
-    Add rdwr_test to the test wrapper script.
-
-2010-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Remove -fpascal-strings from OSX's OS_SPECIFIC_CFLAGS.
-
-    * programs/common.[ch] programs/sndfile-metadata-set.c
-    Apply a patch from Robin Gareus allowing the setting of the time reference
-    field of the BEXT chunk.
-
-2010-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ima_adpcm.c
-    Add a fix from Jonatan Liljedahl to handle predictor overflow when decoding
-    IMA4.
-
-2010-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add a constructor which takes an existing file descriptor and then calls
-    sf_open_fd(). Patch from Sakari Bergen.
-
-2010-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-deinterleave.c programs/sndfile-interleave.c
-    Improve usage messages.
-
-2010-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/id3.c src/Makefile.am
-    Add new file src/id3.c and hook into build.
-
-    * src/sndfile.c src/common.h
-    Detect and skip and ID3 header at the start of the file.
-
-2010-01-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/common.c
-    Fix update_strings() copyright, comment, album and license are correctly
-    written. Thanks to Todd Allen for reporting this.
-
-    * man/Makefile.am
-    Change GNU makeism to something more widely supported. Thanks to Christian
-    Weisgerber for reporting this.
-
-    * configure.ac programs/Makefile.am programs/sndfile-play.c
-    Apply patch from Christian Weisgerber and Jacob Meuserto add support for
-    OpenBSD's sndio.
-
-2010-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Discourage the use of sf_read/write_raw().
-
-2009-12-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Test for Unix pipe() and waitpid() functions.
-
-    * src/sfconfig.h tests/pipe_test.tpl
-    Disable pipe_test if pipe() and waitpid() aren't available.
-
-2009-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/Makefile.am src/create_symbols_file.py
-        src/make-static-lib-hidden-privates.sh
-    Change name of generated file src/Symbols.linux to Symbols.gnu-binutils and
-    and use the same symbols file for other systems which use GNU binutils like
-    Debian's kfreebsd.
-
-    * M4/shave.m4 shave.in
-    Update shave files from upstream.
-
-2009-12-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * man/sndfile-metadata-get.1
-    Fix typo.
-
-    * man/sndfile-interleave.1 man/Makefile.am
-    New man page.
-
-2009-12-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c
-    When decoding to short or int, clip the decoded signal to [-1.0, 1.0] if
-    its too hot. Thanks to Dmitry Baikov for suggesting this.
-
-    * NEWS README doc/*.html
-    Updates for 1.0.21.
-
-2009-12-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-jackplay.c man/sndfile-jackplay.1
-    Remove these which will now be in found in the sndfile-tools package.
-
-    * programs/Makefile.am man/Makefile.am
-    Remove build rules for sndfile-jackplay.
-
-    * configure.ac
-    Remove detection of JACK Audio Connect Kit.
-
-    * programs/sndfile-concat.c man/sndfile-concat.1
-    Add new program with man page.
-
-    * man/Makefile.am programs/Makefile.am
-    Hook sndfile-concat into build system.
-
-2009-12-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/error_test.c
-    Don't terminate when sf_close() returns zero in error_close_test().
-    It seems that Windows 7 behaves differently from earlier versions of
-    Windows.
-
-2009-12-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac M4/*.m4
-    Rename all custom macros from AC_* to MN_*.
-
-    * programs/sndfile-interleave.c
-    Make it actually work.
-
-2009-12-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/*.html configure.ac
-    Corrections and clarifications courtesy of Robin Forder.
-
-    * programs/sndfile-convert.c programs/common.[ch]
-    Move some code from convert to common for reuse.
-
-    * programs/sndfile-interleave.c programs/sndfile-interleave.c
-    Add new programs sndfile-interleave and sndfile-deinterleave.
-
-    * programs/Makefile.am
-    Hook new programs into build.
-
-2009-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/create_symbols_file.py tests/stdio_test.c tests/win32_test.c
-    Minor OS/2 tweaks as suggested by David Yeo.
-
-    * tests/multi_file_test.c
-    Fix file creation flags on windows. Thanks to Bruce Sharpe.
-
-    * src/sf_unistd.h
-    Set all group and other file create permssions to zero.
-
-    * tests/win32_test.c
-    Add a new test.
-
-2009-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/print.css doc/*.html
-    Add a print stylesheet and update all HTML documents to reference it.
-    Thanks to Aditya Bhargava for suggesting this.
-
-    * doc/index.html
-    Minor corrections.
-
-2009-11-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * sndfile.pc.in
-    Add a Libs.private entry to assist with static linking.
-
-2009-11-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/make-static-lib-hidden-privates.sh src/Makefile.am
-    Add a script to hide all non-public symbols in the libsndfile.a static
-    library.
-
-2009-11-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/locale_test.c
-    Correct usage of ENABLE_SNDFILE_WINDOWS_PROTOTYPES.
-
-2009-11-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/windows.c
-    Correct usage of ENABLE_SNDFILE_WINDOWS_PROTOTYPES.
-
-2009-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-convert.c
-    Allow the program to read from stdin by specifying '-' on the command line
-    as the input file.
-
-    * src/sndfile.h.in
-    Hash define ENABLE_SNDFILE_WINDOWS_PROTOTYPES to 1 for greater safety.
-
-    * tests/virtual_io_test.c
-    Add a PAF/PCM_24 test and verify the file length is not negative
-    immediately after openning the file for write.
-
-2009-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    When writing loop lengths, adjust the end position by one to make up for
-    Microsoft's screwed up spec. Thanks to Olivier Tristan for the patch.
-
-2009-10-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Apply patch from Uli Franke allowing FLAC files to be encoded at any sample
-    rate.
-
-2009-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    Fix parsing of odd ulaw encoded file provided by Jan Silovsky.
-
-    * configure.ac
-    Insist on libvorbis >= 1.2.3. Earlier verions have bugs that cause the
-    libsndfile test suite to fail on MIPS, PowerPC and others.
-    See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549899
-
-2009-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * man/sndfile-convert.1
-    Fix warning from Debian's lintian checks.
-
-    * man/sndfile-cmp.1 man/sndfile-jackplay.1 man/sndfile-metadata-get.1
-        man/Makefile.am
-    Add three new minimal manpages and hook into build.
-
-2009-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/test_wrapper.sh.in
-    Don't run cpp_test on x86_64-w64-mingw32.
-
-2009-09-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl
-    On windows, make sure the open() function doesn't get called with a third
-    parameter of 0 which fails for no good reason. Also make sure this third
-    parameter doesn't get called with S_IRGRP when compiling for windows because
-    Wine complains.
-
-    * src/sndfile.hh
-    Add a SndfileHandle constructor for windows that takes a 'const wchar_t *'
-    string.
-
-    * doc/FAQ.html
-    Add Q/A : I'm cross compiling libsndfile for another platform. How can I
-    run the test suite?
-
-    * src/create_symbols_file.py src/Makefile.am
-    Add Symbols.static target, a list of symbols, one per line.
-
-2009-09-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/test_wrapper.sh.in
-    Update to allow all tests to be gathered up into a testsuite tarball and
-    then be run using this script.
-
-    * build-test-tarball.mk.in
-    Add a Make script to build a tarball of all the test binaries and the test
-    wrapper script. This is useful for cross compiling; you can build the
-    binaries, build test test tarball and transfer the test tarball to the
-    target machine for testing.
-
-2009-09-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/*.c
-    Modify SF_FILE struct to allow it to carry either 8-bit or 16-bit strings
-    for the file path, directory and name. Fixes for this change throughout.
-
-    * src/windows.c src/Makefile.am
-    New file defining new windows only public function sf_wchar_open() which
-    takes a 'const wchar_t *' string (LPCWSTR) for the file name parameter.
-
-    * src/sndfile.h.in
-    Add SF_CHANNEL_MAP_ABISONIC_* entries.
-    Add windows only defintion for sf_wchar_open().
-
-    * src/create_symbols_file.py
-    Add sf_wchar_open() to the list of public symbols (windows only).
-
-    * tests/locale_test.c
-    Add a wchar_test() to test sf_wchar_open().
-
-2009-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/*.c
-    Split file stuff into PSF_FILE struct within the SF_PRIVATE struct.
-
-2009-09-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/voc.c
-    When a byte is needed, use unsigned char.
-
-    * src/ima_oki_adpcm.c src/broadcast.c src/test_ima_oki_adpcm.c
-    Include sfconfig.h to prevent compile errors with MinGW compilers.
-
-    * configure.ac
-    Remove AM_CONFIG_HEADER due to warnings from autoconf 2.64.
-
-    * tests/locale_test.c
-    Update to work with xx_XX.UTF-8 style locales. Refactoring.
-
-2009-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Set __USE_MINGW_ANSI_STDIO to 1 when compiling using MinGW compilers.
-    Remove unneeded AC_SUBST.
-    Report Host CPU/OS/vendor.
-
-2009-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix error message string.
-
-    * src/flac.c
-    Add 88200 to the list of supported sample rates.
-
-    * src/ogg.c
-    Fix compiler warning when using gcc-4.5.0.
-
-    * programs/sndfile-info.c tests/utils.tpl
-    Remove WIN32 snprintf #define.
-
-    * src/ima_adpcm.c
-    Fix minor bug in aiff_ima_encode_block. Thanks to Denis Fileev for finding
-    this.
-
-2009-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/caf.c
-    Use the correct C99 format specifier for int64_t.
-
-    * M4/endian.m4
-    Fix detection of CPU endian-ness when cross compiling. Thanks to Pierre
-    Ossman for the bug report.
-
-    * src/caf.c src/sndfile.c
-    Fix reading and writing of PEAK chunks in CAF files.
-
-    * tests/peak_chunk_test.c tests/test_wrapper.sh.in
-    Run peak_chunk_test on CAF files.
-
-2009-09-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/wav.c
-    Use the correct C99 format specifier for int64_t.
-
-2009-08-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/rf64.c src/sndfile.c src/wav.c src/wav_w64.h
-    Apply a patch (massaged slightly) from Uli Franke adding handling of the
-    BEXT chunk in RF64 files.
-
-    * tests/command_test.c
-    Update channel_map_test() function so WAV test passes.
-
-    * src/rf64.c
-    Add channel mapping and ambisonic support.
-
-    * src/sndfile.h
-    Add comments showing correspondance between libsndfile channel map
-    defintiions and those used by Apple and MS.
-
-    Add handling of reading/writing channel map info.
-
-    * tests/command_test.c tests/test_wrapper.sh.in
-    Update channel map tests.
-
-2009-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add function psf_isprint() a replacement for the standard C isprint()
-    function which ignores any locale settings and treats all input as ASCII.
-
-    * src/(aiff|common|rf64|sd2|strings|svx|wav).c
-    Use psf_isprint() instead of isprint().
-
-2009-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/command.c
-    Add string descriptions for SF_FORMAT_RF64 and SF_FORMAT_MPC2K.
-
-2009-06-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-play.c
-    Allow use of Open Sound System audio output under FreeBSD.
-
-2009-06-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add patch from Conrad Parker to add --disable-jack.
-
-2009-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alaw.c src/float32.c src/htk.c src/pcm.c src/sds.c src/ulaw.c
-    Fix bugs where invalid files can cause a divide by zero error (SIGFPE).
-    Thanks to Sami Liedes for reporting this a Debian bug #530831.
-
-2009-05-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/chanmap.[ch]
-    New files for channel map decoding/encoding.
-
-2009-05-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/sndfile.h.in
-    Fix MSVC definition of sf_count_t.
-
-2009-05-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_w64.[ch]
-    Add wavex_channelmask to WAV_PRIVATE struct and add a function to convert
-    an array of SF_CHANNEL_MASK_* values into a bit mask for use in WAV files.
-
-    * src/wav.c
-    Add ability to write the channel mask.
-
-2009-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-info.c
-    Add -c command line option to dump the channel map information.
-
-    * src/wav_w64.c
-    Don't bail from parser if channel map bitmask is faulty.
-
-    * src/common.h src/sndfile.c
-    Remove error code SFE_W64_BAD_CHANNEL_MAP which is not needed any more.
-
-    * src/sndfile.c
-    On SFC_SET_CHANNEL_MAP_INFO pass the channel map command down to container's
-    command handler.
-
-2009-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/common.h src/sndfile.c src/wav_w64.c
-    Apply a patch from Lennart Poettering (PulseAudio) to allow reading of
-    channel data in WAV and W64 files.
-    Add a test for the above.
-
-2009-05-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FAQ.html
-    Update the section about pre-compiled binaries for Win64.
-
-2009-05-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/test_conversions.c
-    Be more careful when including <stdint.h> so compiling on pre-C99 platforms
-    (hello Slowlaris) might actually work.
-
-    * NEWS README doc/*.html
-    Updates for 1.0.20.
-
-2009-04-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/voc.c
-    Fix a bug whereby opening a specially crafted VOC file could result in a
-    heap overflow. Thanks to Tobias Klein (http://www.trapkit.de) for reporting
-    this issue.
-
-    * src/aiff.c
-    Fix potential (heap) buffer overflow when parsing 'MARK' chunk.
-
-2009-04-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/stdin_test.c
-    Check psf->error after opening file.
-
-    * src/file_io.c
-    Fix obscure seeking bug reported by Hugh Secker-Walker.
-
-    * tests/utils.tpl
-    Add check of sf_error to test_open_file_or_die().
-
-    * src/sndfile.c
-    Clear error if opening resource fork fails.
-
-2009-04-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/alaw_test.c tests/locale_test.c tests/ulaw_test.c
-    Cleanup output.
-
-2009-03-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float32.c
-    Fix f2s_clip_array.
-
-2009-03-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float32.c
-    In host_read_f2s call convert instead of f2s_array.
-
-    * src/ima_adpcm.c
-    Remove dead code.
-
-    * src/test_ima_oki_adpcm.c examples/generate.c tests/dither_test.c
-        tests/dwvw_test.c tests/fix_this.c tests/generate.c
-        tests/multi_file_test.c
-    Minor fixes.
-
-2009-03-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/shave.m4 shave.in
-    Pulled update from upstream.
-
-2009-03-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Add pointers to example programs in source code tarball.
-
-2009-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Define SF_PLATFORM_S64 for non-gcc compilers with 'long long' type.
-
-    * configure.ac
-    Add documentation for --disable-external-libs and improve error handling
-    for that option.
-
-    * src/sndfile.c src/sndfile.h.in src/create_symbols_file.py
-    Add public function sf_version_string.
-
-    * tests/sfversion.c
-    Test function sf_version_string.
-
-    * M4/shave.m4 shave-libtool.in shave.in
-    Add new files from 'git clone git://git.lespiau.name/shave'.
-
-    * configure.ac
-    Enable shave.
-
-    * src/Makefile.am src/binheader_writef_check.py Octave/*
-    Shave related tweaks.
-
-2009-03-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/caf.c src/sndfile.c
-    Add SF_MAX_CHANNELS (set to 256) and use it.
-
-    * src/sndfile.h.in
-    Check for either _MSCVER or _MSC_VER being defined.
-
-2009-03-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/vorbis_test.c
-    Relax test slighly to allow test to pass on more CPUs etc.
-
-2009-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Detect vorbis_version_string() correctly.
-
-2009-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Add a 'See Also' section with a link to sndfile-tools.
-
-    * NEWS README doc/*.html
-    Updates for 1.0.19 release.
-
-    * configure.ac
-    Fix --enable-external-libs logic.
-
-2009-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix resource leak and potential read beyond end of buffer.
-
-    * src/nist.c
-    Fix reading of header value sample_n_bytes.
-
-    * src/sd2.c src/wav.c
-    Fix potential read beyond end of buffer.
-
-    * src/sndfile.c src/svx.c
-    Check return values of file_io functions.
-
-    * tests/win32_test.c
-    Fix resource leak.
-
-    * configure.ac
-    Detect the presence/absence of vorbis_version_string() in libvorbis.
-
-    * src/ogg.c
-    Only call vorbis_version_string() from libvorbis if present.
-
-2009-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/win32_test.c
-    Don't use sprintf, even on windows.
-
-    * src/aiff.c src/rf64.c src/wav.c
-    Eliminate dead code, more validation of data read from file.
-
-2009-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ima_adpcm.c
-    Clamp values to a valid range before indexing ima_step_size array.
-
-    * src/GSM610/*.c tests/*c programs/*.c src/audio_detect.c
-    Don't include un-needed headers.
-
-    * programs/sndfile-info.c
-    Remove dead code.
-
-    * tests/test_wrapper.sh.in
-    Add 'set -e' so the script exits on error.
-
-    * src/test_ima_oki_adpcm.c
-    Fix read beyond end of array.
-
-    * tests/win32_test.c
-    Add missing close on file descriptor.
-
-    * src/nist.c programs/sndfile-metadata-set.c
-    Fix 'unused variable' warnings.
-
-    * src/aiff.c
-    Fix potential memory leak in handling of 'MARK' chunk.
-    Remove un-needed test (unsigned > 0).
-
-    * src/sd2.c
-    Improve handling of heap allocated buffer.
-
-    * src/sndfile.c
-    Remove un-needed test (always true).
-
-    * src/wav.c src/rf64.c
-    Ifdef out dead code that will be resurected some time in the future.
-
-    * src/wav.c src/w64.c src/xi.c
-    Handle error return values from psf_ftell.
-
-    * src/wav_w64.c
-    Fix handling and error checking of MSADPCM coefficient arrays.
-
-    * regtest/*.c
-    Bunch of fixes.
-
-    * src/test_file_io.c
-    Use snprintf instead of strncpy in test program.
-
-2009-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c
-    Validate data before using.
-
-    * src/caf.c
-    Validate channels per frame value before using, fixing a possible integer
-    overflow bug, leading to a possible heap overflow. Found by Alin Rad Pop of
-    Secunia Research (CVE-2009-0186).
-
-2009-02-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Octave/octave_test.sh
-    Unset TERM environment variable and export LD_LIBRARY_PATH.
-
-2009-02-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    In windows code, cast LPVOID to 'char*' in printf.
-
-2009-02-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/octave.m4
-    Clear the TERM environment before evaluating anything in Octave. This works
-    around problems that might occur if a users TERM settings are incorrect.
-    Thanks to Rob Til Freedmen for helping to debug this.
-
-    * src/wav.c
-    Handle four zero bytes as a marker within a LIST or INFO chunk.
-    Thanks to Rogério Brito for supplying an example file.
-
-2009-02-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/*.c
-    Use C99 snprintf everywhere.
-
-2009-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/test_wrapper.sh.in
-    New file to act as the template for the test wrapper script.
-
-    * configure.ac
-    Generate tests/test_wrapper.sh from the template.
-
-    * tests/Makefile.am
-    Replace all tests with a single invocation of the test wrapper script.
-
-2009-02-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c
-    Record vorbis library version string.
-
-    * configure.ac
-    Require libvorbis >= 1.2.2.
-
-    * M4/endian.m4
-    Fix bracketing of function for autoconf 2.63. Thanks to Richard Ash.
-
-    * M4/octave.m4 M4/mkoctfile_version.m4
-    Clean up AC_WITH_ARG usage using AC_HELP_STRING.
-
-2009-02-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Octave/Makefile.am
-    Use $(top_buildir) instead of $(builddir) which may not be defined.
-
-    * M4/octave.m4
-    Improve logic and status reporting.
-
-2009-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac  AUTHORS NEWS README doc/*.html
-    Final tweaks for 1.0.18 release.
-
-2009-02-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-convert.c
-    Add 'htk' to the list of convert formats.
-
-    * programs/sndfile-info.c
-    Simplify get_signal_max using SFC_CALC_SIGNAL_MAX command.
-    Increase size of files for which signal max will be calculated.
-
-2009-01-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Fix links for SoX and WavPlay. Thanks to Daniel Griscom.
-
-2009-01-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-metadata-get.c
-    Make valgrind clean.
-    Clean up temp string array usage.
-    Error out if trying to update coding history in RDWR mode.
-
-2009-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Fix links to versions of the LGPL.
-
-2008-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/string_test.c
-    Add test for RDWR mode where the file ends up shorter than when it was
-    opened.
-
-    * src/wav.c
-    Truncate the file on close for RDWR mode where the file ends up shorter
-    than when it was opened.
-
-2008-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/add_cflags.m4
-    Fix problem with quoting of '#include'.
-
-    * M4/add_cxxflags.m4 configure.ac
-    Add new file M4/add_cxxflags.m4 and use it in configure.ac.
-
-2008-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-info.c
-    Apply patch from Conrad Parker to calculate and display total duration when
-    more than one file is dumped.
-
-2008-11-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/Makefile.am
-    Tweaks to generation of Symbols files.
-
-    * tests/win32_ordinal_test.c
-    Update tests for above changes.
-
-2008-11-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/common.c
-    When merging broadcast info, make sure to clear the destination field
-    before copying in the new data.
-
-    * programs/test-sndfile-metadata-set.py
-    Add test for the above.
-
-    * src/broadcast.c
-    Fix checking of required coding_history_size.
-
-2008-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    Add test to detect if coding history is truncated.
-
-    * src/broadcast.c
-    Fix truncation of coding history.
-
-2008-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    Add broadcast_coding_history_size test.
-
-    * programs/*.[ch]
-    Use SF_BROADCAST_INFO_VAR to manipulate larger 'bext' chunks.
-
-    * src/rf64.c
-    Add code to prevent infinite loop on malformed file.
-
-    * src/common.h src/sndfile.c src/w64.c src/wav_w64.c
-    Rationalize and improve error handling when parsing 'fmt ' chunk.
-
-    * M4/octave.m4
-    Simplify and remove cruft.
-    Check for correct Octave version.
-
-    * Octave/*
-    Reduce 3 C++ files to one, fix build for octave 3.0, fix build.
-
-    * Octave/sndfile.cc Octave/PKG_ADD
-    Add Octave function sfversion which returns the libsndfile version that the
-    module is linked against.
-
-    * Octave/Makefile.am
-    Bunch of build and 'make distcheck' fixes.
-
-2008-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/common.c
-    Return 1 if SFC_SET_BROADCAST_INFO fails.
-
-    * programs/test-sndfile-metadata-set.py
-    Update for new programs directory, exit on any error.
-
-    * tests/error_test.c
-    Fix failure behaviour in error_number_test.
-
-    * src/common.h src/sndfile.c
-    Add error number SFE_BAD_BROADCAST_INFO_SIZE.
-
-    * src/*
-    Reimplement handling of broadcast extentioon chunk in WAV/WAVEX files.
-
-    * src/broadcast.c
-    Fix generation of added coding history.
-
-2008-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * programs/sndfile-metadata-get.c programs/sndfile-info.c
-    Exit with non-zero on errors.
-
-2008-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-to-text.c examples/Makefile.am
-    Add a new example program and hook it into the build.
-
-    * examples/ programs/
-    Add a new directory programs and move sndfile-info, sndfile-play and other
-    real programs to the new directory, leaving example programs where they
-    were.
-
-2008-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/Makefile.am
-    Automake 1.10 MinGW cross compiling fixes.
-
-2008-10-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Remove call to deprecated function snd_pcm_sw_params_get_xfer_align.
-    Fix gcc-4.3 compiler warnings.
-
-    * tests/command_test.c
-    Fix a valgrind warning.
-
-    * tests/error_test.c tests/multi_file_test.c tests/peak_chunk_test.c
-        tests/pipe_test.tpl tests/stdio_test.c tests/win32_test.c
-    Fix gcc-4.3 compiler warnings.
-
-2008-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c
-    Fix termination of desitination string in strncpy_crlf.
-    When copying BROADCAST_INFO chunk, make sure destination gets correct line
-    endings.
-
-    * examples/common.c
-    Fix copying of BROADCAST_INFO coding_history field.
-
-2008-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    Add test function instrument_rw_test, but don't hook it into the testing
-    yet.
-
-    * src/common.h src/command.c src/sndfile.c src/flac.c
-    Error code rationalization.
-
-    * src/common.h src/sndfile.c
-    Set psf->error to SFE_CMD_HAS_DATA when adding metadata via sf_command()
-    fails due to psf->have_written being true.
-
-    * doc/command.html
-    Document the SFC_GET/SET_BROADCAST_INFO comamnds.
-
-2008-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    Improve error reporting when '\0' is found in coding history.
-    Fix false failure.
-
-2008-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c
-    Convert all coding history line endings to \r\n.
-
-    * tests/command_test.c
-    Add test to make sure all line endings are converted to \r\n.
-
-2008-10-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c
-    Changed the order of coding history fields.
-
-    * tests/command_test.c
-    Update bextch test to cope with previous change.
-
-    * examples/common.c
-    Add extra length check when copying broadcast info data.
-
-2008-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl tests/pcm_test.tpl
-    Update check_file_hash_or_die to use 64 bit hash.
-
-    * tests/checksum_test.c tests/Makefile.am
-    Add new checksum_test specifically for lossy compression of headerless
-    files.
-
-2008-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/gsm610.c
-    Seek to psf->dataoffset before decoding first block.
-
-    * src/sndfile.c
-    Fix detection of mpc2k files on big endian systems.
-
-2008-10-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c
-    Use '\r\n' newlines in Coding History as required by spec.
-
-2008-10-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_conversions.c
-    Use int64_t instead of 'long long'.
-
-2008-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-metadata-set.c
-    Remove --bext-coding-history-append command line option because it didn't
-    really make sense.
-
-    * examples/sndfile-metadata-(get|set).c
-    Add usage messages.
-
-    * examples/test-sndfile-metadata-set.py
-    Start work on test coding history.
-
-2008-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * README doc/win32.html
-    Bring these up to date.
-
-    * src/aiff.c
-    Fix parsing of REX files.
-
-2008-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Use intptr_t instead of long for return value of _get_osfhandle.
-
-    * src/test_conversions.c src/test_endswap.tpl
-    Fix printing of int64_t values.
-
-    * examples/sndfile-play.c
-    Fix win64 issues.
-
-    * tests/win32_ordinal_test.c
-    Fix calling of GetProcAddress with ordinal under win64.
-
-    * tests/utils.tpl
-    Fix win64 issues.
-
-2008-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/*
-    Rename copy_data.[ch] to common.[ch]. Fix build.
-    Move code from sndfile-metadata-set.c to common.c.
-
-    * examples/Makefile.am tests/Makefile.am regtest/Makefile.am
-    Clean paths.
-
-2008-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/tutorial.html doc/Makefile.am
-    Add file doc/tutorial.html and hook into build/dist system.
-
-2008-09-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-metadata-set.c
-    Clean up handling of bext command line params.
-
-2008-09-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c
-    Add handling/skipping of a couple of new chunk types.
-
-2008-09-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add -funsigned-char to CFLAGS if the compiler supports it.
-
-    * examples/sndfile-metadata-(get|set).c
-    Add handling for more metadata types.
-
-2008-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add macros SF_CONTAINER, SF_CODEC and SF_ENDIAN useful for splitting format
-    field of SF_INFO into component parts.
-
-    * src/*.c
-    Use new macros everywhere it is appropriate.
-
-2008-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-bwf-set.c
-    Massive reworking.
-
-2008-08-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-bwf-set.c
-    Add --info-auto-create-date command line option.
-
-    * examples/sndfile-metadata-set.c examples/sndfile-metadata-get.c
-        examples/Makefile.am examples/test-sndfile-bwf-set.py
-    Rename sndfile-bwf-(set|get).c to sndfile-metadata-(set|get).c.
-    Change command line args.
-
-2008-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Allow 'PAD ' chunk to be modified in RDWR mode.
-
-    * src/sndfile.h.in src/sndfile.c
-    Add handling (incomplete) for SFC_SET_ADD_HEADER_PAD_CHUNK.
-
-    * tests/Makefile.am tests/write_read_test.tpl tests/header_test.tpl
-        tests/misc_test.c
-    Add tests for RF64.
-
-    * src/rf64.c
-    Fixes to make sure all tests pass.
-
-    * tests/Makefile.am tests/string_test.c
-    Add string tests (not yet passing).
-
-2008-08-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/rf64.c
-    First pass at writing RF64 now working.
-
-2008-08-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Add SF_FORMAT_RF64 to format_map.
-
-    * src/common.h src/sndfile.c
-    More RF64 support code.
-
-    * examples/sndfile-bwf-set.c
-    Fix the month number in autogenerated date string and use hypen in date
-    instead of slash.
-
-    * examples/test-sndfile-bwf-set.py
-    Update tests.
-
-    * examples/sndfile-info.c
-    When called with -i or -b option, operate on all files on command line, not
-    just the first.
-
-2008-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/rf64.c
-    New file to handle RF64 (WAV like format supportting > 4Gig files).
-
-    * src/sndfile.h.in src/common.h src/sndfile.c src/Makefile.am
-    Hook the above into build so hacking can begin.
-
-    * src/pcm.c
-    Improve log message when pcm_init fails.
-
-    * src/sndfile-info.c
-    Only calculate and print 'Signal Max' if file is less than 10 megabytes in
-    length.
-
-2008-08-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/string_test.c
-    Polish string_multi_set_test.
-
-    * src/wav.c
-    In RDWR mode, pad the header if necessary (ie LIST chunk has moved or
-    length has changed).
-    Minor fixes in wav_write_strings.
-    Write PAD chunk with default endian-ness, not a specific endian-ness.
-
-    * examples/test-sndfile-bwf-set.py
-    Add Python script to test sndfile-bwf-set/get.
-
-    * examples/sndfile-bwf-set.c
-    Clean up and fixes.
-
-    * src/wav.c
-    Merge function wavex_write_header into wav_write_header, deleting about 70
-    lines of code.
-
-    * src/common.h
-    Double value of SF_MAX_STRINGS.
-
-    * tests/string_test.c
-    Add string tests for WAVEX and RIFX files.
-
-    * tests/command_test.c
-    Add broadcast test for WAVEX files.
-
-2008-08-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/string_test.c
-    Add a new string_rdwr_test (currently failing for WAV).
-    Add a new string_multi_set_test (currently failing).
-
-    * tests/command_test.c
-    Add new broadcast_rdwr_test (currently failing).
-
-    * src/wav.c
-    Fix to WAV parser to allow 'bext' chunk to be updated in place.
-    In wav_write_tailer, seek to psf->dataend if its greater than zero.
-
-    * src/sndfile.c
-    Make sure psf->have_written gets set correctly in mode SFM_RDWR.
-
-    * configure.ac
-    Test for <sys/time.h> and gettimeofday.
-
-    * src/common.c
-    Use gettimeofday() to initialize psf_rand_int32.
-
-    * src/common.h src/sndfile.c
-    Add unique_id field to SF_PRIVATE struct.
-
-    * src/common.h src/sndfile.c src/wav.c src/wav_w64.[ch]
-    Move wavex_ambisonic field from SF_PRIVATE struct to WAV_PRIVATE struct.
-
-    * src/common.h src/strings.c
-    Add function psf_location_string_count.
-
-2008-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Test for localtime and localtime_r.
-
-    * examples/sndfile-convert.c
-    In function copy_metadata(), copy broadcast info if present.
-
-    * examples/copy_data.[ch] examples/Makefile.am
-    Break some functionality out of sndfile-convert.c so it can be used in
-    examples/sndfile-bwf-set.c.
-
-    * tests/utils.tpl
-    Add new function create_short_sndfile().
-
-    * examples/sndfile-bwf-set.c examples/sndfile-bwf-get.c
-        examples/Makefile.am
-    Add new files and hook into build.
-
-2008-08-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Fix comments. Patch from Mark Glines.
-
-2008-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Use zero_data_test on Ogg/Vorbis files.
-
-    * src/ogg.c
-    Fix segfault when closing an Ogg/Vorbis file that has been opened for write
-    but had no actual data written to it. Bug reported by Chinoy Gupta.
-
-    * tests/Makefile.am
-    Make sure to run mist_test on Ogg/Vorbis files.
-
-2008-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * regtest/Makefile.am
-    Use SQLITE3_CFLAGS to locate sqlite headers.
-
-2008-07-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html doc/FAQ.html
-    Add notes about which versions of windows libsndfile works on.
-
-2008-07-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Add a test for correct handling of Ambisonic files. Thanks to Fons
-    Adriaensen for the test.
-
-    * src/wav.c src/wav_w64.c
-    Fix handling of Ambisonic files. Thanks to Fons Adriaensen for the patch.
-
-2008-06-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fix detection/enabling of external libs.
-
-    * M4/extra_pkg.m4 M4/Makefile.am
-    Add m4 macro PKG_CHECK_MOD_VERSION which is a hacked version
-    PKG_CHECK_MODULES. The new macro prints the version number of the package
-    it is searching for.
-
-2008-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Apply a fix from Axel Röbel where if the second loop in the instrument
-    chunk is none, the loop mode is written into the first loop.
-
-2008-05-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_float.c src/test_main.(c|h) src/Makefile.am
-    Add new file to test functions float32_(le|be)_(read|write) and
-    double64_(le|be)_(read|write). Hook into build and testsuite.
-
-    * src/double64.c src/float32.c
-    Fix bugs in functions found by test added above. Thanks to Nicolas Castagne
-    for reporting this bug.
-
-    * src/sndfile.h.in
-    Change time_reference_(low|high) entries of SF_BROADCAST_INFO struct to
-    unsigned.
-
-    * examples/sndfile-info.c
-    Print out the BEXT time reference in a sensible format.
-
-2008-05-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Fuzz fixes.
-
-    * src/ogg.c
-    Add call to ogg_stream_clear to fix valgrind warning.
-
-    * src/aiff.c
-    Fix x86_64 compile issue.
-
-    * configure.ac src/Makefile.am src/flac.c src/ogg.c
-    Link to external versions of FLAC, Ogg and Vorbis.
-
-    * tests/lossy_comp_test.c tests/ogg_test.c tests/string_test.c
-        tests/vorbis_test.c tests/write_read_test.tpl
-    Fix tests when configured with --disable-external-libs.
-
-    * tests/external_libs_test.c tests/Makefile.am
-    Add new test and hook into build and test suite.
-
-    * src/command.c
-    Use HAVE_EXTERNAL_LIBS to ensure that the SFC_GET_FORMAT_* commands return
-    the right data when external libs are disabled.
-
-2008-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Add a test for extending a file during write by seeking past the current
-    end of file.
-
-    * src/sndfile.c
-    Allow seeking past end of file during write.
-
-2008-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html doc/command.html
-    Move all information about the sf_command function to command.html and add
-    a link from documentation of the sf_read/write_raw function to the
-    SFC_RAW_NEEDS_ENDSWAP command.
-
-    * doc/index.html doc/FAQ.html doc/libsndfile.css
-    Minor documentation tweaks.
-
-2008-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add AM_PROG_CC_C_O.
-
-2008-04-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/error_test.c
-    Add a test to make sure if file opened with sf_open_fd, and then the file
-    descriptor is closed, then sf_close will return an error code. Thanks to
-    Dave Flogeras for the bug report.
-
-    * src/sndfile.c
-    Make sf_close return an error is the file descriptor is already closed.
-
-2008-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Set object format to aout for OS/2. Thanks to David Yeo.
-
-    * src/mpc2k.c src/sndfile.c src/sndfile.h.in src/common.h src/Makefile.am
-    Add ability to read MPC 2000 file.
-
-    * tests/write_read_test.tpl tests/misc_test.c tests/header_test.tpl
-        tests/Makefile.am
-    Add tests for MPC 2000 file format.
-
-    * examples/sndfile-convert.c
-    Allow conversion to MPC 2000 file format.
-
-2008-04-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/VORBIS/lib/codebook.c
-    Sync from upstream SVN.
-
-    * autogen.sh configure.ac
-    Minor tweaks.
-
-2008-04-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c
-    Add a patch that fixes finding the length in samples of an Ogg/Vorbis file.
-    The patch as supplied segfaulted and required many hours of debugging.
-
-    * src/OGG/bitwise.c
-    Sync from upstream SVN.
-
-2008-04-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix up handling of 'APPL' chunk. Thanks to Axel Röbel for bringing up
-    this issue.
-
-2008-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/*.c
-    Add calls to sf_close() where needed.
-
-    * tests/utils.tpl tests/multi_file_test.c
-    Always pass 0 as the third argument to open when OS_IS_WIN32.
-
-2008-04-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_*
-    Add files test_main.[ch].
-    Collapse all tests into a single executable.
-
-2008-03-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC
-    Sync to upstream CVS.
-
-2008-03-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Make SF_MIN and SF_MAX macros MinGW friendly.
-
-    * examples/sndfile-(info|play).c
-    Use Sleep function from <windows.h> instead of _sleep.
-
-    * tests/locale_test.c
-    Disable some tests when OS_IS_WIN32.
-
-    * src/FLAC/src/share/replaygain_anal/replaygain_analysis.c
-        src/FLAC/src/share/utf8/utf8.c
-    MinGW fixes.
-
-2008-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Tweaks to pcm16 <-> float conversion answer.
-
-2008-02-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/OGG
-    Sync to SVN upstream.
-
-    * Makefile.am
-    Add 'DISTCHECK_CONFIGURE_FLAGS = --enable-gcc-werror'.
-
-2008-02-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-jackplay.c
-    Minor tweaks to warning message printed when compiled without libjack.
-
-2008-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/peak_chunk_test.c
-    Improve read_write_peak_test to find more errors. Inspired by example
-    provided by Nicolas Castagne.
-
-    * src/aiff.c
-    Another SFM_RDWR fix shown up by above test.
-
-2008-01-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix reading of COMM encoding string.
-
-    * src/chunk.c src/common.h src/Makefile.am
-    New file for storing and retrieving info about header chunks. Hook into
-    build.
-
-    * src/aiff.c
-    Use new chunk logging to fix problem with AIFF in RDWR mode.
-
-2008-01-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/command.c
-    Add WVE to the list of major formats.
-
-    * tests/aiff_rw_test.c
-    Fix error reporting.
-
-2008-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.[ch]
-    Add internal functions str_of_major_format, str_of_minor_format,
-    str_of_open_mode and str_of_endianness.
-
-    * tests/write_read_test.tpl
-    Fix reporting of errors in new_rdwr_XXXX_test.
-
-2008-01-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Apply patch from Yair K. to fix compiles with OSS v4.
-
-    * src/common.h src/float32.c src/double64.c
-    Rename psf->float_enswap to psf->data_endswap.
-
-    * src/sndfile.h.in src/sndfile.c src/pcm.c
-    Add command SFC_RAW_NEEDS_ENDSWAP.
-
-    * tests/command.c
-    Add test for SFC_RAW_NEEDS_ENDSWAP.
-
-    * doc/command.html
-    Document SFC_RAW_NEEDS_ENDSWAP.
-
-    * tests/peak_chunk_test.c
-    Add test function read_write_peak_test. Thanks to Nicolas Castagne for the
-    bug report.
-
-2008-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-cmp.c
-    Add new example program contributed by Conrad Parker.
-
-    * examples/Makefile.am
-    Hook into build.
-
-    * doc/development.html
-    Change use or reconfigure.mk to autogen.sh.
-
-2008-01-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/win32_test.c
-    Add another win32 test.
-
-    * tests/util.tpl
-    Add function file_length_fd which wraps fstat.
-
-    * tests/Makefile.am
-    Run the multi_file_test on AU files.
-
-    * tests/multi_file_test.c
-    Use function file_length_fd() instead of file_length() to overcome stupid
-    win32 bug. Fscking hell Microsoft sucks so much.
-
-2008-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c
-    Fix a rsrc parsing bug. Example file supplied by Uli Franke.
-
-2007-12-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Allow use of either LGPL v2.1 or LGPL v3.
-
-    * tests/header_test.tpl
-    Add header_shrink_test from Axel Röbel.
-
-    * src/wav.c
-    Add fix from Axel Röbel for writing files with float data but no peak
-    chunk (ie peak chunk gets removed after the file is opened).
-
-    * src/aiff.c tests/header_test.tpl
-    Apply similar fix to above for AIFF files.
-
-    * src/wav.c tests/header_test.tpl
-    Apply similar fix to above for WAVEX files.
-
-    * src/command.c
-    Add Ogg/Vorbis to 'get format' commands.
-
-2007-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c
-    Fix seeking on multichannel Ogg Vorbis files. Reported by Bodo.
-    Set the default encoding quality to 0.4 instead of 4.0 (Bodo again).
-
-    * tests/ogg_test.c
-    Add stereo seek tests.
-
-2007-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/ogg_test.c
-    Add a test (currently failing) for stereo seeking on Ogg Vorbis files. Test
-    case supplied by Bodo.
-
-    * tests/utils.(def|tpl)
-    Add compare_XXX_or_die functions.
-
-2007-12-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix a bug where ignoring ssnd_fmt.offset and ssnd_fmt.blocksize caused
-    misaligned reading of 24 bit data. Thanks to Uli Franke for reporting this.
-
-2007-12-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/vox_adpcm.c src/ima_oki_adpcm.[ch] src/Makefile.am
-    Merge in code from the vox-patch branch. Thanks to Robs for the patch
-    which fixes a long standing bug in the VOX codec.
-
-2007-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Fix handling of -override-sample-rate=X option.
-
-2007-11-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c src/VORBIS
-    Merge in Ogg Vorbis support from John ffitch of the Csound project.
-
-2007-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Recognise files with 'vox6' extension as 6kHz OKI VOX ADPCM files. Also
-    recognise 'vox8' as and 'vox' as 8kHz files.
-
-    * configure.ac
-    Detect libjack (JACK Audio Connect Kit).
-
-    * examples/sndfile-jackplay.c examples/Makefile.am
-    Add new example program to play sound files using the JACK audio server.
-    Thanks to Jonatan Liljedahl for allowing this to be included.
-
-2007-11-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Update support table with SD2 and FLAC.
-
-2007-11-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix calculation of internal value psf->read_current when attempting to read
-    past end of audio data.
-    Remove redundant code.
-
-    * tests/lossy_comp_test.c
-    Add read_raw_test to check that raw reads do not go past the end of the
-    audio data section.
-    Clean up error output messages.
-
-    * src/sndfile.c
-    Add code to prevent sf_read_raw from reading past the end of the audio data.
-
-    * tests/Makefile.am
-    Add the wav_pcm lossy_comp_test.
-
-2007-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/Makefile.am src/create_symbols_file.py
-    More OS/2 fixes from David Yeo.
-
-2007-11-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c tests/utils.tpl tests/benchmark.tpl
-    Improve handling of requirements for O_BINARY as suggested by Ed Schouten.
-
-2007-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Fix symbol class when SF_MIN is nested inside SF_MAX or vice versa.
-
-    * src/create_symbols_file.py
-    Add support for OS/2 contributed by David Yeo.
-
-2007-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * M4/gcc_version.m4
-    Add macro AC_GCC_VERSION to detect GCC_MAJOR_VERSION and GCC_MINOR_VERSION.
-
-    * configure.ac
-    Use AC_GCC_VERSION to work around gcc-4.2 inline warning stupidity.
-    See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33995
-    Use -fgnu-inline to prevent stupid warnings.
-
-2007-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/util.tpl
-    Increase the printing width for print_test_name().
-
-    * tests/command_test.c tests/Makefile.am
-    Add tests for correct updating of broadcast WAV coding history.
-
-    * examples/sndfilehandle.cc examples/Makefile.am
-    Add example program using the C++ SndfileHandle class.
-
-2007-10-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/sndfile.c
-    Add error codes SFE_ZERO_MAJOR_FORMAT and SFE_ZERO_MINOR_FORMAT.
-
-2007-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c
-    Identify sample-rate/sample-size/channels by resource id.
-
-2007-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/broadcast.c src/common.h src/sndfile.c
-    Improvements to handling of broadcast info in WAV files. Thanks to Frederic
-    Cornu and other for their input.
-
-2007-10-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC/include/share/alloc.h
-    Mingw fix for SIZE_T_MAX from Uli Franke.
-
-2007-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/open_fail_test.c tests/error_test.c tests/Makefile.am
-    Move tests from open_fail_test.c to error_test.c and remove the former.
-
-2007-10-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/scale_clip_test.(def|tpl)
-    Add tests for SFC_SET_INT_FLOAT_WRITE command.
-
-    * doc/command.html
-    Add docs for SFC_SET_INT_FLOAT_WRITE command.
-
-    * examples/sndfile-play.c tests/dft_cmp.c
-    Fix gcc-4.2 warning messages.
-
-2007-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c
-    Add command SFC_GET_CURRENT_SF_INFO.
-
-    * src/sndfile.h.in src/sndfile.c src/create_symbols_file.py
-    Remove function sf_get_info (only ever in pre-release code).
-
-    * tests/command_test.c
-    Add test for SFC_GET_CURRENT_SF_INFO.
-
-2007-10-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Add parsing of 'exif' chunks. Originally coded by Trent Apted.
-
-    * configure.ac
-    Put config stuff in Cfg directory.
-    Remove check for inttypes.h.
-
-2007-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c
-    Fix writing of 'riff' chunk length and check for correct value in parser.
-
-2007-09-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Link to MP3 FAQ entry.
-
-2007-09-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Move the blocksize check to an earlier stage of flac_buffer_copy.
-
-2007-09-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC
-    Huge merge from FLAC upstream.
-
-2007-09-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/*.c
-    Change license to all example programs to BSD.
-
-2007-09-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC/include/FLAC/metadata.h
-    Include <sys/types.h> to prevent compile error on OSX.
-
-    * Octave/octave_test.sh
-    Disable test on OSX. Can't get it to work.
-
-    * src/flac.c
-    Check the blocksize returned from the FLAC decoder to prevent buffer
-    overruns. Reported by Jeremy Friesner. Thanks.
-
-2007-09-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Makefile.am M4/octave.m4
-    Fix build when Octave headers are not present.
-
-2007-08-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/development.html
-    Add note about bzr repository directory looking empty.
-
-2007-08-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac Octave/* M4/octave_*
-    Bunch of changes to add ability to build GNU Octave modules to read/write
-    sound files using libsndfile from Octave.
-
-2007-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * acinclude.m4 configure.ac ...
-    Get rid of acinclude.m4 and replace it with an M4 directory.
-
-2007-08-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Remove crufty Metrowerks compiler support. Allow header file to be compiled
-    on windows with both GCC and microsoft compiler.
-
-2007-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/dft_cmp.[ch] tests/floating_point_test.tpl
-    Clean up floating point tests.
-
-2007-08-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix segfault when COMM chunk length is byte swapped.
-
-2007-08-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/mat4.c src/mat5.c src/sndfile.c
-    Add a generic SFE_CHANNEL_COUNT_ZERO error, remove format specific errors.
-
-    * src/au.c
-    Fix crash on AU files with zero channel count. Reported by Ben Alison.
-
-2007-08-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/voc.c
-    Fix bug in handling file supplied by Matt Olenik.
-
-2007-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/OGG
-    Merge from OGG upstream sources.
-
-2007-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC
-    Merge from FLAC upstream sources.
-
-2007-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Fix memory leak; set copy parameter to FALSE in call to
-    FLAC__metadata_object_vorbiscomment_append_comment.
-
-    * src/common.[ch]
-    Add function psf_rand_int32().
-
-2007-07-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC
-    Merge from FLAC upstream sources.
-
-    * src/strings.c tests/string_test.c tests/Makefile.am
-    Make sure string tests for SF_STR_LICENSE actually works.
-
-2007-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/string_test.c
-    Add ability to test strings stored in metadata secion of FLAC files.
-
-    * src/string.c
-    Fix logic for testing if audio data has been written and string is added.
-    Make sure SF_STR_ALBUM actually works.
-
-    * src/flac.c
-    Finalize reading/writing string metadata. Tests pass.
-
-    * src/sndfile.h.in tests/string_test.c src/flac.c
-    Add string type SF_STR_LICENSE, update test and use for FLAC files.
-
-    * src/sndfile.h.in
-    Add definition for SFC_SET_SCALE_FLOAT_INT_WRITE command.
-
-    * src/common.h src/double64.c src/float32.c src/sndfile.c
-    Add support for SFC_SET_SCALE_FLOAT_INT_WRITE (still needs testing).
-
-2007-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Apply patch from Ed Schouten to read artist and title metadata from FLAC
-    files.
-    Improve reporting of FLAC metadata.
-
-    * src/sndfile.h.in tests/string_test.c src/flac.c
-    Add string type SF_STR_ALBUM, update test and use for FLAC files.
-
-2007-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC/*
-    Merge from upstream CVS.
-
-2007-06-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC/*
-    Update from upstream CVS.
-
-2007-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/cpp_test.cc
-    Add extra tests for when the SndfileHandle constructor fails.
-
-    * src/sndfile.hh
-    Make sure failure to open the file in the constructor does not allow later
-    calls to other methods to fail.
-
-2007-06-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/util.tpl
-    Add function write_mono_file.
-
-    * tests/generate.[ch] tests/Makefile.am
-    Add files generate.[ch] and hook into build.
-
-    * tests/write_read_test.tpl
-    Add multi_seek_test.
-
-    * src/flac.c
-    Fix buffer overflow bug. Test provided by Jeremy Friesner and fix provided
-    by David Viens.
-
-2007-06-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Minor update.
-
-    * configure.ac src/FLAC/src/libFLAC/ia32/Makefile.am src/Makefile.am
-    Apply patch from Trent Apted make it compile on Intel MacOSX. Thanks Trent.
-
-2007-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fix writing of MSGUID subtypes. Thanks to Bruce Sharpe.
-
-2007-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fix array indexing bug raised by Bruce Sharpe.
-
-2007-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC/src/share/getopt/getopt.c
-    Fix Mac OSX / PowerPC compile warnings.
-
-    * configure.ac
-    Make sure WORDS_BIGENDIAN gets correctly defined for FLAC code.
-
-2007-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Add Q/A about MP3 support.
-
-2007-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/new_file_type.HOWTO
-    Minor updates.
-
-2007-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wve.c
-    Fix a couple bad parameters with psf_log_printf.
-
-    * src/pcm.c
-    Improve error reporting.
-
-    * src/common.h src/common.c
-    Constify psf_hexdump.
-
-2007-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC
-    Ditch and re-import required FLAC code.
-
-    * configure.ac
-    Force FLAC__HAS_OGG variable to 1.
-
-    * src/FLAC/src/libFLAC/stream_encoder.c
-    Fix compiler warnings.
-
-2007-04-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac tests/win32_ordinal_test.c
-    Detect if win32 DLL is beging generated and only run win32_ordinal_test if
-    true.
-
-    * src/G72x/Makefile.am src/Makefile.am
-    Use $(EXEEXT) where possible.
-
-2007-04-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wve.c src/common.h src/sndfile.c
-    Complete definition of SfE_WVE_NO_WVE error message.
-
-    * src/wve.c
-    Fix error in files generated on big endian systems. Robustify parsing.
-
-2007-04-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/double64.c
-    Fix clipping of double to short conversions on 64 bit systems.
-
-    * src/flac.c regtest/database.c tests/cpp_test.cc
-    Fix compile warnings for 64 bit systems.
-
-2007-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/wav_w64.c
-    Use audio detect function when 'fmt ' chunk data is suspicious.
-
-    * configure.ac
-    Add ugly hack to remove -Werror from some Makefiles.
-
-2007-04-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/GSM610/long_term.c src/macbinary3.c tests/cpp_test.cc
-    Add patch from André Pang to clean up compiles on OSX.
-
-    * src/wve.c src/common.h src/sndfile.c src/sndfile.h.in
-        examples/sndfile-convert.c
-    Merge changes from Reuben Thomas to improve WVE support.
-
-    * tests/lossy_comp_test.c tests/Makefile.am
-    Add tests for WVE files.
-
-2007-04-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add a static SndfileHandle::formatCheck method as suggested by Jorge
-    Jiménez.
-
-2007-04-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a bug in sf_error() where the function itself was being compared
-    against zero. Add a check for a NULL return from peak_info_calloc. Fix a
-    possible NULL dereference.
-
-2007-04-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Turn off seekable flag when writing, return SFE_BAD_RDWR_FORMAT when
-    opening file for RDWR.
-
-    * src/sndfile.c
-    Improve error message for SFE_BAD_RDWR_FORMAT.
-
-    * src/mat4.c
-    Fix array indexing issue. Thanks to Ben Allison (Nullsoft) for alerting me.
-
-2007-03-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Add Q/A 19 on project files.
-
-2007-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Guard agains MacOSX universal binary compiles.
-
-    * doc/FAQ.html
-    Add Q/A 18 and clean up Q3.
-
-2007-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Add support for 'in24' files.
-
-2007-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/wav_w64.c src/wav_w64.h
-    Start work towards detecting ausio codec type from the actual audio data.
-
-    * src/audio_detect.c src/test_audio_detect.c
-    Add new file and its unit test.
-
-2007-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/cooledit-fixer.c examples/Makefile.am
-    Remove old broken example program.
-
-2007-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/sndfile.h.in src/create_symbols_file.py
-    Add function sf_get_info.
-
-2007-01-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    For ALSA, use the 'default' device instead of 'plughw:0'.
-
-2007-01-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Allow writing of WAV/WAVEX 'BEXT' chunks in SFM_RDWR mode.
-
-2007-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/development.html doc/embedded_files.html man/sndfile-play.1
-    Minor documentation fixes. Thanks Reuben Thomas.
-
-2006-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Add -override-sample-rate command line option.
-
-2006-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Force errno to zero at start of some tests.
-
-    * src/sndfile.c
-    Minor clean up of error handling.
-
-    * configure.ac
-    Remove an assembler test which was failing on OSX.
-
-2006-11-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Fix the definition of SF_PLATFORM_S64 for MinGW.
-
-    * src/FLAC/Makefile.am src/FLAC/share/grabbag/Makefile.am
-    Fix path problems for MinGW.
-
-2006-11-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.h
-    Add include guard.
-
-    * src/Makefile.am src/flac.c
-    Clean up include paths.
-
-    * src/test_conversions.c
-    New file to test psf_binheader_readf/writef functions.
-
-    * src/Makefile.am src/test_file_io.c src/test_log_printf.c src/common.c
-    Clean up unit testing.
-
-    * src/common.c
-    Fix a bug reading/writing 64 bit header fields. Thanks to Jonathan Woithe
-    for reporting this.
-
-    * src/test_conversions.c
-    Complete unit test for above fix.
-
-2006-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    More refactoring to clean up psf_open_file() and vairous sf_open()
-    functions.
-
-2006-11-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Apply a patch from Jonathan Woithe to allow opening of (malformed) WAV
-    files of over 4 gigabytes.
-
-2006-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Refactor function psf_open_file() to provide a single return point.
-
-    * tests/misc_test.c
-    Fix permission_test to ensure that read only file can be created.
-
-2006-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add SF_PLATFORM_S64 macro as a platform independant way of doing signed 64
-    bit integers.
-
-    * src/aiff.c src/svx.c src/wav.c
-    Add warning in log if files are larger than 4 gigabytes in size.
-
-2006-11-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/FLAC src/OGG confgure.ac src/Makefile.am
-    Pull in all required FLAC and OGG code so external libraries are not
-    needed. This makes compiling on stupid fscking Windoze easier.
-
-2006-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c
-    Add workaround for switched sample rate and sample size.
-
-    * src/wav.c
-    Add workaround for excessively long coding history in the 'bext' chunk.
-
-2006-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c src/wav.c doc/command.html
-    Use SF_AMBISONIC_* instead of SF_TRUE/SF_FALSE.
-
-2006-10-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/wav.c src/wav_w64.c src/common.h doc/command.html
-    Apply a patch from Fons Adriaensen to allow writing on WAVEX Ambisonic
-    files. Still needs a little tweaking before its ready for release.
-
-    * src/*.c
-    Use the UNUSED macro to prevent compiler warnings.
-
-2006-10-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix a bug in parsing AIFF files with a slightly unusual 'basc' chunk. Thanks
-    to David Viens for providing two example files.
-
-    * src/common.(c|h) src/aiff.c
-    Add a function psf_sanitize_string and use it in aiff.c.
-
-2006-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_w64.c
-    Apply a patch from Fons Adriaensen which fixes a minor WAVEX GUID issue.
-
-2006-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/Makefile.am
-    Fix problem related to recent test coverage changes.
-
-2006-10-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac tests/Makefile.am
-    Add --enable-test-coverage configure option.
-
-2006-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add an std::string SndfileHandle constructor.
-
-    * tests/scale_clip_test.tpl
-    Fix the 'make distcheck' target.
-
-2006-10-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/double64.c src/float32.c
-    Add optional clipping on float file data to int read data conversions.
-
-    * tests/tests/scale_clip_test.(def|tpl)
-    Add test for above new code.
-
-2006-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/aiff_rw_test.c
-    Add 'MARK' chunks to make sure they are parsed correctly.
-
-2006-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix parsing of MARK chunks. Many thanks to Sciss for generating files to
-    help debug the problem.
-
-2006-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Make the SF_MIN and SF_MAX macros at least partially type safe.
-
-    * tests/lossy_comp_test.c
-    Fix overflow problems when ensuring that signalis not zero.
-
-2006-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac docs/*.html
-    Changes for release 1.0.17.
-
-2006-08-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Remove inline from functions called by pointer. Thanks to Sampo Savolainen
-    for notifying me of this.
-
-2006-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Add writeSync method.
-    Add copy constructor and assignment operator (thanks Daniel Schmitt).
-    Add methods readRaw and writeRaw.
-    Make read/write/readf/writef simple overlaods instead of templates (thanks
-    to Trent Apted for suggesting this).
-
-    * tests/cpp_test.cc
-    Cleanup. Add tests.
-
-2006-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Templatize the read/write/readf/writef methods as suggested by Lars Luthman.
-    Prevent the potential leak of SNDFILE* pointers in the openRead/openWrite/
-    openReadWrite methods.
-    Add const to SF_INFO pointer in Sndfile constructor.
-    Make the destrictor call the close() method.
-
-    * tests/cpp_test.cc
-    Add more tests.
-
-2006-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/cpp_test.cc
-    Remove the generated file so "make distcheck" passes.
-
-    * src/Makefile.am
-    Add sndfile.hh to distributed header files.
-
-    * src/sndfile.hh
-    Change the license for the C++ wrapper to modified BSD.
-
-2006-07-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.hh
-    Complete it.
-
-    * tests/cpp_test.cc
-    Add more tests.
-
-2006-07-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl
-    Add extern C to generated header file.
-
-    * src/sndfile.hh
-    Work towards completing this.
-
-    * tests/cpp_test.cc tests/Makefile.am
-    Add a C++ test and hook into build.
-
-    * configure.ac
-    Add appropriate CXXFLAGS.
-
-2006-07-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Test if compiler supports -Wpointer-arith.
-
-    * src/common.c
-    Fix a warning resulting from -Wpointer-arith.
-
-2006-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Explicitly set endian-ness as well as setting 16 bit output.
-
-    * examples/sndfile-info.c
-    Make sure to parse info if file fails to open.
-
-    * src/sndfile.c
-    Handle parse error a little better.
-
-    * src/wav_w64.[ch]
-    Minor clean up, add detection of IPP ITU G723.1.
-
-2006-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Make sure psf->dataoffset gets reset to zero when openning headersless
-    files based on the file name extension.
-
-2006-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/(command|lossy_comp|pcm|scale_clip)_test.c tests/fix_this.c
-        tests/write_read_test.(tpl|def)
-    Fix gcc-4.1 compiler warnings about "dereferencing type-punned pointer will
-    break strict-aliasing rules".
-
-    * examples/cooledit-fixer.c
-    More fixes like above.
-
-2006-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Fix a windows bug where the syserr string of SF_PRIVATE was not being set
-    correctly.
-
-    * src/sndfile.c
-    Fixed a logic bug in sf_seek(). Thanks to Paul Davis for finding this.
-
-2006-06-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fixed detection of S_IRGRP.
-
-2006-05-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * sndfile-convert.c
-    Add conversion SF_INSTRUMENT data when present.
-
-2006-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/development.html
-    Removed references to tla on windows.
-
-    * src/common.h src/sndfile.c
-    Add separate void pointers for file containter and file codec data to
-    SF_PRIVATE struct. Still need to move all existing fdata pointers.
-
-    * tests/write_read_test.tpl
-    Change the order of some tests.
-
-    * src/aiff.c
-    When writing 'AIFC' files, make sure get an 'FVER' gets added.
-
-    * src/common.h src/(dwvw|flac|g72x|gsm610|ima_adpcm|ms_adpcm|paf|sds).c
-        src/(sndfile|voc|vox_adpcm|xi).c
-    Remove fdata field from SF_PRIVATE struct and replace it with codec_data.
-
-2006-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/testprog.c Win32/Makefile.am
-    Add a minimal win32 test program.
-
-    * Win32/README-precompiled-dll.txt Mingw-make-dist.sh
-    Update readme and Mingw build script.
-
-2006-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac acinclude.m4
-    Minor fixes for Solaris.
-
-2006-05-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_endswap.(def|tpl)
-    Fix printf formatting for int64_t on 64 bit machines.
-
-2006-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/binhead_check.py
-    New file to check for bad parameters passed to psf_binheader_writef().
-
-    * src/Makefile.am
-    Hook into test suite.
-
-    * src/voc.c src/caf.c src/wav.c src/mat5.c src/mat4.c
-    Fix bugs found by new test program.
-
-    * src/double64.c
-    Clean up double64_get_capability().
-
-2006-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_w64.c
-    Fix a bug on x86_64 where an int was being passed via stdargs and being
-    read using size_t which is 64 bits. Thenks to John ffitch for giving me a
-    login on his box.
-
-2006-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/caf.c src/double64.c examples/sndfile-info.c tests/virtual_io_test.c
-            tests/utils.tpl
-    Fix a couple of signed/unsigned problems.
-
-2006-05-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    Add channel map tests.
-
-    * src/common.h src/sndfile.c
-    Add a pointer to the SF_PRIVATE struct and make sure it gets freed in
-    sf_close().
-
-2006-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac doc/(command|index|api).html NEWS README
-    Updates for 1.0.16 release.
-
-    * src/sndfile.h.in
-    Define enums for channel mapping.
-
-    * examples/sndfile-info.c
-    Clean up usage of SF_INFO struct.
-
-2006-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/util.tpl
-    Add function testing function exit_if_true().
-
-    * tests/floating_point_test.tpl
-    Fix a problem where the test program was not exiting when the test failed.
-
-2006-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c src/common.h src/command.c
-    Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS.
-
-    * doc/commands.html
-    Document new commands. Other minor updates.
-
-    * tests/peak_chunk_test.c
-    Update tests for new commands.
-
-2006-04-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/peak_chunk_test.c
-    Add test for RIFX and WAVEX files.
-    Try and confuse the PEAK chunk writing by enabling and disabling it.
-
-    * src/sndfile.c
-    Fix a bug where enabling and disabling PEAK chunk was screwing up.
-
-2006-03-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Add the block of 190 reserved bytes into this struct to allow for
-    future expansion.
-
-    * src/wav.c src/sndfile.c src/broadcast.c
-    Significant cleanup of broadcast wave stuff.
-
-    * examples/sndfile-info.c
-    Fix print message.
-
-    * tests/command_test.c tests/Makefile.am
-    Complete bext tests, hook test in test suite.
-
-2006-03-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Make coding_history field of SF_BROADCAST_INFO struct a char array instead
-    of a char pointer.
-
-    * src/sndfile.c src/common.h src/wav.c
-    Clean up knock on effects of above chnage.
-
-    * examples/sndfile-info.c
-    Add -b command line option to usage message.
-    Clean up output of broadcast wave info.
-
-    * src/wav.c
-    Ignore and skip the 'levl' chunk.
-
-2006-03-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fix handling of --enable and --disable configure args. Thanks to Diego
-    'Flameeyes' Pettenò who sent the patch.
-
-2006-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/win32.html
-    Make it really clear that although the MSVC++ cannot compile libsndfile,
-    the precompiled DLL can be used in C++ programs compiled with MSVC++.
-
-2006-03-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix bug in writing of INST chunk in AIFF files.
-    Fix potential bug in writing MARK chunks.
-
-    * src/sndfile.c
-    Make sure the instrument chunk can only be written at the start of the file.
-
-    * tests/command_test.c
-    Add check of log buffer.
-
-    * tests/utils.tpl
-    Add usage of space character to psf_binheader_writef.
-
-2006-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/Makefile.am tests/Makefile.am
-    Remove --source-time argument from autogen command lines.
-
-    * src/broadcast.c
-    New file for EBU Broadcast chunk in WAV files.
-
-    * src/sndfile.c src/sndfile.h.in src/wav.c src/common.h
-    Add patch from Paul Davis implementing read/write of the BEXT chunk.
-
-2006-03-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/README-precompiled-dll.txt
-    New file descibing how to use the precompiled DLL.
-
-    * Win32/Makefile.am
-    Add Win32/README-precompiled-dll.txt to EXTRA_DIST files.
-
-    * configure.ac
-    Bump version to 1.0.15.
-
-2006-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    On read, only add the endian flag if the file is big endian.
-
-    * src/ms_adpcm.c
-    Fixed writing of APDCM coeffs in RIFX files.
-
-    * tests/write_read_test.tpl tests/lossy_comp_test.c
-    Add tests for RIFX files.
-
-2006-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Mingw-make-dist.sh
-    Bunch of improvements.
-
-    * doc/win32.html
-    Update MinGW program versions.
-
-2006-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/create_symbols_file.py
-    Fix the library name in created win32 DEF file. Add correct DLL name for
-    Cygwin DLL.
-
-    * Win32/Makefile.am tests/Makefile.am
-    Remove redundant files, add win32_ordinal_test to test suite.
-
-    * tests/win32_ordinal_test.c
-    Update to do test in cygsndfile-1.dll as well.
-
-    * doc/win32.html
-    Fix typo, mention that -mno-cygwin with the Cygwin compiler does not work.
-
-    * src/wav.c src/wav_w64.c src/sndfile.c src/sndfile.h.in
-    Apply large patch from Jesse Chappell which adds support for RIFX files.
-
-2006-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Makefile.am
-    Add Mingw-make-dist.sh to the extra dist files.
-
-    * configure.ac
-    Fix setting SHLIB_VERSION_ARG for MinGW.
-
-    * tests/win32_ordinal_test.c
-    New test program to test that the win32 DLL ordinals agree with the DEF
-    file.
-
-2006-03-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add a static inline function to convert an int to a size_t. This will be
-    a compile to nothing on 32 bit CPUs and a sign extension on 64 bit CPUs.
-
-    * src/aiff.c src/avr.c src/common.c src/xi.c src/gsm610.c
-    Fix an ia64 problem where a varargs function was being passed an int in
-    some places and a size_t in other places.
-
-    * src/sd2.c
-    Add a workaround for situations where OSX seems to add an extra 0x52 bytes
-    to the start of the resource fork.
-
-2006-02-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Mingw-make-dist.sh
-    Add a shell script to build the windows binary/source ZIP file.
-
-    * doc/index.html
-    Add download link for windows binary/source ZIP file. Add links for GPG
-    signatures.
-
-    * doc/win32.html
-    Remove info about building using microsoft compiler.
-
-    * configure.ac
-    Bump version to 1.0.14.
-
-2006-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c
-    Improve logging of errors in resource fork parser.
-
-2006-01-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/Makefile.msvc
-    Replace au_g72x.* with g72x.*. Thanks to ussell Borogove.
-
-2006-01-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Make sure return values are initialised header buffer is full.
-
-    * src/wav.c
-    Add workarounds for messed up WAV files.
-
-2006-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/config.h
-    Undef HAVE_INTTYPES_H for win32.
-
-    * tests/command_test.c
-    Don't exit on error in instrument test for XI files.
-
-    * configure.ac
-    Bump version to 1.0.13.
-
-    * doc/*.html NEWS README
-    Update version numbers.
-
-2006-01-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/xi.c
-    Start work on add read/write of instrument chunks.
-
-    * src/command_test.c
-    Add tests for XI instrument chunk.
-
-    * tests/largefile_test.c tests/Makefile.am
-    Add new test and hook it into the build system. This test will not be run
-    automatically because it requires 3 Gig of disk space and takes 3 minutes
-    to run.
-
-2006-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Fix calculation of samples remaining in win32 code. Thanks Axel Röbel.
-
-    * src/common.h
-    Make sure length of header buffer can hold header plus strings. Thanks Axel
-    Röbel.
-
-2006-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/aiff.c src/wav.c
-    Apply a patch from John ffitch (Csound project).
-    Add detune field to SF_INSTRUMENT struct.
-    Add reading/writing instrument chunks to WAV files.
-
-    * tests/command_test.c
-    Update SF_INSTRUMENT tests.
-
-    * tests/Makefile.am
-    Hook instrument tests into test suite.
-
-2006-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Check for <inttypes.h> because some broken systems (like Solaris) don't have
-    <stdint.h> which is the 1999 ISO C standard file containing int64_t.
-
-    * src/sfendian.h src/common.h
-    Use <inttypes.h> if <stdint.h> is not available.
-
-2005-12-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/peak_chunk_test.c
-    Extend and clean up tests.
-
-    * src/sndfile.c
-    Fix a bug that prevented the turning off of PEAK chunks.
-
-2005-12-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/error_test.c
-    Make the test distclean correct.
-
-    * src/file_io.c
-    Fix an SD2 MacOSX bug (reported by vince schwarzinger).
-
-2005-12-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c tests/command_test.c
-    Apply a big patch from John ffitch (Csound project) to add reading and
-    writing of instrument chunks to AIFF files. Also update the test.
-
-2005-12-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/aiff_rw_test.c tests/virtual_io_test.c tests/utils.tpl
-    Move test function dump_data_to_file() to utils.tpl.
-
-    * tests/error_test.c tests/Makefile.am
-    Updates, including a new test to test that sf_error() returns a valid error
-    number.
-
-2005-12-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/list_formats.c
-    Make sure the SF_INFO struct is memset to all zero before being used.
-    Thanks to Stephen F. Booth.
-
-    * src/sndfile.c
-    Make the return value of sf_error() match the API documentation.
-
-2005-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Allow conversion to raw gsm610.
-
-    * src/common.h src/sndfile.c src/au.c
-    Remove au_nh_open() and all references to it (wasn't working anyway).
-
-    * tests/headerless_test.c
-    Add new test for file extension based detection.
-
-    * src/sndfile.c
-    Rejig file extension based file type detection.
-
-2005-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Add "gsm" as a recognised file extension when no magic number can be found.
-
-    * tests/lossy_comp_test.c tests/Makefile.am
-    Test headerless GSM610.
-
-2005-11-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Fix a minor typo and a minor error. Thanks Christoph Kobe and John Pavel.
-
-2005-10-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_w64.c
-    Add more reporting of 'fmt ' chunk for G721 encoded files.
-
-    * src/wav.c
-    Gernerate a more correct 20 byte 'fmt ' chunk rather than a 16 byte one.
-
-2005-10-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/G72x/g72x.[ch]
-    Minor cleanup of interface.
-
-2005-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ogg.c
-    Removed the horribly broken and non-functional OGG implementation when
-    --enable-experimental was enabled. When OGG does finally work it will be
-    merged.
-
-    * src/caf.c
-    Fix a memory leak.
-
-2005-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/g72x.c src/G72x/*.(c|h) src/common.h src/sndfile.c src/wav.c src/au.c
-    Add support for G721 encoded WAV files.
-
-    * doc/index.html
-    Update support matrix.
-
-    * tests/lossy_comp_test.c
-    For file formats that support it, add string data after the audio data and
-    make sure it isn't treated as audio data on read.
-
-    * src/gsm610.c
-    Add code to ensure that the container close function (ie for WAV files) gets
-    called after the codec's close function. This allows GSM610 encoded WAV files
-    to have string data following the audio data.
-    Add an AIFF specific check on psf->datalength.
-
-    * src/wav.c
-    Simplify wav_close function.
-
-    * src/aiff.c
-    Make sure the tailer data gets written at an even file offset. Pad if
-    necessary.
-
-    * src/common.h
-    Replace the close function pointer in SF_PRIVATE with separate functions
-    codec_close and container_close. The former is always called first.
-
-    *  src/*.c
-    Fix knock on effects of above.
-
-2005-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-info.c
-    Complete dumping SF_INSTRUMENT data.
-
-    * src/dwvw.c src/ima_adpcm.c src/gsm610.c src/ms_adpcm.c
-    Add extra checks in *_init function.
-
-    * tests/lossy_comp_test.c
-    Add a string comment to the end of the files to make sure that the decoder
-    doesn't decode beyond the end of the audio data section.
-
-2005-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-info.c
-    Minor code cleanup.
-    Start work on dumping SF_INSTRUMENT data.
-
-2005-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/common.h src/common.c
-    Update definition of SF_INSTRUMENT struct and create a function to allocate
-    and initialize the struct (input from David Viens).
-    Clean up definition of SF_INSTRUMENT struct.
-
-    * src/wav.c src/wav_w64.c
-    Add support for Ambisoncs B WAVEX files (David Viens).
-
-    * src/aiff.c src/wav.c src/wav_w64.c
-    Start work on reading/writing the SF_INSTRUMENT data.
-
-    * src/sndfile.c
-    Add code to get and set SF_INSTRUMENT data.
-
-    * tests/command_test.* tests/Makefile.am
-    Add test for set and getof SF_INSTRUMENT data.
-    The file command_test.c is no longer autogen generated.
-
-2005-10-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/gsm610.c
-    Minor cleanup.
-
-2005-10-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c
-    Minor cleanup.
-
-2005-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Ensure sfconfig.h is included before any other header file.
-
-    * src/file_io.c
-    Add comments documenting the three sections of the file.
-
-    * src/gsm610.c
-    Make sure SF_FORMAT_WAVEX are handled correctly.
-
-2005-10-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add options to allow disabling of FLAC and ALSA. Suggested by Ben Greear.
-
-2005-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/locale_test.c
-    Modify the way the unicode strings were encoded so that older compilers
-    do not complain. Thanks Axel Röbel.
-
-    * configure.ac
-    Bump the version to 1.0.12 for release.
-
-    * NEWS README Win32/config.h doc/(FAQ|index.html|command|api).html
-    Update version numbers.
-
-2005-09-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Fix valgrind error and minor cleanup.
-
-2005-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/(au|paf|aiff|w64|wav|svx).c
-    Make sure structs are initialised.
-
-2005-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Make -Wdeclaration-after-statement work with --enable-gcc-werror configure
-    option.
-    Add -std=gnu99 (C99 plus posix style stuff like gmtime_r) to CFLAGS if the
-    compiler supports it.
-
-2005-09-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac acinclude.m4
-    Add -Wdeclaration-after-statement to CFLAGS if the compilers supports it.
-
-2005-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/util.(tpl|def)
-    Make the test_write_*_or_die() functions const safe.
-
-2005-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    Make sure the data offset is read from the file header. Thanks to
-    David A. van Leeuwen for a patch.
-
-2005-09-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/sfconfig.h
-    Check for <locale.h> and the function setlocale().
-    Set config variables to zero if not found.
-
-    * tests/locale_test.c tests/Makefile.am
-    Add new test program and hook into build/test system.
-
-2005-09-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/file_io.c
-    On windows, use windows specific types for file handles.
-    Add functions psf_init_files() and psf_use_rsrc().
-
-    * src/sd2.c
-    Make resource fork handling independant of file desciptor/handles.
-
-    * src/sndfile.c src/test_file_io.c
-    Fix knock on effects.
-
-2005-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float_cast.h
-    The lrint and lrintf implementations in Cygwin are both buggy and slow.
-    Add replacements which were pulled from the Public Domain MinGW math.h
-    header file.
-
-2005-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/(lossy_comp_test|virtual_io_test).c
-    More Valgrind fixups.
-
-    * configure.ac
-    Simplify and correct configuring for Cygwin.
-
-    * Win32/config.h Win32/sndfile.h Win32/Makefile.msvc
-    Update build for MSVC.
-
-2005-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c
-    Make sure to close SNDFILE when exiting test when file format is not seekable.
-
-    * tests/(aiff_rw_test|virtual_io_test).c
-    Do a few valgrind fix ups.
-
-2005-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float32.c src/double64.c
-    Replace floating point equality comparisons with greater/less comparisons.
-    Found by John Pavel using the Intel compiler.
-
-    * src/sfconfig.h
-    New file to clean up issues surrounding autoconf generated preprocessor
-    symbols.
-
-    * src/*.(c|h) tests/*.(c|tpl) examples/*.c
-    Fixed a bunch of other stuff found by John Pavel using the Intel compiler.
-
-    * src/file_io.c
-    Remove Mac OS9 Metrowerks compiler specific hacks.
-
-2005-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c
-    Cast integer literal to sf_count_t in call to psf_binheader_writef() to
-    prevent Valgrind error.
-
-2005-08-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Improve documentation of SF_GET_FORMAT_SUBTYPE.
-
-2005-08-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Allow files to be converted to SD2 format.
-
-    * src/sd2.c
-    Fix a bug in reading and writing of SD2 files on little endian CPUs.
-    Thanks to Matthew Willis for finding this.
-
-2005-08-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Update Note2 to point to SFC_SET_SCALE_FLOAT_INT_READ.
-
-2005-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Use $host_os instead of $target_os (thanks to Mo De Jong).
-
-2005-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/Makefile.am
-    Apply a patch from Mo DeJong to allow building outside of the source dir.
-
-    * src/file_io.c
-    Fix psf_fsync() for win32.
-
-    * src/wav.c src/wav_w64.(c|h)
-    Move some code from wav.c to wav_w64.c to improve the log output of files of
-    type WAVE_FORMAT_EXTENSIBLE.
-
-2005-08-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/create_symbols_file.py
-    Make sure sf_write_fsync is an exported symbol.
-
-    * examples/sndfile-convert.c
-    Add support for writing VOX adpcm files.
-
-2005-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Document the new function sf_write_sync().
-
-    * doc/FAQ.html
-    Do you plan to support XYZ codec.
-
-2005-07-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c
-    Add function sf_write_sync() to the API.
-
-    * src/common.h src/file_io.c
-    Low level implementation (win32 not done yet).
-
-    * tests/write_read_test.tpl
-    Use the new function in the tests.
-
-2005-07-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/double64.c src/float32.c src/sndfile.c
-    Change the way PEAK chunk info is stored. Peaks now stored as an sf_count_t
-    for position and a double as the value.
-
-    * src/aiff.c src/caf.c src/wav.c
-    Fix knock on effects of above changes.
-
-    * src/caf.c
-    Implement 'peak' chunk for file wuth data in SF_FORMAT_FLOAT or
-    SF_FORMAT_DOUBLE format.
-
-2005-07-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    Fix a bug where a variable was being used without being initialized.
-
-    * src/flac.c
-    Add extra debug in sf_flac_meta_callback.
-    Make a bunch of private functions static.
-
-    * src/aiff.c src/wav.c
-    Fix allocation for PEAK_CHUNK (bug found using valgrind).
-
-2005-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Move the peak_loc field of SF_PRIVATE to the PEAK_CHUNK struct.
-    Remove had_peak field of SF_PRIVATE, use pchunk != NULL instead.
-    Rename PEAK_CHUNK and PEAK_POS to PEAK_CHUNK_32 and PEAK_POS_32.
-
-    * src/aiff.c src/caf.c src/wav.c src/float32.c src/double64.c
-    Fix knock on effects from above.
-
-2005-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Prevent files with unknown chunks from being opened read/write.
-
-2005-07-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/flac.c
-    Do not use psf->end_of_file because it never gets set to anything.
-
-    * src/common.h
-    Remove unused SF_PRIVATE field end_of_file.
-
-2005-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Change the 'S' format specifier of psf_binheader_writef() to write AIFF
-    style strings (no terminating character).
-
-    * src/aiff.c
-    Move to new (correct) AIFF string style. Thanks to Axel Röbel for being
-    so persistent on this issue.
-
-2005-07-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Allow SFE_UNSUPPORTED_FORMAT as an error from sf_open().
-
-    * doc/api.html doc/command.html
-    Documentation updates (thanks to Kyroz for promoting these updates).
-
-    * src/mat5.c
-    Modify the way the header is written.
-
-2005-07-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/caf.c
-    Add a 'free' chunk to the written file so that the audio data starts at
-    an offset of 0x1000.
-
-    * src/sndfile.c
-    Allow SFE_UNSUPPORTED_FORMAT as an error from sf_open().
-
-2005-07-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/caf.c src/sndfile.c
-    Add support for signed 8 bit integers.
-
-    * tests/write_read_test.tpl
-    Add test for signed 8 bit integers in CAF files.
-
-    * doc/index.html
-    Update matrix for signed 8 bit integers in CAF files.
-
-2005-07-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Update sf_check_format() to support CAF.
-
-    * examples/sndfile-convert.c
-    Add support for ".caf" file extension.
-
-    * doc/index.html
-    Add Apple CAF to the support matrix.
-
-    * src/caf.c
-    Add file write support.
-
-    * src/common.c
-    Fix printing of Frames.
-
-    * tests/Makefile.am tests/write_read_test.tpl tests/lossy_comp_test.c
-        tests/header_test.tpl misc_test.c
-    Add tests for CAF files.
-
-2005-07-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Fix Q/A about reading/writing memory buffers.
-
-    * src/caf.c
-    Bunch of work to support reading of CAF files.
-
-2005-07-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/(aiff|ima_adpcm|mat4|mat5|ms_adpcm).c examples/sndfile-play.c
-    Fix sign conversion errors reported by gcc-4.0.
-
-    * src/caf.c
-    New file for Apple's Core Audio File format.
-
-    * src/sndfile.c src/common.h src/sndfile.h.in src/Makefile.am
-    Hook new file into build system.
-
-2005-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src_wav_w64.c
-    Fix handling of stupidly large 'fmt ' chunks. Thanks to Vadim Berezniker
-    for supplying an example file.
-
-    * src/common.h src/sndfile.c
-    Remove redundant error code SFE_WAV_FMT_TOO_BIG.
-
-2005-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/common.h src/sndfile.c
-    Add public error value SF_ERR_MALFORMED_FILE.
-
-    * src/sndfile.c
-    When parsing a file header fails and we don't have a system error, then set
-    the error number to SF_ERR_MALFORMED_FILE (suggested by Kyroz).
-
-    * configure.ac
-    Allow sqlite support to be disabled in configure script.
-
-    * regtest/database.c regtest/sndfile-regtest.c
-    Fix compiling when sqlite is missing.
-
-2005-06-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Fix psf_is_pipe() and return value of psf_fread() when using virtual i/o.
-
-    * src/sndfile.c
-    Fix VALIDATE_AND_ASSIGN_PSF macro for virtual i/o.
-
-    * tests/virtual_io_test.c
-    Fill in skeleton test program.
-
-    * tests/Makefile.am
-    Move virtual i/o tests to end of tests with stdio/pipe tests.
-
-    * src/(sndfile.h.in|file_io.c|common.h|sndfile.c) tests/virtual_io_test.c
-    Rename some of the virtual i/o functions and data types.
-
-2005-06-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix the return values of sf_commands : SFC_SET_NORM_DOUBLE,
-    SFC_SET_NORM_FLOAT, SFC_GET_LIB_VERSION and SFC_GET_LOG_INFO. Thanks to
-    Kyroz for pointing out these errors.
-
-    * doc/command.html
-    Correct documented return values for SFC_SET_NORM_DOUBLE and
-    SFC_SET_NORM_FLOAT. Thanks to Kyroz again.
-
-2005-05-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * regtest/*
-    Add new files for sndfile-regtest program.
-
-    * configure.ac Makefile.am
-    Hook regetest into build.
-
-    * src/wav.c src/common.c
-    Fix a regression where long ICMT chunks were causing the WAV parser
-    to exit.
-
-2005-05-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * libsndfile.spec.in
-    Add html docs to the files section as suggested by Karsten Jeppesen.
-
-    * src/aiff.c
-    Fix parsing of odd length ANNO chunks.
-
-2005-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Change the include guard to prevent clashes with other code.
-
-2005-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Improve error handling in code for playback under Linux/ALSA.
-
-2005-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ircam.c
-    Fix writing of IRCAM files on big endian systems (thanks to Axel Röbel).
-
-    * src/wav.c
-    Add workaround for files created by the Peak audio editor on Mac which can
-    produce files with very short LIST chunks (thanks to Jonathan Segel who
-    supplied the file).
-
-2005-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Apply a patch From David Viens to make the parsing of basc chunks more
-    robust.
-
-    * src/wav.c
-    Another patch from David Viens to write correct wavex channel masks for
-    the most common channel configurations.
-
-2005-04-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/command.c
-    Only allow FLAC in the format arrays if FLAC is enabled. Thanks to
-    Leigh Smith.
-
-2005-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add a directory field for storing the file directory to the SF_PRIVATE
-    struct.
-
-    * src/sndfile.c
-    Grab the directory name when copying the file path.
-
-    * src/file_io.c
-    Cleanup psf_open_rsrc() and also check for resource fork in
-    .AppleDouble/filename.
-
-2005-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/svx.c
-    Fix a bug in the printing of the channel count. Bug reported by Michael
-    Schwendt. Thanks.
-
-2005-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    Fix a seek bug for 24 bit PAF files.
-
-    * tests/write_read_test.tpl
-    Update write_read_test to trigger the previously hidden PAF seek bug.
-
-2005-01-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/w64.c src/wav.c
-    Do not return a header parse error when the log buffer overflows.
-    Continuing parsing works even on files where the log buffer does overflow.
-    This avoids a bug on some weirdo WAV (and other) files.
-
-    * src/common.h src/sndfile.c
-    Remove SFE_LOG_OVERRIN error and its associated error message.
-
-    * src/file_io.c
-    Fix a rsrc fork problem on MacOSX.
-
-2004-12-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile-play.c
-    In the ALSA output code, added call to snd_pcm_drain() just before
-    snd_pcm_close() as suggested by Thomas Kaeding.
-    In the OSS output code, added two ioctls (SNDCTL_DSP_POST and
-    SNDCTL_DSP_SYNC) just before the close of the audio device.
-
-    * tests/virtual_io_test.c tests/Makefile.am
-    Add a new test program (currently empty) and add it to the build.
-
-2004-12-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.h src/common.h src/file_io.c
-      src/create_symbols_file.py
-    Apply patch from Steve Baker which is the beginnings of a virtual
-    I/O interface.
-
-2004-12-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c src/sndfile.h.in
-    Const-ify the write path throughout the library.
-
-2004-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/development.html
-    Minor improvements.
-
-2004-11-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/bugs.html
-    Minor improvements.
-
-2004-11-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Add workaround for Logic Platinum AIFF files with broken COMT chunks.
-
-2004-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Remove some ambiguities in the SD2 FAQ answer.
-
-2004-11-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/sndfile.h Win32/config.h MacOS9/sndfile.h MacOS9/config.h
-    Updates from autoconfig versions.
-
-2004-11-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fix parsing of COMT chunks. Store SF_STR_COMMENT data in ANNO chunks
-    instead of COMT chunk.
-
-2004-11-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c src/common.h
-    Change the ptr argument to psf_write() from "void*" to a "const void*".
-    Thanks to Tobias Gehrig for suggesting this.
-
-2004-10-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c src/common.h
-    Add functions psf_close_rsrc() and read length of resourse fork into
-    rsrclength field of SF_PRIVATE.
-
-    * src/sd2.c
-    Make sure resource fork gets closed.
-
-    * tests/util.tpl
-    Add functions to check for file descriptor leakage.
-
-    * src/write_read_test.tpl
-    Use the file descriptor leak checks.
-
-    * src/sndfile.h.in
-    Add SFC_GET_LOOP_INFO and SF_LOOP_INFO struct.
-
-    * src/common.h
-    Add SF_LOOP_INFO pointer to SF_PRIVATE.
-
-    * src/wav.c src/aiff.c
-    Improve and add parsing of 'ACID' and 'basc' chunks, filling in
-    SF_LOOP_INFO data in SF_PRIVATE.
-
-2004-10-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sd2.c
-    Further cleanup: remove printfs, change snprintf to LSF_SNPRINTF.
-
-    * Win32/config.h Win32/sndfile.h
-    Updates.
-
-    * tests/util.tpl
-    Add win32 macro for snprintf.
-
-2004-10-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.h
-    Add macros : H2BE_SHORT, H2BE_INT, H2LE_SHORT and H2LE_INT.
-
-    * src/sd2.c
-    Use macros to make sure writing SD2 files on little endian machines works
-    correctly.
-
-    * tests/util.tpl
-    Add a delete_file() function which also deletes the resource fork of SD2
-    files.
-
-    * tests/write_read_test.tpl
-    Use delete_file() so that "make distcheck" works.
-
-2004-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/file_io.c
-    Move resource filename construction and testing to psf_open_rsrc().
-
-    * src/common.h src/sndfile.c
-    Add error SFE_SD2_FD_DISALLOWED.
-
-    * tests/util.tpl tests/*.(c|tpl)
-    Add and allow_fd parameter to test_open_file_or_die() so that use of
-    sf_open_fd() can be avoided when opening SD2 files.
-
-2004-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Update ACID chunk parsing.
-
-    * src/sd2.c
-    More fixes for files with large resource forks.
-
-2004-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/sndfile.c
-    Add error numbers and messages for sd2 files.
-
-    * src/sd2.c
-    Reading of sd2 (resource fork version) now seems to be working.
-
-2004-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.h
-    Update file_io.c to include win32 psf_rsrc_open().
-
-    * tests/floating_point_test.tpl
-    Remove use of __func__ in test programs (MSVC++ doesn't grok this).
-
-    * Win32/(config|sndfile).h MacOS9/(config|sndfile).h
-    Updates.
-
-2004-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.h
-    Fix endswap_int64_t_(array|copy).
-
-    * src/test_endswap.(tpl|def)
-    Add tests for above and inprove all tests.
-
-2004-10-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.h
-    Improve type safety, add endswap_double_array().
-
-    * src/double64.c
-    Use endswap_double_array() instead of endswap_long_array().
-
-    * src/test_endswap.(tpl|def) src/Makefile.am
-    Add preliminary endswap tests and hook into build system.
-
-2004-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/configure.ac src/makefile.am
-    Finally fix the bulding of DLLs on Win32/MinGW.
-
-    * tests/makefile.am
-    Fix running of tests on Win32/MinGW.
-
-2004-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c tests/floating_point_test.tpl
-    Rename SFC_SET_FLOAT_INT_MULTIPLIER to SFC_SET_SCALE_FLOAT_INT_READ.
-
-    * doc/command.html
-    Document SFC_SET_SCALE_FLOAT_INT_READ.
-
-2004-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/floating_point_test.(tpl|def)
-    Derived from floating_point_test.c.
-    Add (float|double)_(short|int)_test functions.
-
-    * tests/util.(tpl|def)
-    Make separate float and double versions of gen_windowed_sine().
-
-    * tests/write_read_test.tpl
-    Fix after changes to gen_windowed_sine().
-
-    * src/(float32|double64).c
-    Implement SFC_SET_FLOAT_INT_MULTIPPLIER.
-
-2004-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * acinclude.m4
-    Fix warnings from automake 1.8 and later.
-
-    * examples/sndfile-info.c
-    Add a "fflush (stdout)" after printing Win32 message.
-
-2004-09-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/Makefile.mingw.in
-    Add a "make install" target.
-
-2004-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/common.h src/sndfile.c src/command.c
-    Start work on adding command SFC_SET_FLOAT_INT_MULTIPLIER.
-
-2004-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Fix a bug converting stereo integer PCM files to float.
-
-2004-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Appy patch from Conrad Parker to make Mac OSX error messages more
-    consistent and informative.
-
-    * doc/api.html
-    Fix a HTML HREF which was wrong.
-
-    * doc/win32.html
-    Add information about when nmake fails.
-
-2004-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Another patch from Denis Cote to prevent race conditions.
-
-2004-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/ms_adpcm.c src/ima_adpcm.c
-    Fix alternative to ISO standard flexible struct array feature for broken
-    compilers.
-
-2004-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/string.c src/sndfile.c
-    Make sf_set_string() return an error if trying to set a string when in
-    read mode.
-
-2004-08-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Change the unnamed union into a named union so gcc-2.95 will compile it.
-
-    * src/*.c
-    Fixes to allow for the above change.
-
-2004-08-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Fixes for Win32. Thanks to Denis Cote.
-
-    * Win32/Win32/Makefile.(msvc|mingw.in)
-    Fix build system after removal of sfendian.h.
-    Build sndfile-convert.
-
-    * src/Makefile.am
-    Remove sfendian.c from dependancies.
-
-2004-08-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Fix typo in comments (thanks Tommi Sakari Uimonen).
-
-2004-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/(a|u)law_test.c
-    Minor cleanup.
-
-2004-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/(pcm|float|double64|ulaw|alaw|xi).c
-    Optimise read/write loops by removing a redundant variable.
-
-2004-07-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Remove call to fsync() in psf_close().
-
-2004-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c
-    Inline x2y_array() functions where possible.
-
-    * configure.ac
-    Detect presence of type int64_t.
-
-    * src/sfendian.c src/sfendian.h
-    Move functions in the first file to the sfendian.h as static inline
-    functions.
-    Improve endswap_long_*() where possible.
-
-2004-07-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c
-    When converting from unsigned char to float or double, subtract 128 before
-    converting to float/double rather than after to save a floating point
-    operation as suggested by Stefan Briesenick.
-
-    * src/(pcm|sfendian|alaw|ulaw|double64|float32).c
-    Optimize inner loops by changing the loop counting slightly as suggested
-    by Stefan Briesenick.
-
-    * configure.ac
-    Detect presence of <byteswap.h>.
-
-    * src/sfendian.h
-    Use <byteswap.h> if present as suggested by Stefan Briesenick.
-
-    * src/pcm.c
-    Update bytewapping.
-
-2004-07-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/*.c
-    Change the psf->buffer field of SF_PRIVATE into a more type safe union with
-    double, float, int etc elements.
-
-2004-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Merge slightly modifed patch from Stanko Juzbasic which allows playback of
-    mono files on MacOSX.
-
-2004-06-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Move copy_metadata() after the second sf_open().
-
-2004-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Fix a bug which caused the program to go into an infinite loop if the source
-    file has no meta-data. Thanks to Ron Parker for reporting this.
-
-    * src/sndfile.h.in
-    Add SF_STR_FIRST and SF_STR_LAST to allow enumeration of string types.
-
-    * Win32/sndfile.h MacOS9/sndfile.h
-    Update these as per the above file.
-
-2004-06-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/common.h src/ogg.c src/sndfile.c src/sndfile.h.in
-      src/Makefile.am
-    Apply large patch from Conrad Parker implementing Ogg Vorbis, Ogg Speex and
-    Annodex support via liboggz and libfishsound. Thanks Conrad.
-
-2004-06-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/avr.c src/ircam.c src/nist.c src/paf.c src/xi.c
-    Add cast to size_t for some parameters passed to psf_binheader_writef. This
-    is Debian bug number 253490. Thanks to Anand Kumria and Andreas Jochens.
-
-    * src/w64.c
-    Found and fixed a bug resulting from use of size_t when writing W64 'fmt '
-    chunk.
-
-2004-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Bump version to 1.0.10 ready for release.
-
-    * Makefile.am
-    Remove redundant files (check_libsndfile.py libsndfile_version_convert.py)
-    from distribution tarball.
-
-    * tests/header_test.tpl
-    Fix uninitialised variable.
-
-    * src/GSM610/short_term.c
-    Fix compiler warning on MSVC++.
-
-2004-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Improve record keeping of chunks seen and return an error if a file with
-    unusual chunks is opened in mode SFM_RDWR.
-
-    * src/mmreg.h
-    This file not needed so remove it.
-
-2004-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/header_test.tpl
-    Add extra_header_test().
-
-    * src/common.h src/sndfile.c
-    Add SFE_RDWR_BAD_HEADER error number and string.
-
-2004-05-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl tests/*.c tests/*.tpl
-    Add a line number argument to check_log_buffer_or_die() and update all
-    files that use that function.
-
-    * tests/header_test.tpl
-    Modify/update tests for files opened SFM_RDWR and SFC_UPDATE_HEADER_AUTO.
-
-    * src/aiff.c src/wav.c
-    Fix another bug in AIFF and WAV files opened in SFM_RDWR and using
-    SFC_UPDATE_HEADER_AUTO.
-
-    * src/test_file_io.c
-    Add a test for psf_ftruncate() function.
-
-2004-05-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix another  weird corner case bug found by Martin Rumori. Thanks.
-
-    * tests/header_test.(tpl|def)
-    Two new files to test for the absence of the above bug and include tests
-    moved from tests/misc_test.c.
-
-    * tests/Makefile.am
-    Hook new tests into build/test system.
-
-    * tests/misc_test.c
-    Remove update_header_test() which has been moved to the new files above.
-
-2004-05-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fixed a bug reported by Martin Rumori on the LAD list. If a file created
-    with a format of SF_FORMAT_FLOAT and then closed before any data is written
-    to it, the header can get screwed up (PEAK chunk gets overwritten).
-
-    * tests/write_read_test.tpl
-    Add a test (empty_file_test) for the above bug.
-
-2004-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/Makefile.mingw.in
-    Added a Makefile for MinGW (needs to be processed by configure).
-
-    * src/mmsystem.h src/mmreg.h
-    Add files from the Wine project (under the LGPL) to allow build of
-    sndfile-play.exe under MinGW.
-
-2004-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/GSM610/gsm610_priv.h
-    Replace ugly macros with inline functions.
-
-    * src/GSM610/*.c
-    Remove temporary variables used by macros and other minor fixes required by
-    above change.
-
-2004-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pipe_test.tpl tests/stdio_test.c Win32/Makefile.msvc
-    Make sure these programs compile (even though they do nothing) on Win32
-    and add them to the "make check" target.
-
-    * src/sfendian.h
-    Fix warning on Sparc CPU and code cleanup.
-
-2004-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Fix warning messages when compiling under MinGW.
-
-2004-05-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Set HAVE_FLEXIBLE_ARRAY in src/config.h depending on whether the compiler
-    accepts the flexible array struct member as per 1999 ISO C standard.
-
-    * src/common.h src/ima_adpcm.c src/paf.c src/ms_adpcm.c
-    Added ugly #if HAVE_FLEXIBLE_ARRAY and provided a non-standards compliant
-    hack for non 1999 ISO C compliant compilers.
-
-2004-04-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/strings.c
-    If adding an SF_STR_SOFTWARE string, only append libsndfile-X.Y.Z if the
-    string does not already have libsndfile in the string. Thanks to Conrad
-    Parker.
-
-    * tests/string_test.c
-    Add test to verify the above.
-
-    * examples/sndfile-convert.c
-    Add ability to transcode meta data as well (Conrad Parker).
-
-2004-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Fix minor error. Thanks to Simon Burton.
-
-    * doc/win32.html
-    Started adding instructions for compiling libsndfile under MinGW.
-
-    * configure.ac
-    Add --enable-bow-docs to enable black text on a white background HTML docs.
-
-    * doc/libsndfile.css.in
-    This is now a template file for configure which sets the foreground and
-    background colours.
-
-2004-04-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Do some MinGW fixes.
-
-    * configure.ac doc/Makefile.am
-    Install HTML docs when doing make install.
-
-2004-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-info.c
-    Print out the dB level with the signal max.
-
-2004-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Define S_ISSOCK in src/file_io.c if required.
-
-2004-04-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Improve printout configuration summary (as suggested by Axel Röbel).
-
-    * doc/index.html
-    Add link to pre-release location.
-
-    * src/sndfile.h.in
-    Remove comma after last element of enum.
-
-    * src/float32.c src/double64.c
-    Fix read/write of float/double encoded raw files to/from pipes.
-
-    * tests/pipe_test.c tests/pipe_test.tpl tests/pipe_test.def
-    Turn pipe_test.c into an autogenerated file and add tests for reading/
-    writing floats and doubles.
-
-    * tests/Makefile.am
-    Hook tests/pipe_test.* into build system.
-
-2004-04-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac acinclude.m4
-    Rename AC_C_STRUCT_HACK macro to AC_C99_FLEXIBLE_ARRAY.
-
-2004-03-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Perform update_header_test in RDWR mode as well.
-
-    * src/aiff.c
-    Fix problems when updating header in RDWR mode.
-
-2004-03-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/w64.c src/wav_w64.c
-    Integrate code supplied by David Viens for supporting microsoft's
-    WAVEFORMATEXTENSIBLE stuff. Thanks David for supplying this.
-
-    * configure.ac doc/*.html
-    Bump version to 1.0.9.
-
-2004-03-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/command.c src/sndfile.c src/sndfile.h.in src/wav.c
-    Started work on supporting microsoft's WAVEFORMATEXTENSIBLE gunk.
-
-2004-03-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/avr.c
-    New file to handle Audio Visual Resaerch files.
-
-    * src/sndfile.h.in src/common.h src/sndfile.c src/command.c
-    Hook AVR into everything else.
-
-    * tests/Makefile.am tests/write_read_test.tpl tests/misc_test.c
-    Add testing for AVR files.
-
-2004-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Fix psf_set_file() for win32. Thanks to Vincent Trussart (Plogue Art et
-    Technologie) for coming up with the solution.
-
-2004-03-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Fixed a bug that was causing valgrind to report a memory leak. The bug was
-    in the test code itself, not the library.
-
-2004-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/generate.cs
-    An example showing how to use libsndfile from C#. Thanks to James Robson
-    for providing this.
-
-2004-03-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Fix problems with WAV files containing large chunks after the 'data'
-    chunk. Thanks to Koen Tanghe for providing a sample file.
-
-2004-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Detect presense of ALSA (Advanced Linux Sound Architecture).
-
-    * examples/sndfile-play.c
-    Add ALSA output support.
-
-    * examples/Makefile.am
-    Add ALSA_LIBS to link line of sndfile-play.c.
-
-2004-03-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * acinclude.m4
-    Add new macro (AC_C_STRUCT_HACK) to detect whether the C compiler allows
-    the use of the what is known as the struct hack introduced by the 1999 ISO
-    C Standard.
-
-    * configure.ac
-    The last release would not compile with gcc-2.95 due to the use of features
-    (ie struct hack) introduced by the 1999 ISO C Standard.
-    Add check to make sure compiler handles this and bomb out if it doesn't.
-
-2004-03-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Fix compiler warning on Win32.
-
-    * src/file_io.c
-    Fix use of an un-initialised variable in Win32 stuff.
-
-    * Win32/config.h examples/sndfile-play.c
-    Win32 fixes.
-
-2004-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fix bug which occurres when configuring for MinGW.
-    If compiler is gcc and cross compiling use -nostdinc.
-
-2004-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/aiff.c src/wav.c src/float32.c src/double64.c
-      src/sndfile.c
-    Fix a bug with PEAK chunk handling for files with more than 16 channels.
-    Thanks to Remy Bruno for finding this.
-
-2004-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Fix a bug which was preventing WAV files being openned correctly if the
-    file had a very large header. Thanks to Eldad Zack for finding this.
-
-2004-03-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/file_io.c
-    Fix cross-compiling from Linux to Win32 using the MinGW tools.
-
-2004-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/create_symbols_file.sh
-    Christian Weisgerber pointed out that the shell script did not run on a
-    real Bourne shell although it did run under Bash in Bourne shell mode.
-
-    * src/create_symbols_file.py
-    Rewrite of above in Python. Also add support for writing Win32 .def files.
-    The Python script generates Symbols.linux, Symbols.darwin and
-    libsndfile.def (Win32 version). These files get shipped with the tarball
-    so there should not be necessary to run the Python script when building
-    the code from the tarball.
-
-    * configure.ac src/Makefile.am Win32/Makefile.am
-    Hook new Python script into the build system.
-
-2004-02-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/configure.ac
-    Add --enable-gcc-werror option and move GCC specific stuff down.
-
-2004-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * acinclude.m4 configure.ac
-    Fix clip mode detection (tested in one of HP's testdrive Itanium II boxes).
-
-    * src/file_io.c
-    Added check for sizeof (off_t) != sizeof (sf_count_t) to prevent recurrence
-    of missing large file support on Linux and Solaris.
-
-2004-02-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Fix a MacOSX specific bug which was caused by a space being inserted in
-    the middle of a file name.
-
-    * configure.ac src/Makefile.am examples/Makefile.am
-    Fix a couple of MacOSX build issues.
-
-2004-02-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Document SFC_SET_CLIPPING and SFC_GET_CLIPPING.
-
-2004-02-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/*.html
-    Applied patch from Frank Neumann (author of lakai) which fixes many minor
-    typos in documentation. Thanks Frank.
-
-2004-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * ChangeLog
-    Changed my email address throughout source and docs.
-
-2004-02-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Make sure config.h is included before stdio.h to make sure large file
-    support is enabled on Linux (and Solaris).
-
-    * tests/misc_test.c
-    Disable update_header test on Win32. This should work but doesn't and
-    I'm not sure why.
-
-    * Make.bat Win32/Makefile.msvc
-    Updates.
-
-2004-01-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Changed logindex, headindex and headend files of SF_PRIVATE from unsigned
-    int to int to prevent weird arithmetic bugs.
-
-    * src/common.c src/aiff.c src/wav.c src/w64.c
-    Fixed compiler warnings resulting from above change.
-
-2004-01-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Fixed a bug in header reader for some files with data after the sample data.
-
-2003-12-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c tests/Makefile.am
-    Add tests for AIFF/IMA files.
-
-2003-12-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/macbinary3.c src/macos.c
-    Two new files required for handling SD2 files.
-
-    * src/common.h
-    Add prototypes for functions in above two files.
-
-    * src/Makefile.am
-    Hook new files into build system.
-
-2003-12-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add checks for mmap() and getpagesize() which might be used at some time
-    for faster file reads.
-    Add detection of MacOSX.
-
-2003-12-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Minor mods to pkg-config section.
-
-2003-12-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/create_symbols_file.sh
-    Andre Pang (also known as Ozone) pointed out that on MacOSX, all non
-    static symbols are exported causing troubles when trying to link
-    libsndfile with another library which has any of the same symbols.
-    He fixed this by supplying the MacOSX linker with a file containing
-    all the public symbols so that only they would be exported and then
-    supplied a patch for libsndfile.
-    This wasn't quite ideal, because I would have to maintain two (3 if
-    you include Win32) separate files containing the exported symbols.
-    A better solution was to create this script which can generate a
-    Symbols file for Linux, MacoSX and any other OS that supports
-    minimising the number of exported symbols.
-
-    * configure.ac src/Makefile.am
-    Hook the new script into the build process.
-
-2003-12-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Added comments about Steve Dekorte's SoundConverter scam.
-
-2003-12-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Axel Röbel pointed out that on Mac OSX a pipe is not considered a fifo
-    (S_ISFIFO (st.st_mode) is false) but a socket (S_ISSOCK (st.st_mode) is
-    true). The test has therefore been changed to is S_ISREG and anything
-    which which does not return true for S_ISREG is considered a pipe.
-
-2003-11-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Fix update_header_test to pass SDS.
-
-    * src/sds.c
-    More minor fixes.
-
-    * tests/floating_point_test.c
-    Add test for SDS files.
-
-    * src/command.c
-    Add SDS to major_formats array.
-
-2003-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl tests/misc_test.c
-    Add tests for SDS files.
-
-    * src/sds.c
-    Fix a bug in header update code.
-
-2003-11-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sds.c
-    Get file write working.
-
-    * src/paf.c
-    Fix a potential bug in paf24_seek().
-
-2003-11-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Add Q/A about u-law encoded WAV files.
-
-    * Win32/*.h
-    Updated so it compiles on Win32.
-
-2003-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Add -alaw and -ulaw command line arguments.
-
-    * configure.ac
-    Add library versioning comments.
-    Add arguments to AC_INIT.
-
-2003-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Ross Bencina has contributed code to replace all of the (mostly broken)
-    Win32 POSIX emulation calls with calls the native Win32 file I/O API.
-    This code still needs testing but is likely to be a huge improvemnt
-    of support for Win32. Thanks Ross.
-
-2003-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/dwvw.c
-    Removed filedes field from the DWVW_PRIVATE struct.
-
-    * src/file_io.c
-    Change psf_fopen() so it returns psf->error instead of the file descriptor.
-    Add new functions psf_set_stdio() and psf_set_file().
-
-    * src/sndfile.c
-    Change these to work with changed psf_fopen() return value.
-    Remove all uses of psf->filedes from sndfile, making it easier to slot native
-    Win32 API file handling functions.
-
-    * src/test_file_io.c
-    Minor changes to make it compile with new file_io.c stuff.
-
-2003-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/gsm610.h
-    Rename a variable from true to true_flag. As Ross Bencina points out,
-    true is defined in the C99 header <stdbool.h>.
-
-    * src/file_io.c
-    If fstat() fails, return SF_TRUE instead of -1 (Ross Bencina).
-
-2003-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Increase the size of SF_BUFFER_LEN and SF_HEADER_LEN.
-
-    * src/sndfile.c
-    Fix sf_read/write_raw which were dividing by psf->bytwidth and
-    psf->blockwidth which can both be zero.
-
-    * examples/sndfile-info.c
-    Increase size of BUFFER_LEN.
-
-2003-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add checks for <sys/wait.h> and ssize_t.
-    Other Win32/MinGW checks.
-
-    * src/aiff.c src/au_g72x.c src/file_io.c src/gsm610.c src/interleave.c
-      src/paf.c src/sds.c src/svx.c src/voc.c src/w64.c src/wav.c src/xi.c
-    Fix compiler warnings.
-
-2003-09-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/scale_clip_test.tpl
-    Add definition of M_PI if needed.
-
-2003-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Detect if S_IRGRP is declared in <unistd.h>.
-
-    * src/file_io.c tests/*.tpl tests/*.c
-    More fixes for Win32/MSVC++ and MinGW. MinGW does have <unistd.h> but that
-    file doesn't declare S_IRGRP.
-
-2003-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/config.h.in
-    Add comment stating that the sf_count_t typedef is determined when
-    libsndfile is being compiled.
-
-    * tests/utils.tpl
-    Modified so that utils.c gets one copy of the GPL and not two.
-
-
-2003-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/unistd.h src/sf_unistd.h
-    Move first file to the second. This will help for Win32/MSVC++ and MinGW.
-
-    * Win32/Makefile.am src/Makefile.am
-    Changed in line with above.
-
-    * Win32/Makefile.msvc
-    Removed "/I Win32" which is no longer required.
-
-    * src/file_io.c src/test_file_io.c tests/*.tpl tests/*.c
-    If HAVE_UNISTD_H include <unistd.h> else include <sf_unistd.h>. This should
-    work for Win32, MinGW and other fakes Unix-like OSes.
-
-    * src/*.c
-    Removed #include <unistd.h> from files which didn't need it.
-
-2003-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * libsndfile.spec.in
-    Apply fix from Andrew Schultz.
-
-2003-09-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/vox_adpcm.c
-    Only set psf->sf.samplerate if the existing value is invalid.
-
-2003-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Started adding support for ALSA output.
-
-2003-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Removed <stdlib.h> from sndfile.h.
-
-    * src/*.c examples/*.c tests/*.c tests/*.tpl
-    Added <stdlib.h> where needed.
-
-2003-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Added ARRAY_LEN, SF_MAX and SF_MIN macros.
-
-2003-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Remove statements about alternative licensing arrangements.
-
-2003-08-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * MacOS MacOS9 Makefile.am configure.ac
-    Change directory name from MacOS to MacOS9
-
-    * MacOS9/MacOS9-readme.txt
-    Change name to make it really obvious, add text to top of file to make it
-    still more obvious again.
-
-2003-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_log_printf.c
-    Add tests for %u conversions.
-
-    * src/common.c
-    Fix psf_log_printf() %u conversions.
-
-2003-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fixed a bug where opening a file with a non-trival header in SFM_RDWR mode
-    would over-write part of the header. Thanks to Axel Röbel for pointing
-    this out. Axel also provided a patch to fix this but I came up with a
-    neater and more general solution.
-    Return error when openning an AIFF file with data after the SSND chunk
-    (Thanks Axel Röbel).
-
-    * tests/aiff_rw_test.c
-    Improvements to test program which will later allow it to be generalised to
-    test WAV, SVX and others as required.
-
-2003-08-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pipe_test.c
-    Add useek_pipe_rw_test() submitted by Russell Francis.
-
-    * src/sndfile.c
-    In sf_open_fd(), check if input file descriptor is a pipe.
-
-    * src/sndfile.[ch]
-    Fix typo in variable name do_not_close_descriptor.
-
-2003-08-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_log_printf.c
-    Improve the tests for %d and %s conversions.
-
-    * src/common.c
-    Fixed a few problems in psf_log_printf() found using new tests.
-
-2003-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add -Wwrite-strings warning to CFLAGS if the compiler is GCC. Thanks to
-    Peter Miller (Aegis author) for suggesting this and supplying a patch.
-
-    * src/*.c examples/*.c tests/*.c
-    Fix all compiler warnings arising from the above.
-
-2003-08-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/aiff_rw_test.c tests/Makefile.am
-    New test program to check for errors re-writing the headers of AIFC files
-    opened in mode SFM_RDWR.
-
-2003-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Applied a patch from Tero Pelander to allow this program to run on systems
-    using devfs which used /dev/sound/dsp instead of /dev/dsp.
-
-2003-07-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/new_file_type.HOWTO
-    Updated document. Still incomplete.
-
-2003-06-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fix VALIDATE_SNDFILE_AND_ASSIGN_PSF which was returning an error rather
-    than saving it and returning zero.
-
-2003-06-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Two fixes for Mac OS9.
-    Fix all casts from sf_count_t to ssize_t (not size_t).
-
-2003-06-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fix for reading files with RIFF length of 8 and data length of 0.
-
-2003-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c tests/*.c tests/*.tpl
-    Added comments to mark code for removal when make Lite version of
-    libsndfile.
-
-2003-06-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Add extra error checking for unrecognised arguments.
-
-2003-06-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ima_adpcm.c
-    Started adding code to write IMA ADPCM encoded AIFF files.
-
-    * src/test_log_printf.c src/Makefile.am
-    New file to test psf_log_printf() function and add hooks into build system.
-
-    * src/common.c
-    Move psf_log_printf() function to top of the file and only compile the rest
-    of the file if if PSF_LOG_PRINTF_ONLY is not defined.
-
-2003-06-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/config.h Win32/sndfile.h
-    Updated with new config variables.
-
-    * Win32/unistd.h src/file_io.c
-    Added implementation of S_ISFIFO macro which Win32 seems to lack and is
-    used in src/file_io.c.
-
-    * tests/utils.tpl
-    Added #include <unitstd.h> to pull in Win32/unistd.h so it compiles for
-    Win32.
-
-    * src/Makefile.msvc
-    Added src\test_file_io.exe build target and run this as the very first
-    test.
-
-    * tests/win32_test.c
-    Add support for testing Cygwin32.
-
-    * configure.ac
-    Detect POSIX fsync() and fdatasync() functions.
-
-    * src/file_io.c
-    If compiling for Cygwin, call fsync() before calling fstat() to retrieve
-    file length.
-
-    * tests/pcm_test.tpl
-    Add a test for lrintf() function. This was required to detect a really
-    broken lrint() and lrintf() on Cygwin.
-
-    * tests/misc_test.c
-    Don't run permission test when compiling under Cygwin.
-
-    * src/float_cast.h
-    Fix fallback macro for lrint() and lrintf() to cast to long instead of int
-    to match official function prototypes.
-
-2003-06-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-convert.c
-    Modifications to improve accuracy of conversions; use double data for
-    floating point and int for everything else.
-
-    * src/ima_apdcm.c
-    Completed work on decoding IMA ADPCM encoded AIFF files. Still need to
-    get encoding working.
-
-2003-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/ima_adpcm.c
-    Start working on getting IMA ADPCM encoded AIFF files working.
-
-2003-05-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fixed the touch command for when the autogen program is not found (Matt
-    Flax).
-
-    * src/ulaw.c src/alaw.c
-    Made these pipe-able.
-
-2003-05-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c src/ircam.c
-    Fixed writing to pipe.
-
-    * src/wav.c src/aiff.c src/nist.c src/mat*.c src/svx.c src/w64.c
-    Return SFE_NO_PIPE_WRITE if an attempt is made to write to a pipe.
-
-2003-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-info.c
-    Modified to detect unknown file lengths.
-
-    * src/mat4.c
-    Fix reading from a pipe.
-
-2003-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pipe_test.c
-    Add more file types to tests.
-
-    * src/mat4.c
-    Removed explicit setting of psf->sf.seekable to SF_TRUE.
-
-    * tests/utils.tpl
-    Add macro for generating and check data in the stdio and pipe tests.
-
-    * tests/stdout_test.c tests/stdin_test.c
-    Use the above macro to generate known data on output and check data on
-    input.
-
-    * src/voc.c src/htk.c common.h sndfile.c
-    Disallow reading/writing VOC and HTK files from/to pipes be returning new
-    error values.
-
-    * src/w64.c
-    Fixes to allow reading from a pipe.
-
-2003-05-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac src/sndfile.h.in
-    When the configure script determines the sizeof (sf_count_t), also set the
-    value of SF_COUNT_MAX in sndfile.h.
-
-    * configure.ac
-    Remove -pedantic flag from default GCC compiler flags.
-
-    * tests/pipe_test.c
-    Add a pipe_read_test() before doing pipe_write_test().
-
-    * tests/scale_clip_test.c
-    Add test to make sure non-normalized values also clip in the right way.
-
-2003-05-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Add test to detect processor clipping capabilities.
-
-    * tests/stdin_test.c tests/stdout_test.c
-    Fix a pair of compiler warnings.
-
-    * src/common.h
-    Add new pipeoffset field to SF_PRIVATE. This will contain the current file
-    offset when operating on a pipe.
-
-    * src/common.c
-    Removed direct calls to psf_fread()/psf_fseek()/psf_fgets() etc from
-    psf_binheader_readf and redirect them to new buffered versions
-    header_read(), header_seek() and header_gets().
-    Add "G" format specifier to emulate fgets() functionality with buffering.
-    This will allow reading some file types from pipes.
-
-    * src/file_io.c
-    When the file descriptor is a pipe, manintain psf->pipeoffset.
-
-    * src/pvf.c
-    Change use of psf_fgets() to psf_binheader_readf() as required but changes to header re
-
-    * src/au.c
-    Fix reading from a pipe.
-
-2003-05-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c
-    Add clipping versions of the f2XXX_array() functions to allow option of
-    clipping data that would otherwise overflow.
-
-    * tests/scale_clip_test.tpl tests/scale_clip_test.def
-    New files test that clipping option does actually work.
-
-2003-05-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Fixed a typo ("OS(" instead of "OS9").
-
-2003-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/open_fail_test.c
-    Include <string.h> to prevent warning message of missing declaration of
-    memset().
-
-2003-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Add new "add_clipping" field to SF_PRIVATE.
-
-    * src/sndfile.h.in src/sndfile.c
-    Add command SFC_SET_CLIPPING which sets/resets add_clipping field.
-
-2003-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Add docs for sf_set_string() and sf_get_string().
-
-    * src/common.h src/sndfile.c
-    Add new SFE_STR_BAD_STRING error.
-
-    * tests/stdin_test.c tests/stdout_test.c
-    Removed all non-error print statements.
-
-    * tests/stdio_test.c tests/pipe_test.c tests/Makefile.am
-    Add print statements removed from two files above.
-
-2003-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * libsndfile.spec.in
-    Fixed a coulpe of minor errors discovered by someone calling themselves
-    Agent Smith.
-
-    * src/common.c src/common.h src/file_io.h
-    Added is_pipe field to SF_PRIVATE and declaration of psf_is_pipe()
-    function. (Axel Röbel)
-
-    * src/sndfile.c
-    Fixed determination of whether the file is a pipe. (Axel Röbel)
-
-    * src/paf.c
-    Force paf24 to start with undefined mode. (Axel Röbel)
-
-    * tests/pipe_test.c
-    Mods to make this test work and actually do the test on RAW files. (Axel
-    Röbel).
-
-2003-05-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a potential bug where psf->sf.seekable was being set to FALSE when
-    operating on stdin or stdout but then the default initialiser was reseting
-    it to TRUE. Thanks to Axel Röbel.
-
-    * src/aiff.c
-    Fixed a bug in the header parser where it was not handling an odd length
-    COMM chunk correctly. Thanks to Axel Röbel.
-
-    * src/test_file_io.c
-    Add more tests.
-
-    * tests/win32_test.c
-    New file for showing the bugs in the Win32 implementation of the POSIX API.
-    It also runs on Linux for sanity checking.
-
-    * tests/Makefile.am Win32/Makefile.msvc
-    Hook the new test program into the build system.
-
-2003-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/test_file_io.c
-    New test program to test operation of functions defined in file_io.c. This
-    should make supporting win32 significantly easier.
-
-    * src/Makefile.am
-    Hook new test program into the build system.
-
-    * src/file_io.c
-    Add compile/run time check that sizeof statbuf.st_size and sf_count_t are
-    the same.
-
-    * src/common.h src/sndfile.c
-    Added new error code and error message for new check.
-
-    * tests/benchmark.tpl
-    Fix to use frames instead of samples in SF_INFO.
-
-2003-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    More stuffing about working around PLAIN OLD-FASHIONED **BUGS** in Win32.
-
-    * examples/sndfile-info.c
-    Applied patch from Conrad Parker to add "--help" and "-h" options as
-    well as an improved usage message.
-
-2003-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c
-    Added embedded file support.
-
-    * tests/multi_file_test.c
-    Added tests for embedded AU files.
-    Added verbose testing mode.
-
-    * src/common.h src/sndfile.c
-    Added an embedded AU specific error code and message.
-
-    * src/wav.c
-    Added patch from Conrad Parker which filled in a little more information
-    about ACIDized WAV files.
-
-2003-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Fixed Win32 version of psf_fseek() which was calling psf_get_filelen()
-    which was in turn calling psf_fseek() which in the end blew the stack.
-    Now of course this would have been easy to find on Linux, but this blow
-    up was happening in kernel32.dll and the fscking MSVC++ debugger couldn't
-    figure out what call caused this (it couldn't even tell me the stack had
-    overflowed) and was absolutley useless for this debugging exercise.
-    On top of that, the reason I got into this mess was that windoze doesn't
-    have a working fstat() function which can return file lengths > 2 Gig. It
-    HAS a fscking _fstati64() but the file length value is only updated AFTER
-    the bloody file is closed. That makes it completely useless.
-    How the hell do people stand working on this crap excuse of an OS?
-
-2003-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/unistd.h src/file_io.c
-    Moved definitions of S_IGRP etc from file_io.c to unistd.h so that these
-    can be used in the test programs.
-
-    * Win32/libsndfile.def
-    Added sf_open_fd.
-
-    * Win32/sndfile.h
-    Updated to match src/sndfile.h.in.
-
-    * Win32/Makefile.msvc
-    Added dither.c and htk.c to libsndfile.dll target.
-
-2003-04-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    First attempt at getting the Win32 versions of the these functions working.
-    They still need to be tested.
-
-2003-04-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/strings.c
-    Found and fixed a bug which was causing psf_store_string() to fail on
-    Motorola 68k processors. Many thanks to Joshua Haberman (Debian maintainer
-    of libsndfile) for compiling and running debug code to help me debug the
-    problem.
-
-2003-04-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/file_io.c src/wav.c src/aiff.c
-    Much hacking to get reading and writing of embedded files working (ie sound
-    files at a non-zero files offset).
-
-    * doc/embedded_files.html
-    First pass atempt at documenting reading/writing embedded files.
-
-2003-04-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Updated answer to "Why doesn't libsndfile do interleaving/de-interleaving?"
-
-2003-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/aiff.c
-    Fix retrieving and storing of string data from files. Need to be careful
-    about using psf->buffer for strings.
-
-2003-04-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Fix psf_fseek() for seeks withing embedded files.
-
-2003-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Changed the definition of SNDFILE slightly to produce warnings when it isn't
-    used correctly. This should have zero affect in code which uses the SNDFILE
-    type correctly.
-
-    * src/sndfile.c
-    Fixed a few compiler warnings cause by the changes to the SNDFILE type.
-
-2003-04-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Added question and answer to the question "How about adding the ability
-    to write/read sound files to/from memory buffers?".
-
-2003-04-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Removed un-needed enums declaring TRUE and FALSE and replaced usage of
-    these with SF_TRUE and SF_FALSE.
-
-    * tests/multi_file_test.c
-    New test program to test sf_open_fd() on files containing data other than
-    a single sound file.
-
-2003-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    When creating files, set the readable by others flag. This still allows
-    further restrictions to be enforced by use of the user's umask. Fix
-    suggested by Eric Lyon.
-
-2003-04-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c
-    Changed sf_open_fd(). Dropped offset parameter and added a close_desc
-    parameter. If close desc is TRUE, the file descritpor passed into the
-    library will be closed when sf_close() is called.
-
-    * tests/utils.tpl
-    Modified call to sf_open_fd() to set close_desc parameter to SF_TRUE.
-
-2003-04-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Add a string (using sf_set_string() function) before and after data section
-    of all files. This will make sure that if string data can be added, it
-    doesn't overwrite real audio data.
-
-2003-04-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Started work on supporting a non-zero offset parameter for sf_open_fd ().
-
-    * src/<file header parsers>.c
-    Removed many uses of psf_fseek (SEEK_END) which to allow for future use of
-    sf_open_fd() with non-zero offset.
-    Associated refactoring.
-
-    * src/aiff.c
-    Implemented functionality required to get sf_get_string() and
-    sf_set_string() working for AIFF files.
-
-2003-04-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl
-    Modified test_open_file_or_die() to alternately use sf_open() and
-    sf_open_fd().
-
-    * src/svx.c
-    Fixed a bug which occurred when openning an existing file for read/write
-    using sf_open_fd(). In this case, the existing NAME chunk needs to be
-    read into psf->filename.
-    Fixed printing of sf_count_t types to logbuffer.
-
-2003-03-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Added prototype for new function sf_open_fd().
-
-    * src/sndfile.c
-    Moved most of the code in sf_open() to a new function psf_open_file().
-    Created new function sf_open_fd() which also uses psf_open_file() but
-    does not currently support the offset parameter.
-
-    * doc/api.html
-    Document sf_open_fd().
-
-2003-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a memory leak reported by Evgeny Karpov. Memory leak only occurred
-    when an attempt was made to read and the open() call fails.
-
-2003-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/open_fail_test.c
-    New test program to check for memory leaks when sf_open fails on a valid
-    file. Currently this must be run manually under valgrid.
-
-    * tests/Makefile.am
-    Hook new test program into build.
-
-2003-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Octave/sndfile_save.m Octave/sndfile_play.m
-    Added a -mat-binary option to the octave save command to force the output
-    to binary mode even if the user has set ascii data as the default. Found
-    by Christopher Moore.
-
-2003-02-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/dither.html
-    New file which will document the interface which allows the addition of
-    audio dither when sample word sizes are being reduced.
-
-    * src/dither.c
-    More work.
-
-2003-02-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    In update_header_test(), make HTK files a special case.
-
-    * doc/index.html
-    Added HTK to the feature matrix.
-
-2003-02-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/htk.c
-    New file for reading/writing HMM Tool Kit files.
-
-    * src/sndfile.h.in src/sndfile.c src/command.c src/Makefile.am
-    Hook in htk.c
-
-    * tests/write_read_test.tpl tests/misc_test.c tests/Makefile.am
-    Add tests for HTK files.
-
-2003-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed a bug where the LIST chunk length was being written incorrectly.
-
-    * tests/string_test.c
-    Added call to check_log_buffer().
-    Minor cleanups.
-
-2003-02-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_w64.h
-    Applied patch from Antoine Mathys to add extra WAV format definitions and
-    a G72x_ADPCM_WAV_FMT struct definition.
-
-    * src/wav_w64.c
-    Applied patch from Antoine Mathys which converts wav_w64_format_str() from
-    one huge inefficient switch statement to a binary search.
-
-    * tests/string_test.c
-    Dump log buffer if tests fail.
-
-2003-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/string_test.c
-    David Viens supplied some modifications to this file which showed up a bug
-    when using sf_set_string() and the sf_writef_float() functions.
-
-    * src/sndfile.c
-    Fixed the above bug.
-
-2003-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Added Q and A on how to detect libsndfile in configure.in (at the suggestion
-    of Davy Durham).
-
-2003-02-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Add enums and typedefs for dither.
-    Deprecate SFC_SET_ADD_DITHER_ON_WRITE and SFC_SET_ADD_DITHER_ON_READ, to be
-    replaced with SFC_SET_DITHER_ON_WRITE and SFC_SET_DITHER_ON_READ which will
-    allow different dither algorithms to be enabled.
-    Added SFC_GET_DITHER_INFO_COUNT and SFC_GET_DITHER_INFO.
-
-    * src/sndfile.h.in src/Version_script.in Win32/libsndfile.def.
-    Added public sf_dither_*() functions.
-
-    * src/sndfile.c
-    Implement commands above.
-
-    * src/dither.c
-    More work. Framework and external hooks into dither algorithms complete.
-
-2003-02-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/version-1.html libsndfile_version_convert.py
-    Remove redundant files.
-
-    * doc/index.html doc/api.html
-    Remove links to version-1.html.
-
-    * src/dither.c
-    New file to allow the addition of audio dither on input and output.
-
-    * src/common.h
-    Add prototype for dither_init() function.
-
-    * Makefile.am doc/Makefile.am
-    Changes for added and removed files.
-
-2003-02-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/Makefile.msvc
-    Changes to force example binaries to be placed in the top level directory
-    instead of the examples/ directory.
-    Add src/strings.c and src/xi.c to the build.
-    Add string_test to build and to tests on WAV files.
-
-    * doc/index.html
-    Added XI to support matrix.
-
-2003-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Added prototypes for sf_get_string() and sf_set_string() and SF_STR_*
-    enum values.
-
-    * src/sndfile.c
-    Added public interface to sf_get_string() and sf_set_string().
-
-    * src/wav.c
-    Added code for setting and getting strings in WAV files.
-
-    * tests/string_test.c
-    New test program for sf_get_string() and sf_set_string() functionality.
-
-    * tests/Makefile.am
-    Hook new test program into build and test framework.
-
-2003-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Added fields to SF_PRIVATE for string data needed to implement
-    sf_get_string() and sf_set_string().
-
-    * src/strings.c
-    New file for storing and retrieving strings to/from files.
-
-    * src/Makefile.am
-    Added strings.c to build.
-
-2003-01-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/xi.c
-    Read seems to be working so looking at write.
-
-    * src/sndfile.h.in
-    Added SF_FORMAT_XI, SF_FORMAT_DPCM_8 and SF_FORMAT_DPCM_16 enum values.
-
-    * tests/floating_point_test.c tests/lossy_comp_test.c tests/Makefile.am
-    Added test for 8 and 16 bit XI format files.
-
-2003-01-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Added a non-lawyer readable summary of the licensing provisions as
-    suggested by Steve Dekorte.
-
-2003-01-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed a compiler warning found by Alexander Lerch.
-
-2003-01-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Fixed the multiple linking of libm.
-
-2003-01-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/Makefile.mcvs
-    Added comments on the correct way to set up the MSVCDir environment
-    variable.
-
-    * doc/win32.html
-    Add on how to set up the MSVCDir environment variable.
-
-2003-01-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c examples/sndfile-info.c
-    When run on Win32 without any command line parameters print a message and
-    then sleep for 5 seconds. This means the when somebody double clicks on
-    these programs in explorer the user will actually see the message.
-
-2003-01-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Bypass permission test if running as root because root is allowed to open
-    a readonly file for write.
-
-2003-01-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/Makefile.msvc
-    Added pvf.c and xi.c source files to project.
-
-    * src/sndfile.h
-    Updated for PVF files.
-
-2003-01-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Modified validate_sfinfo() to force samplerate, channels and sections
-    to be >= 1.
-    In format_from_extension() replaced calls to does_extension_match()
-    with strcmp().
-
-    * src/xi.c
-    More work.
-
-2003-01-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/Makefile.am
-    Added octave.html which had been left out. Found by Jan Weil.
-
-2003-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pvf.c src/common.h src/sndfile.c
-    Fixed error handling for PVF files.
-
-    * src/xi.c
-    New file for handling Fasttracker 2 Extended Instrument files. Not working
-    yet and included when configured with --enable-experimental.
-
-    * src/sndfile.c src/common.h
-    Hooked in new file xi.c.
-
-2002-12-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/rx2.c
-    Added a patch from Marek Peteraj which sheds a little more light on the
-    slices within an RX2 file. Still need to find out data encoding.
-
-2002-12-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Started work on decoding 'acid' and 'strc' chunks.
-
-2002-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/peak_check_test.c
-    Minor cleanup.
-
-2002-12-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl
-    Added check to make sure no error was generated when an attempt was made to
-    read past the end of the file.
-
-2002-12-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/lists.html
-    Added "mailto" links for all three lists.
-
-    * src/pvf.c
-    New file for Portable Voice Format files.
-
-    * src/sndfile.h.in src/sndfile.c src/common.h src/command.c src/Makefile.am
-    Added hooks for SF_FORMAT_PVF format files.
-
-    * tests/write_read_test.tpl tests/std*.c
-    Add tests for SF_FORMAT_PVF.
-
-    * doc/index.html
-    Add PVF to the compatibility matrix.
-
-    * src/pcm.c src/alaw.c src/ulaw.c src/float32.c src/double64.c
-    Previously, attempts to read beyond the end of a file would set psf->error
-    to SFE_SHORT_ERROR. This behaviour diverged from the behaviour of the POSIX
-    read() call but has now been fixed.
-    Attempts to read beyond the end of the file will return a short read count
-    but will not longer set any error.
-
-2002-12-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Add more sanity checking when opening a RAW file for read. When format is
-    not RAW, zero out all members of the SF_INFO struct.
-
-    * tests/raw_test.c
-    Add bad_raw_test() to check for above problem.
-
-    * tests/stdin_test.c examples/sndfile-info.c
-    Set the format field of the SF_INFO struct to zero before calling
-    sf_open().
-
-    * doc/api.html
-    Add information about the need to set the format field of the SF_INFO struct
-    to zero when opening non-RAW files for read.
-
-    * configure.ac
-    Removed use of conversion script on Solaris. Not all Solaris versions
-    support it.
-
-    * doc/lists.html
-    New file containg details of the mailing lists.
-
-    * doc/index.html
-    Add a link to the above new file.
-
-2002-12-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/dft_cmp.c
-    Fixed a SIGFPE on Alpha caused by a log10 (0.0). Thanks to Joshua Haberman
-    for providing the gdb traceback.
-
-2002-11-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Added more capabilities to 'smpl' chunk parser.
-
-    * src/sndfile.c
-    Fixed some (not all) possible problems found with Flawfinder.
-
-2002-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a bug in sf_seek(). This bug could only occur when an attempt was
-    made to read beyond the end and then sf_seek() was called with a whence
-    parameter of SEEK_CUR.
-
-    * src/file_io.c
-    Win32's _fstati64() does not work, it returns BS. Re-implemented
-    psf_get_filelen() in terms of psf_fseek().
-
-    * tests/write_read_test.tpl
-    Add a test to detect above bug.
-
-    * src/float_cast.h
-    Modification to prevent compiler warnings on Mac OS X.
-
-    * src/file_io.c
-    Fixes for windows (what a f**ked OS).
-
-2002-11-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.ac
-    Disable use of native lrint()/lrintf() on Mac OSX. These functions exist on
-    Mac OSX 10.2 but not on 10.1. Forcing the use of the versions in
-    src/float_cast.h means that a library compiled on 10.2 will still work on
-    10.1.
-
-2002-11-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in configure.ac
-    Renamed configure.in to configure.ac as expected by later versions of
-    autoconf.
-    Slight hacking of configure.ac to work with version 2.54 of autoconf.
-    Changed to using -dumpversion instead of --version for determining GCC
-    version numer as suggested by Anand Kumria.
-
-    * src/G72x/Makefile.am
-    Slight hacking required for operation with automake 1.6.3.
-
-2002-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    In psf_binheader_readf() changed type parameter type "b" type from size_t
-    to int to prevent errors on IA64 CPU where sizeof (size_t) != sizeof (int).
-    Thanks to Enrique Robledo Arnuncio for debugging this.
-
-2002-11-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * test/command_test.tpl
-    Changed test value so test would pass on Solaris.
-
-    * src/Version_script.in
-    Modified version numbering so that later versions of 1.0.X can replace
-    earlier versions without recompilation.
-
-    * src/vox_adpcm.c
-    Fixed bug causing short reads.
-
-2002-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * test/floating_point_test.c
-    Code cleanup using functions from util.c.
-    Add test for IEEE replacement floats and doubles.
-
-2002-11-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed a possible divide by zero error when read the 'smpl' chunk. Thanks to
-    Serg Repalov for the example file.
-
-    * tests/pcm_test.tpl
-    Used sf_command (SFC_TEST_IEEE_FLOAT_REPLACE) to test IEEE replacement code.
-    Clean up pcm_double_test().
-
-    * src/float32.c src/double64.c
-    Force use of IEEE replacement code using psf->ieee_replace is TRUE,
-    Print message to log_buffer as well.
-    Rename all broken_read_* and broken_write* functions to replace_read_* and
-    replace_write_*.
-
-    * tests/util.tpl
-    Added string_in_log_buffer().
-
-    * tests/pcm_test.tpl
-    Use string_in_log_buffer() to ensure that IEEE replacement code has been
-    used.
-
-    * configure.in
-    Removed --enable-force-broken-float option. IEEE replacement code is now
-    always tested.
-
-2002-10-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/double64.c
-    Implement code for read/writing IEEE doubles on platforms where the native
-    double format is not IEEE.
-
-    * src/float32.c src/common.h
-    Remove float32_read() and float32_write(). Replace with float32_le_read(),
-    float32_be_read(), float32_le_write() and float32_be_write() to match stuff
-    in src/double64.c.
-
-    * src/common.c
-    Fix all usage of float32_write().
-
-    * src/sndfile.h.in
-    Added SFC_TEST_IEEE_FLOAT_REPLACE command (testing only).
-
-    * src/common.h
-    Added SF_PRIVATE field ieee_replace.
-
-    * src/sndfile.c
-    In sf_command() set/reset psf->ieee_replace.
-
-2002-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pcm_test.tpl
-    Fixed a problem when testing with --enable-force-broken-float. The test was
-    generating a value of negative zero and the broken float code is not able
-    to write negative zero. Removing the negative zero fixed the test.
-
-2002-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Added fix for Cygwin (suggested by Maros Michalik).
-
-2002-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Improved error detection and handling.
-
-    * src/file_io.c src/common.h
-    Removed functions psf_ferror() and psf_clearerr() which were redundant
-    after above improvements.
-
-    * src/aiff.c src/svx.c src/w64.c src/wav.c
-    Removed all use of psf_ferror() and psf_clearerr().
-
-    * src/sndfile.c
-    Removed #include of <stdio.h>, <unistd.h>, <fcntl.h> and <math.h> which
-    are no longer needed.
-
-    * tests/misc_test.c
-    Added test to make sure the correct error message is returned with an
-    existing read-only file is openned for write.
-
-2002-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html doc/api.html
-    Updated for OKI Dialogic ADPCM files.
-
-    * src/command.c
-    Added VOX ADPCM to sub_fomats.
-
-2002-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/vox_adpcm.c src/Makefile.am
-    New file for handling OKI Dialogic ADPCM files.
-
-    * src/sndfile.h
-    Add new subtype SF_FORMAT_VOX_ADPCM.
-
-    * src/sndfile.c
-    Renamed function is_au_snd_file () to format_from_extenstion () and expanded
-    its functionality to detect headerless VOX files.
-
-    * src/raw.c
-    Added hooks for SF_FORMAT_VOX_ADPCM.
-
-    * examples/sndfile-info.c
-    Print out file duration (suggested by Conrad Parker).
-
-    * libsndfile.spec.in
-    Force installation of sndfile.pc file (found by John Thompson).
-
-    * tests/Makefile.am tests/lossy_comp_test.c tests/floating_point_test.c
-    Add tests for SF_FORMAT_VOX_ADPCM.
-
-2002-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Add test which attempts to write to /dev/full (on Linux anyway) to check
-    for correct handling of writing to a full filesystem.
-
-    * src/sndfile.c
-    Return correct error message if the header cannot be written because the
-    filesystem is full.
-
-    * tests/util.tpl
-    Corrected printing of file mode in error reporting.
-
-    * src/mat5.c
-    Fixed a bug where a MAT5 file written by libsndfile could not be opened by
-    Octave 2.1.36.
-
-2002-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/file_io.c
-    All low level file I/O have been modified to be better able to report
-    system errors resulting from calling system level open/read/write etc.
-
-    * src/*.c
-    Updated for compatibility with above changes.
-
-    * examples/cooledit-fixer.c
-    New example program which fixes badly broken file created by Syntrillium's
-    Cooledit which are marked as containing PCM samples but actually contain
-    floating point data.
-
-    * examples/Makefile.am
-    Hooked cooledit-fixer into the build system.
-
-2002-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Document SFC_GET_FORMAT_INFO.
-
-2002-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/wav32_aiff24.c examples/sndfile2oct.c examples/sfhexdump.c
-        examples/sfdump.c
-    Removed these files because they weren't interesting.
-
-    * examples/sfconvert.c examples/sndfile-convert.c
-    Renamed the first to the latter.
-
-    * examples/Makefile.am
-    Added sndfile-convert to the bin_PROGRAMS, so it is installed when the lib
-    is installed.
-    Removed old programs wav32_aiff24 and sndfile2oct.
-
-    * man/sndfile-convert.1
-    New man page.
-
-    * examples/sndfile-convert.c
-    Added some gloss now that sndfile-convert.c is an installed program.
-
-    * src/sndfile.h.in src/sndfile.c src/common.h src/command.h
-    Added command SFC_GET_FORMAT_INFO.
-
-    * tests/command_test.c
-    Added tests form SFC_GET_FORMAT_INFO.
-
-2002-10-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    In sf_format_check() return error if samplerate < 0.
-
-2002-10-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fixed bug in handling of COMM chunks with a 4 byte encoding byte but no
-    encoding string.
-
-2002-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed repeated word in an error message.
-
-2002-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Improved advertising in Features section.
-
-2002-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Added decoding of 'labl' chunks within 'LIST' chunks.
-
-    * src/common.h
-    Added (experimental only) SF_FORMAT_OGG and SF_FORMAT_VORBIS and definition
-    of ogg_open(). This is nowhere near working yet.
-
-    * src/sndfile.c
-    Added detection of 'OggS' file marker and added call to ogg_open() to
-    switch statement.
-
-    * src/ogg.c
-    New file. Very early start of Ogg Vorbis support.
-
-    * src/wav.c
-    Added handling of brain-damaged and broken Cooledit "32 bit 24.0 float
-    type 1" files. These files are marked as being 24 bit WAVE_FORMAT_PCM with
-    a block alignment of 4 times the numbers of channels but are in fact 32 bit
-    floating point.
-
-2002-10-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Modified option --enable-experimental to set ENABLE_EXPERIMENTAL_CODE in
-    config.h to either 0 or 1.
-
-    * src/sndfile.c
-    Modify sf_command (SFC_GET_LIB_VERSION) to append "-exp" to the version
-    string if experimental code has been enabled.
-
-2002-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/Makefile.am
-    Added -lm to libsndfile_la_LIBADD. This means that -lm is not longer needed
-    in the link line when linking something to libsndfile.
-
-    * tests/Makefile.am examples/Makefile.am
-    Removed -lm from all link lines.
-
-    * sndfile.pc.in
-    Removed -lm from Libs line.
-
-2002-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Removed all perror() calls.
-
-    * src/nist.c
-    Removed calls to exit() function.
-    Added check to detect NIST files dammaged from Unix CR -> Win32 CRLF
-    conversion process.
-
-2002-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c
-    New function sf_strerror() which will eventually replace functions
-    sf_perror() and sf_error_str().
-    Function sf_error_number() has also been changed, but this was documented
-    as being for testing only.
-
-    * doc/api.html
-    Documented above changes.
-
-    * tests/*.c examples/*.c
-    Changed to new error functions.
-
-2002-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Detect GCC version, and print a warning message about writeable strings
-    it GCC major version number is less than 3.
-
-2002-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in doc/api.html
-    Documentation fixes.
-
-2002-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/Version_script.in src/Makefile.am configure.in
-    Use the version script to prevent the exporting of all non public symbols.
-    This currently only works with Linux. Will test on Solaris as well.
-
-    * src/float_cast.h
-    Added #ifndef to prevent the #warning directives killing the SGI MIPSpro
-    compiler.
-
-    * src/au_g72x.c src/double64.c src/float32.c src/gsm610.c src/ima_adpcm.c
-        src/ms_adpcm.c
-    Fix benign compiler warnings arising from previously added compiler
-    flags.
-
-2002-09-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a bug in sf_error_str() where errnum was used as the index instead
-    of k. Found by Tim Hockin.
-
-    * examples/sndfile-play.c
-    Fixed a compiler warning resulting from a variable shadowing a previously
-    defined local.
-
-2002-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in src/sndfile.c
-    Added command SFC_SET_RAW_START_OFFSET.
-
-    * doc/command.html
-    Document SFC_SET_RAW_START_OFFSET.
-
-    * tests/raw_test.c tests/Makefile.am
-    Add new file for testing SF_FORMAT_RAW specific functionality.
-
-    * tests/dwvw_test.c
-    Updates.
-
-2002-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Modified reading of 'smpl' chunk to take account of the sampler data field.
-
-    * tests/utils.tpl tests/utils.h
-    Added function print_test_name().
-
-    * tests/misc_test.c tests/write_read_test.tpl tests/lossy_comp_test.c
-        tests/pcm_test.tpl tests/command_test.tpl tests/floating_point_test.c
-    Convert to use function print_test_name().
-
-2002-09-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/octave.html
-    Added a link to some other Octave scripts for reading and writing sound
-    files.
-
-    * src/paf.c
-    Change type of dummy data field to int. This should fix a benign compiler
-    warning on some CPUs.
-    Removed superfluous casts resulting from the above change.
-
-    * src/rx2.c
-    More hacking.
-
-2002-09-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/mat5.c src/common.c
-    Changed usage of snprintf() to LSF_SNPRINTF().
-
-    * Win32/Makefile.msvc
-    Updated to include new files and add new tests.
-
-    * Win32/config.h Win32/sndfile.h
-    Updated.
-
-    * doc/api.html
-    Added note about the possibility of "missing" features actually being
-    implemented as an sf_command().
-
-2002-09-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/misc_test.c
-    Added previously missing update_header_test and zero_data_tests for PAF,
-    MAT4 and MAT5 formats.
-
-    * src/paf.c src/mat4.c src/mat5.c
-    Fixed bugs uncovered by new tests above.
-
-    * src/mat5.c
-    Generalised parsing of name fields of MAT5 files.
-
-    * src/mat5.c src/sndfile.c
-    Added support for unsigned 8 bit PCM MAT5 files.
-
-    * tests/write_read_test.tpl
-    Added test for unsigned 8 bit PCM MAT5 files.
-
-    * doc/index.html
-    Added unsigned 8 bit PCM MAT5 to capabilities matrix.
-
-2002-09-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * test/update_header_test.c tests/misc_test.c
-    Renamed update_header_test.c to misc_test.c.
-    Added zero_data_test() to check for case where file is opened for write and
-    closed immediately. The resulting file can be left in a state where
-    libsndfile cannot open it. Problem reported by Werner Schweer, the author
-    of Muse.
-
-    * src/aiff.c
-    Removed superfluous cast.
-
-    * src/wav.c src/svx.c
-    Fixed case of file generated with no data.
-    Removed superfluous cast.
-
-    * src/sndfile.c
-    Fixed error on IA64 platform caused by incorrect termination of
-    SndfileErrors struct array. This problem was found in the Debian buildd
-    logs (http://buildd.debian.org/).
-
-    * configure.in
-    Added Octave directory.
-
-    * Octave/Makefile.ma
-    New Makfile.am for Octave directory.
-
-    * Octave/sndfile_load.m Octave/sndfile_save.m Octave/sndfile_play.m
-    New files for working with Octave.
-
-    * doc/octave.html
-    Document explaining the use of the above three Octave scripts.
-
-2002-09-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed bug in RDWR mode.
-
-2002-09-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Fixed psf_get_date_str() for systems which don't have gmtime_r() or
-    gmtime().
-
-    * src/file_io.c
-    Added #include <io.h> for Win32. Reported by Koen Tanghe.
-
-2002-09-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Added 'S' format specifier for psf_binheader_writef() which writes a C
-    string, including single null terminator to the header.
-    Added 'j' format specifier to allow jumping forwards or backwards in the
-    header.
-    Added function psf_get_date_str().
-
-    * src/mat5.c
-    Complete read and write support.
-
-    * doc/index.html
-    Added entries for MAT4 and MAT5 in capabilities matrix.
-
-2002-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/mat4.c
-    Completed read and write support.
-
-    * src/common.h src/sndfile.c
-    Added MAT4 and MAT5 specific error messages.
-
-    * tests/write_read_test.tpl tests/Makefile.am
-    Added tests for MAT4 and MAT5 files.
-
-    * tests/stdio_test.c tests/stdout_test.c tests/stdin_test.c
-    Added tests for MAT4 and MAT5 files.
-
-2002-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/command.c
-    Added elements for SF_FORMAT_MAT4 and SF_FORMAT_MAT5 to major_formats
-    array.
-
-    * examples/sfconvert.c
-    Added mat4 and mat5 output targets.
-
-2002-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Added check to prevent errors openning read only formats for read/write.
-
-    * src/interleave.c
-    New file for interleaving non-interleaved data. Non-interleaved data is
-    only supported on read.
-
-    * src/Makefile.am
-    Added src/interleave.c to build.
-
-2002-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/double64.c src/common.h
-    Added double64_be_read(), double64_le_read(), double64_be_write() and
-    double64_le_write() which replace double64_read() and double64_write().
-
-    * src/common.c
-    Cleanup of psf_binheader_readf() and add ability to read big and little
-    endian doubles (required by mat4.c and mat5.c).
-    Add ability for psf_binheader_writef() to write doubles to sound file
-    headers.
-
-2002-09-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/mat5.c
-    New file for reading Matlab (tm) version 5 data files. This is also the
-    native binary file format for version 2.1.X of GNU Octave which will be
-    used for testing.
-    Not complete yet.
-
-    * src/mat4.c
-    New file for reading Matlab (tm) version 4.2 data files. This is also the
-    native binary file format for version 2.0.X of GNU Octave which will be
-    used for testing.
-    Not complete yet.
-
-    * src/sndfile.h.in src/sndfile.c src/common.h src/command.c src/Makefile.am
-    Mods to add Matlab files.
-
-    * src/common.[ch]
-    Added readf_endian field to SF_PRIVATE struct allowing endianness to
-    remembered across calls to sf_binheader_readf().
-    Fixed bug in width_specifier behaviour for printing hex values.
-
-2002-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Check return value of close() call in psf_fclose().
-
-2002-08-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ms_adpcm.c
-    Commented out some code where 0x10000 was being subtracted from a short
-    and the result assigned to a short again. Andrew Zaja found this.
-
-2002-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Fixed typo found by Tommi Ilmonen.
-
-    * src/ima_adpcm.c
-    Changed type of diff from short to int to prevent errors which can occur
-    during very rare circumstances. Thanks to FUWAFUWA.
-
-2002-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/floating_point_test.c
-    Disable testing on machines without lrintf().
-
-    * Win32/Makefile.msvc
-    Added dwd.c and wve.c to build.
-
-    * configure.in
-    Bumped version to 1.0.0.
-
-2002-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Add a #include for Mac OS 9. Thanks to Stephane Letz.
-
-    * src/wav.c
-    Changed an snprintf to LSF_SNPRINTF.
-
-    * doc/Makefile.am
-    Added version-1.html.
-
-2002-08-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Bumped version to 1.0.rc6.
-
-    * src/*.c
-    Modified scaling of normalised floats and doubles to integers. Until now
-    this has been done by multiplying by 0x8000 for short output, 0x80000000
-    for 32 bit ints and so on. Unfortunately this can cause an overflow and
-    wrap around in the target value. All thes values have therefore been
-    reduced to 0x7FFF, 0x7FFFFFFF and so on. The conversion from ints to
-    normalised floats and doubles remains unchanged. This does mean that for
-    repeated conversions normalised float -> pcm16 -> normalised float would
-    result in a decrease in amplitude of 0x7FFF/0x8000 on every round trip.
-    This is undesirable but less undesireable than the wrap around I am trying
-    to avoid.
-
-    * tests/floating_point_test.c
-    Removed file hash checking because new float scaling procedure introduced
-    above prevented the ability to crate a has on both x86 and PowerPC systems.
-
-2002-08-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/txw.c
-    Completed reading of TXW files. Seek doesn't work yet.
-
-    * src/file_io.c
-    Added a MacOS 9 replacement for ftruncate().
-
-    * MacOS/sndfile.h
-    Added MacOS 9 header file. This should be copied into src/ to compile
-    libsndfile for MacOS9.
-
-2002-08-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed commands SF_SET_NORM_DOUBLE and SFC_SET_NORM_FLOAT to return their
-    values after being set. Reported by Jussi Laako.
-
-    * configure.in
-    If autogen is not found, touch all .c and .h files in tests/.
-
-    * src/common.c
-    Added format width specifier to psf_log_printf() for %u, %d, %D and %X.
-
-    * src/dwd.c
-    Completed implementation of read only access to these files.
-
-    * src/common.h src/*.c src/pcm.c
-    Removed redundant field chars from SF_PRIVATE struct and modified
-    pcm_init() to do without it.
-
-2002-08-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wve.c
-    New file implementing read of Psion Alaw files. This will be a read only
-    format. Implementation complete.
-
-    * src/dwd/c
-    Started implementation of DiamondWare Digitized files. Also read only, not
-    complete.
-
-    * src/wav.c
-    Add parsing of 'smpl' chunk.
-
-    * src/paf.c
-    Fixed reading on un-normalized doubles and floats from 24 bit PAF files.
-    This brings it into line with the reading of 8 bit files into
-    un-normalized doubles which returns values in the range [-128, 127].
-
-    * src/common.c
-    Modified psf_log_printf() to accept the %% conversion specifier to allow
-    printing of a single '%'.
-
-    * src/sds.c
-    Read only of 16 bit samples is working. Need to build a test harness for
-    this and other read only formats.
-
-2002-08-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Added --enable-experimental configure option.
-    Removed pkg-config message at the end of the configure process.
-
-    * src/sds.c src/txw.c src/rx2.c src/sd2.c
-    Moved all the code in these files inside #if ENABLE_EXPERIMENTAL_CODE
-    blocks and added new *_open() function for the case where experimental is
-    not enabled. These new functions just return SFE_UNIMPLMENTED.
-
-    * Win32/sndfile.h src/sndfile.h.in src/common.h
-    Removed un-necessary #pragma pack commands.
-
-    * src/file_io.c
-    Implemented psf_ftruncate() and much other hacking for Win32.
-
-    * Win32/Makefile.msvc
-    Updated.
-
-    * doc/win32.html
-    Updated to include the copying of the sndfile.h file from the Win32/
-    directory to the src/ directory.
-
-    * Make.bat
-    Batch file to make compiling on Wi32 a little easier. Implements "make" and
-    "make check".
-
-2002-08-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    Add place holder for ftruncate() on Win32 which doesn't have ftruncate().
-    This will need to be fixed later.
-
-    * src/sndfile.h.in
-    New file (copy of sndfile.h) with sets up @TYPEOF_SF_COUNT_T@ which will be
-    replaced by the correct type during configure.
-
-    * configure.in
-    Modified to find a good type for TYPEOF_SF_COUNT_T.
-
-    * src/aiff.c
-    Fixed a bug when reading malformed headers.
-
-    * src/common.c
-    Set read values to zero before performing read.
-
-2002-08-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Fixed some HTML tags which were not allowing jumps to links within the
-    page.
-
-    * src/sds.c
-    Massive hacking on this.
-
-    * src/wav.c
-    Added recognition of 'clm ' tag.
-
-2002-08-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Added beginning of a capabilities list beyond simple file formats which
-    can be read/written.
-
-    * src/aiff.c
-    Added parsing of INST and MARK chunks of AIFF files. At the moment this
-    data is simply recorded in the log buffer. Later it will be possible to
-    read this data from an application using sf_command().
-
-    * src/wav.c
-    Added parsing of 'cue ' chunk which contains loop information in WAV files.
-
-    * exampes/sndfile-info.c
-    Changed reporting of Samples to Frames.
-
-    * src/wav.c src/w64.c src/aiff.c src/wav_w64.h
-    Moved from a samples to a frames nomenclature to avoid confusion.
-
-    * doc/FAQ.html
-    What's the best format for storing temporary files?
-
-    * src/sds.c
-    New file for reading/writing Midi Sample Dump Standard files.
-
-    * src/Makefile.am src/sndfile.c src/common.[ch]
-    Added hooks for sds.c.
-
-    * examples/sndfile-info.c
-    Changed from using sf_perror() to using sf_error_str().
-
-2002-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Added explanation of mode parameter for sf_open().
-    Added explanation of usage of SFM_* values in sf_seek().
-
-    * src/sndfile.[ch] src/command.c src/file_io.c src/common.h
-    Implemented SFC_FILE_TRUNCATE to allow a file to be truncated. File
-    truncation was suggested by James McCartney.
-
-    * src/command.html
-    Documented SFC_FILE_TRUNCATE.
-
-    * tests/command_test.c
-    Add tests for SFC_FILE_TRUNCATE.
-
-    * src/sndfile.c
-    Added a thrid parameter to the VALIDATE_SNDFILE_AND_ASSIGN_PSF macro to
-    make resetting the error number optional. All uses of the macro other than
-    in error reporting functions were changed to reset the error number.
-
-    * src/pcm.c
-    Fixed a bug were sf_read_* was logging an SFE_SHORT_READ even when no error
-    occurred.
-
-    * tests/write_read_test.tpl
-    Added tests of internal error state.
-
-2002-08-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/GSM610/private.h src/GSM610/*.c src/GSM610/Makefile.am
-    Renamed private.h to gsm610_priv.h to prevent clash with other headers
-    named private.h in other directories. (Probably only a problem on MacOS 9).
-
-    * src/G72x/private.h src/G72x/*.c src/G72x/Makefile.am
-    Renamed private.h to g72x_priv.h to prevent clash with other headers
-    named private.h in other directories. (Probably only a problem on MacOS 9).
-
-    * MacOS/config.h
-    Changed values of HAVE_LRINT and HAVE_LRINTF to force use of code in
-    float_cash.h.
-
-    * src/sndfile.h
-    Changes the name of samples field of the SF_INFO to frames. The old name
-    had caused too much confusion and it simply had to be changed. There will
-    be at least one more pre-release.
-
-2002-08-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/index.html
-    Updated formats matrix to include RAW (header-less) GSM 6.10.
-    Fix specificaltion of table and spelling mistakes.
-
-    * src/sndfile.c src/command.c
-    Fixed bug in SFC_CALC_MAX_SIGNAL family and psf_calc_signal_max ().
-
-    * tests/command.c
-    Removed cruft.
-    Added test for SFC_CALC_MAX_SIGNAL and SFC_CALC_NORM_MAX_SIGNAL.
-
-    * configure.in
-    Update version to 1.0.0rc5.
-
-    * sfendian.h
-    Removed inclusion of un-necessary header.
-
-2002-08-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Minor fixes of info written to log buffer.
-
-    * src/float_cast.h
-    Add definition of HAVE_LRINT_REPLACEMENT.
-
-    * tests/floating_point_test.c
-    Fix file hash check on systems without lrint/lrintf.
-
-    * tests/dft_cmp.c
-    Limit SNR to less than -500.0dB.
-
-    * examples/sndfile2oct.c
-    Fixed compiler warnings.
-
-    * doc/api.html
-    Fixed error where last parameter of sf_error_str() was sf_count_t instead
-    of size_t.
-
-2002-08-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    Why doesn't libsndfile do interleaving/de-interleaving.
-
-    * tests/pcm_test.tpl
-    On Win32 do not perform hash check on files containing doubles.
-
-2002-08-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Defined SF_COUNT_MAX_POSITIVE() macro, a portable way of setting variables
-    of type sf_count_t to their maximum positive value.
-
-    * src/dwvw.c src/w64.c
-    Used SF_COUNT_MAX_POSITIVE().
-
-2002-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    Fixed bug in reading/writing of 24 bit PCM PAF files on big endian systems.
-
-    * tests/floating_point_tests.c
-    Fixed hash values for 24 bit PCM PAF files.
-    Disabled file has check if lrintf() function is not available and added
-    warning.
-    Decreased level of signal from a peak of 1.0 to a value of 0.95 to prevent
-    problems on platforms without lrintf() ie Solaris.
-
-2002-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed a problem with two different kinds of mal-formed WAV file header. The
-    first had the 'fact' chunk before the 'fmt ' chunk, the other had an
-    incomplete 'INFO' chunk at the end of the file.
-
-    * src/w64.c
-    Added fix to allow differentiation between W64 files and ACID files.
-
-    * src/au_g72x.c src/common.h src/sndfile.c
-    Added error for G72x encoded files with more than one channel.
-
-    * tests/pcm_test.tpl tests/utils.tpl
-    Moved function check_file_hash_or_die() to utils.tpl. Function was then
-    modified to calculate the has of the whole file.
-
-    * src/wav.c
-    Fixed problem writing the 'fact' chunk on big endian systems.
-
-    * tests/sfconvert.c
-    Fixed bug where .paf files were being written as Sphere NIST.
-
-2002-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/voc.c
-    Fix for reading headers generated using SFC_UPDATE_HEADER_NOW.
-
-    * doc/command.html
-    Add docs for SFC_UPDATE_HEADER_NOW and SFC_SET_UPDATE_HEADER_AUTO.
-
-2002-07-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * man/sndfile-info.1 man/sndfile-play.1
-    Added manpages supplied by Joshua Haberman the Debian maintainer for
-    libsndfile. Additional tweaks by me.
-
-    * configure.in man/Makefile.am
-    Hooked manpages into autoconf/automake system.
-
-    * src/sndfile.c
-    Added hooks for SFC_SET_UPDATE_HEADER_AUTO.
-
-    * tests/update_header_test.c
-    Improved rigor of testing.
-
-    * src/*.c
-    Fixed problem with *_write_header() functions.
-
-2002-07-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/*.html
-    Updates to documentation to fix problems found by wdg-html-validator.
-
-    * src/common.h src/command.c
-    Added normalize parameter to calls to psf_calc_signal_max() and
-    psf_calc_max_all_channels().
-
-    * src/sndfile.c
-    Added handling for commands SFC_CALC_NORM_SIGNAL_MAX and
-    SFC_CALC_NORM_MAX_ALL_CHANNELS.
-
-    * doc/command.html
-    Added entry for SFC_CALC_NORM_SIGNAL_MAX and SFC_CALC_NORM_MAX_ALL_CHANNELS.
-
-2002-07-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c Win32/Makefile.msvc
-    Get sndfile-play program working on Win32. The Win32 PCM sample I/O API
-    sucks. The sndfile-play program now works on Linux, MacOSX, Solaris and
-    Win32.
-
-2002-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/FAQ.html
-    New file for frequently asked questsions.
-
-2002-07-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Documentation fixes.
-
-    * src/au.[ch] src/au_g72x.c src/G72x/g72x.h
-    Add support of 40kbps G723 ADPCM encoding.
-
-    * tests/lossy_comp_test.c tests/floating_point_test.c
-    Add tests for 40kbps G723 ADPCM encoding.
-
-    * doc/index.html
-    Update support matrix.
-
-2002-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/command.html
-    Documented SFC_GET_SIMPLE_FORMAT_COUNT, SFC_GET_SIMPLE_FORMAT,
-    SFC_GET_FORMAT_* and SFC_SET_ADD_PEAK_CHUNK.
-
-    * src/sndfile.c src/pcm.c
-    Add ability to turn on and off the addition of a PEAK chunk for floating
-    point WAV and AIFF files.
-
-    * src/sndfile.[ch] src/common.h src/command.c
-    Added sf_command SFC_CALC_MAX_ALL_CHANNELS. Implemented by Maurizio Umberto
-    Puxeddu.
-
-    * doc/command.html
-    Docs for SFC_CALC_MAX_ALL_CHANNELS (assisted by Maurizio Umberto Puxeddu).
-
-2002-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/gsm610.c
-    Finalised support for GSM 6.10 AIFF files and added support for GSM 6.10
-    encoded RAW (header-less) files.
-
-    * src/wav.c
-    Add support for IBM_FORMAT_MULAW and IBM_FORMAT_ALAW encodings.
-
-    * src/api.html
-    Fixed more documentation bugs.
-
-2002-07-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h src/common.h
-    Moved some yet-to-be-implelmented values for SF_FORMAT_* from the public
-    header file sndfile.h to the private header file common.h to avoid
-    confusion about the actual capabilities of libsndfile.
-
-2002-07-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/wav.c
-    Fixed file parsing for WAV and AIFF files containing non-audio data after
-    the data chunk.
-
-    * src/aiff.c src/sndfile.c
-    Add support for GSM 6.10 encoded AIFF files.
-
-    * tests/lossy_comp_test.c tests/Makefile.am
-    Add tests for GSM 6.10 encoded AIFF files.
-
-    * src/*.c
-    Fix compiler warnings.
-
-2002-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    For SFC_SET_NORM_* tests, change the file format from SF_FORMAT_WAV to
-    SF_FORMAT_RAW.
-
-    * src/sndfile.c
-    Added sf_command(SFC_TEST_ADD_TRAILING_DATA) to allow testing of reading
-    from AIFF and WAV files with non-audio data after the audio chunk.
-
-    * src/common.h
-    Add test commands SFC_TEST_WAV_ADD_INFO_CHUNK and
-    SFC_TEST_AIFF_ADD_INST_CHUNK. When these commands are working, they will be
-    moved to src/sndfile.h
-
-    * src/aiff.c src/wav.c
-    Begin implementation of XXXX_command() hook for sf_command().
-
-    * tests/write_read_test.tpl
-    Added sf_command (SFC_TEST_ADD_TRAILING_DATA) to ensure above new code was
-    working.
-
-2002-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/update_header_test.c
-    Allow read sample count == write sample count - 1 to fix problems with VOC
-    files.
-
-    * tests/write_read_test.tpl tests/pcm_test.tpl
-    Fixed some problems in the test suite discovered by using Valgrind.
-
-2002-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.[ch] tests/*.c
-    Renamed check_log_buffer() to check_log_buffer_or_die().
-
-    * src/sndfile.c
-    SFC_UPDATE_HEADER_NOW and SFC_SETUPDATE_HEADER_AUTO almost finished. Works
-    for all file formats other than VOC.
-
-2002-07-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.[ch] src/common.h
-    Started adding functionality to allow the file header to be updated before
-    the file is closed on files open for SFM_WRITE. This was requested by
-    Maurizio Umberto Puxeddu who is using libsndfile for file I/O in iCSound.
-
-    * tests/update_header_test.c
-    New test program to test that the above functionality is working correctly.
-
-    * tests/peak_chunk_test.c tests/floating_point_test.c
-    Cleanups.
-
-2002-07-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sfendian.[ch]
-    Changed length count parameters for all endswap_XXX() functions from
-    sf_count_t (which can be 64 bit even on 32 bit architectures) to int. These
-    functions are only called frin inside the library, are always called with
-    integer parameters and doing the actual calculation on 64 bit values is
-    slow in comparision to doing it on ints.
-
-    * examples/sndfile-play.c
-    More playback hacking for Win32.
-
-2002-07-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    In psf_log_printf(), changed %D format conversion specifier to %M (marker) and
-    added %D specifier for printing the sf_count_t type.
-
-    * src/*.c
-    Changed all usage of psf_log_printf() with %D format conversion specifiers
-    to use %M conversion instead.
-
-    * tests/pcm_test.tpl tests/pcm_test.def
-    New files to autogen pcm_test.c.
-
-    * src/pcm.c
-    Fixed bug in scaling floats and doubles to 24 bit PCM and vice versa.
-
-2002-07-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Fix setup of $ac_cv_sys_largefile_CFLAGS so that sndfile.pc gets valid
-    values for CFLAGS.
-
-    * examples/sndfile-play.c
-    Start adding playback support for Win32.
-
-2002-07-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Worked to removed compiler warnings.
-    Extensive refactoring.
-
-    * src/common.[ch]
-    Added function psf_memset() which works like the standard C function memset
-    but takes and sf_count_t as the length parameter.
-
-    * src/sndfile.c
-    Replaced calls to memset(0 with calls to psf_memset() as required.
-
-2002-07-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Added "libsndfile : " to the start of all error messages. This was suggested
-    by Conrad Parker author of Sweep ( http://sweep.sourceforge.net/ ).
-
-    * src/sfendian.[ch]
-    Added endswap_XXXX_copy() functions.
-
-    * src/pcm.c src/float32.c src/double64.c
-    Use endswap_XXXX_copy() functions and removed dead code.
-    Cleanups and optimisations.
-
-2002-07-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/sndfile.h
-    Gave values to all the SFC_* enum values to allow better control of the
-    interface as commands are added and removed.
-    Added new command SFC_SET_ADD_PEAK_CHUNK.
-
-    * src/wav.c src/aiff.c
-    Modified wav_write_header and aiff_write_header to make addition of a PEAK
-    chunk optional, even on floating point files.
-
-    * tests/benchmark.tpl
-    Added call to sf_command(SFC_SET_ADD_PEAK_CHUNK) to turn off addition of a
-    PEAK chunk for the benchmark where we are trying to miximize speed.
-
-    * src.pcm.c
-    Changed tribyte typedef to something more sensible.
-    Further conversion speed ups.
-
-2002-07-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/command.c
-    In major_formats rename "Sphere NIST" to "NIST Sphere".
-
-    * src/common.c src/sfendian.c
-    Moved all endswap_XXX_array() functions to sfendian.c. These functions will
-    be tweaked to provide maximum performance. Since maximum performance on one
-    platform does not guarantee maximum performance on another, a small set of
-    functions will be written and the optimal one chosen at compile time.
-
-    * src/common.h src/sfendian.h
-    Declarations of all endswap_XXX_array() functions moved to sfendian.h.
-
-    * src/Makefile.am
-    Add sfendian.c to build targets.
-
-2002-07-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c src/sfendian.h
-    Re-coded PCM encoders and decoders to match or better the speed of
-    libsndfile version 0.0.28.
-
-2002-06-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Add checking for WAVPACK data in standard PCM WAV file. Return error if
-    found. This WAVPACK is *WAY* broken. It uses the same PCM WAV file header
-    and then stores non-PCM data.
-
-    * tests/benchmark.tpl
-    Added more tests.
-
-2002-06-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/benchmark.tpl
-    Added conditional definition of M_PI.
-    For Win32, set WRITE_PERMS to 0777.
-
-    * Win32/Makefile.msvc
-    Added target to make generate program on Win32.
-
-    * src/samplitude.c
-    Removed handler for Samplitude RAP file format. This file type seems rarer
-    than hens teeth and is completely undocumented.
-
-    * src/common.h src/sndfile.c src/Makefile.am Win32/Makefile.msvc
-    Removed references to sampltiude RAP format.
-
-    * tests/benchmark.tpl
-    Benchmark program now prints the libsndfile version number when run. This
-    program was also backported to version 0 to compare results. Version
-    1.0.0rc2 is faster than version 0.0.28 on most conversions but slower on
-    some. The slow ones need to be fixed before final release.
-
-2002-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/benchmark.def tests/benchmark.tpl
-    New files which generate tests/benchmark.c using Autogen. Added int ->
-    SF_FORMAT_PCM_24 test.
-
-    * tests/benchmark.c
-    Now and Autogen output file.
-
-    * tests/Makefile.am
-    Updated for above changes.
-
-2002-06-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/benchmark.c
-    Basic benchmark program complete. Need to convert it to Autogen.
-
-    * Win32/Makefile.msvc
-    Added benchmark.exe target.
-
-2002-06-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/generate.c
-    New program to generate a number of different output file formats from a
-    single input file. This allows testing of the created files.
-
-    * tests/benchmark.c
-    New test program to benchmark libsndfile. Nowhere near complete yet.
-
-    * examples/Makefile.am tests/Makefile.am
-    New make rules for the two new programs.
-
-2002-06-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/libsndfile.def
-    Removed definition for sf_signal_max().
-
-    * src/sndfile.c
-    Removed cruft.
-
-    * doc/index.html
-    A number of documentation bugs were fixed. Thanks to Anand Kumria.
-
-    * doc/version-1.html
-    Minor doc updates.
-
-    * configure.in
-    Bumped version to 1.0.0rc2.
-
-    * src/sf_command.h src/Makefile.am
-    Removed the header file as it was no longer being used. Thanks to Anand
-    Kunria for spotting this.
-
-    * doc/index.html
-    A number of documentation bugs were fixed. Thanks to Anand Kumria.
-
-2002-06-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Test for Win32 before testing SIZEOF_OFF_T so that it works correctly
-    on Win32..
-
-    * src/file_io.c
-    Win32 fixes to ensure O_BINARY is used for file open.
-
-    * doc/win32.html
-    New file documenting the building libsndfile on Win32.
-
-    * doc/*.html
-    Updating of documentation.
-
-2002-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pcm_test.c
-    Minor changes to allow easier determination of test file name.
-
-    * src/sndfile.[ch]
-    Removed function sf_signal_max().
-
-    * examples/sndfile-play.c
-    Changed call to sf_signal_max() to a call to sf_command().
-
-2002-06-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/format.c src/command.c
-    Renamed format.c to command.c which will now include code for sf_command()
-    calls to perform operations other than format commands.
-
-    * src/sndfile.c src/sndfile.h
-    Removed function sf_get_signal_max() which is replaced by commands passed
-    to sf_command().
-
-    * src/command.c
-    Implement commands SFC_CALC_SIGNAL_MAX.
-
-    * doc/command.html
-    Documented SFC_CALC_SIGNAL_MAX.
-
-2002-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-play.c
-    Mods to make sndfile-play work on Solaris. The program sndfile-play now
-    runs on Linux, MaxOSX and Solaris. Win32 to come.
-
-    * src/format.c
-    Added SF_FORMAT_DWVW_* to subtype_formats array.
-
-    * src/nist.c
-    Added support for 8 bit NIST Sphere files. Example file supplied by Anand
-    Kumria.
-
-2002-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sndfile-info.c
-    Tidy up of output format.
-
-    * examnples/sndfile-play.c
-    Mods to make sndfile-play work on MacOSX using Apple's CoreAudio API.
-
-    * configure.in
-    Add new variables OS_SPECIFIC_INCLUDES and OS_SPECIFIC_LINKS which were
-    required to supply extra include paths and link parameters to get
-    sndfile-play working on MacOSX.
-
-    * examples/Makefile.am
-    Use OS_SPOECIFIC_INCLUDES and OS_SPECIFIC_LINKS to build commands for
-    sndfile-play.
-
-2002-06-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    Added ability to read/write new NIST Sphere file types (A-law, u-law).
-    Header parser was re-written from scratch. Example files supplied by Anand
-    Kumria.
-
-    * src/sndfile.c
-    Support for A-law and u-law NIST files.
-
-    * tests/Makefile.am tests/lossy_comp_test.c
-    Tests for A-law and u-law NIST files.
-
-2002-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.c
-    Fixed an error in error string.
-
-2002-06-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * acinclude.m4
-    Removed exit command to allow cross-compiling.
-
-    * Win32/unistd.h src/file_io.c
-    Moved contents of first file into the second file (enclosed in #ifdef).
-    Win32/unistd.h is now an empty file but still must be there for libsndfile
-    to compile on Win32.
-
-    * src/sd2.c, src/sndfile.c:
-    Fixes for Sound Designer II files on big endian systems.
-
-2002-06-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Modified to work around problems with crappy MacOSX version of sed.
-    Added sanity check for proper values for CFLAGS.
-
-2002-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Code clean up in sf_open ().
-
-    * Win32/Makefile.msvc
-    Michael Fink's contributed MSVC++ makefile was hacked to bits and put back
-    together in a new improved form.
-
-    * src/file_io.c
-    Fixes for Win32; _lseeki64() returns an invalid argument for calls like
-    _lseeki64(fd, 0, SEEK_CUR) so need to use _telli64 (fd) instead.
-
-    * src/common.h src/sndfile.c src/wav.c src/aiff.c
-    Added SFE_LOG_OVERRUN error.
-    Added termination for potential infinite loop when parsing file headers.
-
-    * src/wav.c src/w64.c
-    Fixed bug casuing incorrect header generation when opening file read/write.
-
-2002-06-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/api.html
-    Improved the documentation to make it clearer that the file read method
-    and the underlying file format are completely disconnected. Suggested
-    by Josh Green.
-
-    * doc/command.html
-    Started correcting docs to take into account changes made to the
-    operations of the sf_command () function. Not complete yet.
-
-    * src/sndfile.c
-    Reverted some changes which had broken the partially working SDII header
-    parsing. Now have access to an iBook with OS X so reading and writing SDII
-    files on all platforms should be a reality in the near future. On Mac this
-    will involve reading the resource fork via the standard MacOS API. To move
-    a file from Mac to another OS, the resource and data forks will need to be
-    combined before transfer. The combined file will be read on both Mac and
-    other OSes like any other file.
-
-2002-06-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * ltmain.sh
-    Applied a patch from http://fink.sourceforge.net/doc/porting/libtool.php
-    which allows libsndfile to compile on MacOSX 10.1. This patch should not
-    interfere with compiling on other OSes.
-
-    * src/GSM610/private.h
-    Changes to fix compile problems on MacOSX (see src/GSM610/ChangeLog).
-
-    * src/float_cast.h
-    Added MacOSX replacements for lrint() and lrintf().
-
-2002-06-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Replaced the code to print the filename to the log buffer when a file is
-    opened. This code seems to have been left out during the merge of
-    sf_open_read() and sf_open_write() to make a single  functions sf_open().
-
-2002-06-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed a bug where the WAV header parser was going into an infinite loop
-    on a badly formed LIST chunk. File supplied by David Viens.
-
-2002-05-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Added a message at the end of the configuration process to warn about the
-    need for the use of pkg-config when linking programs against version 1 of
-    libsndfile.
-
-    * doc/pkg-config.html
-    New documentation file containing details of how to use pkg-config to
-    retrieve settings for CFLAGS and library locations for linking files
-    against version 1 of libsndfile.
-
-2002-05-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed minor bug in handling of so-called ACIDized WAV files.
-
-2002-05-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/libsndfile.def Win32/Makefile.msvc
-    Two new files contributed by Michael Fink (from the winLAME project)
-    which allows libsndfile to be built on windows in a MSDOS box by doing
-    "nmake -f Makefile.msvc". Way cool!
-
-2002-05-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    MacOSX is SSSOOOOOOO screwed up!!! I can't believe how hard it is to
-    generate a tarball which will configure and compile on that platform.
-    Joined the libtool mailing list to try and get some answers.
-
-2002-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Changed to autoconf version 2.50. MacOSX uses autoconf version 2.53 which
-    is incompatible with with version 2.13 which had been using until now.
-    The AC_SYS_LARGE_FILE macro distributed withe autoconf 2.50 is missing a
-    few features so AC_SYS_EXTRA_LARGE file was defined to replace it.
-
-    * configure.in
-    Changed to automake version 1.5 to try and make a tarball which will
-    work on MacOSX.
-
-2002-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_gsm610.c
-    Changed name to gsm610.c. Added reading/writing of headerless files.
-
-    * src/sndfile.c src/raw.c
-    Added ability to read/write headerless (SF_FORMAT_RAW) GSM 6.10 files.
-
-2002-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c
-    Clean up in preparation for Autogen-ing this file.
-
-    * src/GSM610/*.[ch]
-    Code cleanup and prepartion forgetting file seek working. Details in
-    src/GSM610/ChangeLog.
-
-    * sndfile.pc.in
-    Testing complete. Is sndfile.m4 still needed?
-
-2002-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.tpl tests/rdwr_test.tpl
-    Merged tests from these two programs into write_read_test.tpl and deleted
-    rdwr_test.tpl.
-
-2002-05-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c src/svx.c src/paf.c
-    Fixed bugs in read/write mode.
-
-2002-05-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/Makefile.am
-    Renamed sfplay.c to sndfile-play.c and sndfile_info.c to sndfile-info.c for
-    consistency when these programs become part of the Debian package
-    sndfile-programs.
-
-    * sndfile.pc.in
-    New file to replace sndfile-config.in. Libsndfile now uses the pkg-config
-    model for providing installation parameters to dependant programs.
-
-    * src/sndfile.c
-    Cleanup of code in sf_open().
-
-2002-05-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/utils.tpl tests/write_read_test.tpl
-    More conversion to Autogen fixes and enchancements.
-
-    * src/*.c
-    Read/write mode is now working for 16, 24 and 32 bit PCM as well as 32
-    bit float and 64 bit double data. More tests still required.
-
-    * src/Makefile.am
-    Added DISTCLEANFILES target to remove config.status and config.last.
-
-    * Win32/Makefile.am MacOS/Makefile.am
-    Added DISTCLEANFILES target to remove Makefile.
-
-2002-05-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch] tests/rdwr_test.c
-    More verifying workings of read/write mode. Fixing bugs found.
-
-    * tests/utils.[ch]
-    Made these files Autogen generated files.
-
-    * tests/util.tpl tests/util.def
-    New Autogen files to generate utils.[ch]. Moved some generic test functions
-    into this file. Autogen is such a great tool!
-
-2002-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c src/float_cast.h Win32/config.h
-    Fixed a couple of Win32 specific bugs pointed out by Michael Fink
-    (maintainer of WinLAME) and David Viens.
-
-    * tests/check_log_buffer.[ch] tests/utils.[ch]
-    Moved check_log_buffer() to utils.[ch] and deleted old file.
-
-2002-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.[ch] src/sndfile.c
-    New function psf_default_seek() which will be the default seek function
-    for things like PCM and floating point data. This default is set for
-    both read and write in sf_open() but can be over-ridden by any codec
-    during it's initialisation.
-
-2002-05-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c
-    AU files use a data size value of -1 to mean unknown. Fixed au_open_read()
-    to allow opening files like this.
-
-    * tests/rdwr_test .c
-    Added more tests.
-
-    * src/sndfile.c
-    Fixed bugs in read/write mode found due to improvements in the test
-    program.
-
-2002-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/rdwr_test .c
-    New file for testing read/write mode.
-
-2002-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * m4/*
-    Removed all m4 macros from this directory as they get concatenated to form
-    the file aclocal.m4 anyway.
-
-    * sndfile.m4
-    Moved this from the m4 directory to the root directory asn this is part of
-    the distribution and is installed during "make install".
-
-2002-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float32.c
-    Removed logging of peaks for all file formats other than AIFF and WAV.
-
-    * tests/write_read_test.tpl tests/write_read_test.def
-    New files which autogen uses to generate write_read_test.c. Doing it this
-    way makes write_read_test.c far easier to maintain. Other test programs
-    will be converted to autogen in the near future.
-
-    * src/*.c
-    Fixed a few bugs found when testing on Sparc (bug endian) Solaris.
-
-2002-04-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * doc/*.html
-    Fixed documention versioning.
-
-    * configure.in
-    Fixed a bug in the routines which search for Large File Support on systems
-    which have large file support by defualt.
-
-2002-04-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch]
-    Found and fixed an issue which can cause a bug in other software (I was
-    porting Conrad Parker's Sweep program from version 0 of the library to
-    version 1). When opening a file for write, the libsndfile code would
-    set the sfinfo.samples field to a maximum value.
-
-    * tests/write_read_test.c
-    Added tests to detect the above problem.
-
-2002-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch]
-    Finished base implementation of read/write mode. Much more testing still
-    needed.
-
-    * m4/largefile.m4
-    Macro for detecting Large File Standard capabilities. This macro was ripped
-    out of the aclocal.m4 file of GNU tar-1.13.
-
-    * configure.in
-    Added detection of large file support. Files larger than 2 Gigabytes should
-    now be supported on 64 bit platforms and many 32 bit platforms including
-    Linux (2.4 kernel, glibc-2.2), *BSD, MacOS, Win32.
-
-    * libsndfile_convert_version.py
-    A Python script which attempts to autoconvert code written to use version 0
-    to version 1.
-
-2002-04-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch]
-    Finished base implementation of read/write mode. Much more testing still
-    needed.
-
-    * tests/write_read_test.c
-    Preliminary tests for read/write mode added. More needed.
-
-2002-04-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.[ch]
-    Removed sf_open_read() and sf_open_write() functions,replacting them with
-    sf_open() which takes an extra mode parameter (SF_OPEN_READ, SF_OPEN_WRITE,
-    or SF_OPEN_RDWR). This new function sf_open can now be modified to allow
-    opening a file formodification (RDWR).
-
-2002-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Completed merging of separate xxx_open_read() and xxx_open_write()
-    functions. All tests pass.
-
-2002-04-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c
-    Massive refactoring required to merge au_open_read() with au_open_write()
-    to create au_open().
-
-2002-04-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Started changes required to allow a sound file to be opened in read/write
-    mode, with separate file pointers for read and write. This involves merging
-    of encoder/decoder functions like pcm_read_init() and pcm_write_init()
-    int a new function pcm_init() as well as doing something similar for all
-    the file type specific functions ie aiff_open_read() and aiff_open_write()
-    were merged to make the function aiff_open().
-
-2002-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/file_io.c
-    New file containing psf_fopen(), psf_fread(), psf_fwrite(), psf_fseek() and
-    psf_ftell() functions. These function will replace use of fopen/fread/fwrite
-    etc and allow access to files larger than 2 gigabytes on a number of 32 bit
-    OSes (Linux on x86, 32 bit Solaris user space apps, Win32 and MacOS).
-
-    * src/*.c
-    Replaced all instances of fopen with psf_open, fread with psd_read, fwrite
-    with psf_write and so on.
-
-2002-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/dwvw.c
-    Finally fixed all known problems with 12, 16 and 24 bit DWVW encoding.
-
-    * tests/floating_point_test.c
-    Added tests for 12, 16 and 24 bit DWVW encoding.
-
-2002-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * m4/endian.m4
-    Defines a new m4 macro AC_C_FIND_ENDIAN, for determining the endian-ness of
-    the target CPU. It first checks for the definition of BYTE_ORDER in
-    <endian.h>, then in <sys/types.h> and <sys/param.h>. If none of these work
-    and the C compiler is not a cross compiler it compiles and runs a program
-    to test for endian-ness. If the compiler is a cross compiler it makes a
-    guess based on $target_cpu.
-
-    * configure.in
-    Modified to use AC_C_FIND_ENDIAN.
-
-    * src/sfendian.h
-    Simplified.
-
-2002-02-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/floating_point_test.c
-    Tests completely rewritten using the dft_cmp function. Now able to
-    calculate a quick guesstimate of the Signal to Noise Ratio of the encoder.
-
-2002-02-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/dft_cmp.[ch]
-    New files containing functions for comparing pre and post lossily
-    compressed data using a quickly hacked DFT.
-
-    * tests/utils.[ch]
-    New files containing functions for saving pre and post encoded data in a
-    file readable by the GNU Octave package.
-
-2002-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * m4/lrint.m4 m4/lrintf.m4
-    Fixed m4 macros to define HAVE_LRINT and HAVE_LRINTF even when the test
-    is cached.
-
-2002-02-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/floating_point_test.c
-    Fixed improper use of strncat ().
-
-2002-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/headerless_test.c
-    New test program to test the ability to open and read a known file type as a
-    RAW header-less file.
-
-2002-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/losy_comp_test.c
-    Added a test to ensure that the data read from a file is not all zeros.
-
-    * examples/sfconvert.c
-    Added "-gsm610" encoding types.
-
-2002-01-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sfconvert.c
-    Added "-dwvw12", "-dwvw16" and "-dwvw24" encoding types.
-
-    * tests/dwvw_test.c
-    New file for testing DWVW encoder/decoder.
-
-2002-01-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/dwvw.c
-    Implemented writing of DWVW. 12 bit seems to work, 16 and 24 bit still broken.
-
-    * src/aiff.c
-    Improved reporting of encoding types.
-
-    * src/voc.c
-    Clean up.
-
-2002-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/dwvw.c
-    New file implementing lossless Delta Word Variable Width (DWVW) encoding.
-    Reading 12 bit DWVW is now working.
-
-    * src/aiff.c common.h sndfile.c
-    Added hooks for DWVW encoded AIFF and RAW files.
-
-2002-01-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c
-    Robustify header parsing.
-
-    * src/wav_w64.h
-    Header file wav.h was renamed to wav_w64.h to signify sharing of
-    definitions across the two file types.
-
-    * src/wav.c src/w64.c src/wav_w64.c
-    Refactoring.
-    Modified and moved functions with a high degree of similarity between
-    wav.c and w64.c to wav_w64.c.
-
-2002-01-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c
-    Completed work on getting read and write working.
-
-    * examples/sfplay.c
-    Added code to scale floating point data so it plays at a reasonable volume.
-
-    * tests/Makefile.am tests/write_read_test.c
-    Added tests for W64 files.
-
-2002-01-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Modded all code in file header writing routines to use
-    psf_new_binheader_writef().
-    Removed psf_binheader_writef() from src/common.c.
-    Globally replaced psf_new_binheader_writef with psf_binheader_writef.
-
-2002-01-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Modded all code in file parsing routines to use psf_new_binheader_readf().
-    Removed psf_binheader_readf() from src/common.c.
-    Globally replaced psf_new_binheader_readf with psf_binheader_readf.
-
-    * src/common.[ch]
-    Added new function psf_new_binheader_writef () which will soon replace
-    psf_binheader_writef (). The new function has basically the same function
-    as the original but has a more flexible and capable interface. It also
-    allows the writing of 64 bit integer values for files contains 64 bit file
-    offsets.
-
-2002-01-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/formats.c src/sndfile.c src/sndfile.h
-    Added code allowing full enumeration of supported file formats via the
-    sf_command () interface.
-    This feature will allow applications to avoid needing recompilation when
-    support for new file formats are added to libsndfile.
-
-    * tests/command_test.c
-    Added test code for the above feature.
-
-    * examples/list_formats.c
-    New file. An example of the use of the supported file enumeration
-    interface. This program lists all the major formats and for each major
-    format the supported subformats.
-
-2002-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch] tests/*.c
-    Changed command parameter of sf_command () function from a test string to
-    an int. The valid values for the command parameter begin with SFC_ and are
-    listed in src/sndfile.h.
-
-2001-12-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/formats.c src/sndfile.c
-    Added an way of enumerating a set of common file formats using the
-    sf_command () interface. This interface was suggested by Dominic Mazzoni,
-    one of the main authors of Audacity (http://audacity.sourceforge.net/).
-
-2001-12-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Added checking of filename parameter in sf_open_read (). Previousy, if a
-    NULL pointer was passed the library would segfault.
-
-2001-12-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c src/common.h
-    Changed the len parameter of the endswap_*_array () functions from type
-    int to type long.
-
-    * src/pcm.c
-    Fixed a problem which
-
-2001-12-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Added conditional #include <sys/types.h> for EMX/gcc on OS/2. Thanks to
-    Paul Hartman for pointing this out.
-
-    * tests/lossy_comp_test.c tests/floating_point_test.c
-    Added definitions for M_PI for when it isn't defined in <math.h>.
-
-2001-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ircam.c
-    Re-implemented the header reader. Old version was making incorrect
-    assumptions about the endian-ness of the file from the magic number at the
-    start of the file. The new code looks at the integer which holds the
-    number of channels and determines the endian-ness from that.
-
-2001-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Added support for other AIFC types ('raw ', 'in32', '23ni').
-    Further work on IMA ADPCM encoding.
-
-2001-11-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ima_adpcm.c
-    Renamed from wav_ima_adpcm.c. This file will soon handle IMA ADPCM
-    encodings for both WAV and AIFF files.
-
-    * src/aiff.c
-    Started adding IMA ADPCM support.
-
-2001-11-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/double.c
-    New file for handling double precision floating point (SF_FORMAT_DOUBLE)
-    data.
-
-    * src/wav.c src/aiff.c src/au.c src/raw.c
-    Added support for SF_FORMAT_DOUBLE data.
-
-    * src/common.[ch]
-    Addition of endswap_long_array () for endian swapping 64 bit integers. This
-    function will work correctly on processors with 32 bit and 64 bit longs.
-    Optimised endswap_short_array () and endswap_int_array ().
-
-    * tests/pcm_test.c
-    Added and extra check. After the first file of each type is written to disk
-    a checksum is performed of the first 64 bytes and checked against a pre-
-    calculated value. This will work whatever the endian-ness of the host
-    machine.
-
-2001-11-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Added handling of u-law, A-law encoded AIFF files. Thanks to Tom Erbe for
-    supplying example files.
-
-    * tests/lossy_comp_test.c
-    Added tests for above.
-
-    * src/common.h src/*.c
-    Removed function typedefs from common.h and function pointer casting in all
-    the other files. This allows the compiler to perform proper type checking.
-    Hopefully this will prevernt problems like the sf_seek bug for OpenBSD,
-    BeOS etc.
-
-    * src/common.[ch]
-    Added new function psf_new_binheader_readf () which will eventually replace
-    psf_binheader_readf (). The new function has basically the same function as
-    the original but has a more flexible and capable interface. It also allows
-    the reading of 64 bit integer values for files contains 64 bit file
-    offsets.
-
-2001-11-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/voc.c
-    Completed implementation of VOC file handling. Can now handle 8 and 16 bit
-    PCM, u-law and A-law files with one or two channels.
-
-    * src/write_read_test.c tests/lossy_comp_test.c
-    Added tests for VOC files.
-
-2001-11-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float_cast.h
-    Added inline asm version of lrint/lrintf for MacOS. Solution provided by
-    Stephane Letz.
-
-    * src/voc.c
-    More work on this braindamaged format. The VOC files produced by SoX also
-    have a number of inconsistencies.
-
-2001-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    Added support for 8 bit PCM PAF files.
-
-    * tests/write_read_test.c
-    Added tests for 8 bit PAF files.
-
-2001-11-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/pcm_test.c
-    New test program to test for correct scaling of integer values between
-    different sized integer containers (ie short -> int).
-    The new specs for libsndfile state that when the source and destination
-    containers are of a different size, the most significant bit of the source
-    value becomes the most significant bit of the destination container.
-
-    * src/pcm.c src/paf.c
-    Modified to pass the above test program.
-
-    * tests/write_read_test.c tests/lossy_comp_test.c
-    Modified to work with the new scaling rules.
-
-2001-11-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/raw.c tests/write_read_test.c tests/write_read_test.c
-    Added ability to do raw reads/writes of float, u-law and A-law files.
-
-    * src/*.[ch] examples/*.[ch] tests/*.[ch]
-    Removed dependance on pcmbitwidth field of SF_INFO struct and moved to new
-    SF_FORMAT_* types and use of SF_ENDIAN_BIG/LITTLE/CPU.
-
-2001-11-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch]
-    Started implmentation of major changes documented in doc/version1.html.
-
-    Removed all usage of off_t which is not part of the ISO C standard. All
-    places which were using it are now using type long which is the type of
-    the offset parameter for the fseek function.
-    This should fix problems on BeOS, MacOS and *BSD like systems which were
-    failing "make check" because sizeof (long) != sizeof (off_t).
-
---------------------------------------------------------------------------------
-This is the boundary between version 1 of the library above and version 0 below.
---------------------------------------------------------------------------------
-
-2001-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sfplay_beos.cpp
-    Added BeOS version of sfplay.c. This needs to be compiled using a C++
-    compiler so is therefore not built by default. Thanks to Marcus Overhagen
-    for providing this.
-
-2001-11-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sfplay.c
-    New example file showing how libsndfile can be used to read and play a
-    sound file.
-    At the moment on Linux is supported. Others will follow in the near future.
-
-2001-11-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c
-    Fixed problem with normalisation code where a value of 1.0 could map to
-    a value greater than MAX_SHORT or MAX_INT. Thanks to Roger Dannenberg for
-    pointing this out.
-
-2001-11-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c
-    Fixed scaling issue when reading/writing 8 bit files using
-    sf_read/sf_write_short ().
-    On read, values are scaled so that the most significant bit in the char
-    ends up in the most significant bit of the short. On write, values are
-    scaled so that most significant bit in the short ends up as the most
-    significant bit in the char.
-
-2001-11-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c src/sndfile.c
-    Added support for 32 bit float data in big and little endian AU files.
-
-    * tests/write_read_test.c
-    Added tests for 32 bit float data in AU files.
-
-2001-11-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c
-    Finalised testing of stereo files where possible.
-
-2001-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_ms_adpcm.c
-    Fixed bug in writing stereo MS ADPCM WAV files. Thanks to Xu Xin for
-    pointing out this problem.
-
-2001-10-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_ms_adpcm.c
-    Modified function srate2blocksize () to handle 44k1Hz stereo files.
-
-2001-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/w64.c
-    Added support for Sonic Foundry 64 bit WAV format. As Linux (my main
-    development platform) does not yet support 64 bit file offsets by default,
-    current handling of this file format treats everything as 32 bit and fails
-    openning the file, if it finds anything that goes beyond 32 bit values.
-
-    * src/sndfile.[hc] src/common.h src/Makefile.am
-    Added hooks for W64 support.
-
-2001-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Added more warnings options to CFLAGS when the gcc compiler is detected.
-
-    * src/*.[ch] tests/*.c examples/*.c
-    Started fixing the warning messages due to the new CFLASG.
-
-    * src/voc.c
-    More work on VOC file read/writing.
-
-    * src/paf.c
-    Found that PAF files were not checking the normalisation flag when reading
-    or writing floats and doubles. Fixed it.
-
-    * tests/floating_point_test.c
-    Added specific test for the above problem.
-
-    * src/float_cast.h src/pcm.c
-    Added a section for Win32 to define lrint () and lrintf () in the header
-    and implement it in the pcm.c
-
-2001-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * sndfile-config.in m4/sndfile.m4
-    These files were donated by Conrad Parker who also provided instructions
-    on how to install them using autoconf/automake.
-
-    * src/float_cast.h
-    Fiddled around with this file some more. On Linux and other gcc supported
-    OSes use the C99 functions lrintf() and lrint() for casting from floating
-    point to int without incurring the huge perfromance penalty (particularly
-    on the i386 family) caused by the regular C cast from float to int.
-    These new C99 functions replace the FLOAT_TO_* and DOUBLE_TO_* macros which
-    I had been playing with.
-
-    * configure.in m4/lrint.m4 m4/lrintf.m4
-    Add detection of these functions.
-
-2001-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/voc.c
-    Completed code for reading VOC files containing a single audio data
-    segment.
-    Started implementing code to handle files with multiple VOC_SOUND_DATA
-    segments but couldn't be bothered finishing it. Multiple segment files can
-    have different sample rates for different sections and other nasties like
-    silence and repeat segments.
-
-2001-10-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/*.c
-    Removed SF_PRIVATE struct field fdata and replaced it with extra_data.
-
-    * src/voc.c
-    Further development of the read part of this woefult file format.
-
-2001-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float_cast.h
-    Implemented gcc and i386 floating point to int cast macros. Standard cast
-    will be used when not on gcc for i385.
-
-    * src/pcm.c
-    Modified all uses of FLOAT/DOUBLE_TO_INT and FLOAT/DOUBLE_TO_SHORT casts to
-    comply with macros in float_cast.h.
-
-2001-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/voc.c
-    Changed the TYPE_xxx enum names to VOC_TYPE_xxx to prevent name clashes
-    on MacOS with CodeWarrior 6.0.
-
-    * MacOS/MacOS-readme.txt
-    Updated the compile instructions. Probably still need work as I don't have
-    access to a Mac.
-
-2001-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/aiff.c common.c
-    Changed all references to snprintf to LSF_SNPRINTF and all vsnprintf to
-    LSF_VSNPRINTF. LSF_VSNPRINTF and LSF_VSNPRINTF are defined in common.h.
-
-    * src/common.h
-    Added checking of HAVE_SNPRINTF and HAVE_VSNPRINTF and defining
-    LSF_VSNPRINTF and LSF_VSNPRINTF to appropriate values.
-
-    * src/missing.c
-    New file containing a minimal implementation of snprintf and vsnprintf
-    functions named missing_snprintf and missing_vsnprintf respectively. These
-    are only compliled into the binary if snprintf and/or vsnprintf are not
-    available.
-
-2001-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ircam.c
-    New file to handle Berkeley/IRCAM/CARL files.
-
-    * src/sndfile.c src/common.h
-    Modified for IRCAM handling.
-
-    * tests/*.c
-    Added tests for IRCAM files.
-
-2001-09-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Apparently microsoft windows (tm) doesn't like ulaw and Alaw WAV files with
-    20 byte format chunks (contrary to ms's own documentation). Fixed the WAV
-    header writing code to generate smaller ms compliant ulaw and Alaw WAV
-    files.
-
-2001-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/stdio_test.sh tests/stdio_test.c
-    Shell script was rewritten as a C program due to incompatibilities of the
-    sh shell on Linux and Solaris.
-
-2001-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/stdio_test.sh tests/stdout_test.c tests/stdin_test.c
-    New test programs to verify the correct operation of reading from stdin and
-    writing to stdout.
-
-    * src/sndfile.c wav.c au.c nist.c paf.c
-    Fixed a bugs uncovered by the new test programs above.
-
-2001-09-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c wav.c
-    Fixed a bug preventing reading a file from stdin. Found by T. Narita.
-
-2001-09-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Fixed a problem on OpenBSD 2.9 which was causing sf_seek() to fail on IMA
-    WAV files. Root cause was the declaration of the func_seek typedef not
-    matching the functions it was actually being used to point to. In OpenBSD
-    sizeof (off_t) != sizeof (int). Thanks to Heikki Korpela for allowing me
-    to log into his OpenBSD machine to debug this problem.
-
-2001-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Implemented sf_command ("norm float").
-
-    * src/*.c
-    Implemented handling of sf_command ("set-norm-float"). Float normalization
-    can now be turned on and off.
-
-    * tests/double_test.c
-    Renamed to floating_point_test.c. Modified to include tests for all scaled
-    reads and writes of floats and doubles.
-
-    * src/au_g72x.c
-    Fixed bug in normalization code found with improved floating_point_test
-    program.
-
-    * src/wav.c
-    Added code for parsing 'INFO' and 'LIST' chunks. Will be used for extract
-    text annotations from WAV files.
-
-    * src/aiff.c
-    Added code for parsing '(c) ' and 'ANNO' chunks. Will be used for extract
-    text annotations from WAV files.
-
-2001-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sf_info.c example/Makefile.am
-    Renamed to sndfile_info.c. The program sndfile_info will now be installed
-    when the library is installed.
-
-    * src/float_cast.h
-    New file defining floating point to short and int casts. These casts will
-    eventually replace all flot and double casts to short and int. See comments
-    at the top of the file for the reasoning.
-
-    * src/*.c
-    Changed all default float and double casts to short or int with macros
-    defined in floatcast.h. At the moment these casts do nothing. They will be
-    replaced with faster float to int cast operations in the near future.
-
-2001-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/command_test.c
-    New file for testing sf_command () functionality.
-
-    * src/sndfile.c
-    Revisiting of error return values of some functions.
-    Started implementing sf_command () a new function will allow on-the-fly
-    modification of library behaviour, or instance, sample value scaling.
-
-    * src/common.h
-    Added hook for format specific sf_command () calls to SNDFILE struct.
-
-    * doc/api.html
-    Updated and errors corrected.
-
-    * doc/command.html
-    New documentation file explaining new sf_command () function.
-
-2001-08-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed error return values from sf_read*() and sf_write*(). There were
-    numerous instances of -1 being returned through size_t. These now all set
-    error int the SF_PRIVATE struct and return 0. Thanks to David Viens for
-    spotting this.
-
-2001-08-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Fixed use of va_arg() calls that were causing warning messages with the
-    latest version of gcc (thanks Maurizio Umberto Puxeddu).
-
-2001-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c src/sfendian.h
-    Moved definition of MAKE_MARKER macro to sfendian.h
-
-2001-07-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Modified sf_get_lib_version () so that version string will be visible using
-    the Unix strings command.
-
-    * examples/Makefile.am examples/sfinfo.c
-    Renamed sfinfo program and source code to sf_info. This prevents a name
-    clash with the program included with libaudiofile.
-
-2001-07-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/read_seek_test.c tests/lossy_comp_test.c
-    Added tests for sf_read_float () and sf_readf_float ().
-
-    * src/voc.c
-    New files for handling Creative Voice files (not complete).
-
-    * src/samplitude.c
-    New files for handling Samplitude files (not complete).
-
-2001-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/au.c src/paf.c src/svx.c src/wav.c
-    Converted these files to using psf_binheader_readf() function. Will soon be
-    ready to attempt to make reading writing from pipes work reliably.
-
-    * src/*.[ch]
-    Added code for sf_read_float () and sf_readf_float () methods of accessing
-    file data.
-
-2001-07-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c src/wav_gsm610.c
-    Removed two printf()s which had escaped notice for some time (thanks
-    Sigbjørn Skjæret).
-
-2001-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_gsm610.c
-    Fixed a bug which prevented GSM 6.10 encoded WAV files generated by
-    libsndfile from being played in Windoze (thanks klay).
-
-2001-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.[ch]
-    Implemented psf_binheader_readf() which will do for file header reading what
-    psf_binheader_writef() did for writing headers. Will eventually allow
-    libsndfile to read and write from pipes, including named pipes.
-
-2001-07-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * MacOS/config.h Win32/config.h
-    Attempted to bring these two files uptodate with src/config.h. As I don't
-    have access to either of these systems support for them may be completely
-    broken.
-
-2001-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float32.c
-    Fixed bug for big endian processors that can't read 32 bit IEEE floats. Now
-    tested on Intel x86 and UltraSparc processors.
-
-2001-06-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Modified to allow REX files (from Propellorhead's Recycle and Reason
-    programs) to be read.
-    REX files are basically an AIFF file with slightly unusual sequence of
-    chunks (AIFF files are supposed to allow any sequence) and some extra
-    application specific information.
-    Not yet able to write a REX file as the details of the application specific
-    data is unknown.
-
-2001-06-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed endian bug when reading PEAK chunk on big endian machines.
-
-    * src/common.c
-    Fixed endian bug when reading PEAK chunk on big endian machines with
-    --enable-force-broken-float configure option.
-    Fix psf_binheader_writef for (FORCE_BROKEN_FLOAT ||______)
-
-2001-06-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in src/config.h.in
-    Removed old CAN_READ_WRITE_x86_IEEE configure variable now that float
-    capabilities are detected at run time.
-    Added FORCE_BROKEN_FLOAT to allow testing of broken float code on machines
-    where the processor can in fact handle floats correctly.
-
-    * src/float32.c
-    Rejigged code reading and writing of floats on broken processors.
-
-    * m4/
-    Removed this directory and all its files as they are no longer needed.
-
-2001-06-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/peak_chunk_test.c
-    New test to validate reading and writing of peak chunk.
-
-    * examples/sfconvert
-    Added -float32 option.
-
-    * src/*.c
-    Changed all error return values to negative values (ie the negative of what
-    they were).
-
-    * src/sndfile.c tests/error_test.c
-    Modified to take account of the previous change.
-
-2001-06-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/float32.c
-    File renamed from wav_float.c and renamed function to something more
-    general.
-    Added runtime detection of floating point capabilities.
-    Added recording of peaks during write for generation of PEAK chunk.
-
-    * src/wav.c src/aiff.c
-    Added handing for PEAK chunk for floating point files. PEAK is read when the
-    file headers are read and generated when the file is closed. Logic is in
-    place for adding PEAK chunk to end of file when writing to a pipe (reading
-    and writing from/to pipe to be implemented soon).
-
-    * src/sndfile.c
-    Modified sf_signal_max () to use PEAK values if present.
-
-2001-06-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Added pcm_read_init () and pcm_write_init () to src/pcm.c and removed all
-    other calls to functions in this file from the filetype specific files.
-
-    * src/*.c
-    Added alaw_read_init (), alaw_write_int (), ulaw_read_init () and
-    ulaw_write_init () and removed all other calls to functions in alaw.c and
-    ulaw.c from the filetype specific files.
-
-    * tests/write_read_test.c
-    Added tests to validate sf_seek () on all file types.
-
-    * src/raw.c
-    Implemented raw_seek () function to fix a bug where
-    sf_seek (file, 0, SEEK_SET) on a RAW file failed.
-
-    * src/paf.c
-    Fixed a bug in paf24_seek () found due to added seeks tests in
-    tests/write_read_test.c
-
-2001-06-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/read_seek_test.c
-    Fixed a couple of broken binary files.
-
-    * src/aiff.c src/wav.c
-    Added handling of PEAK chunks on file read.
-
-2001-05-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * check_libsndfile.py
-    New file for the regression testing of libsndfile.
-    check_libsndfile.py is a Python script which reads in a file containing
-    filenames of audio files. Each file is checked by running the examples/sfinfo
-    program on them and checking for error or warning messages in the libsndfile
-    log buffer.
-
-    * check_libsndfile.list
-    This is an example list of audio files for use with check_libsndfile.py
-
-    * tests/lossy_comp_test.c
-    Changed the defined value of M_PI for math header files which don't have it.
-    This fixed validation test failures on MetroWerks compilers. Thanks to Lord
-    Praetor Satanus of Acheron for bringing this to my attention.
-
-2001-05-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.[ch]
-    Removed psf_header_setf () which was no longer required after refactoring
-    and simplification of header writing.
-    Added 'z' format specifier to psf_binheader_writef () for zero filling header
-    with N bytes. Used by paf.c and nist.c
-
-    * tests/check_log_buffer.c
-    New file implementing check_log_buffer () which reads the log buffer of a
-    SNDFILE* object and searches for error and warning messages. Calls exit ()
-    if any are found.
-
-    * tests/*.c
-    Added calls to check_log_buffer () after each call to sf_open_XXX ().
-
-2001-05-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/wav_ms_adpcm.c src/wav_gsm610.c
-    Major rehack of header writing using psf_binheader_writef ().
-
-2001-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/wav_ima_adpcm.c
-    Major rehack of header writing using psf_binheader_writef ().
-
-2001-05-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Changed return type of get_encoding_str () to prevent compiler warnings on
-    Mac OSX.
-
-    * src/aiff.c src/au.c
-    Major rehack of header writing using psf_binheader_writef ().
-
-2001-05-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h src/common.c
-    Added comments.
-    Name of log buffer changed from strbuffer to logbuffer.
-    Name of log buffer index variable changed from strindex to logindex.
-
-    * src/*.[ch]
-    Changed name of internal logging function from psf_sprintf () to
-    psf_log_printf ().
-    Changed name of internal header generation functions from
-    psf_[ab]h_printf () to psf_asciiheader_printf () and
-    psf_binheader_writef ().
-    Changed name of internal header manipulation function psf_hsetf () to
-    psf_header_setf ().
-
-2001-05-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    Fixed reading and writing of sample_byte_format header. "01" means little
-    endian and "10" means big endian regardless of bit width.
-
-    * configure.in
-    Detect Mac OSX and disable -Wall and -pedantic gcc options. Mac OSX is
-    way screwed up and spews out buckets of warning messages from the system
-    headers.
-    Added --disable-gcc-opt configure option (sets gcc optimisation to -O0 ) for
-    easier debugging.
-    Made decision to harmonise source code version number and .so library
-    version number. Future releases will stick to this rule.
-
-    * doc/new_file_type.HOWTO
-    New file to document the addition of new file types to libsndfile.
-
-2001-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/nist.c
-    New file for reading/writing Sphere NIST audio file format.
-    Originally requested by Elis Pomales in 1999.
-    Retrieved from unstable (and untouched for 18 months) branch of libsndfile.
-    Some vital information gleaned from the source code to Bill Schottstaedt's
-    sndlib library : ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz
-    Currently reading and writing 16, 24 and 32 bit, big-endian and little
-    endian, stereo and mono files.
-
-    * src/common.h src/common.c
-    Added psf_ah_printf () function to help construction of ASCII headers (ie NIST).
-
-    * configure.in
-    Added test for vsnprintf () required by psf_ah_printf ().
-
-    * tests/write_read_test.c
-    Added tests for supported NIST files.
-
-2001-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.c
-    Added tests for little endian AIFC files.
-
-    * src/aiff.c
-    Minor re-working of aiff_open_write ().
-    Added write support for little endian PCM encoded AIFC files.
-
-2001-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Minor re-working of aiff_open_read ().
-    Added read support for little endian PCM encoded AIFC files from the Mac
-    OSX CD ripper program. Guillaume Lessard provided a couple of sample files
-    and a working patch.
-    The patch was not used as is but gave a good guide as to what to do.
-
-2001-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h
-    Fixed comments about endian-ness of WAV and AIFF files. Guillaume Lessard
-    pointed out the error.
-
-2001-04-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/make_sine.c
-    Re-write of this example using sample rate and required frequency in Hz.
-
-2001-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed bug that prevented known file types from being read as RAW PCM data.
-
-2000-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Added handing of COMT chunk.
-
-2000-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sfconvert.c
-    Fixed bug in normalisatio code. Pointed out by Johnny Wu.
-
-2000-11-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * Win32/config.h
-    Fixed the incorrect setting of HAVE_ENDIAN_H parameter. Win32 only issue.
-
-2000-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/Makefile.am
-    Added -lm for write_read_test_LDADD.
-
-2000-10-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/au.c
-    Fixed bug which prevented writing of G723 24kbps AU files.
-
-    * tests/lossy_comp_test.c
-    Corrrection to options for G723 tests.
-
-    * configure.in
-    Added --disable-gcc-pipe option for DJGPP compiler (gcc on MS-DOS) which
-    doesn't allow gcc -pipe option.
-
-2000-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/ulaw.c src/alaw.c src/wav_imaadpcm.c src/msadpcm.c src/wav_gsm610.c
-    Fixed normailsation bugs shown up by new double_test program.
-
-2000-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c
-    Fixed bug in normalisation code (spotted by Steve Lhomme).
-
-    * tests/double_test.c
-    New file to test scaled and unscaled sf_read_double() and sf_write_double()
-    functions.
-
-2000-08-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * COPYING
-    Changed to the LGPL COPYING file (spotted by H. S. Teoh).
-
-2000-08-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h
-    Removed prototype of unimplemented function sf_get_info(). Added prototype
-    for sf_error_number() Thanks to Sigbjørn Skjæret for spotting these.
-
-2000-08-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/newpcm.h
-    New file to contain a complete rewrite of the PCM data handling.
-
-2000-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a leak of FILE* pointers in sf_open_write(). Thanks to Sigbjørn
-    Skjæret for spotting this one.
-
-2000-08-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au_g72x.c src/G72x/g72x.c
-    Added G723 encoded AU file support.
-
-    * tests/lossy_comp_test.c
-    Added tests for G721 and G723 encoded AU files.
-
-2000-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * all files
-    Changed the license to LGPL. Albert Faber who had copyright on
-    Win32/unistd.h gave his permission to change the license on that file. All
-    other files were either copyright erikd AT mega-nerd DOT com or copyright
-    under a GPL/LGPL compatible license.
-
-2000-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c
-    Fixed incorrect error message.
-
-    * src/au_g72x.c src/G72x/*
-    G721 encoded AU files now working.
-
-    * Win32/README-Win32.txt
-    Replaced this file with a new one which gives a full explanation
-    of how to build libsndfile under Win32. Thanks to Mike Ricos.
-
-2000-08-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.[ch]
-    Removed double leading underscores from the start of all variable and
-    function names. Identifiers with a leading underscores are reserved
-    for use by the compiler.
-
-    * src/au_g72x.c src/G72x/*
-    Continued work on G721 encoded AU files.
-
-2000-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/G72x/*
-    New files for reading/writing G721 and G723 ADPCM audio. These files
-    are from a Sun Microsystems reference implementation released under a
-    free software licence.
-    Extensive changes to this code to make it fit in with libsndfile.
-    See the ChangeLog in this directory for details.
-
-    * src/au_g72x.c
-    New file for G721 encoded AU files.
-
-2000-07-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * libsndfile.spec.in
-    Added a spec file for making RPMs. Thanks to Josh Green for supplying this.
-
-2000-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/sndfile.h
-    Add checking for and handling of header-less u-law encoded AU/SND files.
-    Any file with a ".au" or ".snd" file extension and without the normal
-    AU file header is treated as an 8kHz, u-law encoded file.
-
-    * src/au.h
-    New function for opening a headerless u-law encoded file for read.
-
-2000-06-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    Add checking for files shorter than minimal PAF file header length.
-
-2000-06-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.c
-    Added extra sf_perror() calls when sf_write_XXXX fails.
-
-2000-05-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Modified usage of va_arg() macro to work correctly on PowerPC
-    Linux. Thanks to Kyle Wheeler for giving me ssh access to his
-    machine while I was trying to track this down.
-
-    * configure.in src/*.[ch]
-    Sorted out some endian-ness issues brought up by PowerPC Linux.
-
-    * tests/read_seek_test.c
-    Added extra debugging for when tests fail.
-
-2000-05-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Fixed bug in GSM 6.10 handling for big-endian machines. Thanks
-    to Sigbjørn Skjæret for reporting this.
-
-2000-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/wav.c src/wav_gsm610.c
-    Finallised writing of GSM 6.10 WAV files.
-
-    * tests/lossy_comp_test.c
-    Wrote new test code for GSM 6.10 files.
-
-    * examples/sfinfo.c
-    Fixed incorrect format in printf() statement.
-
-2000-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h.in
-    Fixed comments about sf_perror () and sf_error_str ().
-
-2000-03-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Fixed --enable-justsrc option.
-
-2000-03-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * wav.c
-    Fixed checking of bytespersec field of header. Still some weirdness
-    with some files.
-
-2000-03-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/lossy_comp_test.c
-    Added option to test PCM WAV files (sanity check).
-    Fixed bug in sf_seek() tests.
-
-2000-02-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/wav.c
-    Minor changes to allow writing of GSM 6.10 WAV files.
-
-2000-02-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in Makefile.am src/Makefile.am
-    Finally got around to figuring out how to build a single library from
-    multiple source directories.
-    Reading GSM 6.10 files now seems to work.
-
-2000-01-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Added more error reporting in read_fmt_chunk().
-
-1999-12-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sfinfo.c
-    Modified program to accept multiple filenames from the command line.
-
-1999-11-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_ima_adpcm.c
-    Moved code around in preparation to adding ability to read/write IMA ADPCM
-    encoded AIFF files.
-
-1999-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Fixed put_int() and put_short() macros used by _psf_hprintf() which were
-    causing seg. faults on Sparc Solaris.
-
-1999-11-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.c
-    Added string.h to includes. Thanks to Sigbjxrn Skjfret.
-
-    * src/svx.c
-    Fixed __svx_close() function to ensure FORM and BODY chunks are correctly
-    set.
-
-1999-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c
-    Fixed handling of incorrect size field in AU header on read. Thanks to
-    Christoph Lauer for finding this problem.
-
-1999-09-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fixed a bug with incorrect SSND chunk length being written. This also lead
-    to finding an minor error in AIFF header parsing. Thanks to Dan Timis for
-    pointing this out.
-
-1999-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    Fixed a bug with reading and writing 24 bit stereo PAF files. This problem
-    came to light when implementing tests for the new functions which operate
-    in terms of frames rather than items.
-
-1999-09-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Modified file type detection to use first 12 bytes of file rather than
-    file name extension. Required this because NIST files use the same
-    filename extension as Microsoft WAV files.
-
-    * src/sndfile.c src/sndfile.h
-    Added short, int and double read/write functions which work in frames
-    rather than items. This was originally suggested by Maurizio Umberto
-    Puxeddu.
-
-1999-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/svx.c
-    Finished off implementation of write using __psf_hprintf().
-
-1999-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/common.h
-    Added a buffer to SF_PRIVATE for writing the header. This is required
-    to make generating headers for IFF/SVX files easier as well as making
-    it easier to do re-write the headers which will be required when
-    sf_rewrite_header() is implemented.
-
-    * src/common.c
-    Implemented __psf_hprintf() function. This is an internal function
-    which is documented briefly just above the code.
-
-1999-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed a bug in sf_write_raw() where it was returning incorrect values
-    (thanks to Richard Dobson for finding this one). Must put in a test
-    routine for sf_read_raw and sf_write_raw.
-
-    * src/aiff.c
-    Fixed default FORMsize in __aiff_open_write ().
-
-    * src/sndfile.c
-    Added copy of filename to internal data structure. IFF/SVX files
-    contain a NAME header chunk. Both sf_open_read() and sf_open_write()
-    copy the file name (less the leading path information) to the
-    filename field.
-
-    * src/svx.c
-    Started implementing writing of files.
-
-1999-08-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/svx.c
-    New file for reading/writing 8SVX and 16SVX files.
-
-    * src/sndfile.[ch] src/common.h
-    Changes for SVX files.
-
-    * src/aiff.c
-    Fixed header parsing when unknown chunk is found.
-
-1999-08-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/paf.c
-    New file for reading/writing Ensoniq PARIS audio file format.
-
-    * src/sndfile.[ch] src/common.h
-    Changes for PAF files.
-
-    * src/sndfile.[ch]
-    Added stuff for sf_get_lib_version() function.
-
-
-1999-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h MacOS/config.h
-    Fixed minor MacOS configuration issues.
-
-1999-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * MacOS/
-    Added a new directory for the MacOS config.h file and the
-    readme file.
-
-    * src/aiff.c
-    Fixed calculation of datalength when reading SSND chunk. Thanks to
-    Sigbjørn Skjæret for pointing out this error.
-
-1999-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/sndfile.h src/raw.c
-    Further fixing of #includes for MacOS.
-
-1999-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/aiff.c
-    Added call to ferror () in main header parsing loop of __XXX_open_read
-    functions. This should fix problems on platforms (MacOS, AmigaOS) where
-    fseek()ing or fread()ing beyond the end of the file puts the FILE*
-    stream in an error state until clearerr() is called.
-
-    * tests/write_read_test.c
-    Added tests for RAW header-less PCM files.
-
-    * src/common.h
-    Moved definition of struct tribyte to pcm.c which is the only place
-    which needs it.
-
-    * src/pcm.c
-    Modified all code which assumed sizeof (struct tribyte) == 3. This code
-    did not work on MacOS. Thanks to Ben "Jacobs" for pointing this out.
-
-    * src/au.c
-    Removed <sys/stat.h> from list of #includes (not being used).
-
-    * src/sndfile.c
-    Added MacOS specific #ifdef to replace <sys/stat.h>.
-
-    * src/sndfile.h
-    Added MacOS specific #ifdef to replace <sys/stat.h>.
-
-    * src/sndfile.h
-    Added MacOS specific typedef for off_t.
-
-    * MacOS-readme.txt
-    New file with instructions for building libsndfile under MacOS. Thanks
-    to Ben "Jacobs" for supplying these instructions.
-
-1999-07-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Removed sndfile.h from generated file list as there were no longer
-    any autoconf substitutions being made.
-
-    * src/raw.c
-    New file for handling raw header-less PCM files. In order to open these
-    for read, the user must specify format, pcmbitwidth and channels in the
-    SF_INFO struct when calling sf_open_read ().
-
-    * src/sndfile.c
-    Added support for raw header-less PCM files.
-
-1999-07-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * examples/sfinfo.c
-    Removed options so the sfinfo program always prints out all the information.
-
-1999-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/alaw.c
-    New file for A-law encoding (similar to u-law).
-
-    * tests/alaw_test.c
-    New test program to test the A-law encode/decode lookup tables.
-
-    * tests/lossy_comp_test.c
-    Added tests for a-law encoded WAV, AU and AULE files.
-
-1999-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c src/au.c
-    Removed second "#include <unistd.h>". Thanks to Ben "Jacobs" for pointing
-    this out.
-
-1999-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/ulaw_test.c
-    New test program to test the u-law encode/decode lookup tables.
-
-1999-07-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.h
-    Made corrections to comments on the return values from sf_seek ().
-
-    * src/sndfile.c
-    Fixed boundary condition checking bug and accounting bug in sf_read_raw ().
-
-1999-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/au.c src/ulaw.c
-    Finished implementation of u-law encoded AU files.
-
-    * src/wav.c
-    Implemented reading and writing of u-law encoded WAV files.
-
-    * tests/
-    Changed name of adpcm_test.c to lossy_comp_test.c. This test program
-    will now be used to test Ulaw and Alaw encoding as well as APDCM.
-    Added tests for Ulaw encoded WAV files.
-
-1999-07-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/adpcm_test.c
-    Initialised amp variable in gen_signal() to remove compiler warning.
-
-1999-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    In __aiff_open_read () prevented fseek()ing beyond end of file which
-    was causing trouble on MacOS with the MetroWerks compiler. Thanks to
-    Ben "Jacobs" for pointing this out.
-
-    *src/wav.c
-    Fixed as above in __wav_open_read ().
-
-1999-07-01    Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_ms_adpcm.c
-    Implemented MS ADPCM encoding. Code cleanup of decoder.
-
-    * tests/adpcm_test.c
-    Added tests for MS ADPCM WAV files.
-
-    * src/wav_ima_adpcm.c
-    Fixed incorrect parameter in call to srate2blocksize () from
-    __ima_writer_init ().
-
-1999-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/read_seek_test.c
-    Added test for 8 bit AIFF files.
-
-1999-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.c
-    Removed test for IMA ADPCM WAV files which is now done in adpcm_test.c
-
-    * configure.in
-    Added -Wconversion to CFLAGS.
-
-    * src/*.c tests/*.c examples/*.c
-    Fixed all warnings resulting from use of -Wconversion.
-
-1999-06-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Added fact chunk handling on read and write for all non WAVE_FORMAT_PCM
-    WAV files.
-
-    * src/wav_ima.c
-    Changed block alignment to be dependant on sample rate. This should make
-    WAV files created with libsndfile compatible with the MS Windows media
-    players.
-
-    * tests/adpcm_test.c
-    Reimplemented adpcm_test_short and implemented adpcm_test_int and
-    adpcm_test_double.
-    Now have full testing of IMA ADPCM WAV file read, write and seek.
-
-1999-06-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_float.c
-    Fixed function prototype for x86f2d_array () which was causing ocassional
-    seg. faults on Sparc Solaris machines.
-
-1999-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c
-    Fixed bug in __aiff_close where the length fields in the header were
-    not being correctly calculated before writing.
-
-    * tests/write_read_test.c
-    Modified to detect the above bug in WAV, AIFF and AU files.
-
-1999-06-12    Erik de Castro Lopo     <erikd AT mega-nerd DOT com>
-
-    * Win32/*
-    Added a contribution from Albert Faber to allow libsndfile to compile
-    under Win32 systems. libsndfile will now be used as part of LAME the
-    the MPEG 1 Layer 3 encoder (http://internet.roadrunner.com/~mt/mp3/).
-
-1999-06-11    Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in
-    Changed to reflect previous changes.
-
-    * src/wav_ima_adpcm.c
-    Fixed incorrect calculation of bytespersec header field (IMA ADPCM only).
-
-    Fixed bug when writing from int or double data to IMA ADPCM file. Will need
-    to write test code for this.
-
-    Fixed bug in __ima_write () whereby the length of the current block was
-    calculated incorrectly. Thanks to Jongcheon Park for pointing this out.
-
-1999-03-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/*.c
-    Changed all read/write/lseek function calls to fread/fwrite/
-    fseek/ftell and added error checking of return values from
-    fread and fwrite in critical areas of the code.
-
-    * src/au.c
-    Fixed incorrect datasize element in AU header on write.
-
-    * tests/error_test.c
-    Add new test to check all error values have an associated error
-    string. This will avoid embarrassing real world core dumps.
-
-1999-03-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c src/aiff.c
-    Added handling for unknown chunk markers in the file.
-
-1999-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Filled in missing error strings in SndfileErrors array. Missing entries
-    can cause core dumps when calling sf_error-str (). Thanks to Sam
-    <mrsam at-sign geocities.com> for finding this problem.
-
-1999-03-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav_ima_adpcm.c
-    Work on wav_ms_adpcm.c uncovered a bug in __ima_read () when reading
-    stereo files. Caused by not adjusting offset into buffer of decoded
-    samples for 2 channels. A similar bug existed in __ima_write ().
-    Need a test for stereo ADPCM files.
-
-    * src/wav_ms_adpcm.c
-    Decoder working correctly.
-
-1999-03-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * configure.in Makefile.am
-    Added --enable-justsrc configuration variable sent by Sam
-    <mrsam at-sign geocities.com>.
-
-    * src/wav_ima_adpcm.c
-    Fixed bug when reading beyond end of data section due to not
-    checking pima->blockcount.
-    This uncovered __ima_seek () bug due to pima->blockcount being set
-    before calling __ima_init_block ().
-
-1999-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Started implementing MS ADPCM decoder.
-    If file is WAVE_FORMAT_ADPCM and length of data chunk is odd, this
-    encoder seems to add an extra byte. Why not just give an even data
-    length?
-
-1999-03-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Split code out of wav.c to create wav_float.c and wav_ima_adpcm.c.
-    This will make it easier to add and debug other kinds of WAV files
-    in future.
-
-1999-03-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/
-    Added adpcm_test.c which implements test functions for
-    IMA ADPCM reading/writing/seeking etc.
-
-    * src/wav.c
-    Fixed many bugs in IMA ADPCM encoder and decoder.
-
-1999-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Finished implementing IMA ADPCM encoder and decoder (what a bitch!).
-
-1999-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/wav.c
-    Started implementing IMA ADPCM decoder.
-
-1999-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/sndfile.c
-    Fixed bug where the sf_read_XXX functions were returning a
-    incorrect read count when reading past end of file.
-    Fixed bug in sf_seek () when seeking backwards from end of file.
-
-    * tests/read_seek_test.c
-    Added multiple read test to short_test(), int_test () and
-    double_test ().
-    Added extra chunk to all test WAV files to test that reading
-    stops at end of 'data' chunk.
-
-1999-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.c
-    Added tests for little DEC endian AU files.
-
-    * src/au.c
-    Add handling for DEC format little endian AU files.
-
-1999-02-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c src/au.c src/wav.c
-    Add __psf_sprintf calls during header parsing.
-
-    * src/sndfile.c src/common.c
-    Implement sf_header_info (sndfile.c) function and __psf_sprintf (common.c).
-
-    * tests/write_read_test.c
-    Added tests for 8 bit PCM files (WAV, AIFF and AU).
-
-    * src/au.c src/aiff.c
-    Add handling of 8 bit PCM data format.
-
-    * src/aiff.c
-    On write, set blocksize in SSND chunk to zero like everybody else.
-
-1999-02-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c:
-    Fixed bug in let2s_array (cptr was not being initialised).
-
-    * src/sndfile.c:
-    Fixed bug in sf_read_raw and sf_write_raw. sf_seek should
-    now work when using these functions.
-
-1999-02-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * tests/write_read_test.c:
-    Force test_buffer array to be double aligned. Sparc Solaris
-    requires this.
-
-1999-02-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/pcm.c:
-    Fixed a bug which was causing errors in the reading
-    and writing of 24 bit PCM files.
-
-    * doc/api.html
-    Finished of preliminary documentaion.
-
-1999-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>
-
-    * src/aiff.c:
-    Changed reading of 'COMM' chunk to avoid reading an int
-    which overlaps an int (4 byte) boundary.
+  https://github.com/libsndfile/libsndfile/commits/master
diff --git a/M4/Makefile.am b/M4/Makefile.am
deleted file mode 100644 (file)
index 7dd1a3f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-EXTRA_DIST = add_cflags.m4 clip_mode.m4 endian.m4 \
-       flexible_array.m4 llrint.m4 lrint.m4 lrintf.m4 octave.m4 extra_pkg.m4 visibility.m4
-
diff --git a/M4/add_cflags.m4 b/M4/add_cflags.m4
deleted file mode 100644 (file)
index 55a326c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-dnl @synopsis MN_ADD_CFLAGS
-dnl
-dnl Add the given option to CFLAGS, if it doesn't break the compiler
-
-AC_DEFUN([MN_ADD_CFLAGS],
-[AC_MSG_CHECKING([if $CC accepts $1])
-       ac_add_cflags__old_cflags="$CFLAGS"
-       CFLAGS="$1"
-       AC_TRY_LINK([
-                       #include <stdio.h>
-                       ],
-               [puts("Hello, World!"); return 0;],
-               AC_MSG_RESULT([yes])
-                       CFLAGS="$ac_add_cflags__old_cflags $1",
-               AC_MSG_RESULT([no])
-                       CFLAGS="$ac_add_cflags__old_cflags"
-               )
-])# MN_ADD_CFLAGS
diff --git a/M4/add_cxxflags.m4 b/M4/add_cxxflags.m4
deleted file mode 100644 (file)
index 1c0a4de..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-dnl @synopsis MN_ADD_CXXFLAGS
-dnl
-dnl Add the given option to CXXFLAGS, if it doesn't break the compiler
-
-AC_DEFUN([MN_ADD_CXXFLAGS],
-[AC_MSG_CHECKING([if $CXX accepts $1])
-       AC_LANG_ASSERT([C++])
-       ac_add_cxxflags__old_cxxflags="$CXXFLAGS"
-       CXXFLAGS="$1"
-       AC_TRY_LINK([
-                       #include <cstdio>
-                       ],
-               [puts("Hello, World!"); return 0;],
-               AC_MSG_RESULT([yes])
-                       CXXFLAGS="$ac_add_cxxflags__old_cxxflags $1",
-               AC_MSG_RESULT([no])
-                       CXXFLAGS="$ac_add_cxxflags__old_cxxflags"
-               )
-])# MN_ADD_CXXFLAGS
diff --git a/M4/clang.m4 b/M4/clang.m4
deleted file mode 100644 (file)
index 4cf3077..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-dnl @synopsis MN_C_COMPILER_IS_CLANG
-dnl
-dnl Find out if a compiler claiming to be gcc really is gcc (fuck you clang).
-dnl @version 1.0       Oct 31 2013
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any
-dnl purpose is hereby granted without fee, provided that the above copyright
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is
-dnl provided "as is" without express or implied warranty.
-dnl
-
-
-AC_DEFUN([MN_C_COMPILER_IS_CLANG],
-[AC_CACHE_CHECK(whether we are using the CLANG C compiler,
-       mn_cv_c_compiler_clang,
-       [       AC_LANG_ASSERT(C)
-               AC_TRY_LINK([
-                       #include <stdio.h>
-                       ],
-                       [
-                       #ifndef __clang__
-                               This is not clang!
-                       #endif
-                       ],
-               mn_cv_c_compiler_clang=yes,
-               mn_cv_c_compiler_clang=no
-               ])
-       )
-])
diff --git a/M4/endian.m4 b/M4/endian.m4
deleted file mode 100644 (file)
index 5d766ff..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-dnl @synopsis MN_C_FIND_ENDIAN
-dnl
-dnl Determine endian-ness of target processor.
-dnl @version 1.1       Mar 03 2002
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Majority written from scratch to replace the standard autoconf macro 
-dnl AC_C_BIGENDIAN. Only part remaining from the original it the invocation
-dnl of the AC_TRY_RUN macro.
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any 
-dnl purpose is hereby granted without fee, provided that the above copyright 
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is 
-dnl provided "as is" without express or implied warranty.
-
-dnl Find endian-ness in the following way:
-dnl    1) Look in <endian.h>.
-dnl    2) If 1) fails, look in <sys/types.h> and <sys/param.h>.
-dnl    3) If 1) and 2) fails and not cross compiling run a test program.
-dnl    4) If 1) and 2) fails and cross compiling then guess based on target.
-
-AC_DEFUN([MN_C_FIND_ENDIAN],
-[AC_CACHE_CHECK(processor byte ordering, 
-       ac_cv_c_byte_order,
-
-# Initialize to unknown
-ac_cv_c_byte_order=unknown
-
-if test x$ac_cv_header_endian_h = xyes ; then
-
-       # First try <endian.h> which should set BYTE_ORDER.
-
-       [AC_TRY_LINK([
-               #include <endian.h>
-               #if BYTE_ORDER != LITTLE_ENDIAN
-                       not big endian
-               #endif
-               ], return 0 ;, 
-                       ac_cv_c_byte_order=little
-               )]
-                               
-       [AC_TRY_LINK([
-               #include <endian.h>
-               #if BYTE_ORDER != BIG_ENDIAN
-                       not big endian
-               #endif
-               ], return 0 ;, 
-                       ac_cv_c_byte_order=big
-               )]
-
-       fi
-
-if test $ac_cv_c_byte_order = unknown ; then
-
-       [AC_TRY_LINK([
-               #include <sys/types.h>
-               #include <sys/param.h>
-               #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
-                       bogus endian macros
-               #endif
-               ], return 0 ;, 
-
-               [AC_TRY_LINK([
-                       #include <sys/types.h>
-                       #include <sys/param.h>
-                       #if BYTE_ORDER != LITTLE_ENDIAN
-                               not big endian
-                       #endif
-                       ], return 0 ;, 
-                               ac_cv_c_byte_order=little
-                       )]
-                               
-               [AC_TRY_LINK([
-                       #include <sys/types.h>
-                       #include <sys/param.h>
-                       #if BYTE_ORDER != LITTLE_ENDIAN
-                               not big endian
-                       #endif
-                       ], return 0 ;, 
-                               ac_cv_c_byte_order=little
-                       )]
-
-               )]
-
-       fi
-
-if test $ac_cv_c_byte_order = unknown ; then
-       if test $cross_compiling = yes ; then
-               # This is the last resort. Try to guess the target processor endian-ness
-               # by looking at the target CPU type.    
-               [
-               case "$target_cpu" in
-                       alpha* | i?86* | mipsel* | ia64*)
-                               ac_cv_c_byte_order=little
-                               ;;
-                       
-                       m68* | mips* | powerpc* | hppa* | sparc*)
-                               ac_cv_c_byte_order=big
-                               ;;
-       
-                       esac
-               ]
-       else
-               AC_TRY_RUN(
-               [[
-               int main (void) 
-               {       /* Are we little or big endian?  From Harbison&Steele.  */
-                       union
-                       {       long l ;
-                               char c [sizeof (long)] ;
-                       } u ;
-                       u.l = 1 ;
-                       return (u.c [sizeof (long) - 1] == 1);
-                       }
-                       ]], , ac_cv_c_byte_order=big, 
-                       )
-
-               AC_TRY_RUN(
-               [[int main (void) 
-               {       /* Are we little or big endian?  From Harbison&Steele.  */
-                       union
-                       {       long l ;
-                               char c [sizeof (long)] ;
-                       } u ;
-                       u.l = 1 ;
-                       return (u.c [0] == 1);
-                       }]], , ac_cv_c_byte_order=little, 
-                       )
-               fi      
-       fi
-
-)
-
-if test $ac_cv_c_byte_order = big ; then
-       ac_cv_c_big_endian=1
-       ac_cv_c_little_endian=0
-elif test $ac_cv_c_byte_order = little ; then
-       ac_cv_c_big_endian=0
-       ac_cv_c_little_endian=1
-else
-       ac_cv_c_big_endian=0
-       ac_cv_c_little_endian=0
-
-       AC_MSG_WARN([[*****************************************************************]])
-       AC_MSG_WARN([[*** Not able to determine endian-ness of target processor.       ]])
-       AC_MSG_WARN([[*** The constants CPU_IS_BIG_ENDIAN and CPU_IS_LITTLE_ENDIAN in  ]])
-       AC_MSG_WARN([[*** src/config.h may need to be hand editied.                    ]])
-       AC_MSG_WARN([[*****************************************************************]])
-       fi
-
-]
-)# MN_C_FIND_ENDIAN
-
-
diff --git a/M4/gcc_version.m4 b/M4/gcc_version.m4
deleted file mode 100644 (file)
index f8c5cbe..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-dnl @synopsis MN_GCC_VERSION
-dnl
-dnl Find the version of gcc.
-dnl @version 1.0       Nov 05 2007
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any 
-dnl purpose is hereby granted without fee, provided that the above copyright 
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is 
-dnl provided "as is" without express or implied warranty.
-dnl
-
-AC_DEFUN([MN_GCC_VERSION],
-[
-if test "x$ac_cv_c_compiler_gnu" = "xyes" ; then
-
-       AC_MSG_CHECKING([for version of $CC])
-       GCC_VERSION=`$CC -dumpversion`
-       AC_MSG_RESULT($GCC_VERSION)
-
-       changequote(,)dnl
-       GCC_MAJOR_VERSION=`echo $GCC_VERSION | sed "s/\..*//"`
-       GCC_MINOR_VERSION=`echo $GCC_VERSION | sed "s/$GCC_MAJOR_VERSION\.//" | sed "s/\..*//"`
-       changequote([,])dnl
-       fi
-
-AC_SUBST(GCC_VERSION)
-AC_SUBST(GCC_MAJOR_VERSION)
-AC_SUBST(GCC_MINOR_VERSION)
-
-])# MN_GCC_VERSION
-
diff --git a/M4/llrint.m4 b/M4/llrint.m4
deleted file mode 100644 (file)
index 66be206..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-dnl @synopsis MN_C99_FUNC_LLRINT
-dnl
-dnl Check whether C99's llrint function is available.
-dnl @version 1.1       Sep 30 2002
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any 
-dnl purpose is hereby granted without fee, provided that the above copyright 
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is 
-dnl provided "as is" without express or implied warranty.
-dnl
-AC_DEFUN([MN_C99_FUNC_LLRINT],
-[AC_CACHE_CHECK(for llrint,
-  ac_cv_c99_llrint,
-[
-llrint_save_CFLAGS=$CFLAGS
-CFLAGS="-lm"
-AC_TRY_LINK([
-#define                _ISOC9X_SOURCE  1
-#define        _ISOC99_SOURCE  1
-#define                __USE_ISOC99    1
-#define        __USE_ISOC9X    1
-
-#include <math.h>
-#include <stdint.h>
-], int64_t     x ; x = llrint(3.14159) ;, ac_cv_c99_llrint=yes, ac_cv_c99_llrint=no)
-
-CFLAGS=$llrint_save_CFLAGS
-
-])
-
-if test "$ac_cv_c99_llrint" = yes; then
-  AC_DEFINE(HAVE_LLRINT, 1,
-            [Define if you have C99's llrint function.])
-fi
-])# MN_C99_FUNC_LLRINT
-
diff --git a/M4/lrint.m4 b/M4/lrint.m4
deleted file mode 100644 (file)
index c2c21d6..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-dnl @synopsis MN_C99_FUNC_LRINT
-dnl
-dnl Check whether C99's lrint function is available.
-dnl @version 1.3       Feb 12 2002
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any 
-dnl purpose is hereby granted without fee, provided that the above copyright 
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is 
-dnl provided "as is" without express or implied warranty.
-dnl
-AC_DEFUN([MN_C99_FUNC_LRINT],
-[AC_CACHE_CHECK(for lrint,
-  ac_cv_c99_lrint,
-[
-lrint_save_CFLAGS=$CFLAGS
-CFLAGS="-lm"
-AC_TRY_LINK([
-#define                _ISOC9X_SOURCE  1
-#define        _ISOC99_SOURCE  1
-#define                __USE_ISOC99    1
-#define        __USE_ISOC9X    1
-
-#include <math.h>
-], if (!lrint(3.14159)) lrint(2.7183);, ac_cv_c99_lrint=yes, ac_cv_c99_lrint=no)
-
-CFLAGS=$lrint_save_CFLAGS
-
-])
-
-if test "$ac_cv_c99_lrint" = yes; then
-  AC_DEFINE(HAVE_LRINT, 1,
-            [Define if you have C99's lrint function.])
-fi
-])# MN_C99_FUNC_LRINT
-
diff --git a/M4/lrintf.m4 b/M4/lrintf.m4
deleted file mode 100644 (file)
index 04f4d66..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-dnl @synopsis MN_C99_FUNC_LRINTF
-dnl
-dnl Check whether C99's lrintf function is available.
-dnl @version 1.3       Feb 12 2002
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any 
-dnl purpose is hereby granted without fee, provided that the above copyright 
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is 
-dnl provided "as is" without express or implied warranty.
-dnl
-AC_DEFUN([MN_C99_FUNC_LRINTF],
-[AC_CACHE_CHECK(for lrintf,
-  ac_cv_c99_lrintf,
-[
-lrintf_save_CFLAGS=$CFLAGS
-CFLAGS="-lm"
-AC_TRY_LINK([
-#define                _ISOC9X_SOURCE  1
-#define        _ISOC99_SOURCE  1
-#define                __USE_ISOC99    1
-#define        __USE_ISOC9X    1
-
-#include <math.h>
-], if (!lrintf(3.14159)) lrintf(2.7183);, ac_cv_c99_lrintf=yes, ac_cv_c99_lrintf=no)
-
-CFLAGS=$lrintf_save_CFLAGS
-
-])
-
-if test "$ac_cv_c99_lrintf" = yes; then
-  AC_DEFINE(HAVE_LRINTF, 1,
-            [Define if you have C99's lrintf function.])
-fi
-])# MN_C99_FUNC_LRINTF
-
diff --git a/M4/really_gcc.m4 b/M4/really_gcc.m4
deleted file mode 100644 (file)
index 67aed78..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-dnl @synopsis MN_GCC_REALLY_IS_GCC
-dnl
-dnl Find out if a compiler claiming to be gcc really is gcc (fuck you clang).
-dnl @version 1.0       Oct 31 2013
-dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-dnl
-dnl Permission to use, copy, modify, distribute, and sell this file for any
-dnl purpose is hereby granted without fee, provided that the above copyright
-dnl and this permission notice appear in all copies.  No representations are
-dnl made about the suitability of this software for any purpose.  It is
-dnl provided "as is" without express or implied warranty.
-dnl
-
-# If the configure script has already detected GNU GCC, then make sure it
-# isn't CLANG masquerading as GCC.
-
-AC_DEFUN([MN_GCC_REALLY_IS_GCC],
-[      AC_LANG_ASSERT(C)
-       if test "x$ac_cv_c_compiler_gnu" = "xyes" ; then
-               AC_TRY_LINK([
-                       #include <stdio.h>
-                       ],
-                       [
-                       #ifdef __clang__
-                               This is clang!
-                       #endif
-                       ],
-               ac_cv_c_compiler_gnu=yes,
-               ac_cv_c_compiler_gnu=no
-               )
-               fi
-
-])
diff --git a/M4/visibility.m4 b/M4/visibility.m4
deleted file mode 100644 (file)
index ce00e72..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-# visibility.m4 serial 5 (gettext-0.18.2)
-dnl Copyright (C) 2005, 2008, 2010-2017 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl From Bruno Haible.
-
-dnl Tests whether the compiler supports the command-line option
-dnl -fvisibility=hidden and the function and variable attributes
-dnl __attribute__((__visibility__("hidden"))) and
-dnl __attribute__((__visibility__("default"))).
-dnl Does *not* test for __visibility__("protected") - which has tricky
-dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
-dnl Mac OS X.
-dnl Does *not* test for __visibility__("internal") - which has processor
-dnl dependent semantics.
-dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
-dnl "really only recommended for legacy code".
-dnl Set the variable CFLAG_VISIBILITY.
-dnl Defines and sets the variable HAVE_VISIBILITY.
-
-AC_DEFUN([gl_VISIBILITY],
-[
-  AC_REQUIRE([AC_PROG_CC])
-  CFLAG_VISIBILITY=
-  HAVE_VISIBILITY=0
-  if test -n "$GCC"; then
-    dnl First, check whether -Werror can be added to the command line, or
-    dnl whether it leads to an error because of some other option that the
-    dnl user has put into $CC $CFLAGS $CPPFLAGS.
-    AC_MSG_CHECKING([whether the -Werror option is usable])
-    AC_CACHE_VAL([gl_cv_cc_vis_werror], [
-      gl_save_CFLAGS="$CFLAGS"
-      CFLAGS="$CFLAGS -Werror"
-      AC_COMPILE_IFELSE(
-        [AC_LANG_PROGRAM([[]], [[]])],
-        [gl_cv_cc_vis_werror=yes],
-        [gl_cv_cc_vis_werror=no])
-      CFLAGS="$gl_save_CFLAGS"])
-    AC_MSG_RESULT([$gl_cv_cc_vis_werror])
-    dnl Now check whether visibility declarations are supported.
-    AC_MSG_CHECKING([for simple visibility declarations])
-    AC_CACHE_VAL([gl_cv_cc_visibility], [
-      gl_save_CFLAGS="$CFLAGS"
-      CFLAGS="$CFLAGS -fvisibility=hidden"
-      dnl We use the option -Werror and a function dummyfunc, because on some
-      dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning
-      dnl "visibility attribute not supported in this configuration; ignored"
-      dnl at the first function definition in every compilation unit, and we
-      dnl don't want to use the option in this case.
-      if test $gl_cv_cc_vis_werror = yes; then
-        CFLAGS="$CFLAGS -Werror"
-      fi
-      AC_COMPILE_IFELSE(
-        [AC_LANG_PROGRAM(
-           [[extern __attribute__((__visibility__("hidden"))) int hiddenvar;
-             extern __attribute__((__visibility__("default"))) int exportedvar;
-             extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
-             extern __attribute__((__visibility__("default"))) int exportedfunc (void);
-             void dummyfunc (void) {}
-           ]],
-           [[]])],
-        [gl_cv_cc_visibility=yes],
-        [gl_cv_cc_visibility=no])
-      CFLAGS="$gl_save_CFLAGS"])
-    AC_MSG_RESULT([$gl_cv_cc_visibility])
-    if test $gl_cv_cc_visibility = yes; then
-      CFLAG_VISIBILITY="-fvisibility=hidden"
-      HAVE_VISIBILITY=1
-    fi
-  fi
-  AC_SUBST([CFLAG_VISIBILITY])
-  AC_SUBST([HAVE_VISIBILITY])
-  AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
-    [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
-])
index 181f580..0b8bfa1 100644 (file)
 ## Process this file with automake to produce Makefile.in
 
-ACLOCAL_AMFLAGS = -I M4
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/include $(OS_SPECIFIC_CFLAGS)
 
 DISTCHECK_CONFIGURE_FLAGS = --enable-werror
 
+CLEANFILES = programs/*.wav octave-workspace
+
+if FULL_SUITE
 if BUILD_OCTAVE_MOD
-octave_dir = Octave
+SUBDIRS = Octave
+endif
+endif
+
+EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \
+       Scripts/linux-to-win-cross-configure.sh \
+       CMakeLists.txt $(cmake_files) Win32
+
+cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \
+       cmake/CMakeAutoGen.cmake cmake/CMakeAutoGenScript.cmake \
+       cmake/FindOgg.cmake cmake/FindVorbis.cmake cmake/FindSndio.cmake \
+       cmake/FindSpeex.cmake cmake/sqlite/FindSQLite3.cmake \
+       cmake/SndFileChecks.cmake cmake/TestInline.cmake \
+       cmake/TestLargeFiles.cmake cmake/TestInline.c.in \
+       cmake/FindOpus.cmake cmake/SndFileConfig.cmake.in \
+       cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in
+
+pkgconfig_DATA = sndfile.pc
+
+noinst_PROGRAMS =
+
+#===============================================================================
+
+test: check
+
+# Need this target to force building of test programs.
+checkprograms: $(check_PROGRAMS)
+
+########
+# src/ #
+########
+
+BUILT_SOURCES = src/test_endswap.c
+
+SYMBOL_FILES = src/Symbols.gnu-binutils src/Symbols.darwin src/libsndfile-1.def src/Symbols.os2 src/Symbols.static
+
+EXTRA_DIST += include/sndfile.h.in src/config.h.in src/test_endswap.tpl src/test_endswap.def \
+       $(SYMBOL_FILES) src/create_symbols_file.py src/binheader_writef_check.py \
+       src/GSM610/README src/GSM610/COPYRIGHT src/GSM610/ChangeLog \
+       src/G72x/README src/G72x/README.original src/G72x/ChangeLog \
+       src/make-static-lib-hidden-privates.sh \
+       src/config.h.cmake
+
+if USE_WIN_VERSION_FILE
+WIN_VERSION_FILE = src/version-metadata.rc
+else
+WIN_VERSION_FILE =
 endif
 
-SUBDIRS = M4 Win32 src examples tests
+#===============================================================================
+
+lib_LTLIBRARIES = src/libsndfile.la
+include_HEADERS = include/sndfile.hh
+nodist_include_HEADERS = include/sndfile.h
+src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS)
+# MinGW requires -no-undefined if a DLL is to be built.
+src_libsndfile_la_LDFLAGS = -no-undefined -version-info $(SHARED_VERSION_INFO) $(SHLIB_VERSION_ARG)
+src_libsndfile_la_SOURCES = src/sndfile.c src/aiff.c src/au.c src/avr.c src/caf.c src/dwd.c src/flac.c src/g72x.c src/htk.c src/ircam.c \
+       src/macos.c src/mat4.c src/mat5.c src/nist.c src/paf.c src/pvf.c src/raw.c src/rx2.c src/sd2.c \
+       src/sds.c src/svx.c src/txw.c src/voc.c src/wve.c src/w64.c src/wavlike.c src/wav.c src/xi.c src/mpc2k.c src/rf64.c \
+       src/ogg_vorbis.c src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c src/ogg_vcomment.c \
+       src/common.h src/sfconfig.h src/sfendian.h src/wavlike.h src/sf_unistd.h src/ogg.h src/chanmap.h src/ogg_vcomment.h
+nodist_src_libsndfile_la_SOURCES = $(nodist_include_HEADERS)
+src_libsndfile_la_LIBADD = src/GSM610/libgsm.la src/G72x/libg72x.la src/ALAC/libalac.la \
+       src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm
+EXTRA_src_libsndfile_la_DEPENDENCIES = $(SYMBOL_FILES)
+
+noinst_LTLIBRARIES = src/libcommon.la
+src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS)
+src_libcommon_la_SOURCES = src/common.c src/file_io.c src/command.c src/pcm.c src/ulaw.c src/alaw.c \
+       src/float32.c src/double64.c src/ima_adpcm.c src/ms_adpcm.c src/gsm610.c src/dwvw.c src/vox_adpcm.c \
+       src/interleave.c src/strings.c src/dither.c src/cart.c src/broadcast.c src/audio_detect.c \
+       src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/ogg.c src/chanmap.c \
+       src/windows.c src/id3.c src/nms_adpcm.c $(WIN_VERSION_FILE)
+
+check_PROGRAMS = src/test_main
+src_test_main_SOURCES = src/test_main.c src/test_main.h src/test_conversions.c src/test_float.c src/test_endswap.c \
+       src/test_audio_detect.c src/test_log_printf.c src/test_file_io.c src/test_ima_oki_adpcm.c \
+       src/test_strncpy_crlf.c src/test_broadcast_var.c src/test_cart_var.c \
+       src/test_binheader_writef.c src/test_nms_adpcm.c
+src_test_main_LDADD = src/libcommon.la
+
+##############
+# src/GSM610 #
+##############
+
+noinst_LTLIBRARIES += src/GSM610/libgsm.la
+src_GSM610_libgsm_la_SOURCES = src/GSM610/config.h src/GSM610/gsm.h src/GSM610/gsm610_priv.h \
+       src/GSM610/add.c src/GSM610/code.c src/GSM610/decode.c src/GSM610/gsm_create.c \
+       src/GSM610/gsm_decode.c src/GSM610/gsm_destroy.c src/GSM610/gsm_encode.c \
+       src/GSM610/gsm_option.c src/GSM610/long_term.c src/GSM610/lpc.c src/GSM610/preprocess.c \
+       src/GSM610/rpe.c src/GSM610/short_term.c src/GSM610/table.c
+
+############
+# src/G72x #
+############
+
+noinst_LTLIBRARIES += src/G72x/libg72x.la
+src_G72x_libg72x_la_SOURCES = src/G72x/g72x.h src/G72x/g72x_priv.h \
+       src/G72x/g721.c src/G72x/g723_16.c src/G72x/g723_24.c src/G72x/g723_40.c src/G72x/g72x.c
+
+check_PROGRAMS += src/G72x/g72x_test
+src_G72x_g72x_test_SOURCES = src/G72x/g72x_test.c
+src_G72x_g72x_test_LDADD = src/G72x/libg72x.la
+
+############
+# src/ALAC #
+############
+
+noinst_LTLIBRARIES += src/ALAC/libalac.la
+src_ALAC_libalac_la_SOURCES = src/ALAC/ALACAudioTypes.h src/ALAC/ALACBitUtilities.h \
+       src/ALAC/EndianPortable.h src/ALAC/aglib.h src/ALAC/dplib.h src/ALAC/matrixlib.h \
+       src/ALAC/alac_codec.h src/ALAC/shift.h \
+       src/ALAC/ALACBitUtilities.c src/ALAC/ag_dec.c \
+       src/ALAC/ag_enc.c src/ALAC/dp_dec.c src/ALAC/dp_enc.c src/ALAC/matrix_dec.c \
+       src/ALAC/matrix_enc.c src/ALAC/alac_decoder.c src/ALAC/alac_encoder.c
+
+#===============================================================================
+# Generate an OS specific Symbols files. This is done when the author
+# builds the distribution tarball. There should be not need for the
+# end user to create these files.
+
+# "$<" cannot portably be used in the recipe across Make implementations
+# https://www.gnu.org/software/autoconf/manual/autoconf.html#g_t_0024_003c-in-Ordinary-Make-Rules
+SYMBOL_SCRIPT = $(top_srcdir)/src/create_symbols_file.py
+
+src/Symbols.gnu-binutils: $(SYMBOL_SCRIPT)
+       $(PYTHON) $(SYMBOL_SCRIPT) linux $(VERSION) > $(top_srcdir)/$@
+
+src/Symbols.darwin: $(SYMBOL_SCRIPT)
+       $(PYTHON) $(SYMBOL_SCRIPT) darwin $(VERSION) > $(top_srcdir)/$@
+
+src/libsndfile-1.def: $(SYMBOL_SCRIPT)
+       $(PYTHON) $(SYMBOL_SCRIPT) win32 $(VERSION) > $(top_srcdir)/$@
+
+src/Symbols.os2: $(SYMBOL_SCRIPT)
+       $(PYTHON) $(SYMBOL_SCRIPT) os2 $(VERSION) > $(top_srcdir)/$@
+
+src/Symbols.static: $(SYMBOL_SCRIPT)
+       $(PYTHON) $(SYMBOL_SCRIPT) static $(VERSION) > $(top_srcdir)/$@
+
+#===============================================================================
+# Building windows resource files (if needed).
+
+.rc.lo:
+       $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) $< -o $@
+
+#===============================================================================
+# Disable autoheader.
+AUTOHEADER=echo
+
+########
+# docs/ #
+########
 
 if FULL_SUITE
-SUBDIRS += man doc $(octave_dir) regtest programs
+dist_doc_DATA = docs/index.md docs/libsndfile.jpg docs/libsndfile.css docs/print.css docs/api.md \
+       docs/command.md docs/bugs.md docs/formats.md docs/sndfile_info.md docs/new_file_type_howto.md \
+       docs/win32.md docs/FAQ.md docs/lists.md docs/embedded_files.md docs/octave.md \
+       docs/tutorial.md
 endif
 
-DIST_SUBDIRS = M4 man doc Win32 src Octave examples regtest tests programs
+#############
+# examples/ #
+#############
 
-EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \
-       Scripts/linux-to-win-cross-configure.sh Scripts/build-test-tarball.mk.in \
-    CMakeLists.txt CMake/autogen.cmake CMake/build.cmake CMake/check.cmake \
-       CMake/compiler_is_gcc.c CMake/external_libs.cmake CMake/file.cmake \
-       CMake/have_decl_s_irgrp.c CMake/libsndfile.cmake
+check_PROGRAMS += examples/make_sine examples/sfprocess examples/list_formats examples/generate examples/sndfilehandle \
+       examples/sndfile-to-text examples/sndfile-loopify
 
+examples_sndfile_to_text_SOURCES = examples/sndfile-to-text.c
+examples_sndfile_to_text_LDADD = src/libsndfile.la
 
-CLEANFILES = *~
+examples_sndfile_loopify_SOURCES = examples/sndfile-loopify.c
+examples_sndfile_loopify_LDADD = src/libsndfile.la
 
-pkgconfig_DATA = sndfile.pc
+examples_make_sine_SOURCES = examples/make_sine.c
+examples_make_sine_LDADD = src/libsndfile.la
+
+examples_sfprocess_SOURCES = examples/sfprocess.c
+examples_sfprocess_LDADD = src/libsndfile.la
+
+examples_list_formats_SOURCES = examples/list_formats.c
+examples_list_formats_LDADD = src/libsndfile.la
+
+examples_generate_SOURCES = examples/generate.c
+examples_generate_LDADD = src/libsndfile.la
+
+examples_sndfilehandle_SOURCES = examples/sndfilehandle.cc
+examples_sndfilehandle_LDADD = src/libsndfile.la
+
+##########
+# tests/ #
+##########
+
+TESTS_ENVIRONMENT = $(SHELL) tests/test_wrapper.sh
+
+if ENABLE_TEST_COVERAGE
+CPP_TEST =
+else
+CPP_TEST = tests/cpp_test
+endif
 
-m4datadir = $(datadir)/aclocal
+TESTS = tests/pedantic-header-test.sh
+
+check_PROGRAMS += tests/sfversion tests/floating_point_test tests/write_read_test \
+       tests/lossy_comp_test tests/error_test tests/ulaw_test tests/alaw_test tests/dwvw_test \
+       tests/peak_chunk_test tests/command_test tests/stdio_test \
+       tests/pcm_test tests/headerless_test tests/pipe_test tests/header_test tests/misc_test \
+       tests/raw_test tests/string_test tests/multi_file_test tests/chunk_test \
+       tests/scale_clip_test tests/win32_test tests/aiff_rw_test tests/virtual_io_test \
+       tests/locale_test tests/win32_ordinal_test tests/ogg_test tests/compression_size_test \
+       tests/checksum_test tests/external_libs_test tests/rdwr_test tests/format_check_test $(CPP_TEST) \
+       tests/channel_test tests/long_read_write_test tests/stdin_test tests/stdout_test \
+       tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test
+
+BUILT_SOURCES += \
+       tests/write_read_test.c \
+       tests/pcm_test.c \
+       tests/header_test.c \
+       tests/utils.c \
+       tests/scale_clip_test.c \
+       tests/pipe_test.c \
+       tests/rdwr_test.c \
+       tests/floating_point_test.c \
+       tests/benchmark.c
+
+EXTRA_DIST += $(BUILT_SOURCES) \
+       tests/write_read_test.tpl     tests/write_read_test.def \
+       tests/pcm_test.tpl            tests/pcm_test.def \
+       tests/header_test.tpl         tests/header_test.def \
+       tests/utils.tpl               tests/utils.def \
+       tests/scale_clip_test.tpl     tests/scale_clip_test.def \
+       tests/pipe_test.tpl           tests/pipe_test.def \
+       tests/rdwr_test.tpl           tests/rdwr_test.def \
+       tests/floating_point_test.tpl tests/floating_point_test.def \
+       tests/benchmark.tpl           tests/benchmark.def
+
+# 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) src/.libs/$@ $@
+
+clean-local :
+       -rm -f libsndfile-1.dll
+
+endif
 
 #===============================================================================
 
-test: check-recursive
+tests_sfversion_SOURCES = tests/sfversion.c
+tests_sfversion_LDADD = src/libsndfile.la
+
+tests_write_read_test_SOURCES = tests/utils.c tests/generate.c tests/generate.h tests/write_read_test.c tests/utils.h
+tests_write_read_test_LDADD = src/libsndfile.la
+
+tests_lossy_comp_test_SOURCES = tests/utils.c tests/lossy_comp_test.c tests/utils.h
+tests_lossy_comp_test_LDADD = src/libsndfile.la
+
+tests_fix_this_SOURCES = tests/utils.c tests/fix_this.c tests/utils.h
+tests_fix_this_LDADD = src/libsndfile.la
+
+tests_error_test_SOURCES = tests/error_test.c tests/utils.c tests/utils.h
+tests_error_test_LDADD = src/libsndfile.la
+
+tests_ulaw_test_SOURCES = tests/utils.c tests/ulaw_test.c tests/utils.h
+tests_ulaw_test_LDADD = src/libsndfile.la
+
+tests_alaw_test_SOURCES = tests/utils.c tests/alaw_test.c tests/utils.h
+tests_alaw_test_LDADD = src/libsndfile.la
+
+tests_aiff_rw_test_SOURCES = tests/utils.c tests/aiff_rw_test.c tests/utils.h
+tests_aiff_rw_test_LDADD = src/libsndfile.la
 
-# Target to make autogenerated files.
-checkprograms :
-       (cd src ; $(MAKE) libsndfile.la checkprograms)
-       (cd tests ; $(MAKE) checkprograms)
+tests_command_test_SOURCES = tests/command_test.c tests/utils.c tests/utils.h
+tests_command_test_LDADD = src/libsndfile.la
 
-testprogs :
-       (cd src ; $(MAKE) testprogs)
-       (cd tests ; $(MAKE) testprogs)
+tests_locale_test_SOURCES = tests/locale_test.c tests/utils.c tests/utils.h
+tests_locale_test_LDADD = src/libsndfile.la
+
+tests_largefile_test_SOURCES = tests/largefile_test.c tests/utils.c tests/utils.h
+tests_largefile_test_LDADD = src/libsndfile.la
+
+tests_pcm_test_SOURCES = tests/pcm_test.c tests/utils.c tests/utils.h
+tests_pcm_test_LDADD = src/libsndfile.la
+
+tests_headerless_test_SOURCES = tests/utils.c tests/headerless_test.c tests/utils.h
+tests_headerless_test_LDADD = src/libsndfile.la
+
+tests_stdin_test_SOURCES = tests/stdin_test.c tests/utils.c tests/utils.h
+tests_stdin_test_LDADD = src/libsndfile.la
+
+tests_stdout_test_SOURCES = tests/stdout_test.c tests/utils.h
+tests_stdout_test_LDADD = src/libsndfile.la
+
+tests_stdio_test_SOURCES = tests/stdio_test.c tests/utils.c tests/utils.h
+tests_stdio_test_LDADD = src/libsndfile.la
+
+tests_pipe_test_SOURCES = tests/pipe_test.c tests/utils.c tests/utils.h
+tests_pipe_test_LDADD = src/libsndfile.la
+
+tests_benchmark_SOURCES = tests/benchmark.c tests/utils.h
+tests_benchmark_LDADD = src/libsndfile.la
+
+tests_header_test_SOURCES = tests/header_test.c tests/utils.c tests/utils.h
+tests_header_test_LDADD = src/libsndfile.la
+
+tests_misc_test_SOURCES = tests/misc_test.c tests/utils.c tests/utils.h
+tests_misc_test_LDADD = src/libsndfile.la
+
+tests_raw_test_SOURCES = tests/raw_test.c tests/utils.c tests/utils.h
+tests_raw_test_LDADD = src/libsndfile.la
+
+tests_string_test_SOURCES = tests/string_test.c tests/utils.c tests/utils.h
+tests_string_test_LDADD = src/libsndfile.la
+
+tests_dither_test_SOURCES = tests/dither_test.c tests/utils.c tests/utils.h
+tests_dither_test_LDADD = src/libsndfile.la
+
+tests_chunk_test_SOURCES = tests/chunk_test.c tests/utils.c tests/utils.h
+tests_chunk_test_LDADD = src/libsndfile.la
+
+tests_multi_file_test_SOURCES = tests/multi_file_test.c tests/utils.c tests/utils.h
+tests_multi_file_test_LDADD = src/libsndfile.la
+
+tests_virtual_io_test_SOURCES = tests/virtual_io_test.c tests/utils.c tests/utils.h
+tests_virtual_io_test_LDADD = src/libsndfile.la
+
+tests_ogg_test_SOURCES = tests/ogg_test.c tests/utils.c tests/utils.h
+tests_ogg_test_LDADD = src/libsndfile.la
+
+tests_ogg_opus_test_SOURCES = tests/ogg_opus_test.c tests/utils.c tests/utils.h
+tests_ogg_opus_test_LDADD = src/libsndfile.la
+
+tests_compression_size_test_SOURCES = tests/compression_size_test.c tests/utils.c tests/utils.h tests/dft_cmp.h
+tests_compression_size_test_LDADD = src/libsndfile.la
+
+tests_rdwr_test_SOURCES = tests/rdwr_test.c tests/utils.c tests/utils.h
+tests_rdwr_test_LDADD = src/libsndfile.la
+
+tests_win32_test_SOURCES = tests/win32_test.c
+# Link lib here so that generating the testsuite tarball works correctly.
+tests_win32_test_LDADD = src/libsndfile.la
+
+tests_win32_ordinal_test_SOURCES = tests/win32_ordinal_test.c tests/utils.c tests/utils.h
+tests_win32_ordinal_test_LDADD = src/libsndfile.la
+
+tests_external_libs_test_SOURCES = tests/external_libs_test.c tests/utils.c tests/utils.h
+tests_external_libs_test_LDADD = src/libsndfile.la
+
+tests_format_check_test_SOURCES = tests/format_check_test.c tests/utils.c tests/utils.h
+tests_format_check_test_LDADD = src/libsndfile.la
+
+tests_channel_test_SOURCES = tests/channel_test.c tests/utils.c tests/utils.h
+tests_channel_test_LDADD = src/libsndfile.la
+
+tests_long_read_write_test_SOURCES = tests/long_read_write_test.c tests/utils.c tests/utils.h tests/dft_cmp.h
+tests_long_read_write_test_LDADD = src/libsndfile.la
+
+tests_cpp_test_SOURCES = tests/cpp_test.cc tests/utils.c tests/utils.h
+tests_cpp_test_LDADD = src/libsndfile.la
+
+tests_checksum_test_SOURCES = tests/checksum_test.c tests/utils.c tests/utils.h
+tests_checksum_test_LDADD = src/libsndfile.la
+
+# Lite remove start
+tests_dwvw_test_SOURCES = tests/dwvw_test.c tests/utils.c tests/utils.h
+tests_dwvw_test_LDADD = src/libsndfile.la
+
+tests_floating_point_test_SOURCES = tests/utils.c tests/utils.h tests/dft_cmp.c tests/dft_cmp.h tests/floating_point_test.c
+tests_floating_point_test_LDADD = src/libsndfile.la
+
+tests_peak_chunk_test_SOURCES = tests/peak_chunk_test.c tests/utils.c tests/utils.h
+tests_peak_chunk_test_LDADD = src/libsndfile.la
+
+tests_scale_clip_test_SOURCES = tests/scale_clip_test.c tests/utils.c tests/utils.h
+tests_scale_clip_test_LDADD = src/libsndfile.la
+# Lite remove end
+
+#===============================================================================
+# Autogen generated sources.
+# Coerce the multiple inputs -> multiple outputs problem
+# into suffix rules by "linearising" the dependency graph.
+# Yes, this sucks, but GNU make patterns aren't portable,
+# see also https://github.com/libsndfile/libsndfile/issues/369
+
+SUFFIXES = .tpl .def
+
+.tpl.def:
+       touch $@
+
+# unconditionally running touch on the .def
+# files is necessary to keep all timestamps
+# consistent, in order to prevent stale files
+# from calling autogen in tarball releases.
+.def.c:
+       $(MAKE) $(AM_MAKEFLAGS) $<
+       cd $(top_srcdir)/$(@D) && autogen --writable $(<F)
+
+# recommended Automake way for multi-output targets:
+# https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html
+tests/utils.h : tests/utils.c
+       @if test -f $@; then :; else \
+         cd $(top_srcdir) && \
+         rm -f tests/utils.c && \
+         $(MAKE) $(AM_MAKEFLAGS) tests/utils.c; \
+       fi
+
+########
+# man/ #
+########
+
+if FULL_SUITE
+dist_man_MANS = man/sndfile-info.1 man/sndfile-play.1 man/sndfile-convert.1 man/sndfile-cmp.1 \
+       man/sndfile-metadata-get.1 man/sndfile-metadata-set.1 man/sndfile-concat.1 \
+       man/sndfile-interleave.1 man/sndfile-deinterleave.1 man/sndfile-salvage.1
+
+# Same manpage for both programs.
+man/sndfile-metadata-set.1: man/sndfile-metadata-get.1
+       -rm -f $@
+       cd $(top_srcdir)/man && $(LN_S) sndfile-metadata-get.1 sndfile-metadata-set.1
+
+man/sndfile-deinterleave.1: man/sndfile-interleave.1
+       -rm -f $@
+       cd $(top_srcdir)/man && $(LN_S) sndfile-interleave.1 sndfile-deinterleave.1
+
+############
+# ossfuzz/ #
+############
+
+if USE_OSSFUZZ_FLAG
+FUZZ_FLAG = $(LIB_FUZZING_ENGINE)
+FUZZ_LDADD =
+else
+if USE_OSSFUZZ_STATIC
+FUZZ_LDADD = $(LIB_FUZZING_ENGINE)
+FUZZ_FLAG =
+else
+FUZZ_LDADD = libstandaloneengine.la
+FUZZ_FLAG =
+endif
+endif
+
+if USE_OSSFUZZERS
+noinst_PROGRAMS += \
+       ossfuzz/sndfile_fuzzer
+
+noinst_LTLIBRARIES += \
+       ossfuzz/libstandaloneengine.la
+endif
+
+ossfuzz_sndfile_fuzzer_SOURCES = ossfuzz/sndfile_fuzzer.cc
+ossfuzz_sndfile_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
+ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
+ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
+
+ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h
+ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS)
+
+#############
+# programs/ #
+#############
+
+bin_PROGRAMS = programs/sndfile-info programs/sndfile-play programs/sndfile-convert programs/sndfile-cmp \
+       programs/sndfile-metadata-set programs/sndfile-metadata-get programs/sndfile-interleave \
+       programs/sndfile-deinterleave programs/sndfile-concat programs/sndfile-salvage
+endif
+
+# required by test-sndfile-metadata-set.py
+check_PROGRAMS += programs/sndfile-metadata-set programs/sndfile-metadata-get
+
+EXTRA_DIST += programs/test-sndfile-metadata-set.py
+
+programs_sndfile_info_SOURCES = programs/sndfile-info.c programs/common.c programs/common.h
+programs_sndfile_info_LDADD = src/libsndfile.la
+
+programs_sndfile_play_SOURCES = programs/sndfile-play.c programs/common.c programs/common.h
+programs_sndfile_play_LDADD = src/libsndfile.la $(OS_SPECIFIC_LINKS) $(ALSA_LIBS) $(SNDIO_LIBS)
+
+programs_sndfile_convert_SOURCES = programs/sndfile-convert.c programs/common.c programs/common.h
+programs_sndfile_convert_LDADD = src/libsndfile.la
+
+programs_sndfile_cmp_SOURCES = programs/sndfile-cmp.c programs/common.c programs/common.h
+programs_sndfile_cmp_LDADD = src/libsndfile.la
+
+programs_sndfile_metadata_set_SOURCES = programs/sndfile-metadata-set.c programs/common.c programs/common.h
+programs_sndfile_metadata_set_LDADD = src/libsndfile.la
+
+programs_sndfile_metadata_get_SOURCES = programs/sndfile-metadata-get.c programs/common.c programs/common.h
+programs_sndfile_metadata_get_LDADD = src/libsndfile.la
+
+programs_sndfile_interleave_SOURCES = programs/sndfile-interleave.c programs/common.c programs/common.h
+programs_sndfile_interleave_LDADD = src/libsndfile.la
+
+programs_sndfile_deinterleave_SOURCES = programs/sndfile-deinterleave.c programs/common.c programs/common.h
+programs_sndfile_deinterleave_LDADD = src/libsndfile.la
+
+programs_sndfile_concat_SOURCES = programs/sndfile-concat.c programs/common.c programs/common.h
+programs_sndfile_concat_LDADD = src/libsndfile.la
+
+programs_sndfile_salvage_SOURCES = programs/sndfile-salvage.c programs/common.c programs/common.h
+programs_sndfile_salvage_LDADD = src/libsndfile.la
+
+############
+# regtest/ #
+############
+
+if HAVE_SQLITE3
+check_PROGRAMS += regtest/sndfile-regtest
+endif
 
+regtest_sndfile_regtest_SOURCES = regtest/regtest.h regtest/sndfile-regtest.c regtest/database.c regtest/checksum.c
+regtest_sndfile_CPPFLAGS = -I$(top_srcdir)/src $(SQLITE3_CFLAGS) $(OS_SPECIFIC_CFLAGS)
+regtest_sndfile_regtest_LDADD = src/libsndfile.la $(SQLITE3_LIBS)
 
+################
+# test-tarball #
+################
 test-tarball : Scripts/build-test-tarball.mk
-       (cd src ; $(MAKE) all libsndfile.la checkprograms)
-       (cd tests ; $(MAKE) all checkprograms)
+       $(MAKE) $(bin_PROGRAMS) $(check_PROGRAMS)
        $(MAKE) -f Scripts/build-test-tarball.mk
diff --git a/NEWS b/NEWS
index d8f549f..9739aed 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,107 @@
+Version 1.0.31 (2021-01-24)
+
+  * The releaser of libsndfile starting from this version is the libsndfile team
+    member @SoapGentoo, see AUTHORS for details.
+  * Implement fast SSE2 optimized psf_lrintf() and psf_lrintf() functions to
+    improve perfomance when libsndfile is built using Visual C++ (especially)
+    and other compilers on x86 and AMD64 platforms. See also description of
+    ENABLE_SSE2 CMake option in README.md.
+  * Documentation:
+    * Move site to new URL: http://libsndfile.github.io/libsndfile/
+    * Convert documentation pages from HTML to Markdown
+    * Use GitHub's Jekyll static site generator to generate static HTML pages
+      for site
+    * Fix api.md table error, thanks to @zodf0055980
+    * Other docuemntation fixes and updates
+  * Change CMake's project name from sndfile to libsndfile as it should be.
+  * Change behaviour of ENABLE_STATIC_RUNTIME option. In short:
+    * You can use ENABLE_STATIC_RUNTIME for CMake >= 3.15 without error.
+    * You can use your our method to set MSVC runtime library flags if none of
+      ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY were set.
+    Advanced information:
+    * If this option is defined (set to ON or OFF), set CMP0091 policy to OLD
+      (we handle MSVC runtime library flags using compiler flags), set
+      corresponding compiler flags for user.
+    * NEW: If this option is not defined, set CMP0091 policy to OLD (we handle
+      MSVC runtime library flags using compiler flags), don't touch compiler
+      options, allow user to set it manually.
+    * NEW: If new CMake option CMAKE_MSVC_RUNTIME_LIBRARY is set, change
+      CMP0091 policy to NEW (we handle MSVC runtime library flags using that
+      option), don't touch compiler flags.
+    * NEW: If both ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY are set,
+      terminate configuration with fatal error.
+    * For MinGW toolchain this option is experimental. If you enabled it and
+      then disabled again, you need to clear CMake cache (delete
+      CMakeCache.txt).
+  * Make CMake clip test faster.
+  * Fix CMake bug with sndio library dependency, thanks to @drhenault.
+  * Fix memory leak in wav_read_smpl_chunk() function, credit to OSS-Fuzz.
+  * Fix aiff_read_header() memory leak(), credit to OSS-Fuzz.
+  * Fix leak in wav_read_header(), credit to OSS-Fuzz.
+  * Fix leak in wavlike_read_cart_chunk(), credit to OSS-Fuzz.
+  * Fix memory leak in wav_read_acid_chunk(), credit to OSS-Fuzz.
+  * Fix memory leak in aiff_read_basc_chunk(), credit to OSS-Fuzz.
+  * Fix memory leak in wavlike_read_peak_chunk(), credit to OSS-Fuzz.
+  * Fix memory leak in aiff_read_header(), credit to OSS-Fuzz.
+  * Fix use of uninitialized value in exif_subchunk_parse(), credit to OSS-Fuzz.
+  * Fix use of uninitialized value in endswap_int64_t_array(), credit to
+    OSS-Fuzz.
+  * Fix up the fuzzer so that it can't under or overseek,
+    thanks to Max Dymond <cmeister2@gmail.com>.
+  * Fix Autotools configure on macOS, thanks to @tmcguire and @nwh.
+  * Exclude repository-configuration from git-archive, thanks to @umlaeute.
+  * Use version-script when compiling with clang on Unix with Autotools, thanks
+    to @tstellar.
+  * Improve handling of SMPL chunks in WAV files, thanks to @zodf0055980.
+
+Version 1.0.30 (2020-09-18)
+
+  * Fix critical CMake bug with broken ABI of shared libsndfile library.
+  * CMake build system considered to be stable.
+  * Move sndfile.h.in from src/ to include/ directory. To avoid problems,
+    delete old generated sndfile.h from $(top_builddir)/src.
+  * Huge documentation update.
+  * Fix opus test failures on BE platforms, thanks to
+    Arthur Taylor <art@ified.ca>.
+  * Fix bug when sf_open_fd() function sometimes leaves filehandle open, even
+    if `close_desc` parameter is TRUE, thanks to @umläute.
+  * Fix infinite loops on some pathological SD2 files, thanks to
+    Jeremy Friesner <jaf@meyersound.com>.
+  * Switch to GitHub Actions for continuous integration.
+  * Add OSS-Fuzz tests to GitHub Actions workflow, thanks to
+    Max Dymond <cmeister2@gmail.com>.
+  * Fix memory leak in wavlike_read_bext_chunk() function, credit to OSS-Fuzz.
+  * Fix undefined behavior in avr-read_header() function, credit to OSS-Fuzz.
+  * Add INSTALL_PKGCONFIG_MODULE CMake option to control sndfile.pc file
+    installation, see README.md for details.
+  * Add INSTALL_MANPAGES CMake option, see README.md for details.
+  * Fix ENABLE_COMPATIBLE_LIBSNDFILE_NAME CMake option, now it works on MinGW
+    platform too.
+  * Fix ENABLE_CPACK CMake option, see README.md for details.
+  * Fix ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY behavior, see
+    README.md for details.
+  * Fix CMake man pages installation bug when sndfile-deinterleave.1 and
+    sndfile-metadata-set.1 were not installed.
+  * Fix sndfile-regtest paths handling on Windows platform, thanks to
+    Gisle Vanem <gvanem@yahoo.no>.
+
+Version 1.0.29 (2020-08-15)
+  * Add support for Opus files.
+  * Autotool build system improvements.
+  * CMake build system improvements.
+  * Fixes for: CVE-2017-12562, CVE-2017-17456, CVE-2017-17457, CVE-2018-19661,
+    CVE-2018-19662, CVE-2018-19758 and CVE-2019-3832.
+  * Add BWF v2 loudness parameters.
+  * Wave64: Permit and skip arbitrary chunks prior to the data chunk.
+  * Fix ASAN crash in wavlike_ima_seek().
+  * Fix IMA-ADPCM encoding for AIFF files.
+  * sndfile-convert: Handle gsm, vox and opus extensions the same way.
+  * Add SFC_SET_OGG_PAGE_LATENCY_MS command to get Ogg page latency for Ogg Opus
+    files.
+  * Fix parsing of some SD2 files.
+  * Documentation updates.
+  * Minor bug fixes and improvements.
+
 Version 1.0.28 (2017-04-02)
   * Fix buffer overruns in FLAC and ID3 handling code.
   * Move to variable length header storage.
diff --git a/README b/README
index 4718e58..93b4b29 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is libsndfile, 1.0.28
+This is libsndfile, 1.0.29
 
 libsndfile is a library of C routines for reading and writing
 files containing sampled audio data.
@@ -35,9 +35,12 @@ If you really do need to compile from source it should be as easy as:
                make
                make install
 
-Since libsndfile optionally links against libFLAC, libogg and libvorbis, you
-will need to install appropriate versions of these libraries before running
-configure as above.
+Since libsndfile optionally links against libFLAC, libogg, libvorbis and
+libopus, you will need to install appropriate versions of these libraries
+before running configure as above.
+
+You can use CMake now to build under Linux, also under Windows and MacOS, see
+README.md for details. CMake toolchain is usable, but still exterimental.
 
 
 UNIX
@@ -47,11 +50,13 @@ Compile as for Linux.
 
 Win32/Win64
 -----------
-The default Windows compilers are nowhere near compliant with the 1999 ISO
-C Standard and hence not able to compile libsndfile.
 
-Please use the libsndfile binaries available on the libsndfile web site.
+Official Windows binaries are compiled with Autotools and MinGW, but you can use
+CMake to generate solution for Visual Studio. Details are described in
+README.md.
 
+It is still recommended to use the libsndfile binaries available on the
+libsndfile web site.
 
 MacOSX
 ------
@@ -64,8 +69,8 @@ CONTACTS
 libsndfile was written by Erik de Castro Lopo (erikd AT mega-nerd DOT com).
 The libsndfile home page is at :
 
-       http://www.mega-nerd.com/libsndfile/
+       http://libsndfile.github.io/libsndfile/
 
 Bugs and support questions can be raised at :
 
-       https://github.com/erikd/libsndfile/
+       https://github.com/libsndfile/libsndfile/issues
index 569df34..c12bc1a 100644 (file)
--- a/README.md
+++ b/README.md
 # libsndfile
 
-[![Build Status](https://secure.travis-ci.org/erikd/libsndfile.svg?branch=master)](http://travis-ci.org/erikd/libsndfile)
+![C/C++ CI](https://github.com/libsndfile/libsndfile/workflows/C/C++%20CI/badge.svg)
 
 libsndfile is a C library for reading and writing files containing sampled audio
 data.
 
+## Authors
+
+The libsndfile project was originally developed and maintained by
+Erik de Castro Lopo <erikd@mega-nerd.com> aka @erikd. The project was developed
+on Github at <https://github.com/erikd/libsndfile>.
+
+After the release of version 1.0.30, @erikd transferred the project to
+[the libsndfile team](https://github.com/libsndfile), see [AUTHORS](AUTHORS)
+for details.
+
 ## Hacking
 
 The canonical source code repository for libsndfile is at
-[https://github.com/erikd/libsndfile/][github].
+[http://libsndfile.github.io/libsndfile/][github].
 
 You can grab the source code using:
 
-    $ git clone git://github.com/erikd/libsndfile.git
+    git clone https://github.com/libsndfile/libsndfile.git
 
 For building for Android see [BuildingForAndroid][BuildingForAndroid].
 
-There are currently two build systems; the official GNU autotool based one and
-a more limited and experimental CMake based build system. Use of the CMake build
-system is documented below.
+There are currently two build systems: the traditional GNU autotool based one and
+modern CMake based build system. Use of the CMake build system is documented
+below.
 
 Setting up a build environment for libsndfile on Debian or Ubuntu is as simple as:
-```
-sudo apt install autoconf autogen automake build-essential libasound2-dev \
-    libflac-dev libogg-dev libtool libvorbis-dev pkg-config python
-````
+
+    sudo apt install autoconf autogen automake build-essential libasound2-dev \
+      libflac-dev libogg-dev libtool libvorbis-dev libopus-dev pkg-config python
+
 For other Linux distributions or any of the *BSDs, the setup should be similar
 although the package install tools and package names may be slightly different.
 
 Similarly on Mac OS X, assuming [brew] is already installed:
-```
-brew install autoconf autogen automake flac libogg libtool libvorbis pkg-config
-```
+
+    brew install autoconf autogen automake flac libogg libtool libvorbis opus pkg-config
+
 Once the build environment has been set up, building and testing libsndfile is
 as simple as:
 
-    ./autogen.sh
-    ./configure --enable-werror
-    make
-    make check
+    ./autogen.sh
+    ./configure --enable-werror
+    make
+    make check
 
+## The CMake build system
 
-## The CMake build system.
+Although Autotools is the primary and recommended build toolchain, CMake meta
+build generator is also available. The build process with CMake takes
+place in two stages. First, standard build files are created from configuration
+scripts. Then the platform's native build tools are used for the actual
+building. CMake can produce Microsoft Visual Studio project and solution files,
+Unix Makefiles, Xcode projects and [many more](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
 
-The CMake build system is still experimental and probably only works on linux
-because it still relies on GNU autotools for bootstrapping. Using it as simple
-as:
+Some IDE support CMake natively or with plugins, check you IDE documentation
+ for details.
 
-    $ Scripts/cmake-build.sh
+### Requirements
 
-I would be happy to accept patches to make the CMake build system more portable.
+1. C99-compliant compiler toolchain (tested with GCC, Clang and Visual
+   Studio 2015)
+2. CMake 3.1.3 or newer
 
+There are some recommended packages to enable all features of libsndfile:
 
-## Submitting Patches.
+1. Ogg, Vorbis and FLAC libraries and headers to enable these formats support
+2. ALSA development package under Linux to build sndfile-play utility
+3. Sndio development package under BSD to build sndfile-play utility
 
-See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
+### Building from command line
+
+CMake can handle out-of-place builds, enabling several builds from
+the same source tree, and cross-compilation. The ability to build a directory
+tree outside the source tree is a key feature, ensuring that if a build
+directory is removed, the source files remain unaffected.
+
+    mkdir CMakeBuild
+    cd CMakeBuild
+
+Then run `cmake` command with directory where CMakeLists.txt script is located
+as argument (relative paths are supported):
+
+    cmake ..
+
+This command will configure and write build script or solution to CMakeBuild
+directory. CMake is smart enough to create Unix makefiles under Linux or Visual
+Studio solution if you have Visual Studio installed, but you can configure
+[generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
+with `-G` command line parameter:
+
+    cmake .. -G"Unix Makefiles"
+
+The build procedure depends on the selected generator. With "Unix Makefiles" you
+can type:
+
+    make & make install
+
+With "Visual Studio" and some other generators you can open solution or project
+from `CMakeBuild` directory and build using IDE.
+
+Finally, you can use unified command:
+
+    cmake --build .
+
+CMake also provides Qt-based cross platform GUI, cmake-gui. Using it is trivial
+and does not require detailed explanations.
+
+### Configuring CMake
+
+You can pass additional options with `/D<parameter>=<value>` when you run
+`cmake` command. Some useful system options:
+
+* `CMAKE_C_FLAGS` - additional C compiler flags
+* `CMAKE_BUILD_TYPE` - configuration type, `DEBUG`, `RELEASE`, `RELWITHDEBINFO`
+  or `MINSIZEREL`. `DEBUG` is default
+* `CMAKE_INSTALL_PREFIX` - build install location, the same as `--prefix` option
+  of `configure` script
+
+ Useful libsndfile options:
+
+* `BUILD_SHARED_LIBS` - build shared library (DLL under Windows) when `ON`,
+  build static library othervise. This option is `OFF` by default.
+* `BUILD_PROGRAMS` - build libsndfile's utilities from `programs/` directory,
+  `ON` by default.
+* `BUILD_EXAMPLES` - build examples, `ON` by default.
+* `BUILD_TESTING` - build tests. Then you can run tests with `ctest` command,
+  `ON` by default. Setting `BUILD_SHARED_LIBS` to `ON` disables this option.
+* `ENABLE_EXTERNAL_LIBS` - enable Ogg, Vorbis, FLAC and Opus support. This
+  option is available and set to `ON` if all dependency libraries were found.
+* `ENABLE_CPU_CLIP` - enable tricky cpu specific clipper. Enabled and set to
+  `ON` when CPU clips negative\positive. Don't touch it if you are not sure
+* `ENABLE_BOW_DOCS` - enable black-on-white documentation theme, `OFF` by
+  default.
+* `ENABLE_EXPERIMENTAL` - enable experimental code. Don't use it if you are
+  not sure. This option is `OFF` by default.
+* `ENABLE_CPACK` - enable [CPack](https://cmake.org/cmake/help/latest/module/CPack.html) support.
+  This option is `ON` by default.
+* `ENABLE_PACKAGE_CONFIG` - generate and install [package config file](https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#config-file-packages).
+* `INSTALL_PKGCONFIG_MODULE` - generate and install [pkg-config module](https://people.freedesktop.org/~dbn/pkg-config-guide.html).
+* `INSTALL_MANPAGES` - install [man pages](https://en.wikipedia.org/wiki/Man_page) for programs. This option is `ON` by  default
+* `ENABLE_STATIC_RUNTIME` - enable static runtime on Windows platform (MSVC and
+  MinGW), `OFF` by default.
+
+  **Note**: For MSVC compiler this option is deprecated for CMake >= 3.15, see
+  policy [CMP0091](https://cmake.org/cmake/help/latest/policy/CMP0091.html).
+  Use `CMAKE_MSVC_RUNTIME_LIBRARY` option instead.
+
+  **Note**: For MinGW toolchain this option is experimental. If you enabled it
+  and then disabled again, you need to clear CMake cache (delete CMakeCache.txt).
+* `ENABLE_COMPATIBLE_LIBSNDFILE_NAME` - set DLL name to `libsndfile-1.dll`
+  (canonical name) on Windows platform, `sndfile.dll` otherwise, `OFF` by
+  default. Library name can be different depending on platform. The well known
+  DLL name on Windows platform is `libsndfile-1.dll`, because the only way to
+  build Windows library before was MinGW toolchain with Autotools. This name
+  is native for MinGW ecosystem, Autotools constructs it using MinGW platform
+  rules from `sndfile` target. But when you build with CMake using native
+  Windows compiler, the name is `sndfile.dll`. This is name for native Windows
+  platform, because Windows has no library naming rules. It is preffered
+  because you can search library using package manager or CMake's
+  `find_library` command on any platform using the same `sndfile` name.
+
+* `ENABLE_SSE2` - add compiler flag to enable SSE2 if required, `ON` by default.
+
+  This option is for X86 and GCC compatible compilers configurations only.
+
+  If you compile for other SIMD set, e.g. AVX2, you may want to set
+  `ENABLE_SSE2` to `OFF`.
+
+  **Note**: This option is not active for X64 configuration, because SSE2 is
+  always available in this mode and all optimizations are enabled by default.
+
+Deprecated options:
+
+* `DISABLE_EXTERNAL_LIBS` - disable Ogg, Vorbis and FLAC support. Replaced by
+  `ENABLE_EXTERNAL_LIBS`
+* `DISABLE_CPU_CLIP` - disable tricky cpu specific clipper. Replaced by
+  `ENABLE_CPU_CLIP`
+* `BUILD_STATIC_LIBS` - build static library. Use `BUILD_SHARED_LIBS` instead
+
+### Linking from CMake projects
+
+First you need to add `FindOgg.cmake`, `FindVorbis.cmake`, `FindFLAC.cmake` and
+`FindOpus.cmake` files to some directory inside your CMake project (usually
+`cmake`) and add it to `CMAKE_MODULE_PATH`:
+
+    project(SomeApplication)
+    
+    list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
 
+Now you can search `libsndfile` library from your `CMakeLists.txt`
+ with this command:
 
+    find_package(SndFile)
 
+`SndFile_FOUND` is set to `ON` when library is found.
 
+If `libsndfile` dependency is critical, you can add `REQUIRED` to
+ `find_package`:
+
+    find_package(SndFile REQUIRED)
+
+With with option `find_package` will terminate configuration process
+ if `libsndfile` is not found.
+
+You can also add version check:
+
+    find_package(SndFile 1.0.29)
+
+`find_package` will report error, if `libsndfile` version is < 1.0.29.
+
+You can combine `REQUIRED` and version if you need.
+
+To link `libsndfile` library use:
+
+    target_link_libraries(my_application PRIVATE SndFile::sndfile)
+
+### Notes for Windows users
+
+#### System CRT library
+
+First advice about Visual Studio [system CRT libraries](https://docs.microsoft.com/en-us/cpp/c-runtime-library/c-run-time-library-reference?view=vs-2019),
+it is system code linked as static or dynamic library to every C application.
+
+You can find related option in Visual Studio project properties:
+
+    C/C++ -> Code Generation -> Runtime Library
+
+Dynamic version of system CRT library is defaut and it means that end user needs
+to have the same runtime library installed on his system. Most likely it is so,
+but if it is not, the user will see this error message using libsndfile DLL:
+
+    "The program can't start because <crt-dll-name>.dll is missing from your computer. Try reinstalling the program to fix this problem. "
+
+To avoid this, you may want to enable static CRT library linking. In this case
+the size of your DLL will increase slightly the size will increase slightly, but
+you can redistribute the libsndfile DLL without having to install the correct
+version of the system CRT library.
+
+CMake project will use dynamic system CRT libraries by default, just like
+Visual Studio does. But you can change it using `ENABLE_STATIC_RUNTIME` or
+`CMAKE_MSVC_RUNTIME_LIBRARY` options.
+
+**Note**: You cannot use both options at the same time, it will lead to a
+configuration error.
+
+If you have CMake >= 3.15 you should use
+[`CMAKE_MSVC_RUNTIME_LIBRARY`](https://cmake.org/cmake/help/v3.15/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html) option.
+
+This will enable static linking:
+
+    cmake .. -D"MultiThreaded$<$<CONFIG:Debug>:Debug>"
+
+You can use libsndfile `ENABLE_STATIC_RUNTIME` option to to control CRT library
+linking for CMake project: `OFF` or unset (default) for dynamic, and `ON` for
+static linking:
+
+    cmake .. -DENABLE_STATIC_RUNTIME=ON
+
+**Note**: This option is deprecated and may be removed in far future because we
+have standard option `CMAKE_MSVC_RUNTIME_LIBRARY` now.
+
+#### Using Vcpkg package manager
+
+Second advice is about Ogg, Vorbis FLAC and Opus support. Searching external
+libraries under Windows is a little bit tricky. The best way is to use
+[Vcpkg](https://github.com/Microsoft/vcpkg). You need to install static libogg,
+libvorbis, libflac and libopus libraries:
+
+    vcpkg install libogg:x64-windows-static libvorbis:x64-windows-static
+    libflac:x64-windows-static opus:x64-windows-static libogg:x86-windows-static
+    libvorbis:x86-windows-static libflac:x86-windows-static opus:x86-windows-static
+
+Then and add this parameter to cmake command line:
+
+    -DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake
+
+You also need to set `VCPKG_TARGET_TRIPLET` because you use static libraries:
+
+    -DVCPKG_TARGET_TRIPLET=x64-windows-static
+
+**Note**: Use must use the same CRT library for external libraries and the
+libsndfile library itself. For `*-static` triplets Vcpkg uses
+[static CRT](https://vcpkg.readthedocs.io/en/latest/users/triplets/).
+
+## Submitting Patches
+
+See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
 
 [brew]: http://brew.sh/
-[github]: https://github.com/erikd/libsndfile/
-[BuildingForAndroid]: https://github.com/erikd/libsndfile/blob/master/Building-for-Android.md
+[github]: http://libsndfile.github.io/libsndfile/
+[BuildingForAndroid]: https://github.com/libsndfile/libsndfile/blob/master/Building-for-Android.md
diff --git a/Scripts/asan-configure.sh b/Scripts/asan-configure.sh
new file mode 100755 (executable)
index 0000000..0ac43b9
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash -eu
+
+CFLAGS="-fsanitize=address -g" CXXFLAGS=${CFLAGS} ./configure
+
index 931edb6..5dac9d9 100644 (file)
@@ -24,15 +24,12 @@ TARBALL = $(TESTNAME).tar.gz
 # Find the test programs by grepping the script for the programs it executes.
 testprogs := $(shell grep '^\./' tests/test_wrapper.sh | sed -e "s|./||" -e "s/ .*//" | sort | uniq)
 # Also add the programs not found by the above.
-testprogs += sfversion@EXEEXT@ stdin_test@EXEEXT@ stdout_test@EXEEXT@ cpp_test@EXEEXT@ win32_test@EXEEXT@
-
-# Find the single test program in src/ .
-srcprogs := $(shell if test -x src/.libs/test_main$(EXEEXT) ; then echo "src/.libs/test_main$(EXEEXT)" ; else echo "src/test_main$(EXEEXT)" ; fi)
+testprogs += tests/sfversion$(EXEEXT) tests/stdin_test$(EXEEXT) tests/stdout_test$(EXEEXT) \
+                               tests/cpp_test$(EXEEXT) tests/win32_test$(EXEEXT)
 
 libfiles := $(shell if test ! -z $(EXEEXT) ; then echo "src/libsndfile-1.def src/.libs/libsndfile-1.dll" ; elif test -f $(LIBRARY) ; then echo $(LIBRARY) ; fi  ; fi)
 
-testbins := $(addprefix $(TEST_BINDIR),$(subst @EXEEXT@,$(EXEEXT),$(testprogs))) $(libfiles) $(srcprogs)
-
+testbins := $(testprogs) $(libfiles)
 
 all : $(TARBALL)
 
@@ -49,13 +46,16 @@ $(TARBALL) : $(TESTNAME)/test_wrapper.sh
        @echo "Created : $(TARBALL)"
        @echo
 
-$(TESTNAME)/test_wrapper.sh : $(testbins) tests/test_wrapper.sh tests/pedantic-header-test.sh
+$(TESTNAME)/test_wrapper.sh : tests/test_wrapper.sh tests/pedantic-header-test.sh
        rm -rf $(TESTNAME)
        mkdir -p $(TESTNAME)/tests/
+       echo
+       echo $(testbins)
+       echo
        cp $(testbins) $(TESTNAME)/tests/
        cp tests/test_wrapper.sh $(TESTNAME)/
        cp tests/pedantic-header-test.sh $(TESTNAME)/tests/
        chmod u+x $@
 
 tests/test_wrapper.sh : tests/test_wrapper.sh.in
-       (cd tests/ ; make $@)
+       make $@
index e2d09f9..10260f3 100755 (executable)
@@ -1,9 +1,9 @@
-#!/bin/bash -e
+#!/bin/bash -eu
 
-rm -rf CMakeCache.txt CMakeFiles/
+rm -rf CMakeCache.txt CMakeFiles/ _Build
 
-cmake -DWerror=on -Werror=dev -Werror=deprecated .
-
-make clean
-make
-make check
+mkdir _Build
+cd _Build
+cmake ..
+cmake --build .
+ctest -V
index 94a969c..8e1df27 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/python -tt
 #
-# Copyright (C) 2005-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
+# Copyright (C) 2005-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 #
 # Released under the 2 clause BSD license.
 
@@ -121,7 +121,7 @@ class CStyleChecker:
                        , ( re.compile ("[ \t]+$"),     "contains trailing whitespace" )
 
                        , ( re.compile (",[^\s\n]"),            "missing space after comma" )
-                       , ( re.compile (";[a-zA-Z0-9]"),        "missing space after semi-colon" )
+                       , ( re.compile (";[^\s]"),      "missing space after semi-colon" )
                        , ( re.compile ("=[^\s\"'=]"),          "missing space after assignment" )
 
                        # Open and close parenthesis.
@@ -143,6 +143,16 @@ class CStyleChecker:
 
                        # Parens around single argument to return.
                        , ( re.compile ("\s+return\s+\([a-zA-Z0-9_]+\)\s+;"),   "parens around return value" )
+
+                       # Parens around single case argument.
+                       , ( re.compile ("\s+case\s+\([a-zA-Z0-9_]+\)\s+:"),     "parens around single case argument" )
+
+                       # Open curly at end of line.
+                       , ( re.compile ("\)\s*{\s*$"),  "open curly brace at end of line" )
+
+                       # Pre and post increment/decrment.
+                       , ( re.compile ("[^\(\[][+-]{2}[a-zA-Z0-9_]"),       "space after pre increment/decrement" )
+                       , ( re.compile ("[a-zA-Z0-9_][+-]{2}[^\)\,]]"),       "space before post increment/decrement" )
                        ]
 
        def get_error_count (self):
index f967f3b..dc70e73 100755 (executable)
@@ -1,5 +1,4 @@
 #!/bin/sh
-#
 
 if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
        against=HEAD
@@ -8,13 +7,6 @@ else
        against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
        fi
 
-SED="sed -r "  # BSD sed
-if test $(sed --version | grep -c GNU) -gt 0 ; then
-       SED="sed -E "
-       fi
-
-files=$(git diff-index --name-status --cached HEAD | grep -v ^D | ${SED} "s/^[A-Z]+[A-Z0-9]*[ \t]+/ /")
-
 # Redirect output to stderr.
 exec 1>&2
 
@@ -36,6 +28,14 @@ if test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C t
 #-------------------------------------------------------------------------------
 # Check the formatting of all C files.
 
+# http://man.openbsd.org/sed#r
+# http://man.openbsd.org/sed#E
+# http://netbsd.gw.com/cgi-bin/man-cgi?sed++NetBSD-current
+# https://github.com/freebsd/freebsd/blob/master/usr.bin/sed/main.c
+# http://git.savannah.gnu.org/gitweb/?p=sed.git;a=blob;f=sed/sed.c
+# GNU has -r and -E (undocumented); MacOS has -E but not -r; Sunos has neither.
+files=$(git diff-index --name-status --cached HEAD | grep -v ^D | sed -E "s/^[A-Z]+[A-Z0-9]*[ \t]+/ /")
+
 cfiles=""
 for f in $files ; do
        if test `dirname $f` = "src/ALAC" ; then
index b185d58..a2c1969 100755 (executable)
@@ -1,16 +1,23 @@
 #!/usr/bin/make -f
 
+# If this is set to true (via the environment) then CRC checking will be
+# disabled in libogg giving fuzzers a better chance at finding something.
+disable_ogg_crc ?= false
+
 # Build libsndfile as a dynamic/shared library, but statically link to
-# libFLAC, libogg and libvorbis
+# libFLAC, libogg, libopus and libvorbis
+
+ogg_version = libogg-1.3.4
+ogg_sha256sum = c163bc12bc300c401b6aa35907ac682671ea376f13ae0969a220f7ddf71893fe
 
-ogg_version = libogg-1.3.2
-ogg_md5sum = 5c3a34309d8b98640827e5d0991a4015
+vorbis_version = libvorbis-1.3.7
+vorbis_sha256sum = b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b
 
-vorbis_version = libvorbis-1.3.5
-vorbis_md5sum = 28cb28097c07a735d6af56e598e1c90f
+flac_version = flac-1.3.3
+flac_sha256sum = 213e82bd716c9de6db2f98bcadbc4c24c7e2efe8c75939a1a84e28539c4e1748
 
-flac_version = flac-1.3.2
-flac_md5sum = 454f1bfa3f93cc708098d7890d0499bd
+opus_version = opus-1.3.1
+opus_sha256sum = 65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d
 
 #-------------------------------------------------------------------------------
 # Code follows.
@@ -18,13 +25,14 @@ flac_md5sum = 454f1bfa3f93cc708098d7890d0499bd
 ogg_tarball = $(ogg_version).tar.xz
 vorbis_tarball = $(vorbis_version).tar.xz
 flac_tarball = $(flac_version).tar.xz
+opus_tarball = $(opus_version).tar.gz
 
 download_url = http://downloads.xiph.org/releases/
 tarball_dir = Build/Tarballs
 stamp_dir = Build/Stamp
 
 build_dir = $(shell pwd)/Build
-config_options = --prefix=$(build_dir) --disable-shared
+config_options = --prefix=$(build_dir) --disable-shared --enable-option-checking
 
 pwd = $(shell pwd)
 
@@ -42,9 +50,9 @@ config : Build/Stamp/configure
 build : Build/Stamp/build
 
 clean :
-       rm -rf Build/flac-* Build/libogg-* Build/libvorbis-*
+       rm -rf Build/flac-* Build/libogg-* Build/libvorbis-* Build/opus-*
        rm -rf Build/bin Build/include Build/lib Build/share
-       rm -f Build/Stamp/install Build/Stamp/extract Build/Stamp/md5sum
+       rm -f Build/Stamp/install Build/Stamp/extract Build/Stamp/sha256sum Build/Stamp/build-ogg
 
 Build/Stamp/init :
        mkdir -p $(stamp_dir) $(tarball_dir)
@@ -62,25 +70,43 @@ Build/Tarballs/$(vorbis_tarball) : Build/Stamp/init
        (cd $(tarball_dir) && wget $(download_url)vorbis/$(vorbis_tarball) -O $(vorbis_tarball))
        touch $@
 
-Build/Stamp/tarballs : Build/Tarballs/$(flac_tarball) Build/Tarballs/$(ogg_tarball) Build/Tarballs/$(vorbis_tarball)
+Build/Tarballs/$(opus_tarball) : Build/Stamp/init
+       (cd $(tarball_dir) && wget https://archive.mozilla.org/pub/opus/$(opus_tarball) -O $(opus_tarball))
        touch $@
 
-Build/Stamp/md5sum : Build/Stamp/tarballs
-       test `md5sum $(tarball_dir)/$(ogg_tarball) | sed "s/ .*//"` = $(ogg_md5sum)
-       test `md5sum $(tarball_dir)/$(vorbis_tarball) | sed "s/ .*//"` = $(vorbis_md5sum)
-       test `md5sum $(tarball_dir)/$(flac_tarball) | sed "s/ .*//"` = $(flac_md5sum)
+Build/Stamp/tarballs : Build/Tarballs/$(flac_tarball) Build/Tarballs/$(ogg_tarball) Build/Tarballs/$(vorbis_tarball) Build/Tarballs/$(opus_tarball)
        touch $@
 
-Build/Stamp/extract : Build/Stamp/md5sum
-       (cd Build && tar xf Tarballs/$(ogg_tarball))
+Build/Stamp/sha256sum : Build/Stamp/tarballs
+       test `sha256sum $(tarball_dir)/$(ogg_tarball) | sed "s/ .*//"` = $(ogg_sha256sum)
+       test `sha256sum $(tarball_dir)/$(vorbis_tarball) | sed "s/ .*//"` = $(vorbis_sha256sum)
+       test `sha256sum $(tarball_dir)/$(flac_tarball) | sed "s/ .*//"` = $(flac_sha256sum)
+       test `sha256sum $(tarball_dir)/$(opus_tarball) | sed "s/ .*//"` = $(opus_sha256sum)
+       touch $@
+
+Build/Stamp/extract : Build/Stamp/sha256sum
+       # (cd Build && tar xf Tarballs/$(ogg_tarball))
        (cd Build && tar xf Tarballs/$(flac_tarball))
        (cd Build && tar xf Tarballs/$(vorbis_tarball))
+       (cd Build && tar xf Tarballs/$(opus_tarball))
        touch $@
 
-Build/Stamp/install-libs : Build/Stamp/extract
+Build/Stamp/build-ogg : Build/Stamp/sha256sum
+ifeq ($(disable_ogg_crc), true)
+       echo "Ogg/CRC enabled"
+       (cd Build && git clone https://github.com/xiph/ogg $(ogg_version))
+       (cd Build/$(ogg_version) && ./autogen.sh && CFLAGS=-fPIC ./configure $(config_options) --disable-crc && make all install)
+else
+       echo "Ogg/CRC disabled"
+       (cd Build && tar xf Tarballs/$(ogg_tarball))
        (cd Build/$(ogg_version) && CFLAGS=-fPIC ./configure $(config_options) && make all install)
+endif
+       touch $@
+
+Build/Stamp/install-libs : Build/Stamp/extract Build/Stamp/build-ogg
        (cd Build/$(vorbis_version) && CFLAGS=-fPIC ./configure $(config_options) && make all install)
        (cd Build/$(flac_version) && CFLAGS=-fPIC ./configure $(config_options) && make all install)
+       (cd Build/$(opus_version) && CFLAGS=-fPIC ./configure $(config_options) && make all install)
        touch $@
 
 configure : configure.ac
@@ -88,8 +114,8 @@ configure : configure.ac
 
 Build/Stamp/configure : Build/Stamp/install-libs configure
        PKG_CONFIG_LIBDIR=Build/lib/pkgconfig ./configure
-       sed -i 's#^EXTERNAL_XIPH_CFLAGS.*#EXTERNAL_XIPH_CFLAGS = -I$(pwd)/Build/include#' src/Makefile
-       sed -i 's#^EXTERNAL_XIPH_LIBS.*#EXTERNAL_XIPH_LIBS = -static $(pwd)/Build/lib/libFLAC.la $(pwd)/Build/lib/libogg.la $(pwd)/Build/lib/libvorbis.la $(pwd)/Build/lib/libvorbisenc.la -dynamic #' src/Makefile
+       sed -i 's#^EXTERNAL_XIPH_CFLAGS.*#EXTERNAL_XIPH_CFLAGS = -I$(pwd)/Build/include#' Makefile
+       sed -i 's#^EXTERNAL_XIPH_LIBS.*#EXTERNAL_XIPH_LIBS = -static $(pwd)/Build/lib/libFLAC.la $(pwd)/Build/lib/libvorbis.la $(pwd)/Build/lib/libvorbisenc.la $(pwd)/Build/lib/libopus.la $(pwd)/Build/lib/libogg.la -dynamic #' Makefile
        make clean
        touch $@
 
diff --git a/Win32/Makefile.am b/Win32/Makefile.am
deleted file mode 100644 (file)
index 4fe8efa..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-EXTRA_DIST = README-precompiled-dll.txt testprog.c
-
index 4f98f96..dbdb5de 100755 (executable)
@@ -4,8 +4,6 @@
 
 package="libsndfile"
 
-ACLOCAL_FLAGS="-I M4"
-
 olddir=`pwd`
 srcdir=`dirname $0`
 test -z "$srcdir" && srcdir=.
@@ -146,11 +144,6 @@ if test "$DIE" -eq 1; then
         exit 1
 fi
 
-if test ! -d Cfg ; then
-       echo "Creating 'Cfg' directory."
-       mkdir Cfg
-fi
-
 echo "Generating configuration files for $package, please wait ... "
 
 echo "  $ACLOCAL $ACLOCAL_FLAGS"
diff --git a/cmake/CMakeAutoGen.cmake b/cmake/CMakeAutoGen.cmake
new file mode 100644 (file)
index 0000000..f82dc13
--- /dev/null
@@ -0,0 +1,46 @@
+# CMake implementation of AutoGen
+# Copyright (C) 2017 Anonymous Maarten <anonymous.maarten@gmail.com>
+
+set(AUTOGEN_SCRIPT "${CMAKE_MODULE_PATH}/CMakeAutoGenScript.cmake")
+
+function(lsf_autogen DIR_REL NAME_WE)
+       set(EXTS ${ARGN})
+       set(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${DIR_REL}/${NAME_WE}.def")
+       set(OUTPUTS)
+       foreach(EXT ${EXTS})
+               list(APPEND OUTPUTS "${NAME_WE}.${EXT}")
+       endforeach()
+       add_autogen_target("${INPUT}" "${CMAKE_CURRENT_BINARY_DIR}/${DIR_REL}" ${OUTPUTS})
+endfunction()
+
+function(add_autogen_target INPUT OUTPUTDIR)
+       set(OUTPUTFILES "${ARGN}")
+
+       if (OUTPUTDIR)
+               set(PREFIX "${OUTPUTDIR}/")
+       else()
+               set(PREFIX "")
+       endif()
+
+       set(ARTIFACTS)
+       foreach(OUTPUTFILE ${OUTPUTFILES})
+               list(APPEND ARTIFACTS "${PREFIX}${OUTPUTFILE}")
+       endforeach()
+
+       set(EXTRA_ARGS)
+       if (AUTOGEN_DEBUG)
+               list(APPEND EXTRA_ARGS "-DDEBUG=1")
+       endif()
+       if (OUTPUTDIR)
+               list(APPEND EXTRA_ARGS "-DOUTPUTDIR=${OUTPUTDIR}")
+       endif()
+
+       add_custom_command(
+               OUTPUT ${ARTIFACTS}
+               COMMAND ${CMAKE_COMMAND} "-DDEFINITION=${INPUT}" ${EXTRA_ARGS} -P "${AUTOGEN_SCRIPT}"
+               MAIN_DEPENDENCY "${INPUT}"
+               DEPENDS "${AUTOGEN_SCRIPT}"
+               COMMENT "CMakeAutoGen: generating ${OUTPUTFILES}"
+               WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
+       )
+endfunction()
diff --git a/cmake/CMakeAutoGenScript.cmake b/cmake/CMakeAutoGenScript.cmake
new file mode 100644 (file)
index 0000000..ade53e1
--- /dev/null
@@ -0,0 +1,442 @@
+# CMake implementation of AutoGen
+# Copyright (C) 2017 Anonymous Maarten <anonymous.maarten@gmail.com>
+
+set(WS " \t\r\n")
+
+function(cutoff_first_occurrence TEXT OCCURRENCE RESULT)
+    string(FIND "${TEXT}" "${OCCURRENCE}" OCCURRENCE_INDEX)
+    if (OCCURRENCE_INDEX EQUAL -1)
+        set(${TEXT} "" PARENT_SCOPE)
+        return()
+    endif()
+
+    string(LENGTH "${OCCURRENCE}" OCCURRENCE_LENGTH)
+    math(EXPR CUTOFF_INDEX "${OCCURRENCE_INDEX}+${OCCURRENCE_LENGTH}")
+    string(SUBSTRING "${TEXT}" ${CUTOFF_INDEX} -1 TEXT_REMAINDER)
+    set(${RESULT} "${TEXT_REMAINDER}" PARENT_SCOPE)
+
+    endfunction()
+
+function(read_definition DEFINITION_FILENAME TEMPLATE_FILENAME DATA)
+    file(READ "${DEFINITION_FILENAME}" DEFINITION_CONTENTS)
+
+    string(REGEX MATCH "autogen definitions ([a-zA-Z\\._-]+);[${WS}]*" TEMPLATE_MATCH "${DEFINITION_CONTENTS}")
+    if (NOT TEMPLATE_MATCH)
+        message(FATAL_ERROR "${DEFINITION_FILENAME} doest not contain an AutoGen definition.")
+    endif()
+
+    get_filename_component(DEFINITION_DIR "${DEFINITION_FILENAME}" PATH)
+    set(${TEMPLATE_FILENAME} "${DEFINITION_DIR}/${CMAKE_MATCH_1}" PARENT_SCOPE)
+    if (DEBUG)
+        message("found: TEMPLATE_FILENAME=${CMAKE_MATCH_1}")
+    endif()
+
+    cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${TEMPLATE_MATCH}" DEFINITION_CONTENTS)
+
+    set(DEFINITION "")
+
+    while (1)
+        string(REGEX MATCH "([a-zA-Z_][a-zA-Z0-9_]*)[${WS}]*=[${WS}]*{[${WS}]*" GROUPSTART_MATCH "${DEFINITION_CONTENTS}")
+        if (NOT GROUPSTART_MATCH)
+            break()
+        endif()
+        set(GROUPNAME "${CMAKE_MATCH_1}")
+        cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${GROUPSTART_MATCH}" DEFINITION_CONTENTS)
+        if (DEBUG)
+            message("found: GROUPNAME=${GROUPNAME}")
+        endif()
+        set(NBKEYS 0)
+        set(GROUP_KEY_VALUES "")
+        while (1)
+            string(REGEX MATCH "^([a-zA-Z_][a-zA-Z0-9_]*)[${WS}]*=[${WS}]*(([\"']([${WS}a-zA-Z0-9_%\\\"<>\(\)\\.*+/?:,\\-]+)[\"'])|([a-zA-Z0-9_%\\]+))[${WS}]*;[${WS}]*" KEY_VALUE_MATCH "${DEFINITION_CONTENTS}")
+            if (NOT KEY_VALUE_MATCH)
+                break()
+            endif()
+            set(KEY "${CMAKE_MATCH_1}")
+            if ("${CMAKE_MATCH_4}" STREQUAL "")
+                set(VALUE "${CMAKE_MATCH_5}")
+            else()
+                string(REPLACE "\\\"" "\"" VALUE "${CMAKE_MATCH_4}")
+                #set(VALUE "${CMAKE_MATCH_4}")
+            endif()
+
+            if (DEBUG)
+                message("found: KEY=${KEY}, VALUE=${VALUE}")
+            endif()
+            math(EXPR NBKEYS "${NBKEYS}+1")
+            list(APPEND GROUP_KEY_VALUES "${KEY}" "${VALUE}")
+            cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${KEY_VALUE_MATCH}" DEFINITION_CONTENTS)
+        endwhile()
+        string(REGEX MATCH "^[${WS}]*}[${WS}]*;[${WS}]*" GROUPEND_MATCH "${DEFINITION_CONTENTS}")
+        if (NOT GROUPEND_MATCH)
+            message(FATAL_ERROR "Group ${GROUPNAME} did not finish.")
+        endif()
+        cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${GROUPEND_MATCH}" DEFINITION_CONTENTS)
+        list(APPEND DEFINITION "${GROUPNAME}" ${NBKEYS} ${GROUP_KEY_VALUES})
+    endwhile()
+    set(${DATA} "${DEFINITION}" PARENT_SCOPE)
+endfunction()
+
+function(match_autogen_group TEXT START POS0 POS1 MATCH FOUND)
+    string(SUBSTRING "${TEXT}" "${START}" -1 TEXT)
+    string(REGEX MATCH "\\[\\+[${WS}]*([ a-zA-Z0-9=_$%\\(\\)\"\\+\\-]+)[${WS}]*\\+\\]" MATCH_GROUP "${TEXT}")
+    if ("${MATCH_GROUP}" STREQUAL "")
+        set(${FOUND} 0 PARENT_SCOPE)
+        return()
+    endif()
+    string(FIND "${TEXT}" "${MATCH_GROUP}" START_TEXT)
+    math(EXPR POS0_var "${START}+${START_TEXT}")
+    string(LENGTH "${MATCH_GROUP}" MATCH_LENGTH)
+    math(EXPR POS1_var "${POS0_var}+${MATCH_LENGTH}")
+    set(${POS0} "${POS0_var}" PARENT_SCOPE)
+    set(${POS1} "${POS1_var}" PARENT_SCOPE)
+    set(${FOUND} 1 PARENT_SCOPE)
+    string(STRIP "${CMAKE_MATCH_1}" CONTENT)
+    set("${MATCH}" "${CONTENT}" PARENT_SCOPE)
+endfunction()
+
+function(append_output SUFFICES_FILENAMES TEXT POS0 POS1 FILTER)
+    math(EXPR POS_LENGTH "${POS1}-${POS0}")
+    string(LENGTH "${TEXT}" TEXT_LENGTH)
+    string(SUBSTRING "${TEXT}" "${POS0}" "${POS_LENGTH}" TEXT_APPEND)
+    if (DEBUG)
+        message("appending ${POS0}:${POS1}, length=${POS_LENGTH}")
+    endif()
+    append_output_text("${SUFFICES_FILENAMES}" "${TEXT_APPEND}" "${FILTER}")
+endfunction()
+
+function(append_output_text SUFFICES_FILENAMES TEXT_APPEND FILTER)
+    string(LENGTH "${TEXT_APPEND}" TEXT_LENGTH)
+    list(LENGTH SUFFICES_FILENAMES NB)
+    math(EXPR NB_END "${NB}-1")
+    foreach(INDEX RANGE 0 ${NB_END} 3)
+        math(EXPR INDEX_1 "${INDEX}+1")
+        math(EXPR INDEX_2 "${INDEX}+2")
+        list(GET SUFFICES_FILENAMES ${INDEX} SUFFIX)
+        list(GET SUFFICES_FILENAMES ${INDEX_1} FILENAME)
+        list(GET SUFFICES_FILENAMES ${INDEX_2} TEMPFILENAME)
+        set(WRITE_OK 1)
+        if (FILTER)
+            if (NOT "${SUFFIX}" STREQUAL "${FILTER}")
+                set(WRITE_OK 0)
+            endif()
+        endif()
+        if (WRITE_OK)
+            if (DEBUG)
+                message("Write: ${TEXT_LENGTH} characters to ${FILENAME}")
+            endif()
+            file(APPEND "${TEMPFILENAME}" "${TEXT_APPEND}")
+        endif()
+    endforeach()
+endfunction()
+
+function(output_finish SUFFICES_FILENAMES)
+    list(LENGTH SUFFICES_FILENAMES NB)
+    math(EXPR NB_END "${NB}-1")
+    foreach(INDEX RANGE 0 ${NB_END} 3)
+        math(EXPR INDEX_1 "${INDEX}+1")
+        math(EXPR INDEX_2 "${INDEX}+2")
+        list(GET SUFFICES_FILENAMES ${INDEX_1} FILENAME)
+        list(GET SUFFICES_FILENAMES ${INDEX_2} TEMPFILENAME)
+        file(RENAME "${TEMPFILENAME}" "${FILENAME}")
+    endforeach()
+endfunction()
+
+function(stack_push STACK_ARG)
+    set(STACK_LIST "${${STACK_ARG}}")
+    string(REPLACE ";" " " NEWITEM "${ARGN}")
+    if (DEBUG)
+        list(LENGTH STACK_LIST STACK_LENGTH)
+        message("Pushing \"${NEWITEM}\" onto stack (length=${STACK_LENGTH})")
+    endif()
+    list(APPEND STACK_LIST "${NEWITEM}")
+    set(${STACK_ARG} "${STACK_LIST}" PARENT_SCOPE)
+endfunction()
+
+function(stack_pop STACK_ARG ITEM)
+    set(STACK_LIST "${${STACK_ARG}}")
+    list(LENGTH STACK_LIST STACK_LENGTH)
+    if (STACK_LENGTH EQUAL 0)
+        message(FATAL_ERROR "ENDFOR: stack is empty")
+    endif()
+    math(EXPR LAST_ITEM_INDEX "${STACK_LENGTH}-1")
+    list(GET STACK_LIST "${LAST_ITEM_INDEX}" LAST_ITEM)
+    list(REMOVE_AT STACK_LIST "${LAST_ITEM_INDEX}")
+    string(REPLACE " " ";" LAST_ITEM_LIST "${LAST_ITEM}")
+    if (DEBUG)
+        message("Popping \"${LAST_ITEM}\" from stack (length=${STACK_LENGTH})")
+    endif()
+    set(${ITEM} "${LAST_ITEM_LIST}" PARENT_SCOPE)
+    set(${STACK_ARG} "${STACK_LIST}" PARENT_SCOPE)
+endfunction()
+
+function(stack_top STACK_ARG ITEM)
+    set(STACK_LIST "${${STACK_ARG}}")
+    list(LENGTH STACK_LIST STACK_LENGTH)
+    if (STACK_LENGTH EQUAL 0)
+        message(FATAL_ERROR "ENDFOR: stack is empty")
+    endif()
+    math(EXPR LAST_ITEM_INDEX "${STACK_LENGTH}-1")
+    list(GET STACK_LIST "${LAST_ITEM_INDEX}" LAST_ITEM)
+    string(REPLACE " " ";" LAST_ITEM_LIST "${LAST_ITEM}")
+    if (DEBUG)
+        message("Top of stack: \"${LAST_ITEM}\" from stack (length=${STACK_LENGTH})")
+    endif()
+    set(${ITEM} "${LAST_ITEM_LIST}" PARENT_SCOPE)
+endfunction()
+
+function(stack_find_key STACK_LIST TEMPLATE_PARAMETERS KEY VALUE)
+    list(REVERSE STACK_LIST)
+    foreach(STACK_ITEM ${STACK_LIST})
+        string(REPLACE " " ";" STACK_ITEM_LIST "${STACK_ITEM}")
+        list(GET STACK_ITEM_LIST 3 TP_INDEX)
+        math(EXPR TP_SIZE_INDEX "${TP_INDEX}+1")
+        list(GET TEMPLATE_PARAMETERS ${TP_SIZE_INDEX} TP_SIZE)
+        math(EXPR TP_KV_INDEX_START "${TP_INDEX}+2")
+        math(EXPR TP_KV_INDEX_END "${TP_KV_INDEX_START}+2*${TP_SIZE}-1")
+        foreach(TP_KV_INDEX RANGE ${TP_KV_INDEX_START} ${TP_KV_INDEX_END} 2)
+            list(GET TEMPLATE_PARAMETERS ${TP_KV_INDEX} TP_KEY)
+            if("${TP_KEY}" STREQUAL "${KEY}")
+                math(EXPR TP_VALUE_INDEX "${TP_KV_INDEX}+1")
+                list(GET TEMPLATE_PARAMETERS ${TP_VALUE_INDEX} TP_VALUE)
+                set(${VALUE} "${TP_VALUE}" PARENT_SCOPE)
+                return()
+            endif()
+        endforeach()
+    endforeach()
+    message(FATAL_ERROR "Unknown KEY=${KEY}")
+endfunction()
+
+function(template_parameters_find_next_groupname_index TEMPLATE_PARAMETERS GROUPNAME INDEX_LAST INDEX_NEXT)
+    if (${INDEX_LAST} LESS 0)
+        set(INDEX 0)
+    else ()
+        math(EXPR INDEX_1 "1+(${INDEX_LAST})")
+        list(GET TEMPLATE_PARAMETERS ${INDEX_1} GROUPNAME_INDEX_SIZE)
+        math(EXPR INDEX "${INDEX_LAST}+1+2*${GROUPNAME_INDEX_SIZE}+1")
+    endif()
+    list(LENGTH TEMPLATE_PARAMETERS PARAMETERS_LENGTH)
+    while (${INDEX} LESS ${PARAMETERS_LENGTH})
+        list(GET TEMPLATE_PARAMETERS ${INDEX} GROUPNAME_AT_INDEX)
+        if ("${GROUPNAME}" STREQUAL "${GROUPNAME_AT_INDEX}")
+            set("${INDEX_NEXT}" ${INDEX} PARENT_SCOPE)
+            return()
+        endif()
+        math(EXPR INDEX_1 "${INDEX}+1")
+        list(GET TEMPLATE_PARAMETERS ${INDEX_1} GROUPNAME_INDEX_SIZE)
+        math(EXPR INDEX "${INDEX}+1+2*${GROUPNAME_INDEX_SIZE}+1")
+    endwhile()
+    set("${INDEX_NEXT}" -1 PARENT_SCOPE)
+endfunction()
+
+function(calculate_line_number TEXT POSITION LINENUMBER_ARG)
+    #math(EXPR INDEX_MAX "${POSITION}-1")
+    string(SUBSTRING "${TEXT}" 0 ${POSITION} SUBTEXT)
+    string(REGEX MATCHALL "\n" MATCH_NEWLINES "${SUBTEXT}")
+    list(LENGTH MATCH_NEWLINES NBLINES)
+    math(EXPR NBLINES "${NBLINES}+1")
+    set(${LINENUMBER_ARG} ${NBLINES} PARENT_SCOPE)
+endfunction()
+
+function(parse_template TEMPLATE_FILENAME OUTPUT_DIR TEMPLATE_PARAMETERS)
+    file(READ ${TEMPLATE_FILENAME} TEMPLATE_CONTENTS)
+    set(POSITION 0)
+    match_autogen_group("${TEMPLATE_CONTENTS}" "${POSITION}" POS0 POS1 AUTOGEN FOUND)
+    if (NOT FOUND)
+        message(FATAL_ERROR "Header of template not found")
+    endif()
+    string(REGEX MATCH "AutoGen5 template ([ a-zA-Z0-9]*)" SUFFICES_MATCH "${AUTOGEN}")
+    if (NOT SUFFICES_MATCH)
+        message(FATAL_ERROR "No output suffices found")
+    endif()
+    string(STRIP "${CMAKE_MATCH_1}" SUFFICES)
+    string(REPLACE " " ";" SUFFICES "${SUFFICES}")
+    set(SUFFICES_FILENAMES "")
+    get_filename_component(TEMPLATE_NAME_WE "${TEMPLATE_FILENAME}" NAME_WE)
+    foreach(SUFFIX ${SUFFICES})
+        if ("${OUTPUT_DIR}" STREQUAL "")
+            set(DIR_PREFIX "")
+        else()
+            set(DIR_PREFIX "${OUTPUT_DIR}/")
+        endif()
+        string(RANDOM LENGTH 64 RANDOMSTRING)
+        set(FILENAME "${DIR_PREFIX}${TEMPLATE_NAME_WE}.${SUFFIX}")
+        set(TEMPFILENAME "${DIR_PREFIX}${TEMPLATE_NAME_WE}${RANDOMSTRING}.${SUFFIX}")
+        list(APPEND SUFFICES_FILENAMES "${SUFFIX}" "${FILENAME}" "${TEMPFILENAME}")
+        file(WRITE "${FILENAME}" "")
+    endforeach()
+    if (DEBUG)
+        message("Output files: ${SUFFICES_FILENAMES}")
+    endif()
+    set(WRITE_FILTER "")
+    append_output("${SUFFICES_FILENAMES}" "${TEMPLATE_CONTENTS}" 0 "${POS0}" "${WRITE_FILTER}")
+    math(EXPR POS1 "${POS1}+1")
+    set(POSITION "${POS1}")
+    if (DEBUG)
+        message("Output: ${SUFFICES_FILENAMES}")
+    endif()
+
+    set(STACK "")
+    while (1)
+        match_autogen_group("${TEMPLATE_CONTENTS}" "${POSITION}" POS0 POS1 GROUP_MATCH FOUND)
+        if (NOT FOUND)
+            if (DEBUG)
+                message("No group found. Dumping rest of file.")
+            endif()
+            if (NOT "${STACK}" STREQUAL "")
+                message(FATAL_ERROR "Stack not empty at end of file")
+            endif()
+            string(LENGTH "${TEMPLATE_CONTENTS}" TEXT_LENGTH)
+            append_output("${SUFFICES_FILENAMES}" "${TEMPLATE_CONTENTS}" ${POSITION} ${TEXT_LENGTH} "${WRITE_FILTER}")
+            break()
+        endif()
+        append_output("${SUFFICES_FILENAMES}" "${TEMPLATE_CONTENTS}" ${POSITION} ${POS0} "${WRITE_FILTER}")
+        set(POSITION "${POS1}")
+
+        if (GROUP_MATCH MATCHES "^FOR")
+            string(REPLACE " " ";" GROUP_MATCH_LIST "${GROUP_MATCH}")
+            list(GET GROUP_MATCH_LIST 1 FOR_KEY)
+            template_parameters_find_next_groupname_index("${TEMPLATE_PARAMETERS}" "${FOR_KEY}" -1 FOR_INDEX)
+            if (DEBUG)
+                message("FOR_KEY: ${FOR_KEY}")
+                message("FOR_INDEX: ${FOR_INDEX}")
+            endif()
+            if (${FOR_KEY} LESS 0)
+                message(FATAL_ERROR "FOR has key with empty list. Not implemented yet..")
+            endif()
+            stack_push(STACK FOR ${POSITION} ${FOR_KEY} ${FOR_INDEX})
+        elseif (GROUP_MATCH MATCHES "^ENDFOR")
+            string(REPLACE " " ";" GROUP_MATCH_LIST "${GROUP_MATCH}")
+            list(GET GROUP_MATCH_LIST 1 ENDFOR_KEY)
+            stack_pop(STACK FOR_ITEM)
+            list(GET FOR_ITEM 0 FOR_FOR)
+            if (NOT "${FOR_FOR}" STREQUAL "FOR")
+                message(FATAL_ERROR "ENDFOR does not match last item: ${FOR_FOR}")
+            endif()
+            list(GET FOR_ITEM 1 FOR_POSITION)
+            list(GET FOR_ITEM 2 FOR_KEY)
+            if (NOT "${FOR_KEY}" STREQUAL "${ENDFOR_KEY}")
+                calculate_line_number("${TEMPLATE_CONTENTS}" "${POSITION}" LINENUMBER)
+                message("FOR and ENDFOR do not match. (line number ${LINENUMBER}) (FOR:${FOR_KEY}, ENDFOR:${ENDFOR_KEY})")
+            endif()
+            list(GET FOR_ITEM 3 FOR_INDEX_PREV)
+            template_parameters_find_next_groupname_index("${TEMPLATE_PARAMETERS}" "${FOR_KEY}" ${FOR_INDEX_PREV} FOR_INDEX)
+            if (DEBUG)
+                message("FOR_INDEX was ${FOR_INDEX_PREV}, is now ${FOR_INDEX}")
+            endif()
+            if (${FOR_INDEX} LESS 0)
+                if (DEBUG)
+                    message("ENDFOR: FOR_INDEX < 0 (no more key) ==> Continue")
+                endif()
+            else()
+                set(POSITION ${FOR_POSITION})
+                stack_push(STACK FOR ${FOR_POSITION} ${FOR_KEY} ${FOR_INDEX})
+                if (DEBUG)
+                    message("ENDFOR: FOR_INDEX >= 0 (more keys available) ==> Back to position=${FOR_POSITION}")
+                endif()
+            endif()
+        elseif (GROUP_MATCH MATCHES "^CASE")
+            string(REGEX MATCH "^CASE[${WS}]+\\(([a-zA-Z]+)\\)" CASE_MATCH "${GROUP_MATCH}")
+            if ("${CASE_MATCH}" STREQUAL "")
+                message(FATAL_ERROR "Wrong CASE syntax")
+            endif()
+            set(CASE_KEY "${CMAKE_MATCH_1}")
+            if (DEBUG)
+                message("CASE: KEY=${CASE_KEY}")
+            endif()
+            stack_push(STACK CASE "${CASE_KEY}" ${POSITION})
+        elseif (GROUP_MATCH MATCHES "^==")
+            math(EXPR POSITION "${POSITION}+1")
+            string(REGEX MATCH "^==[${WS}]+([a-zA-Z_][a-zA-Z0-9_]*)" CASE_MATCH "${GROUP_MATCH}")
+            if ("${CASE_MATCH}" STREQUAL "")
+                message(FATAL_ERROR "Wrong == syntax")
+            endif()
+            stack_top(STACK CASE_ITEM)
+            list(GET CASE_ITEM 0 CASE_CASE)
+            if(NOT "${CASE_CASE}" STREQUAL "CASE")
+                message(FATAL_ERROR "== block must be in CASE. Top of stack=${CASE_CASE}")
+            endif()
+            set(CASE_VALUE "${CMAKE_MATCH_1}")
+            if (DEBUG)
+                message("case: == VALUE=${CASE_VALUE}")
+            endif()
+            list(GET CASE_ITEM 1 CASE_KEY)
+            if ("${CASE_KEY}" STREQUAL "suffix")
+                if (DEBUG)
+                    message("Setting write filter to ${CASE_VALUE}")
+                endif()
+                set(WRITE_FILTER "${CASE_VALUE}")
+            else()
+                message(FATAL_ERROR "CASE: unsupported argument ${CASE_KEY}")
+            endif()
+        elseif (GROUP_MATCH MATCHES "^ESAC")
+            stack_pop(STACK CASE_ITEM)
+            if (DEBUG)
+                message("ESAC")
+            endif()
+            list(GET CASE_ITEM 0 CASE_CASE)
+            if (NOT "${CASE_CASE}" STREQUAL "CASE")
+                message(FATAL_ERROR "ESAC does not match last item: ${CASE_CASE}")
+            endif()
+            if ("${CASE_KEY}" STREQUAL "suffix")
+                if (DEBUG)
+                    message("Removing write filter")
+                endif()
+                set(WRITE_FILTER "")
+            else()
+                message(FATAL_ERROR "CASE: unsupported argument ${CASE_KEY}")
+            endif()
+        else()
+            string(REGEX MATCH "\\(([a-zA-Z0-9_$%\"${WS}\\+\\-]+)\\)" PARENTHESE_MATCH "${GROUP_MATCH}")
+            if (NOT "${PARENTHESE_MATCH}" STREQUAL "")
+                set(PARENTHESE_CONTENT "${CMAKE_MATCH_1}")
+                string(REPLACE " " ";" PARENTHESE_LIST "${PARENTHESE_CONTENT}")
+                list(GET PARENTHESE_LIST 0 PARENTHESE_COMMAND)
+                if ("${PARENTHESE_COMMAND}" STREQUAL "get")
+                    list(GET PARENTHESE_LIST 1 KEY_QUOTED)
+                    string(REGEX MATCH "\\\"([a-zA-Z_${WS}]+)\\\"" KEY_MATCH "${KEY_QUOTED}")
+                    if ("${KEY_MATCH}" STREQUAL "")
+                        message(FATAL_ERROR "get: empty key")
+                    endif()
+                    set(KEY "${CMAKE_MATCH_1}")
+                    if (DEBUG)
+                        message("Get: key=${KEY}")
+                    endif()
+                    stack_find_key("${STACK}" "${TEMPLATE_PARAMETERS}" "${KEY}" VALUE)
+                    if (DEBUG)
+                        message("Get key=${KEY} ==> value=${VALUE}")
+                    endif()
+                    append_output_text("${SUFFICES_FILENAMES}" "${VALUE}" "${WRITE_FILTER}")
+                elseif("${PARENTHESE_COMMAND}" STREQUAL "tpl-file-line")
+                    list(GET PARENTHESE_LIST 1 FORMAT_LINE)
+                    calculate_line_number("${TEMPLATE_CONTENTS}" "${POSITION}" LINENUMBER)
+                    append_output_text("${SUFFICES_FILENAMES}" "${LINENUMBER}" "${WRITE_FILTER}")
+                else()
+                    message(FATAL_ERROR "Unknown parenthese command: ${PARENTHESE_COMMAND}")
+                endif()
+            else()
+                message(FATAL_ERROR "Unknown command: ${GROUP_MATCH}")
+            endif()
+        endif()
+
+    endwhile()
+    if (NOT "${STACK}" STREQUAL "")
+        message(FATAL_ERROR "STACK was not empty at EOF")
+    endif()
+    output_finish("${SUFFICES_FILENAMES}")
+endfunction()
+
+if ("${DEFINITION}" STREQUAL "")
+    message(FATAL_ERROR "Need definition file")
+endif()
+if (NOT EXISTS "${DEFINITION}")
+    message(FATAL_ERROR "Definition file does not exist (${DEFINITION})")
+endif()
+
+read_definition("${DEFINITION}" TEMPLATE_FILENAME DATA)
+if (DEBUG)
+    message("${TEMPLATE_FILENAME}")
+    message("${DATA}")
+endif()
+
+parse_template("${TEMPLATE_FILENAME}" "${OUTPUTDIR}" "${DATA}")
diff --git a/cmake/CheckCPUArch.c.in b/cmake/CheckCPUArch.c.in
new file mode 100644 (file)
index 0000000..5493139
--- /dev/null
@@ -0,0 +1,7 @@
+int main(void) {
+#if @CHECK_CPU_ARCH_DEFINES@
+    return 0;
+#else
+    fail
+#endif
+}
diff --git a/cmake/CheckCPUArch.cmake b/cmake/CheckCPUArch.cmake
new file mode 100644 (file)
index 0000000..1fdb3c8
--- /dev/null
@@ -0,0 +1,23 @@
+macro (_CHECK_CPU_ARCH ARCH ARCH_DEFINES VARIABLE)
+       if (NOT DEFINED HAVE_${VARIABLE})
+               message (STATUS "Check CPU architecture is ${ARCH}")
+               set (CHECK_CPU_ARCH_DEFINES ${ARCH_DEFINES})
+               configure_file (${PROJECT_SOURCE_DIR}/cmake/CheckCPUArch.c.in ${PROJECT_BINARY_DIR}/CMakeFiles/CMakeTmp/CheckCPUArch.c @ONLY)
+               try_compile (HAVE_${VARIABLE} "${PROJECT_BINARY_DIR}"
+                       "${PROJECT_BINARY_DIR}/CMakeFiles/CMakeTmp/CheckCPUArch.c")
+               if(HAVE_${VARIABLE})
+                       message (STATUS "Check CPU architecture is ${ARCH} - yes")
+                       set (${VARIABLE} 1 CACHE INTERNAL "Result of CHECK_CPU_ARCH_X64" FORCE)
+               else ()
+                       message (STATUS "Check CPU architecture is ${ARCH} - no")
+        endif ()
+    endif ()
+endmacro (_CHECK_CPU_ARCH)
+
+macro (CHECK_CPU_ARCH_X64 VARIABLE)
+    _CHECK_CPU_ARCH (x64 "defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)" ${VARIABLE})
+endmacro (CHECK_CPU_ARCH_X64)
+
+macro (CHECK_CPU_ARCH_X86 VARIABLE)
+    _CHECK_CPU_ARCH (x86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)" ${VARIABLE})
+endmacro (CHECK_CPU_ARCH_X86)
diff --git a/cmake/ClipMode.cmake b/cmake/ClipMode.cmake
new file mode 100644 (file)
index 0000000..0241e03
--- /dev/null
@@ -0,0 +1,92 @@
+include (CheckCSourceRuns)
+include (CMakePushCheckState)
+
+macro (CLIP_MODE)
+       if ((NOT DEFINED CPU_CLIPS_NEGATIVE) AND (NOT DEFINED CPU_CLIPS_POSITIVE))
+               set (CLIP_MODE_POSITIVE_MESSAGE "Target processor clips on positive float to int conversion")
+               set (CLIP_MODE_NEGATIVE_MESSAGE "Target processor clips on negative float to int conversion")
+
+               message (STATUS "Checking processor clipping capabilities...")
+
+               if (CMAKE_CROSSCOMPILING)
+
+                       set (CLIP_MSG "disabled")
+                       set (CPU_CLIPS_POSITIVE FALSE CACHE BOOL ${CLIP_MODE_POSITIVE_MESSAGE})
+                       set (CPU_CLIPS_NEGATIVE FALSE CACHE BOOL ${CLIP_MODE_NEGATIVE_MESSAGE})
+
+               else (NOT CMAKE_CROSSCOMPILING)
+
+                       cmake_push_check_state ()
+                       
+                       set (CMAKE_REQUIRED_QUIET TRUE)
+                       if (LIBM_REQUIRED)
+                               set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${M_LIBRARY})
+                       endif ()
+                       
+                       check_c_source_runs (
+                       "
+                       #define _ISOC9X_SOURCE  1
+                       #define _ISOC99_SOURCE  1
+                       #define __USE_ISOC99    1
+                       #define __USE_ISOC9X    1
+                       #include <math.h>
+                       int main (void)
+                       {       double  fval ;
+                               int k, ival ;
+
+                               fval = 1.0 * 0x7FFFFFFF ;
+                               for (k = 0 ; k < 100 ; k++)
+                               {       ival = (lrint (fval)) >> 24 ;
+                                       if (ival != 127)
+                                               return 1 ;
+                               
+                                       fval *= 1.2499999 ;
+                                       } ;
+                               
+                                       return 0 ;
+                               }
+                       "
+                       CPU_CLIPS_POSITIVE)
+                       
+                       check_c_source_runs (
+                       "
+                       #define _ISOC9X_SOURCE  1
+                       #define _ISOC99_SOURCE  1
+                       #define __USE_ISOC99    1
+                       #define __USE_ISOC9X    1
+                       #include <math.h>
+                       int main (void)
+                       {       double  fval ;
+                               int k, ival ;
+
+                               fval = -8.0 * 0x10000000 ;
+                               for (k = 0 ; k < 100 ; k++)
+                               {       ival = (lrint (fval)) >> 24 ;
+                                       if (ival != -128)
+                                               return 1 ;
+                               
+                                       fval *= 1.2499999 ;
+                                       } ;
+                               
+                                       return 0 ;
+                               }
+                       "
+                       CPU_CLIPS_NEGATIVE)
+
+                       cmake_pop_check_state ()
+
+                       if (CPU_CLIPS_POSITIVE AND (NOT CPU_CLIPS_NEGATIVE))
+                               set (CLIP_MSG "positive")
+                       elseif (CPU_CLIPS_NEGATIVE AND (NOT CPU_CLIPS_POSITIVE))
+                               set (CLIP_MSG "negative")
+                       elseif (CPU_CLIPS_POSITIVE AND CPU_CLIPS_NEGATIVE)
+                               set (CLIP_MSG "both")
+                       else ()
+                               set (CLIP_MSG "none")
+                       endif ()
+
+               endif (CMAKE_CROSSCOMPILING)
+
+               message (STATUS "Checking processor clipping capabilities... ${CLIP_MSG}")
+       endif ()
+endmacro (CLIP_MODE)
diff --git a/cmake/FindFLAC.cmake b/cmake/FindFLAC.cmake
new file mode 100644 (file)
index 0000000..3491706
--- /dev/null
@@ -0,0 +1,67 @@
+# - Find FLAC
+# Find the native FLAC includes and libraries
+#
+#  FLAC_INCLUDE_DIRS - where to find FLAC headers.
+#  FLAC_LIBRARIES    - List of libraries when using libFLAC.
+#  FLAC_FOUND        - True if libFLAC found.
+#  FLAC_DEFINITIONS  - FLAC compile definitons 
+
+if (FLAC_INCLUDE_DIR)
+    # Already in cache, be silent
+    set (FLAC_FIND_QUIETLY TRUE)
+endif ()
+
+find_package (Ogg QUIET)
+
+find_package (PkgConfig QUIET)
+pkg_check_modules(PC_FLAC QUIET flac)
+
+set(FLAC_VERSION ${PC_FLAC_VERSION})
+
+find_path (FLAC_INCLUDE_DIR FLAC/stream_decoder.h
+       HINTS
+               ${PC_FLAC_INCLUDEDIR}
+               ${PC_FLAC_INCLUDE_DIRS}
+               ${FLAC_ROOT}
+       )
+
+# MSVC built libraries can name them *_static, which is good as it
+# distinguishes import libraries from static libraries with the same extension.
+find_library (FLAC_LIBRARY
+       NAMES
+               FLAC
+               libFLAC
+               libFLAC_dynamic
+               libFLAC_static
+       HINTS
+               ${PC_FLAC_LIBDIR}
+               ${PC_FLAC_LIBRARY_DIRS}
+               ${FLAC_ROOT}
+       )
+
+# Handle the QUIETLY and REQUIRED arguments and set FLAC_FOUND to TRUE if
+# all listed variables are TRUE.
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (FLAC
+       REQUIRED_VARS
+               FLAC_LIBRARY
+               FLAC_INCLUDE_DIR
+               Ogg_FOUND
+       VERSION_VAR
+        FLAC_VERSION
+       )
+
+if (FLAC_FOUND)
+       set (FLAC_INCLUDE_DIRS ${FLAC_INCLUDE_DIR})
+       set (FLAC_LIBRARIES ${FLAC_LIBRARY} ${OGG_LIBRARIES})
+    if (NOT TARGET FLAC::FLAC)
+               add_library(FLAC::FLAC UNKNOWN IMPORTED)
+               set_target_properties(FLAC::FLAC PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${FLAC_INCLUDE_DIR}"
+                       IMPORTED_LOCATION "${FLAC_LIBRARY}"
+                       INTERFACE_LINK_LIBRARIES Ogg::ogg
+                       )
+       endif ()
+endif ()
+
+mark_as_advanced(FLAC_INCLUDE_DIR FLAC_LIBRARY)
diff --git a/cmake/FindOgg.cmake b/cmake/FindOgg.cmake
new file mode 100644 (file)
index 0000000..9cf5ce4
--- /dev/null
@@ -0,0 +1,61 @@
+# - Find ogg
+# Find the native ogg includes and libraries
+#
+#  OGG_INCLUDE_DIRS - where to find ogg.h, etc.
+#  OGG_LIBRARIES    - List of libraries when using ogg.
+#  OGG_FOUND        - True if ogg found.
+
+if (OGG_INCLUDE_DIR)
+       # Already in cache, be silent
+       set(OGG_FIND_QUIETLY TRUE)
+endif ()
+
+find_package (PkgConfig QUIET)
+pkg_check_modules (PC_OGG QUIET ogg>=1.3.0)
+
+set (OGG_VERSION ${PC_OGG_VERSION})
+
+find_path (OGG_INCLUDE_DIR ogg/ogg.h
+       HINTS
+               ${PC_OGG_INCLUDEDIR}
+               ${PC_OGG_INCLUDE_DIRS}
+               ${OGG_ROOT}
+       )
+# MSVC built ogg may be named ogg_static.
+# The provided project files name the library with the lib prefix.
+find_library (OGG_LIBRARY
+       NAMES
+               ogg
+               ogg_static
+               libogg
+               libogg_static
+       HINTS
+               ${PC_OGG_LIBDIR}
+               ${PC_OGG_LIBRARY_DIRS}
+               ${OGG_ROOT}
+       )
+# Handle the QUIETLY and REQUIRED arguments and set OGG_FOUND
+# to TRUE if all listed variables are TRUE.
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (Ogg
+       REQUIRED_VARS
+               OGG_LIBRARY
+               OGG_INCLUDE_DIR
+       VERSION_VAR
+               OGG_VERSION
+       )
+
+if (OGG_FOUND)
+       set (OGG_LIBRARIES ${OGG_LIBRARY})
+       set (OGG_INCLUDE_DIRS ${OGG_INCLUDE_DIR})
+       
+       if(NOT TARGET Ogg::ogg)
+       add_library(Ogg::ogg UNKNOWN IMPORTED)
+               set_target_properties(Ogg::ogg PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${OGG_INCLUDE_DIRS}"
+                       IMPORTED_LOCATION "${OGG_LIBRARIES}"
+               )
+  endif ()
+endif ()
+
+mark_as_advanced (OGG_INCLUDE_DIR OGG_LIBRARY)
diff --git a/cmake/FindOpus.cmake b/cmake/FindOpus.cmake
new file mode 100644 (file)
index 0000000..a83686b
--- /dev/null
@@ -0,0 +1,67 @@
+# - Find opus
+# Find the native opus includes and libraries
+#
+#  OPUS_INCLUDE_DIRS - where to find opus.h, etc.
+#  OPUS_LIBRARIES    - List of libraries when using opus.
+#  OPUS_FOUND        - True if Opus found.
+
+if (OPUS_INCLUDE_DIR)
+    # Already in cache, be silent
+    set(OPUS_FIND_QUIETLY TRUE)
+endif ()
+
+find_package (Ogg QUIET)
+
+find_package (PkgConfig QUIET)
+pkg_check_modules(PC_OPUS QUIET opus>=1.1)
+
+set (OPUS_VERSION ${PC_OPUS_VERSION})
+
+find_path (OPUS_INCLUDE_DIR opus/opus.h
+       HINTS
+               ${PC_OPUS_INCLUDEDIR}
+               ${PC_OPUS_INCLUDE_DIRS}
+               ${OPUS_ROOT}
+       )
+
+# MSVC built opus may be named opus_static.
+# The provided project files name the library with the lib prefix.
+
+find_library (OPUS_LIBRARY
+       NAMES
+               opus
+               opus_static
+               libopus
+               libopus_static
+       HINTS
+               ${PC_OPUS_LIBDIR}
+               ${PC_OPUS_LIBRARY_DIRS}
+               ${OPUS_ROOT}
+       )
+
+# Handle the QUIETLY and REQUIRED arguments and set OPUS_FOUND
+# to TRUE if all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args (Opus
+       REQUIRED_VARS
+               OPUS_LIBRARY
+               OPUS_INCLUDE_DIR
+               OGG_FOUND
+       VERSION_VAR
+               OPUS_VERSION
+       )
+
+if (OPUS_FOUND)
+       set (OPUS_LIBRARIES ${OPUS_LIBRARY})
+       set (OPUS_INCLUDE_DIRS ${OPUS_INCLUDE_DIR})
+
+       if (NOT TARGET Opus::opus)
+               add_library (Opus::opus UNKNOWN IMPORTED)
+               set_target_properties (Opus::opus PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${OPUS_INCLUDE_DIRS}"
+                       IMPORTED_LOCATION "${OPUS_LIBRARIES}"
+               )
+       endif ()
+endif ()
+
+mark_as_advanced(OPUS_INCLUDE_DIR OPUS_LIBRARY)
diff --git a/cmake/FindSndio.cmake b/cmake/FindSndio.cmake
new file mode 100644 (file)
index 0000000..6b9b409
--- /dev/null
@@ -0,0 +1,61 @@
+# - Find SoundIO (sndio) includes and libraries
+#
+#   SNDIO_FOUND        - True if SNDIO_INCLUDE_DIR & SNDIO_LIBRARY are
+#                        found
+#   SNDIO_LIBRARIES    - Set when SNDIO_LIBRARY is found
+#   SNDIO_INCLUDE_DIRS - Set when SNDIO_INCLUDE_DIR is found
+#
+#   SNDIO_INCLUDE_DIR - where to find sndio.h, etc.
+#   SNDIO_LIBRARY     - the sndio library
+#
+
+if (SNDIO_INCLUDE_DIR)
+       # Already in cache, be silent
+       set (SNDIO_FIND_QUIETLY TRUE)
+endif ()
+
+find_package (PkgConfig QUIET)
+pkg_check_modules (PC_SNDIO QUIET sndio)
+
+set (SNDIO_VERSION ${PC_SNDIO_VERSION})
+
+find_path (SNDIO_INCLUDE_DIR
+       NAMES
+               sndio.h
+       HINTS
+               ${PC_SNDIO_INCLUDEDIR}
+               ${PC_SNDIO_INCLUDE_DIRS}
+               ${SNDIO_ROOT}
+       )
+
+find_library (SNDIO_LIBRARY
+       NAMES
+               sndio
+       HINTS
+               ${PC_SNDIO_LIBDIR}
+               ${PC_SNDIO_LIBRARY_DIRS}
+               ${SNDIO_ROOT}
+       )
+
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (Sndio
+       REQUIRED_VARS
+               SNDIO_LIBRARY
+               SNDIO_INCLUDE_DIR
+       VERSION_VAR
+               SNDIO_VERSION
+       )
+
+if (SNDIO_FOUND)
+       set (SNDIO_LIBRARIES ${SNDIO_LIBRARY})
+       set (SNDIO_INCLUDE_DIRS ${SNDIO_INCLUDE_DIR})
+       if (NOT TARGET Sndio::Sndio)
+               add_library (Sndio::Sndio UNKNOWN IMPORTED)
+               set_target_properties (Sndio::Sndio PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${SNDIO_INCLUDE_DIRS}"
+                       IMPORTED_LOCATION "${SNDIO_LIBRARIES}"
+               )
+       endif()
+endif()
+
+mark_as_advanced (SNDIO_INCLUDE_DIR SNDIO_LIBRARY)
diff --git a/cmake/FindSpeex.cmake b/cmake/FindSpeex.cmake
new file mode 100644 (file)
index 0000000..c28fe60
--- /dev/null
@@ -0,0 +1,55 @@
+# - Find Speex
+# Find the native Speex includes and libraries
+#
+#       SPEEX_INCLUDE_DIRS - where to find speex.h, etc.
+#       SPEEX_LIBRARIES        - List of libraries when using Speex.
+#       SPEEX_FOUND            - True if Speex found.
+
+if (SPEEX_INCLUDE_DIR)
+       set (SPEEX_FIND_QUIETLY TRUE)
+endif ()
+
+find_package (PkgConfig QUIET)
+pkg_check_modules (PC_SPEEX QUIET speex)
+
+set (SPEEX_VERSION ${PC_SPEEX_VERSION})
+
+find_path (SPEEX_INCLUDE_DIR speex/speex.h
+       HINTS
+               ${PC_SPEEX_INCLUDEDIR}
+               ${PC_SPEEX_INCLUDE_DIRS}
+               ${SPEEX_ROOT}
+       )
+find_library (SPEEX_LIBRARY
+       NAMES
+               speex
+               libspeex
+       HINTS
+               ${PC_SPEEX_LIBDIR}
+               ${PC_SPEEX_LIBRARY_DIRS}
+               ${SPEEX_ROOT}
+       )
+
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (Speex
+       REQUIRED_VARS
+               SPEEX_LIBRARY
+               SPEEX_INCLUDE_DIR
+       VERSION_VAR
+               SPEEX_VERSION
+       )
+
+if (SPEEX_FOUND)
+       set (SPEEX_LIBRARIES ${SPEEX_LIBRARY})
+       set (SPEEX_INCLUDE_DIRS ${SPEEX_INCLUDE_DIR})
+       
+       if (NOT TARGET Speex::Speex)
+               add_library (Speex::Speex UNKNOWN IMPORTED)
+               set_target_properties (Speex::Speex PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${SPEEX_INCLUDE_DIRS}"
+                       IMPORTED_LOCATION "${SPEEX_LIBRARIES}"
+               )
+       endif ()
+endif ()
+
+mark_as_advanced (SPEEX_INCLUDE_DIR SPEEX_LIBRARY)
diff --git a/cmake/FindVorbis.cmake b/cmake/FindVorbis.cmake
new file mode 100644 (file)
index 0000000..57e6055
--- /dev/null
@@ -0,0 +1,210 @@
+#[=======================================================================[.rst:
+FindVorbis
+----------
+
+Finds the native vorbis, vorbisenc amd vorbisfile includes and libraries.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module provides the following imported targets, if found:
+
+``Vorbis::vorbis``
+  The Vorbis library
+``Vorbis::vorbisenc``
+  The VorbisEnc library
+``Vorbis::vorbisfile``
+  The VorbisFile library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables:
+
+``Vorbis_Vorbis_INCLUDE_DIRS``
+  List of include directories when using vorbis.
+``Vorbis_Enc_INCLUDE_DIRS``
+  List of include directories when using vorbisenc.
+``Vorbis_File_INCLUDE_DIRS``
+  List of include directories when using vorbisfile.
+``Vorbis_Vorbis_LIBRARIES``
+  List of libraries when using vorbis.
+``Vorbis_Enc_LIBRARIES``
+  List of libraries when using vorbisenc.
+``Vorbis_File_LIBRARIES``
+  List of libraries when using vorbisfile.
+``Vorbis_FOUND``
+  True if vorbis and requested components found.
+``Vorbis_Vorbis_FOUND``
+  True if vorbis found.
+``Vorbis_Enc_FOUND``
+  True if vorbisenc found.
+``Vorbis_Enc_FOUND``
+  True if vorbisfile found.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
+``Vorbis_Vorbis_INCLUDE_DIR``
+  The directory containing ``vorbis/vorbis.h``.
+``Vorbis_Enc_INCLUDE_DIR``
+  The directory containing ``vorbis/vorbisenc.h``.
+``Vorbis_File_INCLUDE_DIR``
+  The directory containing ``vorbis/vorbisenc.h``.
+``Vorbis_Vorbis_LIBRARY``
+  The path to the vorbis library.
+``Vorbis_Enc_LIBRARY``
+  The path to the vorbisenc library.
+``Vorbis_File_LIBRARY``
+  The path to the vorbisfile library.
+
+Hints
+^^^^^
+
+A user may set ``Vorbis_ROOT`` to a vorbis installation root to tell this module where to look.
+
+#]=======================================================================]
+
+if (Vorbis_Vorbis_INCLUDE_DIR)
+       # Already in cache, be silent
+       set (Vorbis_FIND_QUIETLY TRUE)
+endif ()
+
+set (Vorbis_Vorbis_FIND_QUIETLY TRUE)
+set (Vorbis_Enc_FIND_QUIETLY TRUE)
+set (Vorbis_File_FIND_QUIETLY TRUE)
+
+find_package (Ogg QUIET)
+
+find_package (PkgConfig QUIET)
+pkg_check_modules (PC_Vorbis_Vorbis QUIET vorbis)
+pkg_check_modules (PC_Vorbis_Enc QUIET vorbisenc)
+pkg_check_modules (PC_Vorbis_File QUIET vorbisfile)
+
+set (Vorbis_VERSION ${PC_Vorbis_Vorbis_VERSION})
+
+find_path (Vorbis_Vorbis_INCLUDE_DIR vorbis/codec.h
+       HINTS
+               ${PC_Vorbis_Vorbis_INCLUDEDIR}
+               ${PC_Vorbis_Vorbis_INCLUDE_DIRS}
+               ${Vorbis_ROOT}
+       )
+
+find_path (Vorbis_Enc_INCLUDE_DIR vorbis/vorbisenc.h
+       HINTS
+               ${PC_Vorbis_Enc_INCLUDEDIR}
+               ${PC_Vorbis_Enc_INCLUDE_DIRS}
+               ${Vorbis_ROOT}
+       )
+
+find_path (Vorbis_File_INCLUDE_DIR vorbis/vorbisfile.h
+       HINTS
+               ${PC_Vorbis_File_INCLUDEDIR}
+               ${PC_Vorbis_File_INCLUDE_DIRS}
+               ${Vorbis_ROOT}
+       )
+
+find_library (Vorbis_Vorbis_LIBRARY
+       NAMES
+               vorbis
+               vorbis_static
+               libvorbis
+               libvorbis_static
+       HINTS
+               ${PC_Vorbis_Vorbis_LIBDIR}
+               ${PC_Vorbis_Vorbis_LIBRARY_DIRS}
+               ${Vorbis_ROOT}
+       )
+
+find_library (Vorbis_Enc_LIBRARY
+       NAMES
+               vorbisenc
+               vorbisenc_static
+               libvorbisenc
+               libvorbisenc_static
+       HINTS
+               ${PC_Vorbis_Enc_LIBDIR}
+               ${PC_Vorbis_Enc_LIBRARY_DIRS}
+               ${Vorbis_ROOT}
+       )
+
+find_library (Vorbis_File_LIBRARY
+       NAMES
+               vorbisfile
+               vorbisfile_static
+               libvorbisfile
+               libvorbisfile_static
+       HINTS
+               ${PC_Vorbis_File_LIBDIR}
+               ${PC_Vorbis_File_LIBRARY_DIRS}
+               ${Vorbis_ROOT}
+       )
+
+include (FindPackageHandleStandardArgs)
+
+if (Vorbis_Vorbis_LIBRARY AND Vorbis_Vorbis_INCLUDE_DIR AND Ogg_FOUND)
+    set (Vorbis_Vorbis_FOUND TRUE)
+endif ()
+
+if (Vorbis_Enc_LIBRARY AND Vorbis_Enc_INCLUDE_DIR AND Vorbis_Vorbis_FOUND)
+    set (Vorbis_Enc_FOUND TRUE)
+endif ()
+
+if (Vorbis_Vorbis_FOUND AND Vorbis_File_LIBRARY AND Vorbis_File_INCLUDE_DIR)
+    set (Vorbis_File_FOUND TRUE)
+endif ()
+
+find_package_handle_standard_args (Vorbis
+       REQUIRED_VARS
+               Vorbis_Vorbis_LIBRARY
+               Vorbis_Vorbis_INCLUDE_DIR
+               Ogg_FOUND
+       HANDLE_COMPONENTS
+       VERSION_VAR Vorbis_VERSION)
+
+
+if (Vorbis_Vorbis_FOUND)
+       set (Vorbis_Vorbis_INCLUDE_DIRS ${VORBIS_INCLUDE_DIR})
+       set (Vorbis_Vorbis_LIBRARIES ${VORBIS_LIBRARY} ${OGG_LIBRARIES})
+    if (NOT TARGET Vorbis::vorbis)
+               add_library (Vorbis::vorbis UNKNOWN IMPORTED)
+               set_target_properties (Vorbis::vorbis PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Vorbis_INCLUDE_DIR}"
+                       IMPORTED_LOCATION "${Vorbis_Vorbis_LIBRARY}"
+                       INTERFACE_LINK_LIBRARIES Ogg::ogg
+               )
+       endif ()
+
+       if (Vorbis_Enc_FOUND)
+               set (Vorbis_Enc_INCLUDE_DIRS ${Vorbis_Enc_INCLUDE_DIR})
+               set (Vorbis_Enc_LIBRARIES ${Vorbis_Enc_LIBRARY} ${Vorbis_Enc_LIBRARIES})
+               if (NOT TARGET Vorbis::vorbisenc)
+                       add_library (Vorbis::vorbisenc UNKNOWN IMPORTED)
+                       set_target_properties (Vorbis::vorbisenc PROPERTIES
+                               INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Enc_INCLUDE_DIR}"
+                               IMPORTED_LOCATION "${Vorbis_Enc_LIBRARY}"
+                               INTERFACE_LINK_LIBRARIES Vorbis::vorbis
+                       )
+               endif ()
+       endif ()
+
+       if (Vorbis_File_FOUND)
+               set (Vorbis_File_INCLUDE_DIRS ${Vorbis_File_INCLUDE_DIR})
+               set (Vorbis_File_LIBRARIES ${Vorbis_File_LIBRARY} ${Vorbis_File_LIBRARIES})
+               if (NOT TARGET Vorbis::vorbisfile)
+                       add_library (Vorbis::vorbisfile UNKNOWN IMPORTED)
+                       set_target_properties (Vorbis::vorbisfile PROPERTIES
+                               INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_File_INCLUDE_DIR}"
+                               IMPORTED_LOCATION "${Vorbis_File_LIBRARY}"
+                               INTERFACE_LINK_LIBRARIES Vorbis::vorbis
+                       )
+               endif ()
+       endif ()
+
+endif ()
+
+mark_as_advanced (Vorbis_Vorbis_INCLUDE_DIR Vorbis_Vorbis_LIBRARY)
+mark_as_advanced (Vorbis_Enc_INCLUDE_DIR Vorbis_Enc_LIBRARY)
+mark_as_advanced (Vorbis_File_INCLUDE_DIR Vorbis_File_LIBRARY)
diff --git a/cmake/SndFileChecks.cmake b/cmake/SndFileChecks.cmake
new file mode 100644 (file)
index 0000000..9b52d15
--- /dev/null
@@ -0,0 +1,276 @@
+include (CheckFunctionExists)
+include (CheckIncludeFile)
+include (CheckLibraryExists)
+include (CheckSymbolExists)
+include (CheckTypeSize)
+include (TestBigEndian)
+
+include (TestInline)
+include (ClipMode)
+include (TestLargeFiles)
+include (CheckCPUArch)
+
+test_large_files (_LARGEFILES)
+
+if (LARGE_FILES_DEFINITIONS)
+       add_definitions(${LARGE_FILES_DEFINITIONS})
+endif ()
+
+if (WIN32)
+    set(TYPEOF_SF_COUNT_T __int64)
+else ()
+    set(TYPEOF_SF_COUNT_T int64_t)
+endif ()
+set (SF_COUNT_MAX 0x7fffffffffffffffll)
+
+if (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
+       find_package (Sndio)
+elseif (NOT WIN32)
+       find_package (ALSA)
+endif ()
+
+if (VCPKG_TOOLCHAIN AND (NOT CMAKE_VERSION VERSION_LESS 3.15))
+       set (CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
+endif ()
+
+if (CMAKE_FIND_PACKAGE_PREFER_CONFIG)
+       find_package (Ogg 1.3 CONFIG)
+       find_package (Vorbis CONFIG COMPONENTS Enc)
+       find_package (FLAC CONFIG)
+       find_package (Opus CONFIG)
+
+       include (FindPackageHandleStandardArgs)
+       find_package_handle_standard_args (Ogg CONFIG_MODE)
+       find_package_handle_standard_args (Vorbis CONFIG_MODE)
+       find_package_handle_standard_args (FLAC CONFIG_MODE)
+       find_package_handle_standard_args (Opus CONFIG_MODE)
+else ()
+       find_package (Ogg 1.3)
+       find_package (Vorbis COMPONENTS Enc)
+       find_package (FLAC)
+       find_package (Opus)
+endif ()
+if (Vorbis_FOUND AND FLAC_FOUND AND Opus_FOUND)
+       set (HAVE_EXTERNAL_XIPH_LIBS 1)
+else ()
+       set (HAVE_EXTERNAL_XIPH_LIBS 0)
+endif ()
+
+find_package (Speex)
+find_package (SQLite3)
+
+check_include_file (byteswap.h         HAVE_BYTESWAP_H)
+check_include_file (dlfcn.h                    HAVE_DLFCN_H)
+check_include_file (direct.h           HAVE_DIRECT_H)
+check_include_file (endian.h           HAVE_ENDIAN_H)
+check_include_file (inttypes.h         HAVE_INTTYPES_H)
+check_include_file (io.h                       HAVE_IO_H)
+check_include_file (stdint.h           HAVE_STDINT_H)
+check_include_file (sys/time.h         HAVE_SYS_TIME_H)
+check_include_file (sys/types.h                HAVE_SYS_TYPES_H)
+check_include_file (unistd.h           HAVE_UNISTD_H)
+check_include_file (immintrin.h                HAVE_IMMINTRIN_H)
+
+check_cpu_arch_x86 (CPU_IS_X86)
+check_cpu_arch_x64 (CPU_IS_X64)
+if ((CPU_IS_X86 OR CPU_IS_X64) AND HAVE_IMMINTRIN_H)
+       set (HAVE_SSE2 1)
+endif ()
+
+# Never checked
+# check_include_file (stdlib.h         HAVE_STDLIB_H)
+# check_include_file (string.h         HAVE_STRING_H)
+# check_include_file (strings.h                HAVE_STRINGS_H)
+# check_include_file (sys/stat.h       HAVE_SYS_STAT_H)
+# check_include_file (memory.h         HAVE_MEMORY_H)
+
+if (BUILD_TESTING)
+       check_include_file (locale.h    HAVE_LOCALE_H)
+       check_include_file (sys/wait.h  HAVE_SYS_WAIT_H)
+endif ()
+
+check_type_size (int64_t                       SIZEOF_INT64_T)
+check_type_size (long                          SIZEOF_LONG)
+check_type_size (long\ long                    SIZEOF_LONG_LONG)
+check_type_size (ssize_t                       SIZEOF_SSIZE_T)
+check_type_size (wchar_t                       SIZEOF_WCHAR_T)
+
+# Never used
+# check_type_size (loff_t                      SIZEOF_LOFF_T)
+# check_type_size (offt64_t                    SIZEOF_OFF64_T)
+
+# Never checked
+# check_type_size (size_t                      SIZEOF_SIZE_T)
+
+# Used in configre.ac
+# check_type_size (double                      SIZEOF_DOUBLE)
+# check_type_size (float                       SIZEOF_FLOAT)
+# check_type_size (int                         SIZEOF_INT)
+# check_type_size (short                       SIZEOF_SHORT)
+
+if (ENABLE_TESTING)
+       check_type_size (void*                  SIZEOF_VOIDP)
+endif()
+
+if ((SIZEOF_OFF_T EQUAL 8) OR (SIZEOF_LOFF_T EQUAL 8) OR (SIZEOF_OFF64_T EQUAL 8))
+       set (TYPEOF_SF_COUNT_T "int64_t")
+       set (SF_COUNT_MAX "0x7FFFFFFFFFFFFFFFLL")
+       set (SIZEOF_SF_COUNT_T 8)
+else ()
+       if (WIN32)
+               set (TYPEOF_SF_COUNT_T "__int64")
+               set (SF_COUNT_MAX "0x7FFFFFFFFFFFFFFFLL")
+               set (SIZEOF_SF_COUNT_T 8)
+       else ()
+               message ("")
+               message ("*** The configure process has determined that this system is capable")
+               message ("*** of Large File Support but has not been able to find a type which")
+               message ("*** is an unambiguous 64 bit file offset.")
+               message ("*** Please contact the author to help resolve this problem.")
+               message ("")
+               message (FATAL_ERROR "Bad file offset type.")
+       endif ()
+endif ()
+
+check_type_size (${TYPEOF_SF_COUNT_T} SIZEOF_SF_COUNT_T)
+
+if (NOT WIN32)
+       check_library_exists (m floor "" LIBM_REQUIRED)
+       if (LIBM_REQUIRED)
+               list (APPEND CMAKE_REQUIRED_LIBRARIES m)
+       endif ()
+endif ()
+
+check_library_exists (sqlite3 sqlite3_close "" HAVE_SQLITE3)
+
+check_function_exists (fstat                   HAVE_FSTAT)
+check_function_exists (fstat64                 HAVE_FSTAT64)
+check_function_exists (gettimeofday            HAVE_GETTIMEOFDAY)
+check_function_exists (gmtime                  HAVE_GMTIME)
+check_function_exists (gmtime_r                        HAVE_GMTIME_R)
+check_function_exists (localtime               HAVE_LOCALTIME)
+check_function_exists (localtime_r             HAVE_LOCALTIME_R)
+check_function_exists (lseek                   HAVE_LSEEK)
+check_function_exists (open                            HAVE_OPEN)
+check_function_exists (read                            HAVE_READ)
+check_function_exists (write                   HAVE_WRITE)
+check_function_exists (lrint                   HAVE_LRINT)
+check_function_exists (lrintf                  HAVE_LRINTF)
+
+if (NOT WIN32)
+       check_function_exists (ftruncate        HAVE_FTRUNCATE)
+       check_function_exists (fsync            HAVE_FSYNC)
+endif ()
+
+if (BUILD_TESTING)
+       check_function_exists (pipe                     HAVE_PIPE)
+       check_function_exists (setlocale        HAVE_SETLOCALE)
+       check_function_exists (waitpid          HAVE_WAITPID)
+endif ()
+
+# Never checked
+# check_function_exists (calloc                        HAVE_CALLOC)
+# check_function_exists (free                  HAVE_FREE)
+# check_function_exists (getpagesize   HAVE_GETPAGESIZE)
+# check_function_exists (malloc                        HAVE_MALLOC)
+# check_function_exists (realloc               HAVE_REALLOC)
+# check_function_exists (snprintf              HAVE_SNPRINTF)
+# check_function_exists (vsnprintf             HAVE_VSNPRINTF)
+# check_function_exists (floor                 HAVE_FLOOR)
+# check_function_exists (fmod                  HAVE_FMOD)
+
+# Never used
+# check_function_exists (mmap                  HAVE_MMAP)
+# check_function_exists (ceil                  HAVE_CEIL)
+# check_function_exists (lround                        HAVE_LROUND)
+# check_function_exists (lseek64               HAVE_LSEEK64)
+
+
+check_symbol_exists (S_IRGRP sys/stat.h HAVE_DECL_S_IRGRP)
+
+test_big_endian (WORDS_BIGENDIAN)
+if (WORDS_BIGENDIAN)
+       set (CPU_IS_BIG_ENDIAN 1)
+else ()
+       set (CPU_IS_LITTLE_ENDIAN 1)
+endif ()
+
+if (WIN32)
+       set (OS_IS_WIN32 1)
+       set (USE_WINDOWS_API 1)
+       if (BUILD_SHARED_LIBS)
+               set (WIN32_TARGET_DLL 1)
+       endif ()
+       if (MINGW)
+               add_definitions (-D__USE_MINGW_ANSI_STDIO=1)
+       endif ()
+endif ()
+
+if (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
+       set (OS_IS_OPENBSD 1)
+endif ()
+
+
+if (CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
+       set (COMPILER_IS_GCC 1)
+endif ()
+
+test_inline ()
+clip_mode ()
+
+if (MSVC)
+       add_definitions (-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
+endif (MSVC)
+
+if (DEFINED ENABLE_STATIC_RUNTIME)
+       if (MSVC)
+               if (ENABLE_STATIC_RUNTIME)
+                       foreach (flag_var
+                               CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+                               CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
+                               CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+                               CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
+                               )
+                               if (${flag_var} MATCHES "/MD")
+                                       string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+                               endif ()
+                       endforeach (flag_var)
+               else ()
+                       foreach (flag_var
+                               CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+                               CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
+                               CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+                               CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
+                               )
+                               if (${flag_var} MATCHES "/MT")
+                                       string (REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}")
+                               endif (${flag_var} MATCHES "/MT")
+                       endforeach (flag_var)
+               endif ( )
+       elseif (MINGW)
+               if (ENABLE_STATIC_RUNTIME)
+                       if (CMAKE_C_COMPILER_ID STREQUAL GNU)
+                               set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc")
+                               set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -static-libgcc -s")
+                       endif ()
+                       if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
+                               set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
+                               set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -static-libgcc -static-libstdc++ -s")
+                       endif ()
+                       if (CMAKE_C_COMPILER_ID STREQUAL Clang)
+                               set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static")
+                               set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -static")
+                       endif ()
+                       if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+                               set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
+                               set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -static")
+                       endif ()
+               endif ()
+       else ()
+               message (AUTHOR_WARNING "ENABLE_STATIC_RUNTIME option is for MSVC or MinGW only.")
+       endif ()
+endif ()
+
+if (BUILD_SHARED_LIBS)
+       find_package (PythonInterp REQUIRED)
+endif()
diff --git a/cmake/SndFileConfig.cmake.in b/cmake/SndFileConfig.cmake.in
new file mode 100644 (file)
index 0000000..e33c56b
--- /dev/null
@@ -0,0 +1,32 @@
+set(SndFile_VERSION @PROJECT_VERSION@)
+set(SndFile_VERSION_MAJOR @PROJECT_VERSION_MAJOR@)
+set(SndFile_VERSION_MINOR @PROJECT_VERSION_MINOR@)
+set(SndFile_VERSION_PATCH @PROJECT_VERSION_PATCH@)
+
+set (SndFile_WITH_EXTERNAL_LIBS @SndFile_WITH_EXTERNAL_LIBS@)
+
+@PACKAGE_INIT@
+
+include (CMakeFindDependencyMacro)
+
+if (SndFile_WITH_EXTERNAL_LIBS AND NOT @BUILD_SHARED_LIBS@)
+       find_dependency (Ogg 1.3)
+       find_dependency (Vorbis)
+       find_dependency (FLAC)
+       find_dependency (Opus)
+endif ()
+
+include (${CMAKE_CURRENT_LIST_DIR}/SndFileTargets.cmake)
+
+set_and_check (SndFile_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
+set (SNDFILE_INCLUDE_DIR ${SndFile_INCLUDE_DIR})
+
+set (SndFile_LIBRARY SndFile::sndfile)
+set (SNDFILE_LIBRARY SndFile::sndfile)
+set (SndFile_LIBRARIES SndFile::sndfile)
+set (SNDFILE_LIBRARIES SndFile::sndfile)
+
+
+check_required_components(SndFile)
+
+set (SNDFILE_FOUND 1)
diff --git a/cmake/TestInline.c.in b/cmake/TestInline.c.in
new file mode 100644 (file)
index 0000000..2aed643
--- /dev/null
@@ -0,0 +1,10 @@
+static @INLINE_KEYWORD@ void test_inline(void)
+{
+       return;
+}
+
+int main (void)
+{
+       test_inline ();
+       return 0;
+}
diff --git a/cmake/TestInline.cmake b/cmake/TestInline.cmake
new file mode 100644 (file)
index 0000000..ef15c07
--- /dev/null
@@ -0,0 +1,54 @@
+macro (TEST_INLINE)
+       if (NOT DEFINED INLINE_CODE)
+               message (STATUS "Checking for inline...")
+               set (INLINE_KEYWORD "inline")
+               configure_file (cmake/TestInline.c.in ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c)
+               try_compile (HAVE_INLINE "${CMAKE_CURRENT_BINARY_DIR}"
+                    "${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c")
+               if (HAVE_INLINE)
+                       message (STATUS "Checking for inline... supported")
+               else ()
+                       message (STATUS "Checking for inline... not supported")
+                       
+                       message (STATUS "Checking for __inline...")
+                       set (INLINE_KEYWORD "__inline")
+                       configure_file (cmake/TestInline.c.in ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c)
+                       try_compile (HAVE___INLINE "${CMAKE_CURRENT_BINARY_DIR}"
+                    "${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c")
+                       if (HAVE___INLINE)
+                               message (STATUS "Checking for __inline... supported")
+                       else ()
+                               message (STATUS "Checking for __inline... not supported")
+                               
+                               message (STATUS "Checking for __inline__...")
+                               set (INLINE_KEYWORD "__inline__")
+                               configure_file (cmake/TestInline.c.in ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c)
+                               try_compile (HAVE___INLINE "${CMAKE_CURRENT_BINARY_DIR}"
+                                       "${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c")
+                               if (HAVE___INLINE)
+                                       message (STATUS "Checking for __inline__... supported")
+                                       
+                                       message (STATUS "Checking for __inline__...")
+                                       set (INLINE_KEYWORD "__inline__")
+                                       configure_file (cmake/TestInline.c.in ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/cmake/TestInline.c)
+                                       try_compile (HAVE___INLINE__ "${CMAKE_CURRENT_BINARY_DIR}"
+                                               "${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TestInline.c")
+                               else ()
+                                       message (STATUS "Checking for __inline__... not supported")
+                                       set (INLINE_KEYWORD "")
+                               endif ()
+                               
+                       endif ()                        
+               endif ()
+               
+               if (HAVE_INLINE)
+                       set (INLINE_CODE "/* #undef inline */" CACHE INTERNAL "")
+               elseif (HAVE___INLINE)
+                       set (INLINE_CODE "#define inline __inline" CACHE INTERNAL "")
+               elseif (HAVE___INLINE__)
+                       set (INLINE_CODE "#define inline __inline__" CACHE INTERNAL "")
+               else ()
+                       set (INLINE_CODE "#define inline " CACHE INTERNAL "")
+               endif ()
+       endif ()
+endmacro (TEST_INLINE)
diff --git a/cmake/TestLargeFiles.cmake b/cmake/TestLargeFiles.cmake
new file mode 100644 (file)
index 0000000..075407b
--- /dev/null
@@ -0,0 +1,121 @@
+include (CheckIncludeFile)
+include (CheckTypeSize)
+include (CMakePushCheckState)
+
+macro (TEST_LARGE_FILES VARIABLE)
+
+if (NOT DEFINED ${VARIABLE})
+
+       cmake_push_check_state()
+
+       message (STATUS "")
+       message (STATUS "")
+       message (STATUS "Checking large files support...")
+
+       if (WIN32)
+               set (${VARIABLE} 1 CACHE INTERNAL "Result of tests for large file support" FORCE)
+               message (STATUS "")
+               message (STATUS "Result of checking large files support: supported with WinAPI")
+       else ()
+
+               message (STATUS "")
+               check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+               check_include_file(stdint.h HAVE_STDINT_H)
+               check_include_file(stddef.h HAVE_STDDEF_H)
+               message (STATUS "")
+
+               message (STATUS "Checking size of off_t without any definitions:")
+               check_type_size (off_t SIZEOF_OFF_T)
+               message (STATUS "Checking of off_t without any definitions: ${SIZEOF_OFF_T}")
+               if (SIZEOF_OFF_T EQUAL 8)
+                       set (LARGE_FILES_DEFINITIONS "" CACHE INTERNAL "64-bit off_t required definitions")
+                       set (FILE64 TRUE)
+               else ()
+                       unset (HAVE_SIZEOF_OFF_T CACHE)
+                       unset (SIZEOF_OFF_T CACHE)
+                       unset (SIZEOF_OFF_T_CODE CACHE)
+                       cmake_pop_check_state()
+                       set (FILE64 FALSE)
+               endif ()
+
+               if (NOT FILE64)
+                       set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} /D_FILE_OFFSET_BITS=64)
+                       message (STATUS "")
+                       message (STATUS "Checking size of off_t with _FILE_OFFSET_BITS=64:")
+                       check_type_size (off_t SIZEOF_OFF_T)
+                       message (STATUS "Checking size of off_t with _FILE_OFFSET_BITS=64: ${SIZEOF_OFF_T}")
+                       if (SIZEOF_OFF_T EQUAL 8)
+                               set (_FILE_OFFSET_BITS 64 CACHE INTERNAL "")
+                               set (_FILE_OFFSET_BITS_CODE "#define _FILE_OFFSET_BITS 64" CACHE INTERNAL "")
+                               set (LARGE_FILES_DEFINITIONS ${LARGE_FILES_DEFINITIONS} "/D_FILE_OFFSET_BITS=64" CACHE INTERNAL "64-bit off_t required definitions")
+                               set (FILE64 TRUE)
+                       else ()
+                               set (_FILE_OFFSET_BITS_CODE "" CACHE INTERNAL "")
+                               unset (HAVE_SIZEOF_OFF_T CACHE)
+                               unset (SIZEOF_OFF_T CACHE)
+                               unset (SIZEOF_OFF_T_CODE CACHE)
+                               cmake_pop_check_state()
+                               set (FILE64 FALSE)
+                       endif ()
+               endif ()
+
+               if (NOT FILE64)
+                       set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} /D_LARGE_FILES)
+                       message (STATUS "")
+                       message (STATUS "Checking size of off_t with _LARGE_FILES:")
+                       check_type_size (off_t SIZEOF_OFF_T)
+                       message (STATUS "Checking size of off_t with _LARGE_FILES: ${SIZEOF_OFF_T}")
+                       if (SIZEOF_OFF_T EQUAL 8)
+                               set (_LARGE_FILES 1 CACHE INTERNAL "")
+                               set (LARGE_FILES_DEFINITIONS ${LARGE_FILES_DEFINITIONS} "/D_LARGE_FILES" CACHE INTERNAL "64-bit off_t required definitions")
+                               set (FILE64 TRUE)
+                       else ()
+                               unset (HAVE_SIZEOF_OFF_T CACHE)
+                               unset (SIZEOF_OFF_T CACHE)
+                               unset (SIZEOF_OFF_T_CODE CACHE)
+                               cmake_pop_check_state()
+                               set (FILE64 FALSE)
+                       endif ()
+               endif ()
+
+               if (NOT FILE64)
+                       set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} /D_LARGEFILE_SOURCE)
+                       unset (HAVE_SIZEOF_OFF_T CACHE)
+                       unset (SIZEOF_OFF_T CACHE)
+                       unset (SIZEOF_OFF_T_CODE CACHE)
+                       message (STATUS "")
+                       message (STATUS "Checking size of off_t with _LARGEFILE_SOURCE:")
+                       check_type_size (off_t SIZEOF_OFF_T)
+                       message (STATUS "Checking size of off_t with _LARGEFILE_SOURCE: ${SIZEOF_OFF_T}")
+                       if (SIZEOF_OFF_T EQUAL 8)
+                               set (_LARGEFILE_SOURCE 1 CACHE INTERNAL "")
+                               set (LARGE_FILES_DEFINITIONS ${LARGE_FILES_DEFINITIONS} "/D_LARGEFILE_SOURCE"  CACHE INTERNAL "64-bit off_t required definitions")
+                               set (FILE64 TRUE)
+                       else ()
+                               cmake_pop_check_state()
+                               set (FILE64 FALSE)
+                       endif ()
+               endif ()
+
+               message (STATUS "")
+               if (FILE64)
+                       set (${VARIABLE} 1 CACHE INTERNAL "Result of tests for large file support" FORCE)
+                       if (NOT SIZEOF_OFF_T_REQURED_DEFINITIONS)
+                               message (STATUS "Result of checking large files support: supported")
+                       else ()
+                               message (STATUS "Result of checking large files support: supported with ${LARGE_FILES_DEFINITIONS}")
+                               message (STATUS "Add LARGE_FILES_DEFINITIONS to your compiler definitions or configure with _FILE_OFFSET_BITS,")
+                               message (STATUS "_FILE_OFFSET_BITS_CODE, _LARGE_FILES and _LARGEFILE_SOURCE variables.")
+                       endif ()
+               else ()
+                       message ("Result of checking large files support: not supported")
+                       set (${VARIABLE} 0 CACHE INTERNAL "Result of test for large file support" FORCE)
+               endif ()
+               message ("")
+               message ("")
+
+       endif ()
+
+endif (NOT DEFINED ${VARIABLE})
+
+endmacro (TEST_LARGE_FILES VARIABLE)
diff --git a/cmake/sqlite/FindSQLite3.cmake b/cmake/sqlite/FindSQLite3.cmake
new file mode 100644 (file)
index 0000000..a0385ca
--- /dev/null
@@ -0,0 +1,56 @@
+# - Find SQLite3
+# Find the native SQLite3 includes and libraries
+#
+#  SQLite3_INCLUDE_DIRS - where to find sqlite3.h, etc.
+#  SQLite3_LIBRARIES    - List of libraries when using SQLite3.
+#  SQLite3_FOUND        - True if SQLite3 found.
+
+if (SQLite3_INCLUDE_DIR)
+       # Already in cache, be silent
+       set (SQLite3_FIND_QUIETLY TRUE)
+endif ()
+
+find_package (PkgConfig QUIET)
+pkg_check_modules (PC_SQLite3 QUIET sqlite3)
+
+set (SQLite3_VERSION ${PC_SQLite3_VERSION})
+
+find_path (SQLite3_INCLUDE_DIR sqlite3.h
+       HINTS
+               ${PC_SQLite3_INCLUDEDIR}
+               ${PC_SQLite3_INCLUDE_DIRS}
+               ${SQLite3_ROOT}
+       )
+
+find_library (SQLite3_LIBRARY
+       NAMES
+               sqlite3
+       HINTS
+               ${PC_SQLite3_LIBDIR}
+               ${PC_SQLite3_LIBRARY_DIRS}
+               ${SQLite3_ROOT}
+       )
+
+include (FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args (SQLite3
+       REQUIRED_VARS
+               SQLite3_LIBRARY
+               SQLite3_INCLUDE_DIR
+       VERSION_VAR
+               SQLite3_VERSION
+       )
+
+if (SQLite3_FOUND)
+       set (SQLite3_INCLUDE_DIRS ${SQLite3_INCLUDE_DIR})
+       set (SQLite3_LIBRARIES ${SQLite3_LIBRARY})
+       if (NOT TARGET SQLite::SQLite3)
+               add_library (SQLite::SQLite3 UNKNOWN IMPORTED)
+               set_target_properties (SQLite::SQLite3 PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${SQLite3_INCLUDE_DIRS}"
+                       IMPORTED_LOCATION "${SQLite3_LIBRARIES}"
+               )
+       endif ()
+endif ()
+
+mark_as_advanced (SQLite3_INCLUDE_DIR SQLite3_LIBRARY)
index f4ec6c4..78a79da 100644 (file)
-# Copyright (C) 1999-2017  Erik de Castro Lopo <erikd@mega-nerd.com>.
-
-dnl Require autoconf version
-AC_PREREQ(2.57)
-
-AC_INIT([libsndfile],[1.0.28],[sndfile@mega-nerd.com],
-               [libsndfile],[http://www.mega-nerd.com/libsndfile/])
+dnl Copyright (C) 1999-2021  Erik de Castro Lopo <erikd@mega-nerd.com>.
+
+dnl Require autoconf version >= 2.69
+AC_PREREQ([2.69])
+
+AC_INIT([libsndfile],[1.0.31],[sndfile@mega-nerd.com],
+               [libsndfile],[http://libsndfile.github.io/libsndfile/])
+
+dnl Check whether we want to set defaults for CFLAGS, CXXFLAGS, CPPFLAGS and LDFLAGS
+AC_MSG_CHECKING([whether configure should try to set CFLAGS/CXXFLAGS/CPPFLAGS/LDFLAGS])
+AS_IF([test "x${CFLAGS+set}" = "xset" || test "x${CXXFLAGS+set}" = "xset" || test "x${CPPFLAGS+set}" = "xset" || test "x${LDFLAGS+set}" = "xset"], [
+               enable_flags_setting=no
+               : ${CFLAGS=""}
+               : ${CXXFLAGS=""}
+       ], [
+               enable_flags_setting=yes
+               dnl Set to empty flags so AC_PROG_CC and
+               dnl AC_PROG_CXX do not add -g -O2
+               CFLAGS=""
+               CXXFLAGS=""
+       ])
+AC_MSG_RESULT([${enable_flags_setting}])
 
-# Put config stuff in Cfg.
-AC_CONFIG_AUX_DIR(Cfg)
-AC_CONFIG_MACRO_DIR([M4])
+dnl Put config stuff in 'build-aux'.
+AC_CONFIG_AUX_DIR([build-aux])
 
 AC_CONFIG_SRCDIR([src/sndfile.c])
-AC_CANONICAL_TARGET([])
+AC_CANONICAL_HOST
 
+AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_HEADERS([src/config.h])
 
-AM_INIT_AUTOMAKE
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+AM_INIT_AUTOMAKE([1.14 foreign dist-bzip2 no-dist-gzip serial-tests subdir-objects])
+AM_SILENT_RULES([yes])
 
-AC_LANG([C])
+dnl ====================================================================================
+
+AC_PROG_CC
+AC_PROG_CC_C99
+
+AS_IF([test "x$ac_cv_prog_cc_c99" = "xno"], [
+               AC_MSG_ERROR([libsndfile requires a C99 capable compiler!])
+       ])
 
-AC_PROG_CC_STDC
 AC_USE_SYSTEM_EXTENSIONS
-AM_PROG_CC_C_O
 AC_PROG_CXX
 
-MN_C_COMPILER_IS_CLANG
-MN_GCC_REALLY_IS_GCC
+AC_LANG([C])
+AX_COMPILER_VENDOR
+AX_COMPILER_VERSION
+
+AC_LANG_PUSH([C++])
+AX_COMPILER_VENDOR
+AX_COMPILER_VERSION
+AC_LANG_POP([C++])
 
 AC_PROG_SED
-m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+AM_PROG_AR
 
-LT_INIT
+LT_INIT([win32-dll])
 LT_PROG_RC
 
 AC_PROG_INSTALL
 AC_PROG_LN_S
 
-AC_CHECK_PROG(HAVE_AUTOGEN, autogen, yes, no)
-AC_CHECK_PROG(HAVE_WINE, wine, yes, no)
-AC_CHECK_PROG(HAVE_XCODE_SELECT, xcode-select, yes, no)
-
-#------------------------------------------------------------------------------------
-# Rules for library version information:
-#
-#  1. Start with version information of `0:0:0' for each libtool library.
-#  2. Update the version information only immediately before a public release of
-#     your software. More frequent updates are unnecessary, and only guarantee
-#     that the current interface number gets larger faster.
-#  3. If the library source code has changed at all since the last update, then
-#     increment revision (`c:r:a' becomes `c:r+1:a').
-#  4. If any interfaces have been added, removed, or changed since the last update,
-#     increment current, and set revision to 0.
-#  5. If any interfaces have been added since the last public release, then increment
-#     age.
-#  6. If any interfaces have been removed since the last public release, then set age
-#     to 0.
-
-CLEAN_VERSION=`echo $PACKAGE_VERSION | $SED "s/p.*//"`
-VERSION_MINOR=`echo $CLEAN_VERSION | $SED "s/.*\.//"`
-
-SHARED_VERSION_INFO="1:$VERSION_MINOR:0"
-
-#------------------------------------------------------------------------------------
+AM_PATH_PYTHON
+
+AC_CHECK_PROG([HAVE_AUTOGEN], [autogen], [yes], [no])
+AC_CHECK_PROG([HAVE_WINE], [wine], [yes], [no])
+AC_CHECK_PROG([HAVE_XCODE_SELECT], [xcode-select], [yes], [no])
+
+dnl ------------------------------------------------------------------------------------
+dnl  Rules for library version information:
+dnl
+dnl   1. Start with version information of `0:0:0' for each libtool library.
+dnl   2. Update the version information only immediately before a public release of
+dnl      your software. More frequent updates are unnecessary, and only guarantee
+dnl      that the current interface number gets larger faster.
+dnl   3. If the library source code has changed at all since the last update, then
+dnl      increment revision (`c:r:a' becomes `c:r+1:a').
+dnl   4. If any interfaces have been added, removed, or changed since the last update,
+dnl      increment current, and set revision to 0.
+dnl   5. If any interfaces have been added since the last public release, then increment
+dnl      age.
+dnl   6. If any interfaces have been removed since the last public release, then set age
+dnl      to 0.
+SHARED_VERSION_INFO="1:31:0"
+
+dnl ------------------------------------------------------------------------------------
 
 AC_HEADER_STDC
 
-AC_CHECK_HEADERS(endian.h)
-AC_CHECK_HEADERS(byteswap.h)
-AC_CHECK_HEADERS(locale.h)
-AC_CHECK_HEADERS(sys/time.h)
+AC_CHECK_HEADERS([endian.h])
+AC_CHECK_HEADERS([byteswap.h])
+AC_CHECK_HEADERS([locale.h])
+AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_HEADERS([immintrin.h])
 
 AC_HEADER_SYS_WAIT
 
-AC_CHECK_DECLS(S_IRGRP)
-if test x$ac_cv_have_decl_S_IRGRP = xyes ; then
-       AC_DEFINE_UNQUOTED([HAVE_DECL_S_IRGRP],1,[Set to 1 if S_IRGRP is defined.])
-else
-       AC_DEFINE_UNQUOTED([HAVE_DECL_S_IRGRP],0)
-       fi
+AC_CHECK_DECLS([S_IRGRP])
+AS_IF([test "x$ac_cv_have_decl_S_IRGRP" = "xyes"], [
+               AC_DEFINE_UNQUOTED([HAVE_DECL_S_IRGRP], [1], [Set to 1 if S_IRGRP is defined.])
+       ], [
+               AC_DEFINE_UNQUOTED([HAVE_DECL_S_IRGRP], [0], [Set to 0 if S_IRGRP is not defined.])
+       ])
 
 AM_CONDITIONAL([LINUX_MINGW_CROSS_TEST],
-       [test "$build_os:$target_os:$host_os:$HAVE_WINE" = "linux-gnu:mingw32msvc:mingw32msvc:yes"])
-
-gl_VISIBILITY
+       [test "x${build_os}:${host_os}:${HAVE_WINE}" = "xlinux-gnu:mingw32msvc:yes"])
 
-#====================================================================================
-# Couple of initializations here. Fill in real values later.
+dnl ====================================================================================
+dnl  Couple of initializations here. Fill in real values later.
 
 SHLIB_VERSION_ARG=""
 
-#====================================================================================
-# Finished checking, handle options.
+dnl ====================================================================================
+dnl  Finished checking, handle options.
 
 AC_ARG_ENABLE(experimental,
        AS_HELP_STRING([--enable-experimental], [enable experimental code]))
 
-EXPERIMENTAL_CODE=0
-if test x$enable_experimental = xyes ; then
-       EXPERIMENTAL_CODE=1
-       fi
-AC_DEFINE_UNQUOTED([ENABLE_EXPERIMENTAL_CODE],${EXPERIMENTAL_CODE}, [Set to 1 to enable experimental code.])
-
-AC_ARG_ENABLE(werror,
-       AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles]))
-
-AC_ARG_ENABLE(stack-smash-protection,
-       AS_HELP_STRING([--enable-stack-smash-protection], [Enable GNU GCC stack smash protection]))
+AS_IF([test "x$enable_experimental" = "xyes"], [
+               EXPERIMENTAL_CODE=1
+       ], [
+               EXPERIMENTAL_CODE=0
+       ])
+AC_DEFINE_UNQUOTED([ENABLE_EXPERIMENTAL_CODE], [${EXPERIMENTAL_CODE}], [Set to 1 to enable experimental code.])
 
-AC_ARG_ENABLE(gcc-pipe,
-       AS_HELP_STRING([--disable-gcc-pipe], [disable gcc -pipe option]))
+AC_ARG_ENABLE([werror],
+       [AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])])
 
-AC_ARG_ENABLE(gcc-opt,
-       AS_HELP_STRING([--disable-gcc-opt], [disable gcc optimisations]))
+AC_ARG_ENABLE([stack-smash-protection],
+       [AS_HELP_STRING([--enable-stack-smash-protection], [Enable GNU GCC stack smash protection])])
 
-AC_ARG_ENABLE(cpu-clip,
-       AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper]))
+AC_ARG_ENABLE([cpu-clip],
+       [AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])])
 
-AC_ARG_ENABLE(bow-docs,
-       AS_HELP_STRING([--enable-bow-docs], [enable black-on-white html docs]))
+AC_ARG_ENABLE([bow-docs],
+       [AS_HELP_STRING([--enable-bow-docs], [enable black-on-white html docs])])
 
-AC_ARG_ENABLE(sqlite,
-       AS_HELP_STRING([--disable-sqlite], [disable use of sqlite]))
+AC_ARG_ENABLE([sqlite],
+       [AS_HELP_STRING([--disable-sqlite], [disable use of sqlite])])
 
-AC_ARG_ENABLE(alsa,
-       AS_HELP_STRING([--disable-alsa], [disable use of ALSA]))
+AC_ARG_ENABLE([alsa],
+       [AS_HELP_STRING([--disable-alsa], [disable ALSA support (default=autodetect)])], [], [enable_alsa=auto])
 
-AC_ARG_ENABLE(external-libs,
-       AS_HELP_STRING([--disable-external-libs], [disable use of FLAC, Ogg and Vorbis [[default=no]]]))
+AC_ARG_ENABLE([external-libs],
+       [AS_HELP_STRING([--disable-external-libs], [disable use of FLAC, Ogg and Vorbis [[default=no]]])])
 
 AC_ARG_ENABLE(octave,
-       AS_HELP_STRING([--enable-octave], [disable building of GNU Octave module]))
+       [AS_HELP_STRING([--enable-octave], [enable building of GNU Octave module])])
 
 AC_ARG_ENABLE([full-suite],
-       AS_HELP_STRING([--disable-full-suite], [disable building and installing programs, documentation, only build library [[default=no]]]))
+       [AS_HELP_STRING([--disable-full-suite], [disable building and installing programs, documentation, only build library [[default=no]]])])
 AM_CONDITIONAL([FULL_SUITE], [test "x$enable_full_suite" != "xno"])
 
-AC_ARG_ENABLE(test-coverage,
-       AS_HELP_STRING([--enable-test-coverage], [enable test coverage]))
-AM_CONDITIONAL([ENABLE_TEST_COVERAGE], [test "$enable_test_coverage" = yes])
-
-#====================================================================================
-# Check types and their sizes.
-
-AC_CHECK_SIZEOF(wchar_t,4)
-AC_CHECK_SIZEOF(short,2)
-AC_CHECK_SIZEOF(int,4)
-AC_CHECK_SIZEOF(long,4)
-AC_CHECK_SIZEOF(float,4)
-AC_CHECK_SIZEOF(double,4)
-AC_CHECK_SIZEOF(void*,8)
-AC_CHECK_SIZEOF(size_t,4)
-AC_CHECK_SIZEOF(int64_t,8)
-AC_CHECK_SIZEOF(long long,8)
-
-#====================================================================================
-# Find an appropriate type for sf_count_t.
-# On systems supporting files larger than 2 Gig, sf_count_t must be a 64 bit value.
-# Unfortunately there is more than one way of ensuring this so need to do some
-# pretty rigourous testing here.
-
-# Check for common 64 bit file offset types.
-AC_CHECK_SIZEOF(off_t,1)
-
-if test "$enable_largefile:$ac_cv_sizeof_off_t" = "no:8" ; then
-       echo
-       echo "Error : Cannot disable large file support because sizeof (off_t) == 8."
-       echo
-       exit 1
-       fi
-
-case "$host_os" in
-       mingw32*)
+AC_ARG_ENABLE([test-coverage],
+       [AS_HELP_STRING([--enable-test-coverage], [enable test coverage])])
+AM_CONDITIONAL([ENABLE_TEST_COVERAGE], [test "x$enable_test_coverage" = "xyes"])
+
+AC_ARG_ENABLE([ossfuzzers],
+  [AS_HELP_STRING([--enable-ossfuzzers],
+    [Whether to generate the fuzzers for OSS-Fuzz])],
+  [have_ossfuzzers=yes], [have_ossfuzzers=no])
+AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_ossfuzzers" = "xyes"])
+
+AC_SUBST([LIB_FUZZING_ENGINE])
+AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
+AM_CONDITIONAL([USE_OSSFUZZ_STATIC], [test -f "$LIB_FUZZING_ENGINE"])
+
+dnl ====================================================================================
+dnl  Check types and their sizes.
+
+AC_CHECK_SIZEOF([wchar_t], [4])
+AC_CHECK_SIZEOF([short], [2])
+AC_CHECK_SIZEOF([int], [4])
+AC_CHECK_SIZEOF([long], [4])
+AC_CHECK_SIZEOF([float], [4])
+AC_CHECK_SIZEOF([double], [4])
+AC_CHECK_SIZEOF([void*], [8])
+AC_CHECK_SIZEOF([size_t], [4])
+AC_CHECK_SIZEOF([int64_t], [8])
+AC_CHECK_SIZEOF([long long], [8])
+
+dnl ====================================================================================
+dnl  Find an appropriate type for sf_count_t.
+dnl  On systems supporting files larger than 2 Gig, sf_count_t must be a 64 bit value.
+dnl  Unfortunately there is more than one way of ensuring this so need to do some
+dnl  pretty rigourous testing here.
+
+dnl  Check for common 64 bit file offset types.
+AC_CHECK_SIZEOF([off_t], [1])
+
+AS_IF([test "x$enable_largefile:$ac_cv_sizeof_off_t" = "xno:8"], [
+               AC_MSG_ERROR(["Error : Cannot disable large file support because sizeof (off_t) == 8."])
+       ])
+
+AS_CASE([$host_os],
+       [mingw32*], [
                TYPEOF_SF_COUNT_T="__int64"
                SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
                SIZEOF_SF_COUNT_T=8
-               AC_DEFINE([__USE_MINGW_ANSI_STDIO],1,[Set to 1 to use C99 printf/snprintf in MinGW.])
-               ;;
-       *)
+               AC_DEFINE([__USE_MINGW_ANSI_STDIO], [1], [Set to 1 to use C99 printf/snprintf in MinGW.])
+               ],
+
+       [linux-android*], [
+               TYPEOF_SF_COUNT_T="int64_t"
+               SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
+               SIZEOF_SF_COUNT_T=8
+               ],
+
+       [
                SIZEOF_SF_COUNT_T=0
-               if test "x$ac_cv_sizeof_off_t" = "x8" ; then
-                       # If sizeof (off_t) is 8, no further checking is needed.
-                       TYPEOF_SF_COUNT_T="int64_t"
-                       SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
-                       SIZEOF_SF_COUNT_T=8
-               else
-                       # Save the old sizeof (off_t) value  and then unset it to see if it
-                       # changes when Large File Support is enabled.
-                       pre_largefile_sizeof_off_t=$ac_cv_sizeof_off_t
-                       unset ac_cv_sizeof_off_t
-
-                       AC_SYS_LARGEFILE
-                       if test "x$ac_cv_sys_largefile_CFLAGS" = "xno" ; then
-                               ac_cv_sys_largefile_CFLAGS=""
-                               fi
-                       if test "x$ac_cv_sys_largefile_LDFLAGS" = "xno" ; then
-                               ac_cv_sys_largefile_LDFLAGS=""
-                               fi
-                       if test "x$ac_cv_sys_largefile_LIBS" = "xno" ; then
-                               ac_cv_sys_largefile_LIBS=""
-                               fi
-
-                       AC_CHECK_SIZEOF(off_t,1)
-
-                       if test "x$ac_cv_sizeof_off_t" = "x8" ; then
+               AS_IF([test "x$ac_cv_sizeof_off_t" = "x8"], [
+                               dnl If sizeof (off_t) is 8, no further checking is needed.
                                TYPEOF_SF_COUNT_T="int64_t"
                                SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
                                SIZEOF_SF_COUNT_T=8
-                       elif test "x$TYPEOF_SF_COUNT_T" = "xunknown" ; then
-                               echo
-                               echo "*** The configure process has determined that this system is capable"
-                               echo "*** of Large File Support but has not been able to find a type which"
-                               echo "*** is an unambiguous 64 bit file offset."
-                               echo "*** Please contact the author to help resolve this problem."
-                               echo
-                               AC_MSG_ERROR([[Bad file offset type.]])
-                               fi
-                       fi
-               ;;
-       esac
-
-if test $SIZEOF_SF_COUNT_T = 4 ; then
-       SF_COUNT_MAX="0x7FFFFFFF"
-       fi
-
-AC_DEFINE_UNQUOTED([TYPEOF_SF_COUNT_T],${TYPEOF_SF_COUNT_T}, [Set to long if unknown.])
+                       ], [
+                               dnl Save the old sizeof (off_t) value  and then unset it to see if it
+                               dnl changes when Large File Support is enabled.
+                               pre_largefile_sizeof_off_t=$ac_cv_sizeof_off_t
+                               unset ac_cv_sizeof_off_t
+
+                               AC_SYS_LARGEFILE
+                               AS_IF([test "x$ac_cv_sys_largefile_CFLAGS" = "xno"], [
+                                               ac_cv_sys_largefile_CFLAGS=""
+                                       ])
+                               AS_IF([test "x$ac_cv_sys_largefile_LDFLAGS" = "xno"], [
+                                               ac_cv_sys_largefile_LDFLAGS=""
+                                       ])
+                               AS_IF([test "x$ac_cv_sys_largefile_LIBS" = "xno"], [
+                                               ac_cv_sys_largefile_LIBS=""
+                                       ])
+
+                               AC_CHECK_SIZEOF(off_t,1)
+
+                               AS_IF([test "x$ac_cv_sizeof_off_t" = "x8"], [
+                                               TYPEOF_SF_COUNT_T="int64_t"
+                                               SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
+                                               SIZEOF_SF_COUNT_T=8
+                                       ], [test "x$TYPEOF_SF_COUNT_T" = "xunknown"], [
+                                               AS_ECHO([""])
+                                               AS_ECHO(["*** The configure process has determined that this system is capable"])
+                                               AS_ECHO(["*** of Large File Support but has not been able to find a type which"])
+                                               AS_ECHO(["*** is an unambiguous 64 bit file offset."])
+                                               AS_ECHO(["*** Please contact the author to help resolve this problem."])
+                                               AS_ECHO([""])
+                                               AC_MSG_ERROR([[Bad file offset type.]])
+                                       ])
+                       ])
+       ])
+
+AS_CASE([$host_vendor],
+       [vita], [
+               TYPEOF_SF_COUNT_T="int64_t"
+               SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
+               SIZEOF_SF_COUNT_T=8
+       ])
+
+AS_IF([test "x$SIZEOF_SF_COUNT_T" = "x4"], [
+               SF_COUNT_MAX="0x7FFFFFFF"
+       ])
+
+AC_DEFINE_UNQUOTED([TYPEOF_SF_COUNT_T], [${TYPEOF_SF_COUNT_T}], [Set to long if unknown.])
 AC_SUBST(TYPEOF_SF_COUNT_T)
 
-AC_DEFINE_UNQUOTED([SIZEOF_SF_COUNT_T],${SIZEOF_SF_COUNT_T}, [Set to sizeof (long) if unknown.])
+AC_DEFINE_UNQUOTED([SIZEOF_SF_COUNT_T], [${SIZEOF_SF_COUNT_T}], [Set to sizeof (long) if unknown.])
 AC_SUBST(SIZEOF_SF_COUNT_T)
 
-AC_DEFINE_UNQUOTED([SF_COUNT_MAX],${SF_COUNT_MAX}, [Set to maximum allowed value of sf_count_t type.])
+AC_DEFINE_UNQUOTED([SF_COUNT_MAX], [${SF_COUNT_MAX}], [Set to maximum allowed value of sf_count_t type.])
 AC_SUBST(SF_COUNT_MAX)
 
 AC_TYPE_SSIZE_T
 
-#====================================================================================
-# Determine endian-ness of target processor.
-
-MN_C_FIND_ENDIAN
-
-AC_DEFINE_UNQUOTED(CPU_IS_BIG_ENDIAN, ${ac_cv_c_big_endian},
-       [Target processor is big endian.])
-AC_DEFINE_UNQUOTED(CPU_IS_LITTLE_ENDIAN, ${ac_cv_c_little_endian},
-       [Target processor is little endian.])
-AC_DEFINE_UNQUOTED(WORDS_BIGENDIAN, ${ac_cv_c_big_endian},
-       [Target processor is big endian.])
+dnl ====================================================================================
+dnl  Determine endian-ness of host processor.
+
+AC_C_BIGENDIAN([
+               dnl big-endian
+               ac_cv_c_big_endian=1
+               ac_cv_c_little_endian=0
+       ], [
+               dnl little-endian
+               ac_cv_c_big_endian=0
+               ac_cv_c_little_endian=1
+       ])
 
-#====================================================================================
-# Check for functions.
+AC_DEFINE_UNQUOTED([CPU_IS_BIG_ENDIAN], [${ac_cv_c_big_endian}], [Host processor is big endian.])
+AC_DEFINE_UNQUOTED([CPU_IS_LITTLE_ENDIAN], [${ac_cv_c_little_endian}], [Host processor is little endian.])
 
-AC_CHECK_FUNCS(malloc calloc realloc free)
-AC_CHECK_FUNCS(open read write lseek lseek64)
-AC_CHECK_FUNCS(fstat fstat64 ftruncate fsync)
-AC_CHECK_FUNCS(snprintf vsnprintf)
-AC_CHECK_FUNCS(gmtime gmtime_r localtime localtime_r gettimeofday)
-AC_CHECK_FUNCS(mmap getpagesize)
-AC_CHECK_FUNCS(setlocale)
-AC_CHECK_FUNCS(pipe waitpid)
+dnl ====================================================================================
+dnl  Check for functions.
 
-AC_CHECK_LIB([m],floor)
-AC_CHECK_FUNCS(floor ceil fmod lround)
+AC_CHECK_FUNCS([malloc calloc realloc free])
+AC_CHECK_FUNCS([open read write lseek lseek64])
+AC_CHECK_FUNCS([fstat fstat64 ftruncate fsync])
+AC_CHECK_FUNCS([snprintf vsnprintf])
+AC_CHECK_FUNCS([gmtime gmtime_r localtime localtime_r gettimeofday])
+AC_CHECK_FUNCS([mmap getpagesize])
+AC_CHECK_FUNCS([setlocale])
+AC_CHECK_FUNCS([pipe waitpid])
 
-MN_C99_FUNC_LRINT
-MN_C99_FUNC_LRINTF
+AC_SEARCH_LIBS([floor], [m], [], [
+               AC_MSG_ERROR([unable to find the floor() function!])
+       ])
+AC_CHECK_FUNCS([floor ceil fmod lrint lrintf])
 
-#====================================================================================
-# Check for requirements for building plugins for other languages/enviroments.
+dnl ====================================================================================
+dnl  Check for requirements for building plugins for other languages/enviroments.
 
 dnl Octave maths environment http://www.octave.org/
-if test x$cross_compiling = xno ; then
-       if test x$enable_octave = xno ; then
+AS_IF([test "x$cross_compiling" = "xno"], [
+               AS_IF([test "x$enable_octave" = "xno"], [
+                               AM_CONDITIONAL(BUILD_OCTAVE_MOD, false)
+                       ], [
+                               AC_OCTAVE_BUILD
+                       ])
+       ], [
                AM_CONDITIONAL(BUILD_OCTAVE_MOD, false)
-       else
-               AC_OCTAVE_BUILD
-               fi
-else
-       AM_CONDITIONAL(BUILD_OCTAVE_MOD, false)
-       fi
+       ])
 
-#====================================================================================
-# Check for Ogg, Vorbis and FLAC.
+dnl ====================================================================================
+dnl  Check for Ogg, Vorbis and FLAC.
 
 HAVE_EXTERNAL_XIPH_LIBS=0
 EXTERNAL_XIPH_CFLAGS=""
 EXTERNAL_XIPH_LIBS=""
+EXTERNAL_XIPH_REQUIRE=""
 
-# Check for pkg-config outside the if statement.
+dnl Check for pkg-config outside the if statement.
 PKG_PROG_PKG_CONFIG
-m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR], AC_SUBST([pkgconfigdir], ${libdir}/pkgconfig))
-
-if test -n "$PKG_CONFIG" ; then
-       if test x$enable_external_libs = xno ; then
-               AC_MSG_WARN([[*** External libs (FLAC, Ogg, Vorbis) disabled. ***]])
-       else
-               PKG_CHECK_MOD_VERSION(FLAC, flac >= 1.3.1, ac_cv_flac=yes, ac_cv_flac=no)
-
-               # Make sure the FLAC_CFLAGS value is sane.
-               FLAC_CFLAGS=`echo $FLAC_CFLAGS | $SED "s|include/FLAC|include|"`
-
-               PKG_CHECK_MOD_VERSION(OGG, ogg >= 1.1.3, ac_cv_ogg=yes, ac_cv_ogg=no)
-
-               if test x$enable_experimental = xyes ; then
-                       PKG_CHECK_MOD_VERSION(SPEEX, speex >= 1.2, ac_cv_speex=yes, ac_cv_speex=no)
-               else
-                       SPEEX_CFLAGS=""
-                       SPEEX_LIBS=""
-                       fi
-
-               # Vorbis versions earlier than 1.2.3 have bugs that cause the libsndfile
-               # test suite to fail on MIPS, PowerPC and others.
-               # See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549899
-               PKG_CHECK_MOD_VERSION(VORBIS, vorbis >= 1.2.3, ac_cv_vorbis=yes, ac_cv_vorbis=no)
-               PKG_CHECK_MOD_VERSION(VORBISENC, vorbisenc >= 1.2.3, ac_cv_vorbisenc=yes, ac_cv_vorbisenc=no)
-               enable_external_libs=yes
-               fi
-
-       if test x$ac_cv_flac$ac_cv_ogg$ac_cv_vorbis$ac_cv_vorbisenc = "xyesyesyesyes" ; then
-               HAVE_EXTERNAL_XIPH_LIBS=1
-               enable_external_libs=yes
-
-               EXTERNAL_XIPH_CFLAGS="$FLAC_CFLAGS $OGG_CFLAGS $VORBIS_CFLAGS $VORBISENC_CFLAGS $SPEEX_CFLAGS"
-               EXTERNAL_XIPH_LIBS="$FLAC_LIBS $OGG_LIBS $VORBIS_LIBS $VORBISENC_LIBS $SPEEX_LIBS "
-       else
-               echo
-               AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg and]])
-               AC_MSG_WARN([[*** libvorbis) is either missing (possibly only the development]])
-               AC_MSG_WARN([[*** headers) or is of an unsupported version.]])
-               AC_MSG_WARN([[***]])
-               AC_MSG_WARN([[*** Unfortunately, for ease of maintenance, the external libs]])
-               AC_MSG_WARN([[*** are an all or nothing affair.]])
-               echo
-               enable_external_libs=no
-               fi
-       fi
-
-AC_DEFINE_UNQUOTED([HAVE_EXTERNAL_XIPH_LIBS], $HAVE_EXTERNAL_XIPH_LIBS, [Will be set to 1 if flac, ogg and vorbis are available.])
-
-#====================================================================================
-# Check for libsqlite3 (only used in regtest).
-
-ac_cv_sqlite3=no
-if test x$enable_sqlite != xno ; then
-       PKG_CHECK_MOD_VERSION(SQLITE3, sqlite3 >= 3.2, ac_cv_sqlite3=yes, ac_cv_sqlite3=no)
-       fi
-
-if test x$ac_cv_sqlite3 = "xyes" ; then
-       HAVE_SQLITE3=1
-else
-       HAVE_SQLITE3=0
-       fi
-
-AC_DEFINE_UNQUOTED([HAVE_SQLITE3],$HAVE_SQLITE3,[Set to 1 if you have libsqlite3.])
-AM_CONDITIONAL([HAVE_SQLITE3], [test "x$ac_cv_sqlite3" = "xyes"])
-
-#====================================================================================
-# Determine if the processor can do clipping on float to int conversions.
-
-if test x$enable_cpu_clip != "xno" ; then
-       MN_C_CLIP_MODE
-else
-       echo "checking processor clipping capabilities... disabled"
-       ac_cv_c_clip_positive=0
-       ac_cv_c_clip_negative=0
-       fi
-
-AC_DEFINE_UNQUOTED(CPU_CLIPS_POSITIVE, ${ac_cv_c_clip_positive},
-       [Target processor clips on positive float to int conversion.])
-AC_DEFINE_UNQUOTED(CPU_CLIPS_NEGATIVE, ${ac_cv_c_clip_negative},
-       [Target processor clips on negative float to int conversion.])
-
-#====================================================================================
-# Target OS specific stuff.
+AX_REQUIRE_DEFINED([PKG_INSTALLDIR])
+PKG_INSTALLDIR
+
+AS_IF([test -n "$PKG_CONFIG"], [
+               AS_IF([test "x$enable_external_libs" = "xno"], [
+                               AC_MSG_WARN([[*** External libs (FLAC, Ogg, Vorbis) disabled. ***]])
+                       ], [
+                               PKG_CHECK_MOD_VERSION(FLAC, flac >= 1.3.1, ac_cv_flac=yes, ac_cv_flac=no)
+
+                               dnl Make sure the FLAC_CFLAGS value is sane.
+                               FLAC_CFLAGS=`echo $FLAC_CFLAGS | $SED "s|include/FLAC|include|"`
+
+                               PKG_CHECK_MOD_VERSION(OGG, ogg >= 1.3.0, ac_cv_ogg=yes, ac_cv_ogg=no)
+
+                               AS_IF([test "x$enable_experimental" = "xyes"], [
+                                               PKG_CHECK_MOD_VERSION(SPEEX, speex >= 1.2, ac_cv_speex=yes, ac_cv_speex=no)
+                                       ], [
+                                               SPEEX_CFLAGS=""
+                                               SPEEX_LIBS=""
+                                       ])
+
+                               dnl Vorbis versions earlier than 1.2.3 have bugs that cause the libsndfile
+                               dnl test suite to fail on MIPS, PowerPC and others.
+                               dnl See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549899
+                               PKG_CHECK_MOD_VERSION(VORBIS, vorbis >= 1.2.3, ac_cv_vorbis=yes, ac_cv_vorbis=no)
+                               PKG_CHECK_MOD_VERSION(VORBISENC, vorbisenc >= 1.2.3, ac_cv_vorbisenc=yes, ac_cv_vorbisenc=no)
+
+                               PKG_CHECK_MOD_VERSION(OPUS, opus >= 1.1, ac_cv_opus=yes, ac_cv_opus=no)
+                               enable_external_libs=yes
+                       ])
+
+                       AS_IF([test "x$ac_cv_flac$ac_cv_ogg$ac_cv_vorbis$ac_cv_vorbisenc$ac_cv_opus" = "xyesyesyesyesyes"], [
+                                       HAVE_EXTERNAL_XIPH_LIBS=1
+                                       enable_external_libs=yes
+
+                                       EXTERNAL_XIPH_CFLAGS="$FLAC_CFLAGS $VORBIS_CFLAGS $VORBISENC_CFLAGS $SPEEX_CFLAGS $OPUS_CFLAGS $OGG_CFLAGS "
+                                       EXTERNAL_XIPH_LIBS="$FLAC_LIBS $VORBIS_LIBS $VORBISENC_LIBS $SPEEX_LIBS $OPUS_LIBS $OGG_LIBS "
+                                       EXTERNAL_XIPH_REQUIRE="flac ogg vorbis vorbisenc opus"
+
+                                       if test x$ac_cv_speex = "xyes" ; then
+                                               EXTERNAL_XIPH_REQUIRE="$EXTERNAL_XIPH_REQUIRE speex"
+                                       fi
+                               ], [
+                                       AS_ECHO([""])
+                                       AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg and]])
+                                       AC_MSG_WARN([[*** libvorbis) is either missing (possibly only the development]])
+                                       AC_MSG_WARN([[*** headers) or is of an unsupported version.]])
+                                       AC_MSG_WARN([[***]])
+                                       AC_MSG_WARN([[*** Unfortunately, for ease of maintenance, the external libs]])
+                                       AC_MSG_WARN([[*** are an all or nothing affair.]])
+                                       AS_ECHO([""])
+                                       enable_external_libs=no
+                               ])
+       ])
+
+AC_DEFINE_UNQUOTED([HAVE_EXTERNAL_XIPH_LIBS], [$HAVE_EXTERNAL_XIPH_LIBS], [Will be set to 1 if flac, ogg, vorbis, and opus are available.])
+
+dnl ====================================================================================
+dnl  Check for libsqlite3 (only used in regtest).
+
+ac_cv_sqlite3=0
+AS_IF([test "x$enable_sqlite" != "xno"], [
+               PKG_CHECK_MOD_VERSION([SQLITE3], [sqlite3 >= 3.2], [ac_cv_sqlite3=1], [ac_cv_sqlite3=0])
+       ])
+
+AC_DEFINE_UNQUOTED([HAVE_SQLITE3], [${ac_cv_sqlite3}], [Set to 1 if you have libsqlite3.])
+AM_CONDITIONAL([HAVE_SQLITE3], [test "x$ac_cv_sqlite3" = "x1"])
+
+dnl ====================================================================================
+dnl  Determine if the processor can do clipping on float to int conversions.
+
+AS_IF([test "x$enable_cpu_clip" != "xno"], [
+               MN_C_CLIP_MODE
+       ], [
+               AS_ECHO(["checking processor clipping capabilities... disabled"])
+               ac_cv_c_clip_positive=0
+               ac_cv_c_clip_negative=0
+       ])
+
+AC_DEFINE_UNQUOTED([CPU_CLIPS_POSITIVE], [${ac_cv_c_clip_positive}],
+       [Host processor clips on positive float to int conversion.])
+AC_DEFINE_UNQUOTED([CPU_CLIPS_NEGATIVE], [${ac_cv_c_clip_negative}],
+       [Host processor clips on negative float to int conversion.])
+
+dnl ====================================================================================
+dnl  Host OS specific stuff.
 
 OS_SPECIFIC_CFLAGS=""
 OS_SPECIFIC_LINKS=""
 os_is_win32=0
 os_is_openbsd=0
 use_windows_api=0
-case "$host_os" in
-       darwin* | rhapsody*)
-               if test x$HAVE_XCODE_SELECT = xyes ; then
-                       developer_path=`xcode-select --print-path`
-               else
-                       developer_path="/Developer"
-                       fi
-               OS_SPECIFIC_LINKS="-framework CoreAudio -framework AudioToolbox -framework CoreFoundation"
-               ;;
-       mingw*)
+AS_CASE([$host_os],
+       [darwin* | rhapsody*], [
+               AS_IF([test "x$HAVE_XCODE_SELECT" = "xyes"], [
+                               developer_path=`xcode-select --print-path`
+                       ], [
+                               developer_path="/Developer"
+                       ])
+               OS_SPECIFIC_LINKS="-framework CoreAudio -framework AudioToolbox -framework CoreFoundation"],
+       [mingw*], [
                os_is_win32=1
                use_windows_api=1
-               OS_SPECIFIC_LINKS="-lwinmm"
-               ;;
-       openbsd*)
+               OS_SPECIFIC_LINKS="-lwinmm"],
+       [openbsd*], [
                os_is_openbsd=1
-               ;;
-       esac
+       ])
 
-AC_DEFINE_UNQUOTED(OS_IS_WIN32, ${os_is_win32}, [Set to 1 if compiling for Win32])
-AC_DEFINE_UNQUOTED(OS_IS_OPENBSD, ${os_is_openbsd}, [Set to 1 if compiling for OpenBSD])
-AC_DEFINE_UNQUOTED(USE_WINDOWS_API, ${use_windows_api}, [Set to 1 to use the native windows API])
+AC_DEFINE_UNQUOTED([OS_IS_WIN32], [${os_is_win32}], [Set to 1 if compiling for Win32])
+AC_DEFINE_UNQUOTED([OS_IS_OPENBSD], [${os_is_openbsd}], [Set to 1 if compiling for OpenBSD])
+AC_DEFINE_UNQUOTED([USE_WINDOWS_API], [${use_windows_api}], [Set to 1 to use the native windows API])
 AM_CONDITIONAL(USE_WIN_VERSION_FILE, test ${use_windows_api} -eq 1)
 
-#====================================================================================
-# Check for ALSA.
-
-ALSA_LIBS=""
-
-if test x$enable_alsa != xno ; then
-       AC_CHECK_HEADERS(alsa/asoundlib.h)
-       if test x$ac_cv_header_alsa_asoundlib_h = xyes ; then
-               ALSA_LIBS="-lasound"
-               enable_alsa=yes
-               fi
-       fi
+dnl ====================================================================================
+dnl  Check for ALSA.
+
+AS_IF([test "x$enable_alsa" != "xno"], [
+               PKG_CHECK_MODULES([ALSA], [alsa], [
+                               dnl actually test whether ALSA really works, in
+                               dnl order to dodge wrong cross-compilation pickups
+                               save_CFLAGS="${CFLAGS}"
+                               save_LIBS="${LIBS}"
+                               CFLAGS="${CFLAGS} ${ALSA_CFLAGS}"
+                               LIBS="${LIBS} ${ALSA_LIBS}"
+                               AC_CHECK_HEADERS([alsa/asoundlib.h])
+                               AS_IF([test "x$ac_cv_header_alsa_asoundlib_h" = "xyes"], [
+                                               dnl ALSA definitely works
+                                               AC_DEFINE([HAVE_ALSA], [1], [Set to 1 if you have alsa])
+                                               alsa_works="yes"
+                                       ], [
+                                               dnl picked up wrong ALSA
+                                               alsa_works="no"
+
+                                               dnl reset flags
+                                               ALSA_CFLAGS=""
+                                               ALSA_LIBS=""
+                                       ])
+                               CFLAGS="${save_CFLAGS}"
+                               LIBS="${save_LIBS}"
+                       ], [
+                               dnl could not find ALSA
+                               alsa_works="no"
+                       ])
+
+               AS_IF([test "x$alsa_works" = "xno"], [
+                               AS_IF([test "x$enable_alsa" = "xyes"], [
+                                               dnl explicitly passed --enable-alsa, hence error out loud and clearly
+                                               AC_MSG_ERROR([You explicitly requested alsa support, but alsa could not be found!])
+                                       ], [
+                                               dnl did not explicitly pass --enable-alsa, relying on default automagic on
+                                               enable_alsa="no (auto)"
+                                       ])
+                       ])
+       ])
 
-#====================================================================================
-# Check for OpenBSD's sndio.
+dnl ====================================================================================
+dnl  Check for OpenBSD's sndio.
 
 SNDIO_LIBS=""
 HAVE_SNDIO_H=0
-case "$host_os" in
-       openbsd*)
+AS_CASE([$host_os],
+       [openbsd*], [
                AC_CHECK_HEADERS(sndio.h)
-               if test x$ac_cv_header_sndio_h = xyes ; then
-                       SNDIO_LIBS="-lsndio"
-                       HAVE_SNDIO_H=1
-                       fi
-               ;;
-       *)
-               ;;
-       esac
-
-AC_DEFINE_UNQUOTED([HAVE_SNDIO_H],${HAVE_SNDIO_H},[Set to 1 if <sndio.h> is available.])
-
-#====================================================================================
-# Test for sanity when cross-compiling.
-
-if test $ac_cv_sizeof_short != 2 ; then
-       AC_MSG_WARN([[******************************************************************]])
-       AC_MSG_WARN([[*** sizeof (short) != 2.                                          ]])
-       AC_MSG_WARN([[******************************************************************]])
-       fi
-
-if test $ac_cv_sizeof_int != 4 ; then
-       AC_MSG_WARN([[******************************************************************]])
-       AC_MSG_WARN([[*** sizeof (int) != 4                                             ]])
-       AC_MSG_WARN([[******************************************************************]])
-       fi
-
-if test $ac_cv_sizeof_float != 4 ; then
-       AC_MSG_WARN([[******************************************************************]])
-       AC_MSG_WARN([[*** sizeof (float) != 4.                                          ]])
-       AC_MSG_WARN([[******************************************************************]])
-       fi
-
-if test $ac_cv_sizeof_double != 8 ; then
-       AC_MSG_WARN([[******************************************************************]])
-       AC_MSG_WARN([[*** sizeof (double) != 8.                                         ]])
-       AC_MSG_WARN([[******************************************************************]])
-       fi
-
-if test x"$ac_cv_prog_HAVE_AUTOGEN" = "xno" ; then
-       AC_MSG_WARN([[Touching files in directory tests/.]])
-       touch tests/*.c tests/*.h
-       fi
-
-#====================================================================================
-# Settings for the HTML documentation.
-
-if test x$enable_bow_docs = "xyes" ; then
-       HTML_BGCOLOUR="white"
-       HTML_FGCOLOUR="black"
-else
-       HTML_BGCOLOUR="black"
-       HTML_FGCOLOUR="white"
-       fi
-
-#====================================================================================
-# Now use the information from the checking stage.
+               AS_IF([test "x$ac_cv_header_sndio_h" = "xyes"], [
+                               SNDIO_LIBS="-lsndio"
+                               HAVE_SNDIO_H=1
+                       ])
+       ])
+
+AC_DEFINE_UNQUOTED([HAVE_SNDIO_H], [${HAVE_SNDIO_H}], [Set to 1 if <sndio.h> is available.])
+
+dnl ====================================================================================
+dnl  Test for sanity when cross-compiling.
+
+AS_IF([test "x$ac_cv_sizeof_short" != "x2"], [
+               AC_MSG_WARN([[******************************************************************]])
+               AC_MSG_WARN([[*** sizeof (short) != 2.                                          ]])
+               AC_MSG_WARN([[******************************************************************]])
+       ])
+
+AS_IF([test "x$ac_cv_sizeof_int" != "x4"], [
+               AC_MSG_WARN([[******************************************************************]])
+               AC_MSG_WARN([[*** sizeof (int) != 4                                             ]])
+               AC_MSG_WARN([[******************************************************************]])
+       ])
+
+AS_IF([test "x$ac_cv_sizeof_float" != "x4"], [
+               AC_MSG_WARN([[******************************************************************]])
+               AC_MSG_WARN([[*** sizeof (float) != 4.                                          ]])
+               AC_MSG_WARN([[******************************************************************]])
+       ])
+
+AS_IF([test "x$ac_cv_sizeof_double" != "x8"], [
+               AC_MSG_WARN([[******************************************************************]])
+               AC_MSG_WARN([[*** sizeof (double) != 8.                                         ]])
+               AC_MSG_WARN([[******************************************************************]])
+       ])
+
+AS_IF([test "x$ac_cv_prog_HAVE_AUTOGEN" = "xno"], [
+               AC_MSG_WARN([[Touching files in directory tests/.]])
+               touch tests/*.c tests/*.h
+       ])
+
+dnl ====================================================================================
+dnl  Settings for the HTML documentation.
+
+AS_IF([test "x$enable_bow_docs" = "xyes"], [
+               HTML_BGCOLOUR="white"
+               HTML_FGCOLOUR="black"
+       ], [
+               HTML_BGCOLOUR="black"
+               HTML_FGCOLOUR="white"
+       ])
+
+dnl ====================================================================================
+dnl  Now use the information from the checking stage.
 
 win32_target_dll=0
 COMPILER_IS_GCC=0
 
-if test x$ac_cv_c_compiler_gnu = xyes ; then
-       MN_ADD_CFLAGS(-std=gnu99)
+AS_IF([test "x$enable_flags_setting" = "xyes"], [
+               AX_APPEND_COMPILE_FLAGS([-O2 -pipe], [CFLAGS])
+
+               AC_LANG_PUSH([C++])
+               AX_APPEND_COMPILE_FLAGS([-O2 -pipe], [CXXFLAGS])
+               AC_LANG_POP([C++])
 
-       MN_GCC_VERSION
+               AS_CASE([${host_os}],
+                       [darwin*], [
+                               ldflags_test="-Wl,-dead_strip_dylibs"],
+                       [linux*], [
+                               ldflags_test="-Wl,-O1 -Wl,--as-needed -Wl,--no-undefined -Wl,--gc-sections"]
+                       )
+               AX_APPEND_LINK_FLAGS([${ldflags_test}], [LDFLAGS])
+       ])
 
-       if test "x$GCC_MAJOR_VERSION$GCC_MINOR_VERSION" = "x42" ; then
-               AC_MSG_WARN([****************************************************************])
-               AC_MSG_WARN([** GCC version 4.2 warns about the inline keyword for no good **])
-               AC_MSG_WARN([** reason but the maintainers do not see it as a bug.         **])
-               AC_MSG_WARN([** See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33995      **])
-               AC_MSG_WARN([** Using -fgnu-inline to avoid this stupidity.                **])
-               AC_MSG_WARN([****************************************************************])
-               MN_ADD_CFLAGS([-fgnu89-inline])
-               fi
+AS_IF([test "x$enable_werror" = "xyes"], [
+               AX_APPEND_COMPILE_FLAGS([-Werror], [CFLAGS])
 
-       CFLAGS="$CFLAGS -Wall"
-       CXXFLAGS="$CXXFLAGS -Wall"
+               AC_LANG_PUSH([C++])
+               AX_APPEND_COMPILE_FLAGS([-Werror], [CXXFLAGS])
+               AC_LANG_POP([C++])
+       ])
 
-       MN_ADD_CFLAGS([-Wextra])
-       MN_ADD_CFLAGS([-Wdeclaration-after-statement])
-       MN_ADD_CFLAGS([-Wpointer-arith])
+common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self -Wno-format-truncation"
+AX_APPEND_COMPILE_FLAGS([${common_flags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS])
 
-       AC_LANG_PUSH([C++])
-       MN_ADD_CXXFLAGS([-Wextra])
-       MN_ADD_CXXFLAGS([-Wpointer-arith])
-       AC_LANG_POP([C++])
+AC_LANG_PUSH([C++])
+AX_APPEND_COMPILE_FLAGS([${common_flags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS])
+AC_LANG_POP([C++])
 
-       if test x$enable_stack_smash_protection = "xyes" ; then
+AS_IF([test "x$enable_stack_smash_protection" = "xyes"], [
                XIPH_GCC_STACK_PROTECTOR
                XIPH_GXX_STACK_PROTECTOR
-               fi
-
-       if test x$enable_test_coverage = "xyes" ; then
-               # MN_ADD_CFLAGS([-ftest-coverage])
-               MN_ADD_CFLAGS([-coverage])
-               fi
-
-       dnl some distributions (such as Gentoo) have _FORTIFY_SOURCE always
-       dnl enabled. We test for this situation in order to prevent polluting
-       dnl the console with messages of macro redefinitions.
-       AX_ADD_FORTIFY_SOURCE
-
-       common_flags="-Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self"
-
-       # -Winline -Wconversion "
-       CFLAGS="$CFLAGS     $common_flags -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return -Wvla"
-       CXXFLAGS="$CXXFLAGS $common_flags -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo"
-
-       if test "x$enable_gcc_opt" = "xno" ; then
-               temp_CFLAGS=`echo $CFLAGS | $SED "s/O2/O0/"`
-               CFLAGS=$temp_CFLAGS
-               AC_MSG_WARN([[*** Compiler optimisations switched off. ***]])
-               fi
-
-       # OS specific tweaks.
-       case "$host_os" in
-               darwin* | rhapsody*)
-                       # Disable -Wall, -pedantic and -Wshadow for Apple Darwin/Rhapsody.
-                       # System headers on these systems are broken.
-                       temp_CFLAGS=`echo $CFLAGS | $SED "s/-Wall -pedantic//" | $SED "s/-Wshadow//" | $SED "s/-Waggregate-return//"`
-                       CFLAGS=$temp_CFLAGS
-                       SHLIB_VERSION_ARG="-Wl,-exported_symbols_list -Wl,\$(srcdir)/Symbols.darwin"
-                       ;;
-               linux*|kfreebsd*-gnu*|gnu*)
-                       SHLIB_VERSION_ARG="-Wl,--version-script=\$(srcdir)/Symbols.gnu-binutils"
-                       ;;
-               mingw*)
-                       SHLIB_VERSION_ARG="-Wc,-static-libgcc -Wl,\$(srcdir)/libsndfile-1.def"
-                       win32_target_dll=1
-                       if test x"$enable_shared" = xno ; then
-                               win32_target_dll=0
-                               fi
-                       ;;
-               os2*)
-                       SHLIB_VERSION_ARG="-Wl,-export-symbols \$(srcdir)/Symbols.os2"
-                       ;;
-               *)
-                       ;;
-               esac
-       if test x$enable_gcc_pipe != "xno" ; then
-               CFLAGS="$CFLAGS -pipe"
-               fi
-
-       COMPILER_IS_GCC=1
-       fi
-
-if test x$enable_werror = "xyes" ; then
-       MN_ADD_CFLAGS([-Werror])
-
-       AC_LANG_PUSH([C++])
-       MN_ADD_CXXFLAGS([-Werror])
-       AC_LANG_POP([C++])
-       fi
-
-
-AC_DEFINE_UNQUOTED([WIN32_TARGET_DLL], ${win32_target_dll}, [Set to 1 if windows DLL is being built.])
-AC_DEFINE_UNQUOTED([COMPILER_IS_GCC], ${COMPILER_IS_GCC}, [Set to 1 if the compile is GNU GCC.])
+       ])
+
+AS_IF([test "x$enable_test_coverage" = "xyes"], [
+               AX_APPEND_COMPILE_FLAGS([-coverage], [CFLAGS])
+       ])
+
+dnl some distributions (such as Gentoo) have _FORTIFY_SOURCE always
+dnl enabled. We test for this situation in order to prevent polluting
+dnl the console with messages of macro redefinitions.
+AX_ADD_FORTIFY_SOURCE
+
+AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [
+               dnl OS specific tweaks.
+               AS_CASE([$host_os],
+                       [darwin* | rhapsody*], [
+                               dnl Disable -Wall, -pedantic and -Wshadow for Apple Darwin/Rhapsody.
+                               dnl System headers on these systems are broken.
+                               temp_CFLAGS=`echo $CFLAGS | $SED "s/-Wall -pedantic//" | $SED "s/-Wshadow//" | $SED "s/-Waggregate-return//"`
+                               CFLAGS=$temp_CFLAGS
+                               SHLIB_VERSION_ARG="-Wl,-exported_symbols_list -Wl,\$(top_srcdir)/src/Symbols.darwin"],
+                       [mingw*], [
+                               SHLIB_VERSION_ARG="-Wc,-static-libgcc -Wl,\$(top_srcdir)/src/libsndfile-1.def"
+                               win32_target_dll=1
+                               AS_IF([test "x$enable_shared" = "xno"], [
+                                               win32_target_dll=0
+                                       ])
+                               AX_APPEND_COMPILE_FLAGS([-mstackrealign], [CFLAGS])
+                               ],
+                       [os2*], [
+                               SHLIB_VERSION_ARG="-Wl,-export-symbols \$(top_srcdir)/src/Symbols.os2"
+                       ])
+
+               COMPILER_IS_GCC=1
+       ])
+
+AS_CASE([$host_os], [linux*|kfreebsd*-gnu*|gnu*],  [SHLIB_VERSION_ARG="-Wl,--version-script=\$(top_srcdir)/src/Symbols.gnu-binutils"])
+
+AC_DEFINE_UNQUOTED([WIN32_TARGET_DLL], [${win32_target_dll}], [Set to 1 if windows DLL is being built.])
+AC_DEFINE_UNQUOTED([COMPILER_IS_GCC], [${COMPILER_IS_GCC}], [Set to 1 if the compile is GNU GCC.])
 
 CFLAGS="$CFLAGS $OS_SPECIFIC_CFLAGS"
 
-if test x"$CFLAGS" = x ; then
-       echo "Error in configure script. CFLAGS has been screwed up."
-       exit
-       fi
+AS_IF([test "x$CFLAGS" = "x"], [
+               AC_MSG_ERROR(["Error in configure script. CFLAGS has been screwed up."])
+       ])
 
 HOST_TRIPLET="${host_cpu}-${host_vendor}-${host_os}"
 
-AC_DEFINE_UNQUOTED([HOST_TRIPLET], "${HOST_TRIPLET}", [The host triplet of the compiled binary.])
+AC_DEFINE_UNQUOTED([HOST_TRIPLET], [${HOST_TRIPLET}], [The host triplet of the compiled binary.])
 
-if test "$HOST_TRIPLET" = "x86_64-w64-mingw32" ; then
-       OS_SPECIFIC_LINKS=" -static-libgcc $OS_SPECIFIC_LINKS"
-       fi
+AS_IF([test "$HOST_TRIPLET" = "x86_64-w64-mingw32"], [
+               OS_SPECIFIC_LINKS=" -static-libgcc $OS_SPECIFIC_LINKS"
+       ])
 
 WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/p.*//" -e "s/\./,/g"`
 
 
-if test "$enable_static" = no ; then
-       SRC_BINDIR=src/.libs/
-       TEST_BINDIR=tests/.libs/
-else
-       SRC_BINDIR=src/
-       TEST_BINDIR=tests/
-       fi
+AS_IF([test "x$enable_static" = "xno"], [
+               SRC_BINDIR=src/.libs/
+               TEST_BINDIR=tests/.libs/
+       ], [
+               SRC_BINDIR=src/
+               TEST_BINDIR=tests/
+       ])
 
-#-------------------------------------------------------------------------------
+dnl -------------------------------------------------------------------------------
 
 AC_SUBST(HOST_TRIPLET)
 
@@ -617,41 +659,47 @@ AC_SUBST(HTML_FGCOLOUR)
 AC_SUBST(SHLIB_VERSION_ARG)
 AC_SUBST(SHARED_VERSION_INFO)
 AC_SUBST(CLEAN_VERSION)
+AC_SUBST(VERSION_MAJOR)
+AC_SUBST(GEN_TOOL)
+
 AC_SUBST(WIN_RC_VERSION)
 
 AC_SUBST(HAVE_EXTERNAL_XIPH_LIBS)
 AC_SUBST(OS_SPECIFIC_CFLAGS)
 AC_SUBST(OS_SPECIFIC_LINKS)
-AC_SUBST(ALSA_LIBS)
 AC_SUBST(SNDIO_LIBS)
 
 AC_SUBST(EXTERNAL_XIPH_CFLAGS)
 AC_SUBST(EXTERNAL_XIPH_LIBS)
+AC_SUBST(EXTERNAL_XIPH_REQUIRE)
 AC_SUBST(SRC_BINDIR)
 AC_SUBST(TEST_BINDIR)
 
-dnl The following line causes the libtool distributed with the source
-dnl to be replaced if the build system has a more recent version.
-AC_SUBST(LIBTOOL_DEPS)
-
-AC_CONFIG_FILES([ \
-       src/Makefile man/Makefile examples/Makefile tests/Makefile regtest/Makefile \
-       M4/Makefile doc/Makefile Win32/Makefile Octave/Makefile programs/Makefile \
-       Makefile \
-       src/version-metadata.rc tests/test_wrapper.sh tests/pedantic-header-test.sh \
-       doc/libsndfile.css Scripts/build-test-tarball.mk libsndfile.spec sndfile.pc \
-       src/sndfile.h \
-       echo-install-dirs
+AC_CONFIG_FILES([
+       Makefile Octave/Makefile
+       src/version-metadata.rc include/sndfile.h
+       tests/test_wrapper.sh tests/pedantic-header-test.sh
+       libsndfile.spec sndfile.pc
+       Scripts/build-test-tarball.mk
        ])
 AC_OUTPUT
 
-# Make sure these are executable.
-chmod u+x tests/test_wrapper.sh Scripts/build-test-tarball.mk echo-install-dirs
+dnl ====================================================================================
 
-#====================================================================================
+AS_IF([test -z "$PKG_CONFIG"], [
+               AS_ECHO(["    *****************************************************************"])
+               AS_ECHO(["    ***          The pkg-config program is missing.               ***"])
+               AS_ECHO(["    *** External FLAC/Ogg/Vorbis libs cannot be found without it. ***"])
+               AS_ECHO(["    ***       http://pkg-config.freedesktop.org/wiki/             ***"])
+               AS_ECHO(["    *****************************************************************"])
+       ])
 
+AX_RECURSIVE_EVAL([$libdir], [full_absolute_libdir])
+AX_RECURSIVE_EVAL([$bindir], [full_absolute_bindir])
+AX_RECURSIVE_EVAL([$pkgconfigdir], [full_absolute_pkgconfigdir])
+AX_RECURSIVE_EVAL([$htmldir], [full_absolute_htmldir])
 AC_MSG_RESULT([
--=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-
+-=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-=-
 
   Configuration summary :
 
@@ -661,38 +709,35 @@ AC_MSG_RESULT([
     Host Vendor : ......................... ${host_vendor}
     Host OS : ............................. ${host_os}
 
+    CFLAGS : .............................. ${CFLAGS}
+    CXXFLAGS : ............................ ${CXXFLAGS}
+    CPPFLAGS : ............................ ${CPPFLAGS}
+    LDFLAGS : ............................. ${LDFLAGS}
+
     Experimental code : ................... ${enable_experimental:-no}
     Using ALSA in example programs : ...... ${enable_alsa:-no}
-    External FLAC/Ogg/Vorbis : ............ ${enable_external_libs:-no}
+    External FLAC/Ogg/Vorbis/Opus : ....... ${enable_external_libs:-no}
+    Building Octave interface : ........... ${OCTAVE_BUILD}
+
+  Tools :
+
+    C Compiler Vendor is : ................ ${ax_cv_c_compiler_vendor} (${ax_cv_c_compiler_version})
+    CXX Compiler Vendor is : .............. ${ax_cv_cxx_compiler_vendor} (${ax_cv_cxx_compiler_version})
+
+    Sanitizer enabled : ................... ${enable_sanitizer:-no}
+    Stack smash protection : .............. ${enable_stack_smash_protection:-no}
+
+  Installation directories :
+
+    Library directory : ................... ${full_absolute_libdir}
+    Program directory : ................... ${full_absolute_bindir}
+    Pkgconfig directory : ................. ${full_absolute_pkgconfigdir}
+    HTML docs directory : ................. ${full_absolute_htmldir}
+
+Compiling some other packages against libsndfile may require
+the addition of '$full_absolute_pkgconfigdir' to the
+PKG_CONFIG_PATH environment variable.
 ])
 
-if test -z "$PKG_CONFIG" ; then
-       echo "    *****************************************************************"
-       echo "    ***          The pkg-config program is missing.               ***"
-       echo "    *** External FLAC/Ogg/Vorbis libs cannot be found without it. ***"
-       echo "    ***       http://pkg-config.freedesktop.org/wiki/             ***"
-       echo "    *****************************************************************"
-       echo
-       fi
-
-echo "  Tools :"
-echo
-echo "    Compiler is Clang : ................... ${mn_cv_c_compiler_clang}"
-echo "    Compiler is GCC : ..................... ${ac_cv_c_compiler_gnu}"
-
-if test x$ac_cv_c_compiler_gnu = xyes ; then
-       echo "    GCC version : ......................... ${GCC_VERSION}"
-       if test $GCC_MAJOR_VERSION -lt 3 ; then
-               echo "\n"
-               echo "    ** This compiler version allows applications to write"
-               echo "    ** to static strings within the library."
-               echo "    ** Compile with GCC version 3.X or above to avoid this problem."
-               fi
-       fi
-echo "    Sanitizer enabled : ................... ${enable_sanitizer:-no}"
-echo "    Stack smash protection : .............. ${enable_stack_smash_protection:-no}"
-
-./echo-install-dirs
-
-# Remove symlink created by Scripts/android-configure.sh.
+dnl Remove symlink created by Scripts/android-configure.sh.
 rm -f gdbclient
diff --git a/doc/FAQ.html b/doc/FAQ.html
deleted file mode 100644 (file)
index 24ccc9d..0000000
+++ /dev/null
@@ -1,851 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile : Frequently Asked Questions.
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <META NAME="Description" CONTENT="The libsndfile FAQ.">
-       <META NAME="Keywords"    CONTENT="WAV AIFF AU libsndfile sound audio dsp Linux">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<H1><B>libsndfile : Frequently Asked Questions.</B></H1>
-<P>
-<A HREF="#Q001">Q1 : Do you plan to support XYZ codec in libsndfile?</A><BR/>
-<A HREF="#Q002">Q2 : In version 0 the SF_INFO struct had a pcmbitwidth field
-               but version 1 does not. Why?</A><BR/>
-<A HREF="#Q003">Q3 : Compiling is really slow on MacOS X. Why?</A><BR/>
-<A HREF="#Q004">Q4 : When trying to compile libsndfile on Solaris I get a "bad
-               substitution" error during linking. What can I do to fix this?</A><BR/>
-<A HREF="#Q005">Q5 : Why doesn't libsndfile do interleaving/de-interleaving?</A><BR/>
-<A HREF="#Q006">Q6 : What's the best format for storing temporary files?</A><BR/>
-<A HREF="#Q007">Q7 : On Linux/Unix/MacOS X, what's the best way of detecting the
-       presence of libsndfile?</A><BR/>
-<A HREF="#Q008">Q8 : I have libsndfile installed and now I want to use it. I
-       just want a simple Makefile! What do I do?</A><BR/>
-<A HREF="#Q009">Q9 : How about adding the ability to write/read sound files to/from
-       memory buffers?</A><BR/>
-<A HREF="#Q010">Q10 : Reading a 16 bit PCM file as normalised floats and then
-       writing them back changes some sample values. Why?</A><BR/>
-<A HREF="#Q011">Q11 : I'm having problems with u-law encoded WAV files generated by
-       libsndfile in Winamp. Why?</A><BR/>
-<A HREF="#Q012">Q12 : I'm looking at sf_read*. What are items? What are frames?</A><BR/>
-<A HREF="#Q013">Q13 : Why can't libsndfile open this Sound Designer II (SD2)
-       file?</A><BR/>
-<A HREF="#Q014">Q14 : I'd like to statically link libsndfile to my closed source
-       application. Can I buy a license so that this is possible?</A><BR/>
-<A HREF="#Q015">Q15 : My program is crashing during a call to a function in libsndfile.
-       Is this a bug in libsndfile?</A><BR/>
-<A HREF="#Q016">Q16 : Will you accept a fix for compiling libsndfile with compiler X?
-       </A><BR/>
-<A HREF="#Q017">Q17 : Can libsndfile read/write files from/to UNIX pipes?
-       </A><BR/>
-<A HREF="#Q018">Q18 : Is it possible to build a Universal Binary on Mac OS X?
-       </A><BR/>
-<A HREF="#Q019">Q19 : I have project files for Visual Studio / XCode / Whatever. Why
-       don't you distribute them with libsndfile?
-       </A><BR/>
-<A HREF="#Q020">Q20 : Why doesn't libsndfile support MP3? Lots of other Open Source
-       projects support it!
-       </A><BR/>
-<A HREF="#Q021">Q21 : How do I use libsndfile in a closed source or commercial program
-       and comply with the license?
-       </A><BR/>
-<A HREF="#Q022">Q22 : What versions of windows does libsndfile work on?
-       </A><BR/>
-<A HREF="#Q023">Q23 : I'm cross compiling libsndfile for another platform. How can I
-       run the test suite?
-       </A><BR/>
-<HR>
-
-<!-- ========================================================================= -->
-<A NAME="Q001"></A>
-<H2><BR/><B>Q1 : Do you plan to support XYZ codec in libsndfile?</B></H2>
-<P>
-If source code for XYZ codec is available under a suitable license (LGPL, BSD,
-MIT etc) then yes, I'd like to add it.
-</P>
-<P>
-If suitable documentation is available on how to decode and encode the format
-then maybe, depending on how much work is involved.
-</P>
-<P>
-If XYZ is some proprietary codec where no source code or documentation is
-available then no.
-</P>
-<P>
-So if you want support for XYZ codec, first find existing source code or
-documentation.
-If you can't find either then the answer is no.
-</P>
-<!-- ========================================================================= -->
-<A NAME="Q002"></A>
-<H2><BR/><B>Q2 : In version 0 the SF_INFO struct had a pcmbitwidth field
-               but version 1 does not. Why?</B></H2>
-<P>
-       This was dropped for a number of reasons:
-</P>
-<UL>
-       <LI> pcmbitwidth makes little sense on compressed or floating point formats
-       <LI> with the new API you really don't need to know it
-</UL>
-<P>
-As documented
-    <A HREF="api.html#note1">here</A>
-there is now a well defined behaviour which ensures that no matter what the
-bit width of the source file, the scaling always does something sensible.
-This makes it safe to read 8, 16, 24 and 32 bit PCM files using sf_read_short()
-and always have the optimal behaviour.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q003"></A>
-<H2><BR/><B>Q3 : Compiling is really slow on MacOS X. Why?</B></H2>
-<P>
-When you configure and compile libsndfile, it uses the /bin/sh shell for a number
-of tasks (ie configure script and libtool).
-Older versions of OS X (10.2?) shipped a really crappy Bourne shell as /bin/sh
-which resulted in <b>really</b> slow compiles.
-Newer version of OS X ship GNU Bash as /bin/sh and this answer doesn't apply in that
-case.
-</P>
-<P>
-To fix this I suggest that you install the GNU Bash shell, rename /bin/sh to
-/bin/sh.old and make a symlink from /bin/sh to the bash shell.
-Bash is designed to behave as a Bourne shell when is is called as /bin/sh.
-</P>
-<P>
-When I did this on my iBook running MacOS X, compile times dropped from 13 minutes
-to 3 minutes.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q004"></A>
-<H2><BR/><B>Q4 : When trying to compile libsndfile on Solaris I get a "bad
-               substitution" error on linking. Why?</B></H2>
-<P>
-It seems that the Solaris Bourne shell disagrees with GNU libtool.
-</P>
-<P>
-To fix this I suggest that you install the GNU Bash shell, rename /bin/sh to
-/bin/sh.old and make a symlink from /bin/sh to the bash shell.
-Bash is designed to behave as a Bourne shell when is is called as /bin/sh.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q005"></A>
-<H2><BR/><B>Q5 : Why doesn't libsndfile do interleaving/de-interleaving?</B></H2>
-<P>
-This problem is bigger than it may seem at first.
-</P>
-<P>
-For a stereo file, it is a pretty safe bet that a simple interleaving/de-interleaving
-could satisfy most users.
-However, for files with more than 2 channels this is unlikely to be the case.
-If the user has a 4 channel file and want to play that file on a stereo output
-sound card they either want the first 2 channels or they want some mixed combination
-of the 4 channels.
-</P>
-<P>
-When you add more channels, the combinations grow exponentially and it becomes
-increasingly difficult to cover even a sensible subset of the possible combinations.
-On top of that, coding any one style of interleaver/de-interleaver is trivial, while
-coding one that can cover all combinations is far from trivial.
-This means that this feature will not be added any time soon.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q006"></A>
-<H2><BR/><B>Q6 : What's the best format for storing temporary files?</B></H2>
-
-<P>
-When you want to store temporary data there are a number of requirements;
-</P>
-<UL>
-       <LI> A simple, easy to parse header.
-       <LI> The format must provide the fastest possible read and write rates (ie
-               avoid conversions and encoding/decoding).
-       <LI> The file format must be reasonably common and playable by most players.
-       <LI> Able to store data in either endian-ness.
-</UL>
-<P>
-The format which best meets these requirements is AU, which allows data to be
-stored in any one of short, int, float and double (among others) formats.
-</P>
-<P>
-For instance, if an application uses float data internally, its temporary files
-should use a format of (SF_ENDIAN_CPU | SF_FORMAT_AU | SF_FORMAT_FLOAT) which
-will store big endian float data in big endian CPUs and little endian float data
-on little endian CPUs.
-Reading and writing this format will not require any conversions or byte swapping
-regardless of the host CPU.
-</P>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q007"></A>
-<H2><BR/><B>Q7 : On Linux/Unix/MaxOS X, what's the best way of detecting the presence
-       of libsndfile using autoconf?</B></H2>
-
-<P>
-libsndfile uses the pkg-config (man pkg-config) method of registering itself with the
-host system.
-The best way of detecting its presence is using something like this in configure.ac
-(or configure.in):
-</P>
-<PRE>
-        PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.2, ac_cv_sndfile=1, ac_cv_sndfile=0)
-
-        AC_DEFINE_UNQUOTED([HAVE_SNDFILE],${ac_cv_sndfile},
-                       [Set to 1 if you have libsndfile.])
-
-        AC_SUBST(SNDFILE_CFLAGS)
-        AC_SUBST(SNDFILE_LIBS)
-</PRE>
-<P>
-This will automatically set the <B>SNDFILE_CFLAGS</B> and <B>SNDFILE_LIBS</B>
-variables which can be used in Makefile.am like this:
-</P>
-<PRE>
-        SNDFILE_CFLAGS = @SNDFILE_CFLAGS@
-        SNDFILE_LIBS = @SNDFILE_LIBS@
-</PRE>
-<P>
-If you install libsndfile from source, you will probably need to set the
-<B>PKG_CONFIG_PATH</B> environment variable as suggested at the end of the
-libsndfile configure process. For instance on my system I get this:
-</P>
-<PRE>
-        -=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-
-
-          Configuration summary :
-
-            Version : ..................... 1.0.5
-            Experimental code : ........... no
-
-          Tools :
-
-            Compiler is GCC : ............. yes
-            GCC major version : ........... 3
-
-          Installation directories :
-
-            Library directory : ........... /usr/local/lib
-            Program directory : ........... /usr/local/bin
-            Pkgconfig directory : ......... /usr/local/lib/pkgconfig
-
-        Compiling some other packages against libsndfile may require
-        the addition of "/usr/local/lib/pkgconfig" to the
-        PKG_CONFIG_PATH environment variable.
-</PRE>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q008"></A>
-<H2><BR/><B>Q8 : I have libsndfile installed and now I want to use it. I just want
-               a simple Makefile! What do I do?</B></H2>
-
-<P>
-The <B>pkg-config</B> program makes finding the correct compiler flag values and
-library location far easier.
-During the installation of libsndfile, a file named <B>sndfile.pc</B> is installed
-in the directory <B>${libdir}/pkgconfig</B> (ie if libsndfile is installed in
-<B>/usr/local/lib</B>, <B>sndfile.pc</B> will be installed in
-<B>/usr/local/lib/pkgconfig/</B>).
-</P>
-<P>
-In order for pkg-config to find sndfile.pc it may be necessary to point the
-environment variable <B>PKG_CONFIG_PATH</B> in the right direction.
-</P>
-<PRE>
-        export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
-</PRE>
-
-<P>
-Then, to compile a C file into an object file, the command would be:
-</P>
-<PRE>
-        gcc `pkg-config --cflags sndfile` -c somefile.c
-</PRE>
-<P>
-and to link a number of objects into an executable that links against libsndfile,
-the command would be:
-</P>
-<PRE>
-        gcc `pkg-config --libs sndfile` obj1.o obj2.o -o program
-</PRE>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q009"></A>
-<H2><BR/><B>Q9 : How about adding the ability to write/read sound files to/from
-       memory buffers?</B></H2>
-
-<P>
-This has been added for version 1.0.13.
-</P>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q010"></A>
-<H2><BR/><B>Q10 : Reading a 16 bit PCM file as normalised floats and then
-       writing them back changes some sample values. Why?</B></H2>
-
-<P>
-This is caused by the fact that the conversion from 16 bit short to float is
-done by dividing by 32768 (0x8000 in hexadecimal) while the conversion from
-float to 16 bit short is done by multiplying by 32767 (0x7FFF in hex).
-So for instance, a value in a 16 bit PCM file of 20000 gets read as a floating
-point number of 0.6103515625 (20000.0 / 0x8000).
-Converting that back to a 16 bit short results in a value of 19999.3896484375
-(0.6103515625 * 0x7FFF) which then gets rounded down to 19999.
-</P>
-<P>
-You will notice that for this particular case, the error is 1 in 20000 or
-0.005%.
-Interestingly, for values of less than 16369, dividing by 0x8000 followed
-by multiplying by 0x7FFF and then rounding the result, gives back the
-original value.
-It turns out that as long as the host operating system supplies the 1999 ISO
-C Standard functions <B>lrintf</B> and <B>lrint</B> (or a replacement has
-been supplied) then the maximum possible error is 1 in 16369 or about 0.006%.
-</P>
-<P>
-Regardless of the size of the error, the reason why this is done is rather
-subtle.
-</P>
-<P>
-In a file containing 16 bit PCM samples, the values are restricted to the range
-[-32768, 32767] while we want floating point values in the range [-1.0, 1.0].
-The only way to do this conversion is to do a floating point division by a value
-of 0x8000.
-Converting the other way, the only way to ensure that floating point values in
-the range [-1.0, 1.0] are within the valid range allowed by a 16 bit short is
-to multiply by 0x7FFF.
-</P>
-<P>
-Some people would say that this is a severe short-coming of libsndfile.
-I would counter that anybody who is constantly converting back and forth
-between 16 bit shorts and normalised floats is going to suffer other losses
-in audio quality that they should also be concerned about.
-</P>
-<P>
-Since this problem only occurs when converting between integer data on disk and
-normalized floats in the application, it can be avoided by using something
-other than normalized floats in the application.
-Alternatives to normalized floats are the <b>short</b> and <b>int</b> data
-types (ie using sf_read_short or sf_read_int) or using un-normalized floats
-(see
-       <a href="command.html#SFC_SET_NORM_FLOAT">
-       SFC_SET_NORM_FLOAT</a>).
-</P>
-<P>
-Another way to deal with this problem is to consider 16 bit short data as a
-final destination format only, not as an intermediate storage format.
-All intermediate data (ie which is going to be processed further) should be
-stored in floating point format which is supported by all of the most common
-file formats.
-If floating point files are considered too large (2 times the size of a 16 bit
-PCM file), it would also be possible to use 24 bit PCM as an intermediate
-storage format (and which is also supported by most common file types).
-</P>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q011"></A>
-<H2><BR/><B>Q11 : I'm having problems with u-law encoded WAV files generated by
-       libsndfile in Winamp. Why?
-</B></H2>
-
-<P>
-This is actually a Winamp problem.
-The official Microsoft spec suggests that the 'fmt ' chunk should be 18 bytes.
-Unfortunately at least one of Microsoft's own applications (Sound Recorder on
-Win98 I believe) did not accept 18 bytes 'fmt ' chunks.
-</P>
-<P>
-Michael Lee did some experimenting and found that:
-</P>
-<PRE>
-    I have checked that Windows Media Player 9, QuickTime Player 6.4,
-    RealOne Player 2.0 and GoldWave 5.06 can all play u-law files with
-    16-byte or 18-byte 'fmt ' chunk. Only Winamp (2.91) and foobar2000
-    are unable to play u-law files with 16-byte 'fmt ' chunk.
-</PRE>
-
-<P>
-Even this is a very small sampling of all the players out there.
-For that reason it is probably not a good idea to change this now because there
-is the risk of breaking something that currently works.
-</P>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q012"></A>
-<H2><BR/><B>Q12 : I'm looking at sf_read*. What are items? What are frames?
-</B></H2>
-
-<P>
-An <tt>item</tt> is a single sample of the data type you are reading; ie a
-single <tt>short</tt> value for <tt>sf_read_short</tt> or a single <tt>float</tt>
-for <tt>sf_read_float</tt>.
-</P>
-
-<P>
-For a sound file with only one channel, a frame is the same as a item (ie a
-single sample) while for multi channel sound files, a single frame contains a
-single item for each channel.
-</P>
-
-<P>
-Here are two simple, correct examples, both of which are assumed to be working
-on a stereo file, first using items:
-</P>
-
-<PRE>
-        #define CHANNELS 2
-        short data [CHANNELS * 100] ;
-        sf_count items_read = sf_read_short (file, data, 200) ;
-        assert (items_read == 200) ;
-</PRE>
-
-<P>
-and now reading the exact same amount of data using frames:
-</P>
-
-<PRE>
-        #define CHANNELS 2
-        short data [CHANNELS * 100] ;
-        sf_count frames_read = sf_readf_short (file, data, 100) ;
-        assert (frames_read == 100) ;
-</PRE>
-
-<!-- ========================================================================= -->
-
-<A NAME="Q013"></A>
-<H2><BR/><B>Q13 : Why can't libsndfile open this Sound Designer II (SD2) file?
-</B></H2>
-
-<P>
-This is somewhat complicated.
-First some background.
-</P>
-
-<P>
-SD2 files are native to the Apple Macintosh platform and use features of
-the Mac filesystem (file resource forks) to store the file's sample rate,
-number of channels, sample width and more.
-When you look at a file and its resource fork on Mac OS X it looks like
-this:
-</P>
-
-<PRE>
-        -rw-r--r--  1 erikd erikd   46512 Oct 18 22:57 file.sd2
-        -rw-r--r--  1 erikd erikd     538 Oct 18 22:57 file.sd2/rsrc
-</PRE>
-
-<P>
-Notice how the file itself looks like a directory containing a single file
-named <B>rsrc</B>.
-When libsndfile is compiled for MacOS X, it should open (for write and read)
-SD2 file with resource forks like this without any problems.
-It will also handle files with the resource fork in a separate file as
-described below.
-</P>
-
-<P>
-When SD2 files are moved to other platforms, the resource fork of the file
-can sometimes be dropped altogether.
-All that remains is the raw audio data and no information about the number
-of channels, sample rate or bit width which makes it a little difficult for
-libsndfile to open the file.
-</P>
-
-<P>
-However, it is possible to safely move an SD2 file to a Linux or Windows
-machine.
-For instance, when an SD2 file is copied from inside MacOS X to a windows
-shared directory or a Samba share (ie Linux), MacOS X is clever enough to
-store the resource fork of the file in a separate hidden file in the
-same directory like this:
-</P>
-<PRE>
-        -rw-r--r--  1 erikd erikd     538 Oct 18 22:57 ._file.sd2
-        -rw-r--r--  1 erikd erikd   46512 Oct 18 22:57 file.sd2
-</PRE>
-
-<P>
-Regardless of what platform it is running on, when libsndfile is asked to
-open a file named <B>"foo"</B> and it can't recognize the file type from
-the data in the file, it will attempt to open the resource fork and if
-that fails, it then tries to open a file named <B>"._foo"</B> to see if
-the file has a valid resource fork.
-This is the same regardless of whether the file is being opened for read
-or write.
-</P>
-
-<P>
-In short, libsndfile should open SD2 files with a valid resource fork on
-all of the platforms that libsndfile supports.
-If a file has lost its resource fork, the only option is the open the file
-using the SF_FORMAT_RAW option and guessing its sample rate, channel count
-and bit width.
-</P>
-
-<P>
-Occasionally, when SD2 files are moved to other systems, the file is
-       <A HREF="http://www.macdisk.com/binhexen.php3">BinHexed</A>
-which wraps the resource fork and the data fork together.
-For these files, it would be possible to write a BinHex parser but
-there is not a lot to gain considering how rare these BinHexed SD2
-files are.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q014"></A>
-<H2><BR/><B>Q14 : I'd like to statically link libsndfile to my closed source
-       application. Can I buy a license so that this is possible?
-</B></H2>
-
-<P>
-Unfortunately no.
-libsndfile contains code written by other people who have agreed that their
-code be used under the GNU LGPL but no more.
-Even if they were to agree, there would be significant difficulties in
-dividing up the payments fairly.
-</P>
-
-<P>
-The <B>only</B> way you can legally use libsndfile as a statically linked
-library is if your application is released under the GNU GPL or LGPL.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q015"></A>
-<H2><BR/><B>Q15 : My program is crashing during a call to a function in libsndfile.
-       Is this a bug in libsndfile?
-</B></H2>
-
-<P>
-libsndfile is being used by large numbers of people all over the world
-without any problems like this. That means that it is much more likely
-that your code has a bug than libsndfile. However, it is still possible
-that there is a bug in libsndfile.
-</P>
-<P>
-To figure out whether it is your code or libsndfile you should do the
-following:
-</P>
-       <UL>
-       <LI>Make sure you are compiling your code with warnings switched on and
-               that you fix as many warnings as possible.
-               With the GNU compiler (gcc) I would recommend at least
-               <B>-W -Wall -Werror</B> which will force you to fix all warnings
-               before you can run the code.
-       <LI>Try using a memory debugger.
-               <A HREF="http://valgrind.kde.org/">Valgrind</A> on x86 Linux is excellent.
-               <A HREF="http://www.ibm.com/software/awdtools/purify/">Purify</A> also
-               has a good reputation.
-       <LI>If the code is clean after the above two steps and you still get
-               a crash in libsndfile, then send me a small snippet of code (no
-               more than 30-40 lines) which includes the call to sf_open() and
-               also shows how all variables passed to/returned from sf_open()
-               are defined.
-       </UL>
-
-<!-- ========================================================================= -->
-<A NAME="Q016"></A>
-<H2><BR/><B>Q16 : Will you accept a fix for compiling libsndfile with compiler X?
-</B></H2>
-
-<P>
-If compiler X is a C++ compiler then no.
-C and C++ are different enough to make writing code that compiles as valid C
-and valid C++ too difficult.
-I would rather spend my time fixing bugs and adding features.
-</P>
-
-<P>
-If compiler X is a C compiler then I will do what I can as long as that does
-not hamper the correctness, portability and maintainability of the existing
-code.
-It should be noted however that libsndfile uses features specified by the 1999
-ISO C Standard.
-This can make compiling libsndfile with some older compilers difficult.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q017"></A>
-<H2><BR/><B>Q17 : Can libsndfile read/write files from/to UNIX pipes?
-</B></H2>
-
-<P>
-Yes, libsndfile can read files from pipes.
-Unfortunately, the write case is much more complicated.
-</P>
-
-<P>
-File formats like AIFF and WAV have information at the start of the file (the
-file header) which states the length of the file, the number of sample frames
-etc.
-This information must be filled in correctly when the file header is written,
-but this information is not reliably known until the file is closed.
-This means that libsndfile cannot write AIFF, WAV and many other file types
-to a pipe.
-</P>
-
-<P>
-However, there is at least one file format (AU) which is specifically designed
-to be written to a pipe.
-Like AIFF and WAV, AU has a header with a sample frames field, but it is
-specifically allowable to set that frames field to 0x7FFFFFFF if the file
-length is not known when the header is written.
-The AU file format can also hold data in many of the standard formats (ie
-SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_FLOAT etc) as well as allowing
-data in both big and little endian format.
-</P>
-
-<P>
-See also <A HREF="#Q006">FAQ Q6</A>.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q018"></A>
-<H2><BR/><B>Q18 : Is it possible to build a Universal Binary on Mac OS X?
-</B></H2>
-
-<P>
-Yes, but you must do two separate configure/build/test runs; one on PowerPC
-and one on Intel.
-It is then possible to merge the binaries into a single universal binary using
-one of the programs in the Apple tool chain.
-</P>
-
-<P>
-It is <b>not</b> possible to build a working universal binary via a single
-compile/build run on a single CPU.
-</P>
-
-<P>
-The problem is that the libsndfile build process detects features of the CPU its
-being built for during the configure process and when building a universal binary,
-configure is only run once and that data is then used for both CPUs.
-That configure data will be wrong for one of those CPUs.
-You will still be able to compile libsndfile, and the test suite will pass on
-the machine you compiled it on.
-However, if you take the universal binary test suite programs compiled on one
-CPU and run them on the other, the test suite will fail.
-</P>
-
-<P>
-Part of the problem is that the CPU endian-ness is detected at configure time.
-Yes, I know the Apple compiler defines one of the macros __LITTLE_ENDIAN__
-and __BIG_ENDIAN__, but those macros are not part of the 1999 ISO C Standard
-and they are not portable.
-</P>
-
-<P>
-Endian issues are not the only reason why the cross compiled binary will fail.
-The configure script also detects other CPU specific idiosyncrasies to provide
-more optimized code.
-</P>
-
-<P>
-Finally, the real show stopper problem with universal binaries is the problem
-with the test suite.
-libsndfile contains a huge, comprehensive test suite.
-When you compile a universal binary and run the test suite, you only test the
-native compile.
-The cross compiled binary (the one with the much higher chance of having
-problems) cannot be tested.
-</P>
-
-<P>
-Now, if you have read this far you're probably thinking there must be a way
-to fix this and there probably is.
-The problem is that its a hell of a lot of work and would require significant
-changes to the configure process, the internal code and the test suite.
-In addition, these changes must not break compilation on any of the platforms
-libsndfile is currently working on.
-</p>
-
-
-<!-- ========================================================================= -->
-<A NAME="Q019"></A>
-<H2><BR/><B>Q19 : I have project files for Visual Studio / XCode / Whatever. Why
-       don't you distribute them with libsndfile?
-</B></H2>
-
-<P>
-There's a very good reason for this.
-I will only distribute things that I actually have an ability to test and
-maintain.
-Project files for a bunch of different compilers and Integrated Development
-Environments are simply too difficult to maintain.
-</P>
-
-<P>
-The problem is that every time I add a new file to libsndfile or rename an
-existing file I would have to modify all the project files and then test that
-libsndfile still built with all the different compilers.
-</P>
-
-<P>
-Maintaining these project files is also rather difficult if I don't have access
-to the required compiler/IDE.
-If I just edit the project files without testing them I will almost certainly
-get it wrong.
-If I release a version of libsndfile with broken project files, I'll get a bunch
-of emails from people complaining about it not building and have no way of
-fixing or even testing it.
-</P>
-
-<P>
-I currently release sources that I personally test on Win32, Linux and
-MacOS X (PowerPC) using the compiler I trust (GNU GCC).
-Supporting one compiler on three (actually much more because GCC is available
-almost everywhere) platforms is doable without too much pain.
-I also release binaries for Win32 with instructions on how to use those
-binaries with Visual Studio.
-As a guy who is mainly interested in Linux, I'm not to keen to jump through
-a bunch of hoops to support compilers and operating systems I don't use.
-</P>
-
-<P>
-So, I hear you want to volunteer to maintain the project files for Some Crappy
-Compiler 2007?
-Well sorry, that won't work either.
-I have had numerous people over the years offer to maintaining the project
-files for Microsoft's Visual Studio.
-Every single time that happened, they maintained it for a release or two and
-then disappeared off the face of the earth.
-Hence, I'm not willing to enter into an arrangement like that again.
-</P>
-
-<!-- ========================================================================= -->
-<A NAME="Q020"></A>
-<H2><BR/><B>Q20 : Why doesn't libsndfile support MP3? Lots of other Open Source
-       projects support it!
-</B></H2>
-
-<P>
-MP3 is not supported for one very good reason; doing so requires the payment
-of licensing fees.
-As can be seen from
-       <a href="http://www.mp3licensing.com/royalty/software.html">
-       mp3licensing.com</a>
-the required royalty payments are not cheap.
-</P>
-
-<p>
-Yes, I know other libraries ignore the licensing requirements, but their legal
-status is extremely dubious.
-At any time, the body selling the licenses could go after the authors of those
-libraries.
-Some of those authors may be students and hence wouldn't be worth pursuing.
-</P>
-
-<p>
-However, libsndfile is released under the name of a company, Mega Nerd Pty Ltd;
-a company which has income from from libsamplerate licensing, libsndfile based
-consulting income and other unrelated consulting income.
-Adding MP3 support to libsndfile could place that income under legal threat.
-</p>
-
-<p>
-Fortunately, Ogg Vorbis exists as an alternative to MP3.
-Support for Ogg Vorbis was added to libsndfile (mostly due to the efforts of
-John ffitch of the Csound project) in version 1.0.18.
-</p>
-
-
-<!-- ========================================================================= -->
-<A NAME="Q021"></A>
-<H2><BR/><B>Q21 : How do I use libsndfile in a closed source or commercial program
-       and comply with the license?
-</B></H2>
-
-<p>
-Here is a checklist of things you need to do to make sure your use of libsndfile
-in a closed source or commercial project complies with the license libsndfile is
-released under, the GNU Lesser General Public License (LGPL):
-</p>
-
-<ul>
-<li>Make sure you are linking to libsndfile as a shared library (Linux and Unix
-       systems), Dynamic Link Library (Microsoft Windows) or dynlib (Mac OS X).
-       If you are using some other operating system that doesn't allow dynamically
-       linked libraries, you will not be able to use libsndfile unless you release
-       the source code to your program.
-<li>In the licensing documentation for your program, add a statement that your
-       software depends on libsndfile and that libsndfile is released under the GNU
-       Lesser General Public License, either
-               <a href="http://www.gnu.org/licenses/lgpl-2.1.txt">version 2.1</a>
-       or optionally
-               <a href="http://www.gnu.org/licenses/lgpl.txt">version 3</a>.
-<li>Include the text for both versions of the license, possibly as separate
-       files named libsndfile_lgpl_v2_1.txt and libsndfile_lgpl_v3.txt.
-</ul>
-
-<!-- ========================================================================= -->
-<A NAME="Q022"></A>
-<H2><BR/><B>Q22 : What versions of Windows does libsndfile work on?
-</B></H2>
-
-<p>
-Currently the precompiled windows binaries are thoroughly tested on Windows XP.
-As such, they should also work on Win2k and Windows Vista.
-They may also work on earlier versions of Windows.
-</p>
-
-<p>
-Since version 0.1.18 I have also been releasing precompiled binaries for Win64,
-the 64 bit version of Windows.
-These binaries have received much less testing than the  32 bit versions, but
-should work as expected.
-I'd be very interested in receiving feedback  on these binaries.
-</p>
-
-<!-- ========================================================================= -->
-<A NAME="Q023"></A>
-<H2><BR/><B>Q23 : I'm cross compiling libsndfile for another platform. How can I
-       run the test suite?
-</B></H2>
-
-<p>
-</p>
-
-<p>
-Since version 1.0.21 the top level Makefile has an extra make target,
-'test-tarball'.
-Building this target creates a tarball called called:
-</p>
-
-<center><tt>
-libsndfile-testsuite-${host_triplet}-${version}.tar.gz
-</tt></center>
-
-<p>
-in the top level directory.
-This tarball can then be copied to the target platform.
-Once untarred and test script <tt>test_wrapper.sh</tt> can be run from
-the top level of the extracted tarball.
-</p>
-
-<!-- ========================================================================= -->
-<HR>
-<P>
-       The libsndfile home page is here :
-               <A HREF="http://www.mega-nerd.com/libsndfile/">
-                       http://www.mega-nerd.com/libsndfile/</A>.
-<BR/>
-Version : 1.0.28
-</P>
-
-</BODY>
-</HTML>
diff --git a/doc/Makefile.am b/doc/Makefile.am
deleted file mode 100644 (file)
index 5e2ed3b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-html_DATA = index.html libsndfile.jpg libsndfile.css api.html command.html \
-                       bugs.html sndfile_info.html new_file_type.HOWTO \
-                       win32.html FAQ.html lists.html embedded_files.html octave.html \
-                       tutorial.html
-
-EXTRA_DIST = $(html_DATA)
-
diff --git a/doc/api.html b/doc/api.html
deleted file mode 100644 (file)
index ec4305e..0000000
+++ /dev/null
@@ -1,810 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       The libsndfile API
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <META NAME="Description" CONTENT="The libsndfile API.">
-       <META NAME="Keywords"    CONTENT="WAV AIFF AU libsndfile sound audio dsp Linux">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<BR>
-<H1><B>libsndfile</B></H1>
-<P>
-       Libsndfile is a library designed to allow the reading and writing of many
-       different sampled sound file formats (such as MS Windows WAV and the Apple/SGI
-       AIFF format) through one standard library interface.
-</P>
-<!-- pepper -->
-<P>
-       During read and write operations, formats are seamlessly converted between the
-       format the application program has requested or supplied and the file's data
-       format. The application programmer can remain blissfully unaware of issues
-       such as file endian-ness and data format. See <A HREF="#note1">Note 1</A> and
-       <A HREF="#note2">Note 2</A>.
-</P>
-<!-- pepper -->
-<P>
-       Every effort is made to keep these documents up-to-date, error free and
-       unambiguous.
-       However, since maintaining the documentation is the least fun part of working
-       on libsndfile, these docs can and do fall behind the behaviour of the library.
-       If any errors, omissions or ambiguities are found, please notify me (erikd)
-       at mega-nerd dot com.
-</P>
-<!-- pepper -->
-<P>
-       To supplement this reference documentation, there are simple example programs
-       included in the source code tarball.
-       The test suite which is also part of the source code tarball is also a good
-       place to look for the correct usage of the library functions.
-</P>
-<!-- pepper -->
-<P>
-       <B> Finally, if you think there is some feature missing from libsndfile, check that
-       it isn't already implemented (and documented)
-               <A HREF="command.html">here</A>.
-       </B>
-</P>
-
-<H2><B>Synopsis</B></H2>
-<P>
-The functions of libsndfile are defined as follows:
-</P>
-<!-- pepper -->
-<PRE>
-      #include &lt;stdio.h&gt;
-      #include &lt;sndfile.h&gt;
-
-      SNDFILE*    <A HREF="#open">sf_open</A>          (const char *path, int mode, SF_INFO *sfinfo) ;
-      SNDFILE*    <A HREF="#open">sf_wchar_open</A>    (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
-      SNDFILE*    <A HREF="#open_fd">sf_open_fd</A>       (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
-      SNDFILE*           <A HREF="#open_virtual">sf_open_virtual</A>  (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
-      int         <A HREF="#check">sf_format_check</A>  (const SF_INFO *info) ;
-
-      sf_count_t  <A HREF="#seek">sf_seek</A>          (SNDFILE *sndfile, sf_count_t frames, int whence) ;
-
-      int         <A HREF="command.html">sf_command</A>       (SNDFILE *sndfile, int cmd, void *data, int datasize) ;
-
-      int         <A HREF="#error">sf_error</A>         (SNDFILE *sndfile) ;
-      const char* <A HREF="#error">sf_strerror</A>      (SNDFILE *sndfile) ;
-      const char* <A HREF="#error">sf_error_number</A>  (int errnum) ;
-
-      int         <A HREF="#error">sf_perror</A>        (SNDFILE *sndfile) ;
-      int         <A HREF="#error">sf_error_str</A>     (SNDFILE *sndfile, char* str, size_t len) ;
-
-      int         <A HREF="#close">sf_close</A>         (SNDFILE *sndfile) ;
-      void        <A HREF="#write_sync">sf_write_sync</A>    (SNDFILE *sndfile) ;
-
-      sf_count_t  <A HREF="#read">sf_read_short</A>    (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
-      sf_count_t  <A HREF="#read">sf_read_int</A>      (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
-      sf_count_t  <A HREF="#read">sf_read_float</A>    (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
-      sf_count_t  <A HREF="#read">sf_read_double</A>   (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
-
-      sf_count_t  <A HREF="#readf">sf_readf_short</A>   (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
-      sf_count_t  <A HREF="#readf">sf_readf_int</A>     (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
-      sf_count_t  <A HREF="#readf">sf_readf_float</A>   (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
-      sf_count_t  <A HREF="#readf">sf_readf_double</A>  (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
-
-      sf_count_t  <A HREF="#write">sf_write_short</A>   (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
-      sf_count_t  <A HREF="#write">sf_write_int</A>     (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
-      sf_count_t  <A HREF="#write">sf_write_float</A>   (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
-      sf_count_t  <A HREF="#write">sf_write_double</A>  (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
-
-      sf_count_t  <A HREF="#writef">sf_writef_short</A>  (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
-      sf_count_t  <A HREF="#writef">sf_writef_int</A>    (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
-      sf_count_t  <A HREF="#writef">sf_writef_float</A>  (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
-      sf_count_t  <A HREF="#writef">sf_writef_double</A> (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
-
-      sf_count_t  <A HREF="#raw">sf_read_raw</A>      (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
-      sf_count_t  <A HREF="#raw">sf_write_raw</A>     (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
-
-      const char* <A HREF="#string">sf_get_string</A>    (SNDFILE *sndfile, int str_type) ;
-      int         <A HREF="#string">sf_set_string</A>    (SNDFILE *sndfile, int str_type, const char* str) ;
-
-</PRE>
-<!-- pepper -->
-<P>
-SNDFILE* is an anonymous pointer to data which is private to the library.
-</P>
-
-
-<A NAME="open"></A>
-<H2><B>File Open Function</B></H2>
-
-<PRE>
-      SNDFILE*  sf_open    (const char *path, int mode, SF_INFO *sfinfo) ;
-</PRE>
-
-<P>
-The sf_open() function opens the sound file at the specified path.
-The filename is byte encoded, but may be utf-8 on Linux, while on Mac OS X it
-will use the filesystem character set.
-On Windows, there is also a Windows specific sf_wchar_open() that takes a
-UTF16_BE encoded filename.
-</P>
-
-<PRE>
-      SNDFILE*  sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
-</PRE>
-
-<P>
-The SF_INFO structure is for passing data between the calling function and the library
-when opening a file for reading or writing. It is defined in sndfile.h as follows:
-</P>
-<!-- pepper -->
-<PRE>
-      typedef struct
-      {    sf_count_t  frames ;     /* Used to be called samples. */
-           int         samplerate ;
-           int         channels ;
-           int         format ;
-           int         sections ;
-           int         seekable ;
-       } SF_INFO ;
-</PRE>
-
-<P>
-The mode parameter for this function can be any one of the following three values:
-</P>
-<!-- pepper -->
-<PRE>
-      SFM_READ    - read only mode
-      SFM_WRITE   - write only mode
-      SFM_RDWR    - read/write mode
-</PRE>
-
-<P>
-When opening a file for read, the <b>format</B> field should be set to zero before
-calling sf_open().
-The only exception to this is the case of RAW files where the caller has to set
-the samplerate, channels and format fields to valid values.
-All other fields of the structure are filled in by the library.
-</P>
-<!-- pepper -->
-<P>
-When opening a file for write, the caller must fill in structure members samplerate,
-channels, and format.
-</P>
-<!-- pepper -->
-<P>
-The format field in the above SF_INFO structure is made up of the bit-wise OR of a
-major format type (values between 0x10000 and 0x08000000), a minor format type
-(with values less than 0x10000) and an optional endian-ness value.
-The currently understood formats are listed in sndfile.h as follows and also include
-bitmasks for separating major and minor file types.
-Not all combinations of endian-ness and major and minor file types are valid.
-</P>
-<!-- pepper -->
-<PRE>
-      enum
-      {   /* Major formats. */
-          SF_FORMAT_WAV          = 0x010000,     /* Microsoft WAV format (little endian). */
-          SF_FORMAT_AIFF         = 0x020000,     /* Apple/SGI AIFF format (big endian). */
-          SF_FORMAT_AU           = 0x030000,     /* Sun/NeXT AU format (big endian). */
-          SF_FORMAT_RAW          = 0x040000,     /* RAW PCM data. */
-          SF_FORMAT_PAF          = 0x050000,     /* Ensoniq PARIS file format. */
-          SF_FORMAT_SVX          = 0x060000,     /* Amiga IFF / SVX8 / SV16 format. */
-          SF_FORMAT_NIST         = 0x070000,     /* Sphere NIST format. */
-          SF_FORMAT_VOC          = 0x080000,     /* VOC files. */
-          SF_FORMAT_IRCAM        = 0x0A0000,     /* Berkeley/IRCAM/CARL */
-          SF_FORMAT_W64          = 0x0B0000,     /* Sonic Foundry's 64 bit RIFF/WAV */
-          SF_FORMAT_MAT4         = 0x0C0000,     /* Matlab (tm) V4.2 / GNU Octave 2.0 */
-          SF_FORMAT_MAT5         = 0x0D0000,     /* Matlab (tm) V5.0 / GNU Octave 2.1 */
-          SF_FORMAT_PVF          = 0x0E0000,     /* Portable Voice Format */
-          SF_FORMAT_XI           = 0x0F0000,     /* Fasttracker 2 Extended Instrument */
-          SF_FORMAT_HTK          = 0x100000,     /* HMM Tool Kit format */
-          SF_FORMAT_SDS          = 0x110000,     /* Midi Sample Dump Standard */
-          SF_FORMAT_AVR          = 0x120000,     /* Audio Visual Research */
-          SF_FORMAT_WAVEX        = 0x130000,     /* MS WAVE with WAVEFORMATEX */
-          SF_FORMAT_SD2          = 0x160000,     /* Sound Designer 2 */
-          SF_FORMAT_FLAC         = 0x170000,     /* FLAC lossless file format */
-          SF_FORMAT_CAF          = 0x180000,     /* Core Audio File format */
-          SF_FORMAT_WVE          = 0x190000,     /* Psion WVE format */
-          SF_FORMAT_OGG          = 0x200000,     /* Xiph OGG container */
-          SF_FORMAT_MPC2K        = 0x210000,     /* Akai MPC 2000 sampler */
-          SF_FORMAT_RF64         = 0x220000,     /* RF64 WAV file */
-
-          /* Subtypes from here on. */
-
-          SF_FORMAT_PCM_S8       = 0x0001,       /* Signed 8 bit data */
-          SF_FORMAT_PCM_16       = 0x0002,       /* Signed 16 bit data */
-          SF_FORMAT_PCM_24       = 0x0003,       /* Signed 24 bit data */
-          SF_FORMAT_PCM_32       = 0x0004,       /* Signed 32 bit data */
-
-          SF_FORMAT_PCM_U8       = 0x0005,       /* Unsigned 8 bit data (WAV and RAW only) */
-
-          SF_FORMAT_FLOAT        = 0x0006,       /* 32 bit float data */
-          SF_FORMAT_DOUBLE       = 0x0007,       /* 64 bit float data */
-
-          SF_FORMAT_ULAW         = 0x0010,       /* U-Law encoded. */
-          SF_FORMAT_ALAW         = 0x0011,       /* A-Law encoded. */
-          SF_FORMAT_IMA_ADPCM    = 0x0012,       /* IMA ADPCM. */
-          SF_FORMAT_MS_ADPCM     = 0x0013,       /* Microsoft ADPCM. */
-
-          SF_FORMAT_GSM610       = 0x0020,       /* GSM 6.10 encoding. */
-          SF_FORMAT_VOX_ADPCM    = 0x0021,       /* Oki Dialogic ADPCM encoding. */
-
-          SF_FORMAT_G721_32      = 0x0030,       /* 32kbs G721 ADPCM encoding. */
-          SF_FORMAT_G723_24      = 0x0031,       /* 24kbs G723 ADPCM encoding. */
-          SF_FORMAT_G723_40      = 0x0032,       /* 40kbs G723 ADPCM encoding. */
-
-          SF_FORMAT_DWVW_12      = 0x0040,       /* 12 bit Delta Width Variable Word encoding. */
-          SF_FORMAT_DWVW_16      = 0x0041,       /* 16 bit Delta Width Variable Word encoding. */
-          SF_FORMAT_DWVW_24      = 0x0042,       /* 24 bit Delta Width Variable Word encoding. */
-          SF_FORMAT_DWVW_N       = 0x0043,       /* N bit Delta Width Variable Word encoding. */
-
-          SF_FORMAT_DPCM_8       = 0x0050,       /* 8 bit differential PCM (XI only) */
-          SF_FORMAT_DPCM_16      = 0x0051,       /* 16 bit differential PCM (XI only) */
-
-          SF_FORMAT_VORBIS       = 0x0060,       /* Xiph Vorbis encoding. */
-
-          /* Endian-ness options. */
-
-          SF_ENDIAN_FILE         = 0x00000000,   /* Default file endian-ness. */
-          SF_ENDIAN_LITTLE       = 0x10000000,   /* Force little endian-ness. */
-          SF_ENDIAN_BIG          = 0x20000000,   /* Force big endian-ness. */
-          SF_ENDIAN_CPU          = 0x30000000,   /* Force CPU endian-ness. */
-
-          SF_FORMAT_SUBMASK      = 0x0000FFFF,
-          SF_FORMAT_TYPEMASK     = 0x0FFF0000,
-          SF_FORMAT_ENDMASK      = 0x30000000
-      } ;
-</PRE>
-<!-- pepper -->
-<P>
-Every call to sf_open() should be matched with a call to sf_close() to free up
-memory allocated during the call to sf_open().
-</P>
-<!-- pepper -->
-<P>
-On success, the sf_open function returns a non-NULL pointer which should be
-passed as the first parameter to all subsequent libsndfile calls dealing with
-that audio file.
-On fail, the sf_open function returns a NULL pointer.
-An explanation of the error can obtained by passing NULL to
-       <A HREF="#error">sf_strerror</A>.
-</P>
-
-<A NAME="open_fd"></A>
-<H3><B>File Descriptor Open</B></H3>
-
-<PRE>
-      SNDFILE*  sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
-</PRE>
-
-<P>
-<b>Note:</b> On Microsoft Windows, this function does not work if the
-application and the libsndfile DLL are linked to different versions of the
-Microsoft C runtime DLL.
-</P>
-<P>
-The second open function takes a file descriptor of a file that has already been
-opened.
-Care should be taken to ensure that the mode of the file represented by the
-descriptor matches the mode argument.
-This function is useful in the following circumstances:
-</P>
-
-<UL>
-       <LI>Opening temporary files securely (ie use the tmpfile() to return a
-               FILE* pointer and then using fileno() to retrieve the file descriptor
-               which is then passed to libsndfile).
-       <LI>Opening files with file names using OS specific character encodings
-               and then passing the file descriptor to sf_open_fd().
-       <LI>Opening sound files embedded within larger files.
-                       <A HREF="embedded_files.html">More info</A>.
-</UL>
-
-<P>
-Every call to sf_open_fd() should be matched with a call to sf_close() to free up
-memory allocated during the call to sf_open().
-</P>
-
-<P>
-When sf_close() is called, the file descriptor is only closed if the <B>close_desc</B>
-parameter was TRUE when the sf_open_fd() function was called.
-</P>
-
-<P>
-On success, the sf_open_fd function returns a non-NULL pointer which should be
-passed as the first parameter to all subsequent libsndfile calls dealing with
-that audio file.
-On fail, the sf_open_fd function returns a NULL pointer.
-</P>
-
-<A NAME="open_virtual"></A>
-<h3><b>Virtual File Open Function</b></h3>
-<pre>
-      SNDFILE*         sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
-</pre>
-<p>
-       Opens a soundfile from a virtual file I/O context which is provided
-       by the caller. This is usually used to interface libsndfile to a stream or buffer
-       based system. Apart from the sfvirtual and the user_data parameters this function behaves
-       like <a href="#open">sf_open</a>.
-</p>
-
-<pre>
-      typedef struct
-      {    sf_vio_get_filelen  get_filelen ;
-           sf_vio_seek         seek ;
-           sf_vio_read         read ;
-           sf_vio_write        write ;
-           sf_vio_tell         tell ;
-      } SF_VIRTUAL_IO ;
-</pre>
-<p>
-Libsndfile calls the callbacks provided by the SF_VIRTUAL_IO structure when opening, reading
-and writing to the virtual file context. The user_data pointer is a user defined context which
-will be available in the callbacks.
-</p>
-<pre>
-      typedef sf_count_t  (*sf_vio_get_filelen) (void *user_data) ;
-      typedef sf_count_t  (*sf_vio_seek)        (sf_count_t offset, int whence, void *user_data) ;
-      typedef sf_count_t  (*sf_vio_read)        (void *ptr, sf_count_t count, void *user_data) ;
-      typedef sf_count_t  (*sf_vio_write)       (const void *ptr, sf_count_t count, void *user_data) ;
-      typedef sf_count_t  (*sf_vio_tell)        (void *user_data) ;
-</pre>
-<h4>sf_vio_get_filelen</h4>
-<pre>
-      typedef sf_count_t  (*sf_vio_get_filelen) (void *user_data) ;
-</pre>
-<p>
-The virtual file contex must return the length of the virtual file in bytes.<br>
-</p>
-<h4>sf_vio_seek</h4>
-<pre>
-      typedef sf_count_t  (*sf_vio_seek)        (sf_count_t offset, int whence, void *user_data) ;
-</pre>
-<p>
-The virtual file context must seek to offset using the seek mode provided by whence which is one of<br>
-</p>
-<pre>
-      SEEK_CUR
-      SEEK_SET
-      SEEK_END
-</pre>
-<p>
-The return value must contain the new offset in the file.
-</p>
-<h4>sf_vio_read</h4>
-<pre>
-      typedef sf_count_t  (*sf_vio_read)        (void *ptr, sf_count_t count, void *user_data) ;
-</pre>
-<p>
-The virtual file context must copy ("read") "count" bytes into the
-buffer provided by ptr and return the count of actually copied bytes.
-</p>
-<h4>sf_vio_write</h4>
-<pre>
-      typedef sf_count_t  (*sf_vio_write)       (const void *ptr, sf_count_t count, void *user_data) ;
-</pre>
-<p>
-The virtual file context must process "count" bytes stored in the
-buffer passed with ptr and return the count of actually processed bytes.<br>
-</p>
-<h4>sf_vio_tell</h4>
-<pre>
-      typedef sf_count_t  (*sf_vio_tell)        (void *user_data) ;
-</pre>
-<p>
-Return the current position of the virtual file context.<br>
-</p>
-
-
-<A NAME="check"></A>
-<BR><H2><B>Format Check Function</B></H2>
-
-<PRE>
-      int  sf_format_check (const SF_INFO *info) ;
-</PRE>
-<!-- pepper -->
-<P>
-This function allows the caller to check if a set of parameters in the SF_INFO struct
-is valid before calling sf_open (SFM_WRITE).
-</P>
-<P>
-sf_format_check returns TRUE if the parameters are valid and FALSE otherwise.
-</P>
-
-<A NAME="seek"></A>
-<BR><H2><B>File Seek Functions</B></H2>
-
-<PRE>
-      sf_count_t  sf_seek  (SNDFILE *sndfile, sf_count_t frames, int whence) ;
-</PRE>
-
-<P>
-The file seek functions work much like lseek in unistd.h with the exception that
-the non-audio data is ignored and the seek only moves within the audio data section of
-the file.
-In addition, seeks are defined in number of (multichannel) frames.
-Therefore, a seek in a stereo file from the current position forward with an offset
-of 1 would skip forward by one sample of both channels.
-</P>
-
-<P>
-like lseek(), the whence parameter can be any one of the following three values:
-</P>
-
-<PRE>
-      SEEK_SET  - The offset is set to the start of the audio data plus offset (multichannel) frames.
-      SEEK_CUR  - The offset is set to its current location plus offset (multichannel) frames.
-      SEEK_END  - The offset is set to the end of the data plus offset (multichannel) frames.
-</PRE>
-<!-- pepper -->
-<P>
-Internally, libsndfile keeps track of the read and write locations using separate
-read and write pointers.
-If a file has been opened with a mode of SFM_RDWR, bitwise OR-ing the standard whence
-values above with either SFM_READ or SFM_WRITE allows the read and write pointers to
-be modified separately.
-If the SEEK_* values are used on their own, the read and write pointers are
-both modified.
-</P>
-
-<P>
-Note that the frames offset can be negative and in fact should be when SEEK_END is used for the
-whence parameter.
-</P>
-<P>
-sf_seek will return the offset in (multichannel) frames from the start of the audio data
-or -1 if an error occured (ie an attempt is made to seek beyond the start or end of the file).
-</P>
-
-<A NAME="error"></A>
-<H2><BR><B>Error Reporting Functions</B></H2>
-
-
-<PRE>
-      int         sf_error        (SNDFILE *sndfile) ;
-</PRE>
-<P>
-This function returns the current error number for the given SNDFILE.
-The error number may be one of the following:
-</P>
-<PRE>
-        enum
-        {   SF_ERR_NO_ERROR             = 0,
-            SF_ERR_UNRECOGNISED_FORMAT  = 1,
-            SF_ERR_SYSTEM               = 2,
-            SF_ERR_MALFORMED_FILE       = 3,
-            SF_ERR_UNSUPPORTED_ENCODING = 4
-        } ;
-</PRE>
-<!-- pepper -->
-<P>
-or any one of many other internal error values.
-Applications should only test the return value against error values defined in
-&lt;sndfile.h&gt; as the internal error values are subject to change at any
-time.
-For errors not in the above list, the function sf_error_number() can be used to
-convert it to an error string.
-</P>
-
-<PRE>
-      const char* sf_strerror     (SNDFILE *sndfile) ;
-      const char* sf_error_number (int errnum) ;
-</PRE>
-
-<P>
-The error functions sf_strerror() and sf_error_number() convert the library's internal
-error enumerations into text strings.
-</P>
-<PRE>
-      int         sf_perror     (SNDFILE *sndfile) ;
-      int         sf_error_str  (SNDFILE *sndfile, char* str, size_t len) ;
-</PRE>
-
-<P>
-The functions sf_perror() and sf_error_str() are deprecated and will be dropped
-from the library at some later date.
-</P>
-
-<A NAME="close"></A>
-<H2><BR><B>File Close Function</B></H2>
-
-<PRE>
-      int  sf_close  (SNDFILE *sndfile) ;
-</PRE>
-<!-- pepper -->
-<P>
-The close function closes the file, deallocates its internal buffers and returns
-0 on success or an error value otherwise.
-</P>
-<BR>
-
-<A NAME="write_sync"></A>
-<H2><BR><B>Write Sync Function</B></H2>
-
-<PRE>
-      void  sf_write_sync  (SNDFILE *sndfile) ;
-</PRE>
-<!-- pepper -->
-<P>
-If the file is opened SFM_WRITE or SFM_RDWR, call the operating system's function
-to force the writing of all file cache buffers to disk. If the file is opened
-SFM_READ no action is taken.
-</P>
-<BR>
-
-
-<A NAME="read"></A>
-<H2><BR><B>File Read Functions</B></H2>
-
-<PRE>
-      sf_count_t  sf_read_short   (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
-      sf_count_t  sf_read_int     (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
-      sf_count_t  sf_read_float   (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
-      sf_count_t  sf_read_double  (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
-</PRE>
-
-<A NAME="readf"></A>
-<PRE>
-      sf_count_t  sf_readf_short   (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
-      sf_count_t  sf_readf_int     (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
-      sf_count_t  sf_readf_float   (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
-      sf_count_t  sf_readf_double  (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
-</PRE>
-<!-- pepper -->
-<P>
-The file read functions fill the array pointed to by ptr with the
-requested number of items or frames.
-</P>
-
-<P>
-For the frames-count functions, the frames parameter specifies the number
-of frames. A frame is just a block of samples, one for each
-channel. <B>Care must be taken to ensure that there is enough space
-in the array pointed to by ptr, to take (frames * channels) number of
-items (shorts, ints, floats or doubles).
-</B></P>
-
-<P>
-For the items-count functions, the items parameter must be an integer product
-of the number of channels or an error will occur. Here, an item is just a
-sample.
-</P>
-
-<P>
-Note: The only difference between the "items" and "frames" versions of
-each read function is the units in which the object count is specified
-- calling sf_readf_short with a count argument of N, on a SNDFILE with
-C channels, is the same as calling sf_read_short with a count argument
-of N*C. The buffer pointed to by "ptr" should be the same number of
-bytes in each case.
-</P>
-
-<!-- pepper -->
-<P>
-Note: The data type used by the calling program and the data format of
-the file do not need to be the same. For instance, it is possible to
-open a 16 bit PCM encoded WAV file and read the data using
-sf_read_float(). The library seamlessly converts between the two
-formats on-the-fly. See
-<A HREF="#note1">Note 1</A>.
-</P>
-<!-- pepper -->
-<P>
-The sf_read_XXXX and sf_readf_XXXX functions return the number of
-items or frames read, respectively. Unless the end of the file was
-reached during the read, the return value should equal the number of
-objects requested. Attempts to read beyond the end of the file will
-not result in an error but will cause the read functions to return
-less than the number of objects requested or 0 if already at the end
-of the file.
-</P>
-
-<A NAME="write"></A>
-<H2><BR><B>File Write Functions</B></H2>
-
-<PRE>
-      sf_count_t  sf_write_short   (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
-      sf_count_t  sf_write_int     (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
-      sf_count_t  sf_write_float   (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
-      sf_count_t  sf_write_double  (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
-</PRE>
-
-<A NAME="writef"></A>
-<PRE>
-      sf_count_t  sf_writef_short  (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
-      sf_count_t  sf_writef_int    (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
-      sf_count_t  sf_writef_float  (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
-      sf_count_t  sf_writef_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
-</PRE>
-
-<P>
-The file write functions write the data in the array pointed to by ptr to the file.
-</P>
-
-<P>
-For items-count functions, the items parameter specifies the size of
-the array and must be an integer product of the number of channels or
-an error will occur.
-</P>
-
-<P>
-For the frames-count functions, the array is expected to be large enough
-to hold a number of items equal to the product of frames and the
-number of channels.
-</P>
-
-<P>As with the read functions <A HREF="#read">above</A>, the only
-difference in the items and frames version of each write function is
-the units in which the buffer size is specified. Again, the data type
-used by the calling program and the data format of the file do not
-need to be the same (<A HREF="#note1">Note 1</A>).
-</P>
-
-<P>
-The sf_write_XXXX and sf_writef_XXXX functions respectively return the
-number of items or frames written (which should be the same as the
-items or frames parameter).
-</P>
-
-
-<A NAME="raw"></A>
-<H2><BR><B>Raw File Read and Write Functions</B></H2>
-<!-- pepper -->
-<PRE>
-      sf_count_t  sf_read_raw     (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
-      sf_count_t  sf_write_raw    (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
-</PRE>
-
-<P>
-<b>Note:</b> Unless you are writing an external decoder/encode that uses
-libsndfile to handle the file headers, you should not be using these
-functions.
-</P>
-
-<P>
-The raw read and write functions read raw audio data from the audio file (not to be
-confused with reading RAW header-less PCM files). The number of bytes read or written
-must always be an integer multiple of the number of channels multiplied by the number
-of bytes required to represent one sample from one channel.
-</P>
-<!-- pepper -->
-<P>
-The raw read and write functions return the number of bytes read or written (which
-should be the same as the bytes parameter).
-</P>
-
-<P>
-<B>
-Note : The result of using of both regular reads/writes and raw reads/writes on
-compressed file formats other than SF_FORMAT_ALAW and SF_FORMAT_ULAW is undefined.
-</B>
-</P>
-
-<p>
-See also : <a href="command.html#SFC_RAW_NEEDS_ENDSWAP">SFC_RAW_NEEDS_ENDSWAP</a>
-</p>
-
-<A NAME="string"></A>
-<H2><BR><B>Functions for Reading and Writing String Data</B></H2>
-
-
-<PRE>
-      const char* sf_get_string   (SNDFILE *sndfile, int str_type) ;
-      int         sf_set_string   (SNDFILE *sndfile, int str_type, const char* str) ;
-</PRE>
-
-<P>
-These functions allow strings to be set on files opened for write and to be
-retrieved from files opened for read where supported by the given file type.
-The <B>str_type</B> parameter can be any one of the following string types:
-</P>
-
-<PRE>
-          enum
-          {   SF_STR_TITLE,
-              SF_STR_COPYRIGHT,
-              SF_STR_SOFTWARE,
-              SF_STR_ARTIST,
-              SF_STR_COMMENT,
-              SF_STR_DATE,
-              SF_STR_ALBUM,
-              SF_STR_LICENSE,
-              SF_STR_TRACKNUMBER,
-              SF_STR_GENRE
-          } ;
-</PRE>
-
-<P>
-The sf_get_string() function returns the specified string if it exists and a
-NULL pointer otherwise.
-In addition to the string ids above, SF_STR_FIRST (== SF_STR_TITLE) and
-SF_STR_LAST (always the same as the highest numbers string id) are also
-available to allow iteration over all the available string ids.
-</P>
-
-<P>
-The sf_set_string() function sets the string data.
-It returns zero on success and non-zero on error.
-The error code can be converted to a string using sf_error_number().
-</P>
-
-<P>
-Strings passed to and retrieved from these two functions are assumed to be
-utf-8.
-However, while formats like Ogg/Vorbis and FLAC fully support utf-8, others
-like WAV and AIFF officially only support ASCII.
-Writing utf-8 strings to WAV and AIF files with libsndfile will work when read
-back with libsndfile, but may not work with other programs.
-</P>
-
-<P>
-The suggested method of dealing with tags retrived using sf_get_string() is to
-assume they are utf-8.
-Similarly if you have a string in some exotic format like utf-16, it should be
-encoded to utf-8 before being written using libsndfile.
-</P>
-
-<HR>
-
-<A NAME="note1"></A>
-<H2><BR><B>Note 1</B></H2>
-<!-- pepper -->
-<P>
-When converting between integer PCM formats of differing size
-(e.g. using sf_read_int() to read a 16 bit PCM encoded WAV file)
-libsndfile obeys one simple rule:
-</P>
-
-<P CLASS=indent_block>
-Whenever integer data is moved from one sized container to another sized container,
-the most significant bit in the source container will become the most significant bit
-in the destination container.
-</P>
-
-<P>
-When converting between integer data and floating point data, different rules apply.
-The default behaviour when reading floating point data (sf_read_float() or
-sf_read_double ()) from a file with integer data is normalisation. Regardless of
-whether data in the file is 8, 16, 24 or 32 bit wide, the data will be read as
-floating point data in the range [-1.0, 1.0]. Similarly, data in the range [-1.0, 1.0]
-will be written to an integer PCM file so that a data value of 1.0 will be the largest
-allowable integer for the given bit width. This normalisation can be turned on or off
-using the <A HREF="command.html">sf_command</A> interface.
-</P>
-
-<A NAME="note2"></A>
-<H2><BR><B>Note 2</B></H2>
-
-<P>
-Reading a file containg floating point data (allowable with WAV, AIFF, AU and other
-file formats) using integer read methods (sf_read_short() or sf_read_int()) can
-produce unexpected results.
-For instance the data in the file may have a maximum absolute value &lt; 1.0 which
-would mean that all sample values read from the file will be zero.
-In order to read these files correctly using integer read methods, it is recommended
-that you use the
-     <A HREF="command.html">sf_command</A>
-interface, a command of
-     <A HREF="command.html#SFC_SET_SCALE_FLOAT_INT_READ">SFC_SET_SCALE_FLOAT_INT_READ</A>
-and a parameter of SF_TRUE to force correct scaling.
-</P>
-<!-- pepper -->
-<HR>
-<!-- pepper -->
-<P>
-       The libsndfile home page is
-               <A HREF="http://www.mega-nerd.com/libsndfile/">here</A>.
-</P>
-<P>
-Version : 1.0.28
-</P>
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-
-</BODY>
-</HTML>
diff --git a/doc/bugs.html b/doc/bugs.html
deleted file mode 100644 (file)
index 3a441fe..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       Bug Reporting
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<CENTER>
-               <H1><B>Reporting Bugs in libsndfile</B></H1>
-</CENTER>
-<P>
-       Before even attempting to report a bug in libsndfile please make sure you have
-       read the
-               <A HREF="FAQ.html">Frequently Asked Questions</A>.
-       If you are having a problem writing code using libsndfile make sure you read
-       the
-               <A HREF="api.html">Application Programming Interface</A>
-       documentation.
-</P>
-<P>
-       That said, I am interested in finding and fixing all genuine bugs in libsndfile.
-       Bugs I want to fix include any of the following problems (and probably others) :
-</P>
-       <UL>
-       <LI>    Compilation problems on new platforms.
-       <LI>    Errors being detected during the `make check' process.
-       <LI>    Segmentation faults occuring inside libsndfile.
-       <LI>    libsndfile hanging when opening a file.
-       <LI>    Supported sound file types being incorrectly read or written.
-       <LI>    Omissions, errors or spelling mistakes in the documentation.
-       </UL>
-
-<P>
-       When submitting a bug report you must include :
-</P>
-       <UL>
-       <LI>    Your system (CPU and memory size should be enough).
-       <LI>    The operating system you are using.
-       <LI>    Whether you are using a package provided by your distribution or you
-                       compiled it youself.
-       <LI>    If you compiled it yourself, the compiler you are using. (Also make
-                       sure to run 'make check'.)
-       <LI>    A description of the problem.
-       <LI>    Information generated by the sndfile-info program (see next paragraph).
-       <LI>    If you are having problems with sndfile-play and ALSA on Linux, I will
-                       need information about your kernel, ALSA version, compiler version,
-                       whether you compiled the kernel/ALSA your self or installed from a
-                       package etc.
-       </UL>
-
-<P>
-       If libsndfile compiles and installs correctly but has difficulty reading a particular
-       file or type of file you should run the <B>sndfile-info</B> program (from the examples
-       directory of the libsndfile distribution) on the file. See
-               <A HREF="sndfile_info.html">here</A>
-       for an example of the use of the <B>sndfile-info</B> program.
-</P>
-<P>
-       Please do not send me a sound file which fails to open under libsndfile unless I
-       specifically ask you to. The above information should usually suffice for most
-       problems.
-</P>
-<P>
-       Once you have the above information you should submit a ticket on the libsnfile
-               <A HREF="https://github.com/erikd/libsndfile/issues">github issue tracker</A>.
-
-</P>
-</BODY>
-</HTML>
diff --git a/doc/command.html b/doc/command.html
deleted file mode 100644 (file)
index a00f7ea..0000000
+++ /dev/null
@@ -1,1872 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile : the sf_command function.
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <!-- Another version at the bottom of the page.  -->
-       <META NAME="Description" CONTENT="The libsndfile API.">
-       <META NAME="Keywords"    CONTENT="WAV AIFF AU libsndfile sound audio dsp Linux">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<H1><B>sf_command</B></H1>
-<PRE>
-
-        int    sf_command (SNDFILE *sndfile, int cmd, void *data, int datasize) ;
-</PRE>
-<P>
-       This function allows the caller to retrieve information from or change aspects of the
-       library behaviour.
-       Examples include retrieving a string containing the library version or changing the
-       scaling applied to floating point sample data during read and write.
-       Most of these operations are performed on a per-file basis.
-</P>
-<P>
-       The cmd parameter is an integer identifier which is defined in &lt;sndfile.h&gt;.
-       All of the valid command identifiers have names beginning with "SFC_".
-       Data is passed to and returned from the library by use of a void pointer.
-       The library will not read or write more than datasize bytes from the void pointer.
-       For some calls no data is required in which case data should be NULL and datasize
-       may be used for some other purpose.
-</P>
-<P>
-       The available commands are as follows:
-</P>
-
-<CENTER>
-<TABLE BORDER="0" WIDTH="90%" CELLPADDING="4">
-<TR>
-       <TD><A HREF="#SFC_GET_LIB_VERSION">SFC_GET_LIB_VERSION</A></TD>
-       <TD>Retrieve the version of the library.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_LOG_INFO">SFC_GET_LOG_INFO</A></TD>
-       <TD>Retrieve the internal per-file operation log.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_CALC_SIGNAL_MAX">SFC_CALC_SIGNAL_MAX</A></TD>
-       <TD>Calculate the measured maximum signal value.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_CALC_NORM_SIGNAL_MAX">SFC_CALC_NORM_SIGNAL_MAX</A></TD>
-       <TD>Calculate the measured normalised maximum signal value.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_CALC_MAX_ALL_CHANNELS">SFC_CALC_MAX_ALL_CHANNELS</A></TD>
-       <TD>Calculate the peak value for each channel.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_CALC_NORM_MAX_ALL_CHANNELS">SFC_CALC_NORM_MAX_ALL_CHANNELS</A></TD>
-       <TD>Calculate the normalised peak for each channel.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_SIGNAL_MAX">SFC_GET_SIGNAL_MAX</A></TD>
-       <TD>Retrieve the peak value for the file (as stored in the file header).</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_MAX_ALL_CHANNELS">SFC_GET_MAX_ALL_CHANNELS</A></TD>
-       <TD>Retrieve the peak value for each channel  (as stored in the file header).</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_NORM_FLOAT">SFC_SET_NORM_FLOAT</A></TD>
-       <TD>Modify the normalisation behaviour of the floating point reading and writing functions.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_SET_NORM_DOUBLE">SFC_SET_NORM_DOUBLE</A></TD>
-       <TD>Modify the normalisation behaviour of the double precision floating point reading and writing functions.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_NORM_FLOAT">SFC_GET_NORM_FLOAT</A></TD>
-       <TD>Retrieve the current normalisation behaviour of the floating point reading and writing functions.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_NORM_DOUBLE">SFC_GET_NORM_DOUBLE</A></TD>
-       <TD>Retrieve the current normalisation behaviour of the double precision floating point reading and writing functions.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_SET_SCALE_FLOAT_INT_READ">SFC_SET_SCALE_FLOAT_INT_READ</A></TD>
-       <TD>Set/clear the scale factor when integer (short/int) data is read from a file
-       containing floating point data.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_SCALE_INT_FLOAT_WRITE">SFC_SET_SCALE_INT_FLOAT_WRITE</A></TD>
-       <TD>Set/clear the scale factor when integer (short/int) data is written to a file
-       as floating point data.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_SIMPLE_FORMAT_COUNT">SFC_GET_SIMPLE_FORMAT_COUNT</A></TD>
-       <TD>Retrieve the number of simple formats supported by libsndfile.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_SIMPLE_FORMAT">SFC_GET_SIMPLE_FORMAT</A></TD>
-       <TD>Retrieve information about a simple format.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_FORMAT_INFO">SFC_GET_FORMAT_INFO</A></TD>
-       <TD>Retrieve information about a major or subtype format.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_FORMAT_MAJOR_COUNT">SFC_GET_FORMAT_MAJOR_COUNT</A></TD>
-       <TD>Retrieve the number of major formats.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_FORMAT_MAJOR">SFC_GET_FORMAT_MAJOR</A></TD>
-       <TD>Retrieve information about a major format type.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_FORMAT_SUBTYPE_COUNT">SFC_GET_FORMAT_SUBTYPE_COUNT</A></TD>
-       <TD>Retrieve the number of subformats.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_GET_FORMAT_SUBTYPE">SFC_GET_FORMAT_SUBTYPE</A></TD>
-       <TD>Retrieve information about a subformat.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_ADD_PEAK_CHUNK">SFC_SET_ADD_PEAK_CHUNK</A></TD>
-       <TD>Switch the code for adding the PEAK chunk to WAV and AIFF files on or off.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_UPDATE_HEADER_NOW">SFC_UPDATE_HEADER_NOW</A></TD>
-       <TD>Used when a file is open for write, this command will update the file
-               header to reflect the data written so far.</TD>
-</TR>
-<TR>
-       <TD><A HREF="#SFC_SET_UPDATE_HEADER_AUTO">SFC_SET_UPDATE_HEADER_AUTO</A></TD>
-       <TD>Used when a file is open for write, this command will cause the file header
-               to be updated after each write to the file.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_FILE_TRUNCATE">SFC_FILE_TRUNCATE</A></TD>
-       <TD>Truncate a file open for write or for read/write.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_RAW_START_OFFSET">SFC_SET_RAW_START_OFFSET</A></TD>
-       <TD>Change the data start offset for files opened up as SF_FORMAT_RAW.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_CLIPPING">SFC_SET_CLIPPING</A></TD>
-       <TD>Turn on/off automatic clipping when doing floating point to integer
-               conversion.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_CLIPPING">SFC_GET_CLIPPING</A></TD>
-       <TD>Retrieve current clipping setting.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_EMBED_FILE_INFO">SFC_GET_EMBED_FILE_INFO</A></TD>
-       <TD>Retrieve information about audio files embedded inside other files.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_WAVEX_GET_AMBISONIC">SFC_GET_AMBISONIC</A></TD>
-       <TD>Test a WAVEX file for Ambisonic format</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_WAVEX_SET_AMBISONIC">SFC_SET_AMBISONIC</A></TD>
-       <TD>Modify a WAVEX header for Ambisonic format</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_VBR_ENCODING_QUALITY">SFC_SET_VBR_ENCODING_QUALITY</A></TD>
-       <TD>Set the Variable Bit Rate encoding quality</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_COMPRESSION_LEVEL">SFC_SET_COMPRESSION_LEVEL</A></TD>
-       <TD>Set the compression level.</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_RAW_NEEDS_ENDSWAP">SFC_RAW_NEEDS_ENDSWAP</a></td>
-       <TD>Determine if raw data needs endswapping</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_BROADCAST_INFO">SFC_GET_BROADCAST_INFO</A></TD>
-       <TD>Retrieve the Broadcast Chunk info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_BROADCAST_INFO">SFC_SET_BROADCAST_INFO</A></TD>
-       <TD>Set the Broadcast Chunk info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_CART_INFO">SFC_SET_CART_INFO</A></TD>
-       <TD>Set the Cart Chunk info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_CART_INFO">SFC_GET_CART_INFO</A></TD>
-       <TD>Retrieve the Cart Chunk info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_LOOP_INFO">SFC_GET_LOOP_INFO</A></TD>
-       <TD>Get loop info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_INSTRUMENT">SFC_GET_INSTRUMENT</A></TD>
-       <TD>Get instrument info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_INSTRUMENT">SFC_SET_INSTRUMENT</A></TD>
-       <TD>Set instrument info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_CUE_COUNT">SFC_GET_CUE_COUNT</A></TD>
-       <TD>Get the cue marker count</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_GET_CUE">SFC_GET_CUE</A></TD>
-       <TD>Get cue marker info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_SET_CUE">SFC_SET_CUE</A></TD>
-       <TD>Set cue marker info</TD>
-</TR>
-
-<TR>
-       <TD><A HREF="#SFC_RF64_AUTO_DOWNGRADE">SFC_RF64_AUTO_DOWNGRADE</A></TD>
-       <TD>Enable auto downgrade from RF64 to WAV</TD>
-</TR>
-
-<!--
-<TR>
-       <TD><A HREF="#add-dither">add dither</A></TD>
-       <TD>Add dither to output on write.</TD>
-</TR>
--->
-</TABLE>
-</CENTER>
-
-<BR><BR>
-
-<HR>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_LIB_VERSION"></A>
-<H2><BR><B>SFC_GET_LIB_VERSION</B></H2>
-<P>
-Retrieve the version of the library as a string.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : Not used
-        cmd      : SFC_GET_LIB_VERSION
-        data     : A pointer to a char buffer
-        datasize : The size of the buffer
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        char  buffer [128] ;
-        sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
-</PRE>
-
-<DL>
-<DT>Return value:</DT>
-       <DD><DD>This call will return the length of the retrieved version string.
-</DL>
-<DL>
-<DT>Notes:</DT>
-<DD>
-The string returned in the buffer passed to this function will not overflow
-the buffer and will always be null terminated .
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_LOG_INFO"></A>
-<H2><BR><B>SFC_GET_LOG_INFO</B></H2>
-<P>
-Retrieve the log buffer generated when opening a file as a string. This log
-buffer can often contain a good reason for why libsndfile failed to open a
-particular file.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_LOG_INFO
-        data     : A pointer to a char buffer
-        datasize : The size of the buffer
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        char  buffer [2048] ;
-        sf_command (sndfile, SFC_GET_LOG_INFO, buffer, sizeof (buffer)) ;
-</PRE>
-
-<DL>
-<DT>Return value:</DT>
-       <DD><DD>This call will return the length of the retrieved version string.
-</DL>
-<DL>
-<DT>Notes:</DT>
-<DD>
-The string returned in the buffer passed to this function will not overflow
-the buffer and will always be null terminated .
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_CALC_SIGNAL_MAX"></A>
-<H2><BR><B>SFC_CALC_SIGNAL_MAX</B></H2>
-<P>
-Retrieve the measured maximum signal value. This involves reading through
-the whole file which can be slow on large files.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_CALC_SIGNAL_MAX
-        data     : A pointer to a double
-        datasize : sizeof (double)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        double   max_val ;
-        sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &amp;max_val, sizeof (max_val)) ;
-</PRE>
-
-<DL>
-<DT>Return value:</DT>
-       <DD><DD>Zero on success, non-zero otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_CALC_NORM_SIGNAL_MAX"></A>
-<H2><BR><B>SFC_CALC_NORM_SIGNAL_MAX</B></H2>
-<P>
-Retrieve the measured normalised maximum signal value. This involves reading
-through the whole file which can be slow on large files.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_CALC_NORM_SIGNAL_MAX
-        data     : A pointer to a double
-        datasize : sizeof (double)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        double   max_val ;
-        sf_command (sndfile, SFC_CALC_NORM_SIGNAL_MAX, &amp;max_val, sizeof (max_val)) ;
-</PRE>
-
-<DL>
-<DT>Return value:</DT>
-       <DD><DD>Zero on success, non-zero otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_CALC_MAX_ALL_CHANNELS"></A>
-<H2><BR><B>SFC_CALC_MAX_ALL_CHANNELS</B></H2>
-<P>
-Calculate the peak value (ie a single number) for each channel.
-This involves reading through the whole file which can be slow on large files.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_CALC_MAX_ALL_CHANNELS
-        data     : A pointer to a double
-        datasize : sizeof (double) * number_of_channels
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        double   peaks [number_of_channels] ;
-        sf_command (sndfile, SFC_CALC_MAX_ALL_CHANNELS, peaks, sizeof (peaks)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>Zero if peaks have been calculated successfully and non-zero otherwise.
-</DL>
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_CALC_NORM_MAX_ALL_CHANNELS"></A>
-<H2><BR><B>SFC_CALC_NORM_MAX_ALL_CHANNELS</B></H2>
-<P>
-Calculate the normalised peak for each channel.
-This involves reading through the whole file which can be slow on large files.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_CALC_NORM_MAX_ALL_CHANNELS
-        data     : A pointer to a double
-        datasize : sizeof (double) * number_of_channels
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        double   peaks [number_of_channels] ;
-        sf_command (sndfile, SFC_CALC_NORM_MAX_ALL_CHANNELS, peaks, sizeof (peaks)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>Zero if peaks have been calculated successfully and non-zero otherwise.
-</DL>
-
-
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_SIGNAL_MAX"></A>
-<H2><BR><B>SFC_GET_SIGNAL_MAX</B></H2>
-<P>
-Retrieve the peak value for the file as stored in the file header.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_SIGNAL_MAX
-        data     : A pointer to a double
-        datasize : sizeof (double)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        double   max_peak ;
-        sf_command (sndfile, SFC_GET_SIGNAL_MAX, &amp;max_peak, sizeof (max_peak)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>SF_TRUE if the file header contained the peak value. SF_FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_MAX_ALL_CHANNELS"></A>
-<H2><BR><B>SFC_GET_MAX_ALL_CHANNELS</B></H2>
-<P>
-Retrieve the peak value for the file as stored in the file header.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_SIGNAL_MAX
-        data     : A pointer to an array of doubles
-        datasize : sizeof (double) * number_of_channels
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        double   peaks [number_of_channels] ;
-        sf_command (sndfile, SFC_GET_MAX_ALL_CHANNELS, peaks, sizeof (peaks)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>SF_TRUE if the file header contains per channel peak values for the file.
-               SF_FALSE otherwise.
-</DL>
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_NORM_FLOAT"></A>
-<H2><BR><B>SFC_SET_NORM_FLOAT</B></H2>
-<P>
-This command only affects data read from or written to using the floating point functions:
-</P>
-<PRE>
-       size_t    <A HREF="api.html#read">sf_read_float</A>    (SNDFILE *sndfile, float *ptr, size_t items) ;
-       size_t    <A HREF="api.html#readf">sf_readf_float</A>   (SNDFILE *sndfile, float *ptr, size_t frames) ;
-
-       size_t    <A HREF="api.html#write">sf_write_float</A>   (SNDFILE *sndfile, float *ptr, size_t items) ;
-       size_t    <A HREF="api.html#writef">sf_writef_float</A>  (SNDFILE *sndfile, float *ptr, size_t frames) ;
-</PRE>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_NORM_FLOAT
-        data     : NULL
-        datasize : SF_TRUE or SF_FALSE
-</PRE>
-<P>
-For read operations setting normalisation to SF_TRUE means that the data from all
-subsequent reads will be be normalised to the range [-1.0, 1.0].
-</P>
-<P>
-For write operations, setting normalisation to SF_TRUE means than all data supplied
-to the float write functions should be in the range [-1.0, 1.0] and will be scaled
-for the file format as necessary.
-</P>
-<P>
-For both cases, setting normalisation to SF_FALSE means that no scaling will take place.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        sf_command (sndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE) ;
-
-        sf_command (sndfile, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>Returns the previous float normalisation mode.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_NORM_DOUBLE"></A>
-<H2><BR><B>SFC_SET_NORM_DOUBLE</B></H2>
-<P>
-This command only affects data read from or written to using the double precision
-floating point functions:
-</P>
-<PRE>
-       size_t    <A HREF="api.html#read">sf_read_double</A>    (SNDFILE *sndfile, double *ptr, size_t items) ;
-       size_t    <A HREF="api.html#readf">sf_readf_double</A>   (SNDFILE *sndfile, double *ptr, size_t frames) ;
-
-       size_t    <A HREF="api.html#write">sf_write_double</A>   (SNDFILE *sndfile, double *ptr, size_t items) ;
-       size_t    <A HREF="api.html#writef">sf_writef_double</A>  (SNDFILE *sndfile, double *ptr, size_t frames) ;
-</PRE>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_NORM_DOUBLE
-        data     : NULL
-        datasize : SF_TRUE or SF_FALSE
-</PRE>
-<P>
-For read operations setting normalisation to SF_TRUE means that the data
-from all subsequent reads will be be normalised to the range [-1.0, 1.0].
-</P>
-<P>
-For write operations, setting normalisation to SF_TRUE means than all data supplied
-to the double write functions should be in the range [-1.0, 1.0] and will be scaled
-for the file format as necessary.
-</P>
-<P>
-For both cases, setting normalisation to SF_FALSE means that no scaling will take place.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        sf_command (sndfile, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ;
-
-        sf_command (sndfile, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>Returns the previous double normalisation mode.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_NORM_FLOAT"></A>
-<H2><BR><B>SFC_GET_NORM_FLOAT</B></H2>
-<P>
-Retrieve the current float normalisation mode.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_NORM_FLOAT
-        data     : NULL
-        datasize : anything
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        normalisation = sf_command (sndfile, SFC_GET_NORM_FLOAT, NULL, 0) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>Returns TRUE if normalisation is on and FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_NORM_DOUBLE"></A>
-<H2><BR><B>SFC_GET_NORM_DOUBLE</B></H2>
-<P>
-Retrieve the current float normalisation mode.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_NORM_DOUBLE
-        data     : NULL
-        datasize : anything
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        normalisation = sf_command (sndfile, SFC_GET_NORM_DOUBLE, NULL, 0) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>Returns TRUE if normalisation is on and FALSE otherwise.
-</DL>
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_SCALE_FLOAT_INT_READ"></A>
-<H2><BR><B>SFC_SET_SCALE_FLOAT_INT_READ</B></H2>
-<P>
-Set/clear the scale factor when integer (short/int) data is read from a file
-containing floating point data.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_SCALE_FLOAT_INT_READ
-        data     : NULL
-        datasize : TRUE or FALSE
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        sf_command (sndfile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>Returns the previous SFC_SET_SCALE_FLOAT_INT_READ setting for this file.
-</DL>
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_SCALE_INT_FLOAT_WRITE"></A>
-<H2><BR><B>SFC_SET_SCALE_INT_FLOAT_WRITE</B></H2>
-<P>
-Set/clear the scale factor when integer (short/int) data is written to a file
-as floating point data.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_SCALE_FLOAT_INT_READ
-        data     : NULL
-        datasize : TRUE or FALSE
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        sf_command (sndfile, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>Returns the previous SFC_SET_SCALE_INT_FLOAT_WRITE setting for this file.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_SIMPLE_FORMAT_COUNT"></A>
-<H2><BR><B>SFC_GET_SIMPLE_FORMAT_COUNT</B></H2>
-<P>
-Retrieve the number of simple formats supported by libsndfile.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_SIMPLE_FORMAT_COUNT
-        data     : a pointer to an int
-        datasize : sizeof (int)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        int  count ;
-        sf_command (sndfile, SFC_GET_SIMPLE_FORMAT_COUNT, &amp;count, sizeof (int)) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>0
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_SIMPLE_FORMAT"></A>
-<H2><BR><B>SFC_GET_SIMPLE_FORMAT</B></H2>
-<P>
-Retrieve information about a simple format.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_SIMPLE_FORMAT
-        data     : a pointer to an  SF_FORMAT_INFO struct
-        datasize : sizeof (SF_FORMAT_INFO)
-</PRE>
-<P>
-The SF_FORMAT_INFO struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-        typedef struct
-        {   int         format ;
-            const char  *name ;
-            const char  *extension ;
-        } SF_FORMAT_INFO ;
-</PRE>
-<P>
-When sf_command() is called with SF_GET_SIMPLE_FORMAT, the value of the format
-field should be the format number (ie 0 &lt;= format &lt;= count value obtained using
-SF_GET_SIMPLE_FORMAT_COUNT).
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        SF_FORMAT_INFO format_info ;
-        int             k, count ;
-
-        sf_command (sndfile, SFC_GET_SIMPLE_FORMAT_COUNT, &amp;count, sizeof (int)) ;
-
-        for (k = 0 ; k &lt; count ; k++)
-        {   format_info.format = k ;
-            sf_command (sndfile, SFC_GET_SIMPLE_FORMAT, &amp;format_info, sizeof (format_info)) ;
-            printf ("%08x  %s %s\n", format_info.format, format_info.name, format_info.extension) ;
-            } ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>0 on success and non-zero otherwise.
-       <DD>The value of the format field of the SF_FORMAT_INFO struct will be a value which
-               can be placed in the format field of an SF_INFO struct when a file is to be opened
-               for write.
-       <DD>The name field will contain a char* pointer to the name of the string, eg. "WAV (Microsoft 16 bit PCM)".
-       <DD>The extension field will contain the most commonly used file extension for that file type.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_FORMAT_INFO"></A>
-<H2><BR><B>SFC_GET_FORMAT_INFO</B></H2>
-<P>
-Retrieve information about a major or subtype format.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_FORMAT_INFO
-        data     : a pointer to an SF_FORMAT_INFO struct
-        datasize : sizeof (SF_FORMAT_INFO)
-</PRE>
-<P>
-The SF_FORMAT_INFO struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-        typedef struct
-        {   int         format ;
-            const char  *name ;
-            const char  *extension ;
-        } SF_FORMAT_INFO ;
-</PRE>
-<P>
-When sf_command() is called with SF_GET_FORMAT_INFO, the format field is
-examined and if (format &amp; SF_FORMAT_TYPEMASK) is a valid format then the struct
-is filled in with information about the given major type.
-If (format &amp; SF_FORMAT_TYPEMASK) is FALSE and (format &amp; SF_FORMAT_SUBMASK) is a
-valid subtype format then the struct is filled in with information about the given
-subtype.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        SF_FORMAT_INFO format_info ;
-
-        format_info.format = SF_FORMAT_WAV ;
-        sf_command (sndfile, SFC_GET_FORMAT_INFO, &amp;format_info, sizeof (format_info)) ;
-        printf ("%08x  %s %s\n", format_info.format, format_info.name, format_info.extension) ;
-
-        format_info.format = SF_FORMAT_ULAW ;
-        sf_command (sndfile, SFC_GET_FORMAT_INFO, &amp;format_info, sizeof (format_info)) ;
-        printf ("%08x  %s\n", format_info.format, format_info.name) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>0 on success and non-zero otherwise.
-</DL>
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_FORMAT_MAJOR_COUNT"></A>
-<H2><BR><B>SFC_GET_FORMAT_MAJOR_COUNT</B></H2>
-<P>
-Retrieve the number of major formats.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_FORMAT_MAJOR_COUNT
-        data     : a pointer to an int
-        datasize : sizeof (int)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        int  count ;
-        sf_command (sndfile, SFC_GET_FORMAT_MAJOR_COUNT, &amp;count, sizeof (int)) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>0
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_FORMAT_MAJOR"></A>
-<H2><BR><B>SFC_GET_FORMAT_MAJOR</B></H2>
-<P>
-Retrieve information about a major format type.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_FORMAT_MAJOR
-        data     : a pointer to an  SF_FORMAT_INFO struct
-        datasize : sizeof (SF_FORMAT_INFO)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        SF_FORMAT_INFO format_info ;
-        int             k, count ;
-
-        sf_command (sndfile, SFC_GET_FORMAT_MAJOR_COUNT, &amp;count, sizeof (int)) ;
-
-        for (k = 0 ; k &lt; count ; k++)
-        {   format_info.format = k ;
-            sf_command (sndfile, SFC_GET_FORMAT_MAJOR, &amp;format_info, sizeof (format_info)) ;
-            printf ("%08x  %s %s\n", format_info.format, format_info.name, format_info.extension) ;
-            } ;
-</PRE>
-<P>
-For a more comprehensive example, see the program list_formats.c in the examples/
-directory of the libsndfile source code distribution.
-</P>
-<DL>
-<DT>Return value: </DT>
-       <DD>0 on success and non-zero otherwise.
-       <DD>The value of the format field will be one of the major format identifiers such as
-               SF_FORMAT_WAV or SF_FORMAT_AIFF.
-       <DD>The name field will contain a char* pointer to the name of the string, eg. "WAV (Microsoft)".
-       <DD>The extension field will contain the most commonly used file extension for that file type.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_FORMAT_SUBTYPE_COUNT"></A>
-<H2><BR><B>SFC_GET_FORMAT_SUBTYPE_COUNT</B></H2>
-<P>
-Retrieve the number of subformats.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_FORMAT_SUBTYPE_COUNT
-        data     : a pointer to an int
-        datasize : sizeof (int)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        int   count ;
-        sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE_COUNT, &amp;count, sizeof (int)) ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>0
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_FORMAT_SUBTYPE"></A>
-<H2><BR><B>SFC_GET_FORMAT_SUBTYPE</B></H2>
-<P>
-Enumerate the subtypes (this function does not translate a subtype into
-a string describing that subtype).
-A typical use case might be retrieving a string description of all subtypes
-so that a dialog box can be filled in.
-</P>
-<P>
-
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-        sndfile  : Not used.
-        cmd      : SFC_GET_FORMAT_SUBTYPE
-        data     : a pointer to an SF_FORMAT_INFO struct
-        datasize : sizeof (SF_FORMAT_INFO)
-</PRE>
-<P>
-Example 1: Retrieve all sybtypes supported by the WAV format.
-</P>
-<PRE>
-        SF_FORMAT_INFO format_info ;
-        int             k, count ;
-
-        sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE_COUNT, &amp;count, sizeof (int)) ;
-
-        for (k = 0 ; k &lt; count ; k++)
-        {   format_info.format = k ;
-            sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE, &amp;format_info, sizeof (format_info)) ;
-            if (! sf_format_check (format_info.format | SF_FORMAT_WAV))
-               continue ;
-            printf ("%08x  %s\n", format_info.format, format_info.name) ;
-            } ;
-</PRE>
-<P>
-Example 2: Print a string describing the SF_FORMAT_PCM_16 subtype.
-</P>
-<PRE>
-        SF_FORMAT_INFO format_info ;
-        int             k, count ;
-
-        sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE_COUNT, &amp;count, sizeof (int)) ;
-
-        for (k = 0 ; k &lt; count ; k++)
-        {   format_info.format = k ;
-            sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE, &amp;format_info, sizeof (format_info)) ;
-            if (format_info.format == SF_FORMAT_PCM_16)
-            {   printf ("%08x  %s\n", format_info.format, format_info.name) ;
-                break ;
-                } ;
-            } ;
-</PRE>
-<P>
-For a more comprehensive example, see the program list_formats.c in the examples/
-directory of the libsndfile source code distribution.
-</P>
-<DL>
-<DT>Return value: </DT>
-       <DD>0 on success and non-zero otherwise.
-       <DD>The value of the format field will be one of the major format identifiers such as
-               SF_FORMAT_WAV or SF_FORMAT_AIFF.
-       <DD>The name field will contain a char* pointer to the name of the string; for instance
-               "WAV (Microsoft)" or "AIFF (Apple/SGI)".
-       <DD>The extension field will be a NULL pointer.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_ADD_PEAK_CHUNK"></A>
-<H2><BR><B>SFC_SET_ADD_PEAK_CHUNK</B></H2>
-<P>
-By default, WAV and AIFF files which contain floating point data (subtype SF_FORMAT_FLOAT
-or SF_FORMAT_DOUBLE) have a PEAK chunk.
-By using this command, the addition of a PEAK chunk can be turned on or off.
-</P>
-<P>
-Note : This call must be made before any data is written to the file.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_ADD_PEAK_CHUNK
-        data     : Not used (should be NULL)
-        datasize : TRUE or FALSE.
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        /* Turn on the PEAK chunk. */
-        sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
-
-        /* Turn off the PEAK chunk. */
-        sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-<DD>Returns SF_TRUE if the peak chunk will be written after this call.
-<DD>Returns SF_FALSE if the peak chunk will not be written after this call.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_UPDATE_HEADER_NOW"></A>
-<H2><BR><B>SFC_UPDATE_HEADER_NOW</B></H2>
-<P>
-The header of an audio file is normally written by libsndfile when the file is
-closed using <B>sf_close()</B>.
-</P>
-<P>
-There are however situations where large files are being generated and it would
-be nice to have valid data in the header before the file is complete.
-Using this command will update the file header to reflect the amount of data written
-to the file so far.
-Other programs opening the file for read (before any more data is written) will
-then read a valid sound file header.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_UPDATE_HEADER_NOW
-        data     : Not used (should be NULL)
-        datasize : Not used.
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        /* Update the header now. */
-        sf_command (sndfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-<DD>0
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_UPDATE_HEADER_AUTO"></A>
-<H2><BR><B>SFC_SET_UPDATE_HEADER_AUTO</B></H2>
-<P>
-Similar to SFC_UPDATE_HEADER_NOW but updates the header at the end of every call
-to the <B>sf_write*</B> functions.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_UPDATE_HEADER_NOW
-        data     : Not used (should be NULL)
-        datasize : SF_TRUE or SF_FALSE
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-        /* Turn on auto header update. */
-        sf_command (sndfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
-
-        /* Turn off auto header update. */
-        sf_command (sndfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_FALSE) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-<DD>TRUE if auto update header is now on; FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_FILE_TRUNCATE"></A>
-<H2><BR><B>SFC_FILE_TRUNCATE</B></H2>
-<P>
-Truncate a file that was opened for write or read/write.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_FILE_TRUNCATE
-        data     : A pointer to an sf_count_t.
-        datasize : sizeof (sf_count_t)
-</PRE>
-
-<P>
-Truncate the file to the number of frames specified by the sf_count_t pointed
-to by data.
-After this command, both the read and the write pointer will be
-at the new end of the file.
-This command will fail (returning non-zero) if the requested truncate position
-is beyond the end of the file.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        /* Truncate the file to a length of 20 frames. */
-        sf_count_t  frames = 20 ;
-        sf_command (sndfile, SFC_FILE_TRUNCATE, &amp;frames, sizeof (frames)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>Zero on sucess, non-zero otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_RAW_START_OFFSET"></A>
-<H2><BR><B>SFC_SET_RAW_START_OFFSET</B></H2>
-<P>
-Change the data start offset for files opened up as SF_FORMAT_RAW.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_RAW_START_OFFSET
-        data     : A pointer to an sf_count_t.
-        datasize : sizeof (sf_count_t)
-</PRE>
-
-<P>
-For a file opened as format SF_FORMAT_RAW, set the data offset to the value
-given by data.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        /* Reset the data offset to 5 bytes from the start of the file. */
-        sf_count_t  offset = 5 ;
-        sf_command (sndfile, SFC_SET_RAW_START_OFFSET, &amp;offset, sizeof (offset)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>Zero on success, non-zero otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_CLIPPING"></A>
-<H2><BR><B>SFC_SET_CLIPPING</B></H2>
-<P>
-Turn on/off automatic clipping when doing floating point to integer conversion.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_CLIPPING
-        data     : NULL
-        datasize : SF_TRUE or SF_FALSE.
-</PRE>
-
-<P>
-Turn on (datasize == SF_TRUE) or off (datasize == SF_FALSE) clipping.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        sf_command (sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>Clipping mode (SF_TRUE or SF_FALSE).
-</DL>
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_CLIPPING"></A>
-<H2><BR><B>SFC_GET_CLIPPING</B></H2>
-<P>
-Turn on/off automatic clipping when doing floating point to integer conversion.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_CLIPPING
-        data     : NULL
-        datasize : 0
-</PRE>
-
-<P>
-Retrieve the current cliiping setting.
-</P>
-<P>
-Example:
-</P>
-<PRE>
-        sf_command (sndfile, SFC_GET_CLIPPING, NULL, 0) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>Clipping mode (SF_TRUE or SF_FALSE).
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_EMBED_FILE_INFO"></A>
-<H2><BR><B>SFC_GET_EMBED_FILE_INFO</B></H2>
-<P>
-Get the file offset and file length of a file enbedded within another
-larger file.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_CLIPPING
-        data     : a pointer to an  SF_EMBED_FILE_INFO struct
-        datasize : sizeof (SF_EMBED_FILE_INFO)
-</PRE>
-<P>
-The SF_EMBED_FILE_INFO struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-        typedef struct
-        {   sf_count_t offset ;
-            sf_count_t length ;
-        } SF_EMBED_FILE_INFO ;
-</PRE>
-<DL>
-<DT>Return value: </DT>
-       <DD>0 on success and non-zero otherwise.
-       <DD>The value of the offset field of the SF_EMBED_FILE_INFO struct will be
-               the offsets in bytes from the start of the outer file to the start of
-               the audio file.
-       <DD>The value of the offset field of the SF_EMBED_FILE_INFO struct will be
-               the length in bytes of the embedded file.
-</DL>
-
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_WAVEX_GET_AMBISONIC"></A>
-<H2><BR><B>SFC_WAVEX_GET_AMBISONIC</B></H2>
-<P>
-Test if the current file has the GUID of a WAVEX file for any of the Ambisonic
-formats.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_WAVEX_GET_AMBISONIC
-        data     : NULL
-        datasize : 0
-</PRE>
-<P>
-       The Ambisonic WAVEX formats are defined here :
-               <A HREF="http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html">
-                       http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html</A>.
-</P>
-<DL>
-<DT>Return value: </DT>
-       <DD>SF_AMBISONIC_NONE or SF_AMBISONIC_B_FORMAT or zero if the file format
-               does not support ambisonic formats.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_WAVEX_SET_AMBISONIC"></A>
-<H2><BR><B>SFC_WAVEX_SET_AMBISONIC</B></H2>
-<P>
-Set the GUID of a new WAVEX file to indicate an Ambisonics format.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_WAVEX_SET_AMBISONIC
-        data     : NULL
-        datasize : SF_AMBISONIC_NONE or SF_AMBISONIC_B_FORMAT
-</PRE>
-<P>
-Turn on (SF_AMBISONIC_B_FORMAT) or off (SF_AMBISONIC_NONE) encoding.
-This command is currently only supported for files with SF_FORMAT_WAVEX format.
-</P>
-<P>
-       The Ambisonic WAVEX formats are defined here :
-               <A HREF="http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html">
-                       http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html</A>.
-</P>
-<DL>
-<DT>Return value: </DT>
-       <DD>Return the ambisonic value that has just been set or zero if the file
-               format does not support ambisonic encoding.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_VBR_ENCODING_QUALITY"></A>
-<H2><BR><B>SFC_SET_VBR_ENCODING_QUALITY</B></H2>
-<P>
-Set the Variable Bit Rate encoding quality.
-The encoding quality value should be between 0.0 (lowest quality) and 1.0
-(highest quality).
-Currenly this command is only implemented for FLAC and Ogg/Vorbis files.
-It has no effect on un-compressed file formats.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_VBR_ENCODING_QUALITY
-        data     : A pointer to a double value
-        datasize : sizeof (double)
-</PRE>
-<P>
-The command must be sent before any audio data is written to the file.
-</P>
-<P>
-</P>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if VBR encoding quality was set.
-    SF_FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_COMPRESSION_LEVEL"></A>
-<H2><BR><B>SFC_SET_COMPRESSION_LEVEL</B></H2>
-<P>
-Set the compression level.
-The compression level should be between 0.0 (minimum compression level) and 1.0
-(highest compression level).
-Currenly this command is only implemented for FLAC and Ogg/Vorbis files.
-It has no effect on un-compressed file formats.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_COMPRESSION_LEVEL
-        data     : A pointer to a double value
-        datasize : sizeof (double)
-</PRE>
-<P>
-The command must be sent before any audio data is written to the file.
-</P>
-<P>
-</P>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if compression level was set.
-    SF_FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_RAW_NEEDS_ENDSWAP"></A>
-<H2><BR><B>SFC_RAW_NEEDS_ENDSWAP</B></H2>
-<P>
-Determine if raw data read using
-       <a href="api.html#raw">
-       sf_read_raw</a>
-needs to be end swapped on the host CPU.
-</P>
-<P>
-For instance, will return SF_TRUE on when reading WAV containing
-SF_FORMAT_PCM_16 data on a big endian machine and SF_FALSE on a little endian
-machine.
-</P>
-<P>
-Parameters:
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_RAW_NEEDS_ENDSWAP
-        data     : NULL
-        datasize : 0
-</PRE>
-
-<DL>
-<DT>Return value: </DT>
-       <DD>SF_TRUE or SF_FALSE
-</DL>
-
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_BROADCAST_INFO"></A>
-<H2><BR><B>SFC_GET_BROADCAST_INFO</B></H2>
-<P>
-Retrieve the Broadcast Extension Chunk from WAV (and related) files.
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_BROADCAST_INFO
-        data     : a pointer to an SF_BROADCAST_INFO struct
-        datasize : sizeof (SF_BROADCAST_INFO)
-</PRE>
-<P>
-The SF_BROADCAST_INFO struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-    typedef struct
-    {   char            description [256] ;
-        char            originator [32] ;
-        char            originator_reference [32] ;
-        char            origination_date [10] ;
-        char            origination_time [8] ;
-        unsigned int    time_reference_low ;
-        unsigned int    time_reference_high ;
-        short           version ;
-        char            umid [64] ;
-        char            reserved [190] ;
-        unsigned int    coding_history_size ;
-        char            coding_history [256] ;
-    } SF_BROADCAST_INFO ;
-</PRE>
-
-<DL>
-<DT>Return value: </DT>
-       <DD>SF_TRUE if the file contained a Broadcast Extension chunk or SF_FALSE
-       otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_BROADCAST_INFO"></A>
-<H2><BR><B>SFC_SET_BROADCAST_INFO</B></H2>
-<P>
-Set the Broadcast Extension Chunk for WAV (and related) files.
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_BROADCAST_INFO
-        data     : a pointer to an SF_BROADCAST_INFO struct
-        datasize : sizeof (SF_BROADCAST_INFO)
-</PRE>
-
-<DL>
-<DT>Return value: </DT>
-       <DD>SF_TRUE if setting the Broadcast Extension chunk was successful and SF_FALSE
-       otherwise.
-
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_GET_CART_INFO"></A>
-<H2><BR><B>SFC_GET_CART_INFO</B></H2>
-<P>Retrieve the Cart Chunk from WAV (and related) files.  Based on AES46 standard for CartChunk (see <a href="http://www.cartchunk.org/">CartChunk.org</a> for more information.
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_GET_CART_INFO
-        data     : a pointer to an SF_CART_INFO struct
-        datasize : sizeof (SF_CART_INFO)
-</PRE>
-<P>
-The SF_CART_INFO struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-#define SF_CART_INFO_VAR(p_tag_text_size) \
-                        struct
-                        {       char            version [4] ;
-                                char            title [64] ;
-                                char            artist [64] ;
-                                char            cut_id [64] ;
-                                char            client_id [64] ;
-                                char            category [64] ;
-                                char            classification [64] ;
-                                char            out_cue [64] ;
-                                char            start_date [10] ;
-                                char            start_time [8] ;
-                                char            end_date [10] ;
-                                char            end_time [8] ;
-                                char            producer_app_id [64] ;
-                                char            producer_app_version [64] ;
-                                char            user_def [64] ;
-                                long    level_reference ;
-                                SF_CART_TIMER   post_timers [8] ;
-                                char            reserved [276] ;
-                                char            url [1024] ;
-                                unsigned int    tag_text_size ;
-                                char            tag_text[p_tag_text_size] ;
-                        }
-</PRE>
-
-<DL>
-<DT>Return value: </DT>
-       <DD>SF_TRUE if the file contained a Cart chunk or SF_FALSE
-       otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-<A NAME="SFC_SET_CART_INFO"></A>
-<H2><BR><B>SFC_SET_CART_INFO</B></H2>
-<P>
-Set the Cart Chunk for WAV (and related) files.
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-        sndfile  : A valid SNDFILE* pointer
-        cmd      : SFC_SET_CART_INFO
-        data     : a pointer to an SF_CART_INFO struct
-        datasize : sizeof (SF_CART_INFO)
-</PRE>
-
-<DL>
-<DT>Return value: </DT>
-       <DD>SF_TRUE if setting the Cart chunk was successful and SF_FALSE
-       otherwise.
-</DL>
-<!-- ========================================================================= -->
-
-<A NAME="SFC_GET_LOOP_INFO"></A>
-<H2><BR><B>SFC_GET_LOOP_INFO</B></H2>
-<P>
-Retrieve loop information for file including time signature, length in
-beats and original MIDI base note
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_GET_LOOP_INFO
-         data     : a pointer to an SF_LOOP_INFO struct
-         datasize : sizeof (SF_LOOP_INFO)
-</PRE>
-<P>
-The SF_BROADCAST_INFO struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-        typedef struct
-        {   short    time_sig_num ;   /* any positive integer    > 0  */
-            short    time_sig_den ;   /* any positive power of 2 > 0  */
-            int        loop_mode ;    /* see SF_LOOP enum             */
-
-            int        num_beats ;    /* this is NOT the amount of quarter notes !!!*/
-                                      /* a full bar of 4/4 is 4 beats */
-                                      /* a full bar of 7/8 is 7 beats */
-
-            float    bpm ;            /* suggestion, as it can be calculated using other fields:*/
-                                      /* file's lenght, file's sampleRate and our time_sig_den*/
-                                      /* -> bpms are always the amount of _quarter notes_ per minute */
-
-            int    root_key ;         /* MIDI note, or -1 for None */
-            int future [6] ;
-        } SF_LOOP_INFO ;
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-         SF_LOOP_INFO loop;
-         sf_command (sndfile, SFC_GET_LOOP_INFO, &amp;loop, sizeof (loop)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <DD>SF_TRUE if the file header contains loop information for the file.
-    SF_FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-
-
-<A NAME="SFC_GET_INSTRUMENT"></A>
-<H2><BR><B>SFC_GET_INSTRUMENT</B></H2>
-<P>
-Retrieve instrument information from file including MIDI base note,
-keyboard mapping and looping informations(start/stop and mode).
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_GET_INSTRUMENT
-         data     : a pointer to an SF_INSTRUMENT struct
-         datasize : sizeof (SF_INSTRUMENT)
-</PRE>
-
-<P>
-The SF_INSTRUMENT struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-        enum
-        {    /*
-            **    The loop mode field in SF_INSTRUMENT will be one of the following.
-            */
-            SF_LOOP_NONE = 800,
-            SF_LOOP_FORWARD,
-            SF_LOOP_BACKWARD,
-            SF_LOOP_ALTERNATING
-        } ;
-
-        typedef struct
-        {   int gain ;
-            char basenote, detune ;
-            char velocity_lo, velocity_hi ;
-            char key_lo, key_hi ;
-            int loop_count ;
-
-            struct
-            {   int mode ;
-                unsigned int start ;
-                unsigned int end ;
-                unsigned int count ;
-            } loops [16] ; /* make variable in a sensible way */
-        } SF_INSTRUMENT ;
-</PRE>
-
-<P>
-Example:
-</P>
-<PRE>
-         SF_INSTRUMENT inst ;
-         sf_command (sndfile, SFC_GET_INSTRUMENT, &amp;inst, sizeof (inst)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if the file header contains instrument information for the
-    file. SF_FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-
-
-<A NAME="SFC_SET_INSTRUMENT"></A>
-<H2><BR><B>SFC_SET_INSTRUMENT</B></H2>
-<P>
-Set the instrument information for the file.
-</P>
-<p>
-Parameters:
-</p>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_SET_INSTRUMENT
-         data     : a pointer to an SF_INSTRUMENT struct
-         datasize : sizeof (SF_INSTRUMENT)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-         SF_INSTRUMENT inst ;
-         sf_command (sndfile, SFC_SET_INSTRUMENT, &amp;inst, sizeof (inst)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if the file header contains instrument information for the
-    file. SF_FALSE otherwise.
-</DL>
-
-
-<!-- ========================================================================= -->
-
-<A NAME="SFC_GET_CUE"></A>
-<H2><BR><B>SFC_GET_CUE_COUNT</B></H2>
-<P>
-Retrieve the number of cue markers available for retrieval using the
-SFC_GET_CUE command.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_GET_CUE
-         data     : a pointer to a uint32_t
-         datasize : sizeof (uint32_t)
-</PRE>
-
-
-<P>
-Example:
-</P>
-<PRE>
-         uint32_t cue_count ;
-         sf_command (sndfile, SFC_GET_CUE_COUNT, &amp;cue_count, sizeof (cue_count)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if the file header contains cue marker information for the
-    file. SF_FALSE otherwise.
-</DL>
-
-<!-- ========================================================================= -->
-
-<A NAME="SFC_GET_CUE"></A>
-<H2><BR><B>SFC_GET_CUE</B></H2>
-<P>
-Retrieve cue marker information from file.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_GET_CUE
-         data     : a pointer to an SF_CUES struct
-         datasize : sizeof (SF_CUES)
-</PRE>
-
-<P>
-The SF_CUES struct is defined in &lt;sndfile.h&gt; as:
-</P>
-<PRE>
-    typedef struct
-    {  int cue_count ;
-
-       struct
-       {       int32_t   indx ;
-               uint32_t  position ;
-               int32_t   fcc_chunk ;
-               int32_t   chunk_start ;
-               int32_t   block_start ;
-               uint32_t  sample_offset ;
-               char name [256] ;
-       } cue_points [100] ;
-    } SF_CUES ;
-</PRE>
-
-<P>
-There is also an SF_CUES_VAR #define that allows reading/writing more than 100
-cue markers.
-</P>
-
-<P>
-Example:
-</P>
-<PRE>
-         SF_CUES cues ;
-         sf_command (sndfile, SFC_GET_CUE, &amp;cues, sizeof (cues)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if the file header contains cue marker information for the
-    file. SF_FALSE otherwise.
-</DL>
-
-
-<!-- ========================================================================= -->
-
-
-<A NAME="SFC_SET_CUE"></A>
-<H2><BR><B>SFC_SET_CUE</B></H2>
-<P>
-Set the cue marker information for the file.
-</P>
-<P>
-Parameters:
-</P>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_SET_CUE
-         data     : a pointer to an SF_CUES struct
-         datasize : sizeof (SF_CUES)
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-         SF_CUES cues ;
-         sf_command (sndfile, SFC_SET_CUE, &amp;cues, sizeof (cues)) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <dd>SF_TRUE if the file header contains cue marker information for the
-       file. SF_FALSE otherwise.
-</DL>
-
-
-<!-- ========================================================================= -->
-
-
-<A NAME="SFC_RF64_AUTO_DOWNGRADE"></A>
-<H2><BR><B>SFC_RF64_AUTO_DOWNGRADE</B></H2>
-<P>
-Enable auto downgrade from RF64 to WAV.
-</P>
-<P>
-The EBU recomendation is that when writing RF64 files and the resulting file is
-less than 4Gig in size, it should be downgraded to a WAV file (WAV files have a
-maximum size of 4Gig).
-libsndfile doesn't follow the EBU recommendations exactly, , mainly because the
-test suite needs to be able test reading/writing RF64 files without having to
-generate files larger than 4 gigabytes.
-</P>
-<p>
-Note: This command should be issued before the first bit of audio data has been
-written to the file.
-Calling this command after audio data has been written will return the current
-value of this setting, but will not allow it to be changed.
-</p>
-<p>
-Parameters:
-</p>
-<PRE>
-         sndfile  : A valid SNDFILE* pointer
-         cmd      : SFC_RF64_AUTO_DOWNGRADE
-         data     : NULL
-         datasize : SF_TRUE or SF_FALSE
-</PRE>
-<P>
-Example:
-</P>
-<PRE>
-         /* Enable auto downgrade on file close. */
-         sf_command (sndfile, SFC_RF64_AUTO_DOWNGRADE, NULL, SF_TRUE) ;
-</PRE>
-<DL>
-<DT>Return value:</DT>
-       <dd>Returns SF_TRUE if SFC_RF64_AUTO_DOWNGRADE is set and SF_FALSE
-       otherwise.
-</DL>
-
-
-
-<!-- ========================================================================= -->
-
-
-<HR>
-<P>
-       The libsndfile home page is here :
-               <A HREF="http://www.mega-nerd.com/libsndfile/">
-                       http://www.mega-nerd.com/libsndfile/</A>.
-<BR>
-Version : 1.0.25
-</P>
-
-</BODY>
-</HTML>
diff --git a/doc/development.html b/doc/development.html
deleted file mode 100644 (file)
index abd13b3..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile Development
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-<!-- pepper -->
-<H1><BR>libsndfile Development</H1>
-<!-- pepper -->
-<P>
-libsndfile is being developed by a small community of users and hackers.
-People interested in helping can join the libsndfile-devel
-       <A HREF="lists.html">mailing list</A>
-or raise an issue on Github.
-</P>
-<!-- pepper -->
-<P>
-The main repository can be found on Github:
-</P>
-<!-- pepper -->
-<center>
-<A HREF="https://github.com/erikd/libsndfile/">
-                       https://github.com/erikd/libsndfile/</A>
-</center>
-<!-- pepper -->
-<P>
-and includes
-       <a href="https://github.com/erikd/libsndfile/blob/master/README.md">
-       instuctions</a>
-on how to build libsndfile from the Git repo.
-</P>
-<!-- pepper -->
-</BODY>
-</HTML>
-
diff --git a/doc/donate.html b/doc/donate.html
deleted file mode 100644 (file)
index c611f47..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile : donate.
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <!-- Another version at the bottom of the page.  -->
-       <META NAME="Description" CONTENT="The libsndfile API.">
-       <META NAME="Keywords"    CONTENT="WAV AIFF AU libsndfile sound audio dsp Linux">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<br/>
-<!-- pepper -->
-<center>
-       <IMG SRC="libsndfile.jpg" HEIGHT=98 WIDTH=367 ALT="libsndfile.jpg">
-</center>
-<!-- pepper -->
-<br/>
-
-<p>
-Dear libsndfile user,
-</p>
-<!-- pepper -->
-<p>
-This library was developed on Linux for Linux. I am not a Windows user and
-maintaining this library for Windows costs me significant amounts of time above
-and beyond the time taken to make it work on Linux and Unix-like systems.
-</p>
-<!-- pepper -->
-<p>
-I therefore ask Windows users of libsndfile to donate to ensure that libsndfile's
-support for Windows continues. As long as donations continue to flow in at a decent
-rate, I will continue to release precompiled Windows binaries in sync with the
-Linux/Unix version. If donations are poor, support for windows will fall behind.
-</p>
-<!-- pepper -->
-
-<p>
-You are free to donate any amount you chose.
-As a guideline:
-</p>
-<!-- pepper -->
-<ul>
-<li>If you are simply a user of libsndfile that would like to ensure that
-       the development of libsndfile continues, a donation of $10US would be more
-       than adequate.
-       </li>
-<li>If you are shareware author that distributes libsndfile with your app and
-       makes more than $1000 a year from your shareware, a one off donation of $50
-       would be appropriate.
-       </li>
-<li>If your company is a commercial software house that distributes one or more
-       products that ship with libsndfile, a donation of $100 every second or third
-       year would be appropriate.
-       </li>
-</ul>
-
-<!-- pepper -->
-<p>
-Donations can be made in Bitcoin to the Bitcoin address
-       <b>15hVWemFiH6DLJ22SBYPk9b4fgWtxBEvfQ</b>
-
-which can be verified by checking the following GPG signature.
-</p>
-
-<pre>
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA256
-
-libsndfile Bitcoin address : 15hVWemFiH6DLJ22SBYPk9b4fgWtxBEvfQ
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.12 (GNU/Linux)
-
-iQIcBAEBCAAGBQJSK7MUAAoJEEXYQ7zIiotIgXEP/R8hy65tlV7TiPw9bY9BklXS
-/Vl8FU2RhDkBt61ZmxbfDTybyQ5Vce/3wWph15L4RvpoX1OyeintQFmwwuPjOGiq
-eIz0nT9vDorG37Xdo5NZNBu9Tp1Od9MNtxFaAsRWFrDfvKEKljBHrcfM972cYrAp
-DaFd0Ik+bHKom9iQXFB7TFd0w2V4uszVMQDUGqb/vRNeRURZS7ypeMNwc8tZyTKR
-waEGMTa5sxxRjs7MqGRxSovnFT7JV3TNfdkBInUliIR/XvrudFR9J4Fiv+8Dk9P8
-WNjm6uFxvgIqiu1G9bjrwwr+DsBju93ljGNcZoayAKw5vwbX6KTcCbc31k9dP8Hf
-p6YdmPlZVKZmva+P3nLSJBTlxNu24Jm+ha+ZM/svDXTaPFWC8l5FP17kK0Bj8wCq
-N7pDz6RchEn10u+HdhfT1XiUjxj0zNXrr0GGj9apjl0RlT0O49eBttV0oXIdBRLi
-nTEaOWITpCgu7ggw1kWXHIWEncuiaSuJy/iH8PgNepWVj/6PxQRMrTqG4ux2Snk8
-Ua4vO8YHLMZX/XvSUS7eMtgfM7AO6YjJ/ac9bQif9bh6LsYEVVklysMUin6ZRS7Z
-Cms23FnqeQKtJOzdvqSJiV06lK6fP+tYdM4WSYn+AfL4IfYl2v48xXVU8XOOK9BH
-bJPKMDcz1ZvfYtX5mSW1
-=WXGB
------END PGP SIGNATURE-----
-</pre>
-
-<p>
-Thanks and regards,
-<br/>
-Erik de Castro Lopo
-<br/>
-Main libsndfile author and maintainer
-</p>
-
-<!-- pepper -->
-
-       <img src=
-       "/cgi-bin/Count.cgi?ft=6|frgb=55;55;55|tr=0|trgb=0;0;0|wxh=15;20|md=6|dd=B|st=1|sh=1|df=libsndfile-donate.dat"
-       HEIGHT=0 WIDTH=0 ALT="">
-
-
-</BODY>
-</HTML>
diff --git a/doc/embedded_files.html b/doc/embedded_files.html
deleted file mode 100644 (file)
index c73e86a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile : Embedded Sound Files.
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <META NAME="Description" CONTENT="The libsndfile API.">
-       <META NAME="Keywords"    CONTENT="WAV AIFF AU libsndfile sound audio dsp Linux">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-<!-- pepper -->
-<BODY>
-<!-- pepper -->
-<H1><B>Embedded Sound Files.</B></H1>
-
-<P>
-By using the open SNDFILE with a file descriptor function:
-</P>
-<!-- pepper -->
-<PRE>
-      SNDFILE*  sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
-</PRE>
-<!-- pepper -->
-<P>
-it is possible to open sound files embedded within larger files.
-There are however a couple of caveats:
-<P>
-<!-- pepper -->
-<UL>
-       <LI> Read/Write mode (SFM_RDWR) is not supported.
-       <LI> Writing of embedded files is only supported at the end of the file.
-       <LI> Reading of embedded files is only supported at file offsets greater
-                       than zero.
-       <LI> Not all file formats are supported (currently only WAV, AIFF and AU).
-</UL>
-<!-- pepper -->
-<P>
-The test program <B>multi_file_test.c</B> in the <B>tests/</B> directory of the
-source code tarball shows how this functionality is used to read and write
-embedded files.
-</P>
-<!-- pepper -->
-</BODY>
-</HTML>
diff --git a/doc/index.html b/doc/index.html
deleted file mode 100644 (file)
index b802e8f..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-    <META NAME="Version"     CONTENT="libsndfile-1.0.28">
-       <META NAME="Description" CONTENT="The libsndfile Home Page">
-       <META NAME="Keywords"    CONTENT="WAV AIFF AU SVX PAF NIST W64 libsndfile sound audio dsp Linux">
-       <META NAME="ROBOTS"      CONTENT="NOFOLLOW">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-<!-- pepper -->
-<CENTER>
-       <IMG SRC="libsndfile.jpg" HEIGHT=98 WIDTH=367 ALT="libsndfile.jpg">
-</CENTER>
-<!-- pepper -->
-<CENTER>
-               <A HREF="#History">History</A> -+-
-               <A HREF="#Features">Features</A> -+-
-               <A HREF="#Similar">Similar or Related Projects</A> -+-
-               <A HREF="NEWS">News</A>
-               <br>
-               <A HREF="development.html">Development</A> -+-
-               <A HREF="api.html">Programming Interface</A> -+-
-               <A HREF="bugs.html">Bug Reporting</A> -+-
-               <A HREF="#Download">Download</A>
-               <br>
-               <A HREF="FAQ.html">FAQ</A> -+-
-               <A HREF="lists.html">Mailing Lists</A> -+-
-               <A HREF="ChangeLog">Change Log</A> -+-
-               <A HREF="#Licensing">Licensing Information</A> -+-
-               <A HREF="#SeeAlso">See Also</A>
-</CENTER>
-
-<br><br>
-<P>
-       Libsndfile is a C library for reading and writing files containing sampled sound
-       (such as MS Windows WAV and the Apple/SGI AIFF format) through one standard
-       library interface. It is released in source code format under the
-               <A HREF="http://www.gnu.org/copyleft/lesser.html">Gnu Lesser General Public License</A>.
-</P>
-<!-- pepper -->
-<P>
-       The library was written to compile and run on a Linux system but should compile
-       and run on just about any Unix (including MacOS X).
-       There are also pre-compiled binaries available for 32 and 64 bit windows.
-</P>
-<P>
-       It was designed to handle both little-endian (such as WAV) and big-endian
-       (such as AIFF) data, and to compile and run correctly on little-endian (such as Intel
-       and DEC/Compaq Alpha) processor systems as well as big-endian processor systems such
-       as Motorola 68k, Power PC, MIPS and Sparc.
-       Hopefully the design of the library will also make it easy to extend for reading and
-       writing new sound file formats.
-</P>
-<!-- pepper -->
-<P>
-    It has been compiled and tested (at one time or another) on the following systems:
-</P>
-<!-- pepper -->
-<UL>
-       <LI>Every platform supported by Debian GNU/Linux including x86_64-linux-gnu,
-               i486-linux-gnu, powerpc-linux-gnu, sparc-linux-gnu, alpha-linux-gnu,
-               mips-linux-gnu and armel-linux-gnu.</LI>
-       <LI>powerpc-apple-darwin7.0 (Mac OS X 10.3)</LI>
-       <LI>sparc-sun-solaris2.8 (using gcc)</LI>
-       <LI>mips-sgi-irix5.3 (using gcc)</LI>
-       <LI>QNX 6.0</LI>
-       <LI>i386-unknown-openbsd2.9</LI>
-</UL>
-<!-- pepper -->
-<P>
-       At the moment, each new release is being tested on i386 Linux, x86_64 Linux,
-       PowerPC Linux, Win32 and Win64.
-</P>
-<!-- pepper -->
-
-<A NAME="Capabilities"></A>
-<A NAME="Features"></A>
-<H1><B>Features</B></H1>
-<P>
-       libsndfile has the following main features :
-</P>
-       <UL>
-       <lI> Ability to read and write a large number of file formats.
-       <LI> A simple, elegant and easy to use Applications Programming Interface.
-       <LI> Usable on Unix, Win32, MacOS and others.
-       <LI> On the fly format conversion, including endian-ness swapping, type conversion
-                       and bitwidth scaling.
-       <LI> Optional normalisation when reading floating point data from files containing
-                       integer data.
-       <LI> Ability to open files in read/write mode.
-       <LI> The ability to write the file header without closing the file (only on files
-                       open for write or read/write).
-       <LI> Ability to query the library about all supported formats and retrieve text
-                       strings describing each format.
-       </UL>
-<P>
-       libsndfile has a comprehensive test suite so that each release is as bug free
-       as possible.
-       When new bugs are found, new tests are added to the test suite to ensure that
-       these bugs don't creep back into the code.
-       When new features are added, tests are added to the test suite to make sure that
-       these features continue to work correctly even when they are old features.
- </P>
-<P>
-       The following table lists the file formats and encodings that libsndfile can read
-       and write.
-       The file formats are arranged across the top and encodings along the left
-       edge.
-</P>
-<br>
-
-<TABLE BORDER="1" cellpadding="2">
-       <TR><TD>&nbsp;</TD>
-       <TD ALIGN="center">Micro- soft<br>WAV</TD>
-       <TD ALIGN="center">SGI / Apple<br>AIFF / AIFC</TD>
-       <TD ALIGN="center">Sun / DEC /<br>NeXT<br>AU / SND</TD>
-       <TD ALIGN="center">Header- less<br>RAW</TD>
-       <TD ALIGN="center">Paris Audio<br>File<br>PAF</TD>
-       <TD ALIGN="center">Commo- dore<br>Amiga<br>IFF / SVX</TD>
-       <TD ALIGN="center">Sphere<br>Nist<br>WAV</TD>
-       <TD ALIGN="center">IRCAM<br>SF</TD>
-       <TD ALIGN="center">Creative<br>VOC</TD>
-       <TD ALIGN="center">Sound forge<br>W64</TD>
-       <TD ALIGN="center"><A HREF="octave.html">GNU Octave 2.0</A><br>MAT4</TD>
-       <TD ALIGN="center"><A HREF="octave.html">GNU Octave 2.1</A><br>MAT5</TD>
-       <TD ALIGN="center">Portable Voice Format<br>PVF</TD>
-       <TD ALIGN="center">Fasttracker 2<br>XI</TD>
-       <TD ALIGN="center">HMM Tool Kit<br>HTK</TD>
-       <TD ALIGN="center">Apple<br>CAF</TD>
-       <TD ALIGN="center">Sound<br>Designer II<br>SD2</TD>
-       <TD ALIGN="center">Free Lossless Audio Codec<br>FLAC</TD>
-       </TR>
-<TR><TD>Unsigned 8 bit PCM</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>Signed 8 bit PCM</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-</TR>
-
-<TR><TD>Signed 16 bit PCM</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-</TR>
-
-<TR><TD>Signed 24 bit PCM</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-</TR>
-
-<TR><TD>Signed 32 bit PCM</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>32 bit float</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>64 bit double</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>u-law encoding</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-<TR><TD>A-law encoding</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>IMA ADPCM</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>MS ADPCM</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>GSM 6.10</TD>
-       <TD ALIGN="center">R/W</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>G721 ADPCM 32kbps</TD>
-       <TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>G723 ADPCM 24kbps</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>G723 ADPCM 40kbps</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>12 bit DWVW</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>16 bit DWVW</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-
-<TR><TD>24 bit DWVW</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-<TR><TD>Ok Dialogic ADPCM</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-<TR><TD>8 bit DPCM</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-<TR><TD>16 bit DPCM</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-       <TD>&nbsp;</TD><TD ALIGN="center">R/W</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>
-</TR>
-</TABLE>
-
-<p>
-From version 1.0.18, libsndfile also reads and writes
-       <a href="http://flac.sourceforge.net/">FLAC</a>
-and
-       <a href="http://www.vorbis.com/">Ogg/Vorbis</a>.
-</p>
-
-<!-- pepper -->
-
-<P>
-       Some of the file formats I am also interested in adding are:
-</P>
-       <UL>
-       <LI> Kurzweil K2000 sampler files.
-       <LI> Ogg Speex.
-       </UL>
-<P>
-       I have decided that I will not be adding support for MPEG Layer 3 (commonly
-       known as MP3) due to the patent issues surrounding this file format.
-       See
-               <a href="FAQ.html#Q020">
-               the FAQ</a>
-       for more.
-</P>
-<P>
-       Other file formats may also be added on request.
-</P>
-
-<!-- pepper -->
-
-<A NAME="History"></A>
-<H1><B>History</B></H1>
-<P>
-       My first attempt at reading and writing WAV files was in 1990 or so under Windows
-       3.1.
-       I started using Linux in early 1995 and contributed some code to the
-               <A HREF="http://www.vaxxine.com/ve3wwg/gnuwave.html">wavplay</A>
-       program.
-       That contributed code would eventually mutate into this library.
-       As one of my interests is Digital Signal Processing (DSP) I decided that as well as
-       reading data from an audio file in the native format (typically 16 bit short integers)
-       it would also be useful to be able to have the library do the conversion to floating
-       point numbers for DSP applications.
-       It then dawned on me that whatever file format (anything from 8 bit unsigned chars,
-       to 32 bit floating point numbers) the library should be able to convert the data to
-       whatever format the library user wishes to use it in.
-       For example, in a sound playback program, the library caller typically wants the sound
-       data in 16 bit short integers to dump into a sound card even though the data in the
-       file may be 32 bit floating point numbers (ie Microsoft's WAVE_FORMAT_IEEE_FLOAT
-       format).
-       Another example would be someone doing speech recognition research who has recorded
-       some speech as a 16 bit WAV file but wants to process it as double precision floating
-       point numbers.
-</P>
-<P>
-    Here is the release history for libsndfile :
-</P>
-       <UL>
-       <LI>Version 0.0.8 (Feb 15 1999) First official release.
-       <LI>Version 0.0.28 (Apr 26 2002) Final release of version 0 of libsndfile.
-       <LI>Version 1.0.0rc1 (Jun 24 2002) Release candidate 1 of version 1 of libsndfile.
-       <LI>Version 1.0.0rc6 (Aug 14 2002) MacOS 9 fixes.
-       <LI>Version 1.0.0 (Aug 16 2002) First 1.0.X release.
-       <LI>Version 1.0.1 (Sep 14 2002) Added MAT4 and MAT5 file formats.
-       <LI>Version 1.0.2 (Nov 24 2002) Added VOX ADPCM format.
-       <LI>Version 1.0.3 (Dec 09 2002) Fixes for Linux on ia64 CPUs.
-       <LI>Version 1.0.4 (Feb 02 2003) New file formats and functionality.
-       <LI>Version 1.0.5 (May 03 2003) One new file format and new functionality.
-       <LI>Version 1.0.6 (Feb 08 2004) Large file fix for Linux/Solaris, new functionality
-               and Win32 improvements.
-       <LI>Version 1.0.7 (Feb 24 2004) Fix build problems on MacOS X and fix ia64/MIPS etc
-               clip mode detction.
-       <LI>Version 1.0.8 (Mar 14 2004) Minor bug fixes.
-       <LI>Version 1.0.9 (Mar 30 2004) Add AVR format. Improve handling of some WAV files.
-       <LI>Version 1.0.10 (Jun 15 2004) Minor bug fixes. Fix support for Win32 MinGW compiler.
-       <LI>Version 1.0.11 (Nov 15 2004) Add SD2 file support, reading of loop data in WAV and AIFF.
-                               Minor bug fixes.
-       <LI>Version 1.0.12 (Sep 30 2005) Add FLAC and CAF file support, virtual I/O interface.
-                               Minor bug fixes and cleanups.
-       <LI>Version 1.0.13 (Jan 21 2006) Add read/write of instrument chunks. Minor bug fixes.
-       <LI>Version 1.0.14 (Feb 19 2006) Minor bug fixes. Start shipping windows binary/source ZIP.
-       <LI>Version 1.0.15 (Mar 16 2006) Minor bug fixes.
-       <LI>Version 1.0.16 (Apr 30 2006) Add support for RIFX. Other minor feature enhancements and
-                               bug fixes.
-       <LI>Version 1.0.17 (Aug 31 2006) Add C++ wrapper sndfile.hh. Minor bug fixes and cleanups.
-       <LI>Version 1.0.18 (Feb 07 2009) Add Ogg/Vorbis suppport, remove captive libraries, many
-                               new features and bug fixes. Generate Win32 and Win64 pre-compiled binaries.
-       <LI>Version 1.0.19 (Mar 02 2009) Fix for CVE-2009-0186. Huge number of minor fixes as a
-                               result of static analysis.
-       <LI>Version 1.0.20 (May 14 2009) Fix for potential heap overflow.
-       <LI>Version 1.0.21 (December 13 2009) Bunch of minor bug fixes.
-       <LI>Version 1.0.22 (October 04 2010) Bunch of minor bug fixes.
-       <LI>Version 1.0.23 (October 10 2010) Minor bug fixes.
-       <LI>Version 1.0.24 (March 23 2011) Minor bug fixes.
-       <LI>Version 1.0.25 (July 13 2011) Fix for Secunia Advisory SA45125. Minor bug fixes and
-                               improvements.
-       <LI>Version 1.0.26 (November 22 2015) Fix for CVE-2014-9496, CVE-2014-9756 and CVE-2015-7805.
-                               Add ALAC/CAF support. Minor bug fixes and improvements.
-       <LI>Version 1.0.27 (June 19 2016) Fix a seek regression in 1.0.26. Add metadata read/write
-                               for CAF and RF64. FIx PAF endian-ness issue.
-       <LI>Version 1.0.28 (April 2 2017) Fix buffer overruns in FLAC and ID3 handling code. Reduce default
-                               header memory requirements. Fix detection of Large File Support for 32 bit systems.
-       </UL>
-
-<A NAME="Similar"></A>
-<H1><B>Similar or Related Projects</B></H1>
-
-       <UL>
-       <LI><A HREF="http://sox.sourceforge.net/">SoX</A> is a program for
-               converting between sound file formats.
-       <LI><A HREF="http://www.hitsquad.com/smm/programs/WavPlay/">Wavplay</A> started out
-               as a minimal WAV file player under Linux and has mutated into Gnuwave, a client/server
-               application for more general multimedia and games sound playback.
-       <LI><A HREF="http://www.68k.org/~michael/audiofile/">Audiofile</A> (libaudiofile) is
-               a library similar to libsndfile but with a different programming interface. The
-               author Michael Pruett has set out to clone (and fix some bugs in) the libaudiofile
-               library which ships with SGI's IRIX OS.
-       <LI><A HREF="ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz">sndlib.tar.gz</A> is
-               another library written by Bill Schottstaedt of CCRMA.
-       </UL>
-
-<A NAME="Licensing"></A>
-<H1><B>Licensing</B></H1>
-<P>
-       libsndfile is released under the terms of the GNU Lesser General Public License,
-       of which there are two versions;
-               <a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">version 2.1</a>
-       and
-               <a href="http://www.gnu.org/copyleft/lesser.html">version 3</a>.
-       To maximise the compatibility of libsndfile, the user may choose to use libsndfile
-       under either of the above two licenses.
-       You can also read a simple explanation of the ideas behind the GPL and the LGPL
-               <A HREF="http://www.gnu.org/copyleft/copyleft.html">here</A>.
-</P>
-<P>
-       You can use libsndfile with
-               <A HREF="http://www.gnu.org/">Free Software</A>,
-               <A HREF="http://www.opensource.org/">Open Source</A>,
-       proprietary, shareware or other closed source applications as long as libsndfile
-       is used as a dynamically loaded library and you abide by a small number of other
-       conditions (read the LGPL for more info).
-       With applications released under the GNU GPL you can also use libsndfile statically
-       linked to your application.
-</P>
-<P>
-       I would like to see libsndfile used as widely as possible but I would prefer it
-       if you released software that uses libsndfile as
-               <A HREF="http://www.gnu.org/">Free Software</A>
-       or
-               <A HREF="http://www.opensource.org/">Open Source</A>.
-       However, if you put in a great deal of effort building a significant application
-       which simply uses libsndfile for file I/O, then I have no problem with you releasing
-       that as closed source and charging as much money as you want for it as long as you
-       abide by <A HREF="http://www.gnu.org/copyleft/lesser.html">the license</A>.
-</P>
-
-<A NAME="Download"></A>
-<H1><B>Download</B></H1>
-<P>
-       Here is the latest version. It is available in the following formats:
-</P>
-       <UL>
-       <LI>Source code as a .tar.gz :
-                       <A HREF="files/libsndfile-1.0.28.tar.gz">libsndfile-1.0.28.tar.gz</A>
-                       and
-                       <A HREF="files/libsndfile-1.0.28.tar.gz.asc">GPG signature</A>.
-       <LI>Win32 installer:
-                       <A HREF="files/libsndfile-1.0.28-w32-setup.exe">
-                       libsndfile-1.0.28-w32-setup.exe</A> (thoroughly tested under
-                       <a href="http://www.winehq.com/">Wine</a>)
-                       and
-                       <A HREF="files/libsndfile-1.0.28-w32-setup.exe.asc">GPG signature</A>.
-       <LI>Win64 installer:
-                       <A HREF="files/libsndfile-1.0.28-w64-setup.exe">
-                       libsndfile-1.0.28-w64-setup.exe</A> (thoroughly tested under
-                       <a href="http://www.winehq.com/">Wine</a>)
-                       and
-                       <A HREF="files/libsndfile-1.0.28-w64-setup.exe.asc">GPG signature</A>.
-       </UL>
-<P>
-    The GPG signature can be validated at
-               <A HREF="https://keybase.io/erikd/">Keybase.IO</A>.
-</P>
-<P>
-The Win32 installer should work on Windows Vista or later.
-</p>
-
-<P>
-       Pre-release versions of libsndfile are available
-                       <A HREF="http://www.mega-nerd.com/tmp/">here</A>
-       and are announced on the
-                       <A HREF="lists.html">libsndfile-devel</A>
-       mailing list.
-</P>
-
-<A NAME="SeeAlso"></A>
-<H1><B>See Also</B></H1>
-       <UL>
-       <LI><a href="http://www.mega-nerd.com/libsndfile/tools/">
-               sndfile-tools</a>
-               : a small collection of programs which use libsndfile.
-       </UL>
-
-<br><br>
-
-<hr>
-
-<P>
-       The latest version of this document can be found
-               <A HREF="http://www.mega-nerd.com/libsndfile/">here</A>.
-</P>
-<P>
-Author :
-       <A HREF="m&#97;ilt&#111;:&#101;rikd&#64;&#109;eg&#97;-&#110;erd.&#99;om">
-               Erik de Castro Lopo</a>
-</P>
-<!-- pepper -->
-<P>
-This page has been accessed
-       <IMG SRC=
-       "/cgi-bin/Count.cgi?ft=6|frgb=55;55;55|tr=0|trgb=0;0;0|wxh=15;20|md=7|dd=B|st=1|sh=1|df=libsndfile.dat"
-       HEIGHT=30 WIDTH=100 ALT="counter.gif">
-times.
-</P>
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-
-<br><br>
-</BODY>
-</HTML>
diff --git a/doc/lists.html b/doc/lists.html
deleted file mode 100644 (file)
index 7d95170..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile Mailing Lists
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-<!-- pepper -->
-<H1><BR>libsndfile Mailing Lists</H1>
-<!-- pepper -->
-<P>
-There are three mailing lists for libsndfile:
-</P>
-<!-- pepper -->
-<UL>
-       <LI> <B>libsndfile-announce&#64;mega-nerd.com</B>&nbsp;&nbsp;<!-- pepper -->
-               <A HREF="m&#97;ilt&#111;:li&#98;sndfile-announce-request@meg&#97;-nerd.&#99;om?subject=subscribe">Subscribe</A>
-               <BR>
-               A list which will announce each new release of libsndfile.
-               Noone can post to this list except the author.
-               <BR><BR>
-
-       <LI> <B>libsndfile-devel&#64;mega-nerd.com</B>&nbsp;&nbsp;<!-- pepper -->
-               <A HREF="m&#97;ilt&#111;:li&#98;sndfile-devel-request@meg&#97;-nerd.&#99;om?subject=subscribe">Subscribe</A>
-               <BR>
-               A list for discussing bugs, porting issues and feature requests.
-               Posting is restricted to subscribers.
-               <BR><BR>
-
-       <LI> <B>libsndfile-users&#64;mega-nerd.com</B>&nbsp;&nbsp;<!-- pepper -->
-               <A HREF="m&#97;ilt&#111;:li&#98;sndfile-users-request@meg&#97;-nerd.&#99;om?subject=subscribe">Subscribe</A>
-               <BR>
-               A list for discussing the use of libsndfile in other programs.
-               Posting is restricted to subscribers.
-               <!-- pepper -->
-               <BR><BR>
-</UL>
-<!-- pepper -->
-<P>
-The libsndfile-devel and libsndfile-users list will automatically receive a 
-copy of all emails to the libsndfile-announce list.
-</P>
-<BR>
-<!-- pepper -->
-</BODY>
-</HTML>
diff --git a/doc/octave.html b/doc/octave.html
deleted file mode 100644 (file)
index b696e6b..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile and GNU Octave
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<BR>
-<H1><B>libsndfile and GNU Octave</B></H1>
-<P>
-       <A HREF="http://www.octave.org/">GNU Octave</A> is a high-level interactive
-       language for numerical computations.
-       There are currently two development streams, a stable 2.0.X series and a
-       development 2.1.X series.
-       Octave reads and writes data in binary formats that were originally developed
-       for
-               <A HREF="http://www.mathworks.com/">MATLAB</A>.
-       Version 2.0.X of Octave uses binary data files compatible with MATLAB
-       version 4.2 while Octave 2.1.X uses binary data files compatible
-       with MATLAB version 5.0 as well as being able to read the older MATLAB 4.2
-       format.
-</P>
-<P>
-       From version 1.0.1 of libsndfile onwards, libsndfile has the ability of reading
-       and writing a small subset of the binary data files used by both versions
-       of GNU Octave.
-       This gives people using GNU Octave for audio based work an easy method of
-       moving audio data between GNU Octave and other programs which use libsndfile.
-</P>
-<P>
-       For instance it is now possible to do the following:
-</P>
-
-       <UL>
-       <LI> Load a WAV file into a sound file editor such as
-               <A HREF="http://www.metadecks.org/software/sweep/">Sweep</A>.
-       <LI> Save it as a MAT4 file.
-       <LI> Load the data into Octave for manipulation.
-       <LI> Save the modified data.
-       <LI> Reload it in Sweep.
-       </UL>
-<P>
-       Another example would be using the MAT4 or MAT5 file formats as a format which
-       can be easily loaded into Octave for viewing/analyzing as well as a format
-       which can be played with command line players such as the one included with
-       libsndfile.
-</P>
-
-<H2><B>Details</B></H2>
-<P>
-       Octave, like most programming languages, uses variables to store data, and
-       Octave variables can contain both arrays and matrices.
-       It is also able to store one or more of these variables in a file.
-       When reading Octave files, libsndfile expects a file to contain two
-       variables and their associated data.
-       The first variable should contain a variable holding the file sample rate
-       while the second variable contains the audio data.
-</P>
-<P>
-       For example, to generate a sine wave and store it as a binary file which
-       is compatible with libsndfile, do the following:
-</P>
-<PRE>
-        octave:1 > samplerate = 44100 ;
-        octave:2 > wavedata = sin ((0:1023)*2*pi/1024) ;
-        octave:3 > save sine.mat samplerate wavedata
-</PRE>
-
-<P>
-       The process of reading and writing files compatible with libsndfile can be
-       made easier by use of two Octave script files :
-</P>
-<PRE>
-        octave:4 > [data fs] = sndfile_load ("sine.mat") ;
-        octave:5 > sndfile_save ("sine2.mat", data, fs) ;
-</PRE>
-<P>
-       In addition, libsndfile contains a command line program which which is able
-       to play the correct types of Octave files.
-       Using this command line player <B>sndfile-play</B> and a third Octave script
-       file allows Octave data to be played from within Octave on any of the platforms
-       which <B>sndfile-play</B> supports (at the moment: Linux, MacOS X, Solaris and
-       Win32).
-</P>
-<PRE>
-        octave:6 > sndfile_play (data, fs) ;
-</PRE>
-<P>
-       These three Octave scripts are installed automatically in Octave's site
-       script directory when libsndfile is installed (except on Win32) ie when
-       libsndfile is being installed into /usr/local, the Octave scripts will
-       be installed in /usr/local/share/octave/site/m/.
-</P>
-
-<P>
-       There are some other Octave scripts for audio to be found
-               <A HREF="http://octave.sourceforge.net/audio/index.html">here</A>.
-</P>
-
-<BR>
-<!-- ========================================================================= -->
-
-<HR>
-<P>
-       The libsndfile home page is here :
-               <A HREF="http://www.mega-nerd.com/libsndfile/">
-                       http://www.mega-nerd.com/libsndfile/</A>.
-</P>
-
-</BODY>
-</HTML>
diff --git a/doc/sndfile_info.html b/doc/sndfile_info.html
deleted file mode 100644 (file)
index a84f241..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       sndfile-info
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-
-<P>
-       Here is an example of the output from the <B>sndfile-info</B> program distributed with 
-       libsndfile.
-</P>
-
-<P>
-       This file was opened and parsed correctly but had been truncated so that the values
-       in the <B>FORM</B> and <B>SSND</B> chunks were incorrect.
-</P>
-<PRE>
-        <B>erikd@hendrix ></B> examples/sndfile-info truncated.aiff 
-        truncated.aiff
-        size : 200000
-        FORM : 307474 (should be 199992)
-         AIFF
-         COMM : 18
-          Sample Rate : 16000
-          Samples     : 76857
-          Channels    : 2
-          Sample Size : 16
-         SSND : 307436 (should be 199946)
-          Offset     : 0
-          Block Size : 0
-        
-        --------------------------------
-        Sample Rate : 16000
-        Frames      : 76857
-        Channels    : 2
-        Bit Width   : 16
-        Format      : 0x00020001
-        Sections    : 1
-        Seekable    : TRUE
-        Signal Max  : 32766
-               
-</PRE>
-
-
-</BODY>
-</HTML>
diff --git a/doc/tutorial.html b/doc/tutorial.html
deleted file mode 100644 (file)
index e311239..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       libsndfile Tutorial
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-<!-- pepper -->
-<H1><BR>libsndfile Tutorial</H1>
-<!-- pepper -->
-<P>
-<b>More coming soon.</b>
-</P>
-<!-- pepper -->
-<P>
-For now, the best place to look for example code is the <tt>examples/</tt>
-directory of the source code distribution and the libsndfile test suite which
-is located in the <tt>tests/</tt> directory of the source code distribution.
-</P>
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-</BODY>
-</HTML>
-
diff --git a/doc/win32.html b/doc/win32.html
deleted file mode 100644 (file)
index 6ee3153..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-
-<HEAD>
-       <TITLE>
-       Building libsndfile on Win32
-       </TITLE>
-       <META NAME="Author"      CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
-       <LINK REL="stylesheet" HREF="libsndfile.css" TYPE="text/css" MEDIA="all">
-       <LINK REL="stylesheet" HREF="print.css" TYPE="text/css" MEDIA="print">
-</HEAD>
-
-<BODY>
-<!-- pepper -->
-<H1><BR>Building libsndfile on Win32</H1>
-
-<P><B>
-Note : For pre-compiled binaries for windows, both for win32 and win64, see the
-main web page.
-</B></P>
-
-<P>
-There is currently only one way of building libsndfile for Win32 and Win64;
-cross compiling from Linux using the MinGW cross compiler.
-</P>
-
-<P>
-libsndfile is written to be compiled by a compiler which supports large
-chunks of the 1999 ISO C Standard.
-Unfortunately, the microsoft compiler supports close to nothing of this
-standard and hence is not suitable for libsndfile.
-</P>
-
-<P>
-It <b>may</b> be possible to compile libsndfile on windows using the
-       <a href="http://www.mingw.org/">MinGW</a>
-compiler suite, but I haven't tested that and have no interest in supporting
-that.
-</P>
-
-<!--===========================================================================-->
-
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-<BR>
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-<!-- pepper -->
-
-</BODY>
-</HTML>
diff --git a/docs/FAQ.md b/docs/FAQ.md
new file mode 100644 (file)
index 0000000..cca4714
--- /dev/null
@@ -0,0 +1,480 @@
+---
+layout: default
+title: libsndfile : Frequently Asked Questions.
+---
+
+# libsndfile : Frequently Asked Questions
+
+1. [Do you plan to support XYZ codec in libsndfile?](#Q001)
+2. [In version 0 the SF\_INFO struct had a pcmbitwidth field but version 1 does not. Why?](#Q002)
+3. [Compiling is really slow on MacOS X. Why?](#Q003)
+4. [When trying to compile libsndfile on Solaris I get a "bad substitution" error during linking. What can I do to fix this?](#Q004)
+5. [Why doesn't libsndfile do interleaving/de-interleaving?](#Q005)
+6. [What's the best format for storing temporary files?](#Q006)
+7. [On Linux/Unix/MacOS X, what's the best way of detecting the presence of libsndfile?](#Q007)
+8. [I have libsndfile installed and now I want to use it. I just want a simple Makefile\! What do I do?](#Q008)
+9. [How about adding the ability to write/read sound files to/from memory buffers?](#Q009)
+10. [Reading a 16 bit PCM file as normalised floats and then writing them back changes some sample values. Why?](#Q010)
+11. [I'm having problems with u-law encoded WAV files generated by libsndfile in Winamp. Why?](#Q011)
+12. [I'm looking at sf\_read\*. What are items? What are frames?](#Q012)
+13. [Why can't libsndfile open this Sound Designer II (SD2) file?](#Q013)
+14. [I'd like to statically link libsndfile to my closed source application. Can I buy a license so that this is possible?](#Q014)
+15. [My program is crashing during a call to a function in libsndfile. Is this a bug in libsndfile?](#Q015)
+16. [Will you accept a fix for compiling libsndfile with compiler X?](#Q016)
+17. [Can libsndfile read/write files from/to UNIX pipes?](#Q017)
+18. [Is it possible to build a Universal Binary on Mac OS X?](#Q018)
+19. [I have project files for Visual Studio / XCode / Whatever. Why don't you distribute them with libsndfile?](#Q019)
+20. [Why doesn't libsndfile support MP3?](#Q020)
+21. [How do I use libsndfile in a closed source or commercial program and comply with the license?](#Q021)
+22. [What versions of windows does libsndfile work on?](#Q022)
+23. [I'm cross compiling libsndfile for another platform. How can I run the test suite?](#Q023)
+
+-----
+
+## Q1 : Do you plan to support XYZ codec in libsndfile? {#Q001}
+
+If source code for XYZ codec is available under a suitable license (LGPL, BSD,
+MIT etc) then yes, I'd like to add it.
+
+If suitable documentation is available on how to decode and encode the format
+then maybe, depending on how much work is involved.
+
+If XYZ is some proprietary codec where no source code or documentation is
+available then no.
+
+So if you want support for XYZ codec, first find existing source code or
+documentation. If you can't find either then the answer is no.
+
+## Q2 : In version 0 the SF\_INFO struct had a pcmbitwidth field but version 1 does not. Why? {#Q002}
+
+This was dropped for a number of reasons:
+
+- pcmbitwidth makes little sense on compressed or floating point formats
+- with the new API you really don't need to know it
+
+As documented [here](api.md#note-1) there is now a well defined behaviour which
+ensures that no matter what the bit width of the source file, the scaling always
+does something sensible. This makes it safe to read 8, 16, 24 and 32 bit PCM
+files using `sf_read_short()` and always have the optimal behaviour.
+
+## Q3 : Compiling is really slow on MacOS X. Why? {#Q003}
+
+When you configure and compile libsndfile, it uses the /bin/sh shell for a
+number of tasks (ie configure script and libtool). Older versions of OS X
+(10.2?) shipped a really crappy Bourne shell as /bin/sh which resulted in
+**really** slow compiles. Newer version of OS X ship GNU Bash as /bin/sh and
+this answer doesn't apply in that case.
+
+To fix this I suggest that you install the GNU Bash shell, rename /bin/sh to
+/bin/sh.old and make a symlink from /bin/sh to the bash shell. Bash is designed
+to behave as a Bourne shell when it is called as /bin/sh.
+
+When I did this on my iBook running MacOS X, compile times dropped from 13
+minutes to 3 minutes.
+
+## Q4 : When trying to compile libsndfile on Solaris I get a "bad substitution" error on linking. Why? {#Q004}
+
+It seems that the Solaris Bourne shell disagrees with GNU libtool.
+
+To fix this I suggest that you install the GNU Bash shell, rename /bin/sh to
+/bin/sh.old and make a symlink from /bin/sh to the bash shell. Bash is designed
+to behave as a Bourne shell when it is called as /bin/sh.
+
+## Q5 : Why doesn't libsndfile do interleaving/de-interleaving? {#Q005}
+
+This problem is bigger than it may seem at first.
+
+For a stereo file, it is a pretty safe bet that a simple interleaving/
+de-interleaving could satisfy most users. However, for files with more than 2
+channels this is unlikely to be the case. If the user has a 4 channel file and
+want to play that file on a stereo output sound card they either want the first
+2 channels or they want some mixed combination of the 4 channels.
+
+When you add more channels, the combinations grow exponentially and it becomes
+increasingly difficult to cover even a sensible subset of the possible
+combinations. On top of that, coding any one style of interleaver/de-interleaver
+is trivial, while coding one that can cover all combinations is far from
+trivial. This means that this feature will not be added any time soon.
+
+## Q6 : What's the best format for storing temporary files? {#Q006}
+
+When you want to store temporary data there are a number of requirements:
+
+- A simple, easy to parse header.
+- The format must provide the fastest possible read and write rates (ie avoid
+  conversions and encoding/decoding).
+- The file format must be reasonably common and playable by most players.
+- Able to store data in either endian-ness.
+
+The format which best meets these requirements is AU, which allows data to be
+stored in any one of short, int, float and double (among others) formats.
+
+For instance, if an application uses float data internally, its temporary files
+should use a format of (SF_ENDIAN_CPU | SF_FORMAT_AU | SF_FORMAT_FLOAT) which
+will store big endian float data in big endian CPUs and little endian float data
+on little endian CPUs. Reading and writing this format will not require any
+conversions or byte swapping regardless of the host CPU.
+
+## Q7 : On Linux/Unix/MaxOS X, what's the best way of detecting the presence of libsndfile using autoconf? {#Q007}
+
+libsndfile uses the pkg-config (man pkg-config) method of registering itself
+with the host system. The best way of detecting its presence is using something
+like this in configure.ac (or configure.in):
+
+    PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.2, ac_cv_sndfile=1, ac_cv_sndfile=0)
+
+    AC_DEFINE_UNQUOTED([HAVE_SNDFILE],${ac_cv_sndfile},
+        [Set to 1 if you have libsndfile.])
+
+    AC_SUBST(SNDFILE_CFLAGS)
+    AC_SUBST(SNDFILE_LIBS)
+
+This will automatically set the **SNDFILE_CFLAGS** and **SNDFILE_LIBS**
+variables which can be used in Makefile.am like this:
+
+    SNDFILE_CFLAGS = @SNDFILE_CFLAGS@
+    SNDFILE_LIBS = @SNDFILE_LIBS@
+
+If you install libsndfile from source, you will probably need to set the
+**PKG_CONFIG_PATH** environment variable as suggested at the end of the
+libsndfile configure process. For instance on my system I get this:
+
+    -=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-
+
+        Configuration summary :
+
+        Version : ..................... 1.0.5
+        Experimental code : ........... no
+
+        Tools :
+
+        Compiler is GCC : ............. yes
+        GCC major version : ........... 3
+
+        Installation directories :
+
+        Library directory : ........... /usr/local/lib
+        Program directory : ........... /usr/local/bin
+        Pkgconfig directory : ......... /usr/local/lib/pkgconfig
+
+    Compiling some other packages against libsndfile may require
+    the addition of "/usr/local/lib/pkgconfig" to the
+    PKG_CONFIG_PATH environment variable.
+
+## Q8 : I have libsndfile installed and now I want to use it. I just want a simple Makefile\! What do I do? {#Q008}
+
+The **pkg-config** program makes finding the correct compiler flag values and
+library location far easier. During the installation of libsndfile, a file named
+**sndfile.pc** is installed in the directory **${libdir}/pkgconfig** (ie if
+libsndfile is installed in **/usr/local/lib**, **sndfile.pc** will be installed
+in **/usr/local/lib/pkgconfig/**).
+
+In order for pkg-config to find sndfile.pc it may be necessary to point the
+environment variable **PKG_CONFIG_PATH** in the right direction.
+
+    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
+
+Then, to compile a C file into an object file, the command would be:
+
+    gcc `pkg-config --cflags sndfile` -c somefile.c
+
+and to link a number of objects into an executable that links against
+libsndfile, the command would be:
+
+    gcc `pkg-config --libs sndfile` obj1.o obj2.o -o program
+
+## Q9 : How about adding the ability to write/read sound files to/from memory buffers? {#Q009}
+
+This has been [added](api.md#open_virtual) for version 1.0.12.
+
+## Q10 : Reading a 16 bit PCM file as normalised floats and then writing them back changes some sample values. Why? {#Q010}
+
+This is caused by the fact that the conversion from 16 bit short to float is
+done by dividing by 32768 (0x8000 in hexadecimal) while the conversion from
+float to 16 bit short is done by multiplying by 32767 (0x7FFF in hex). So for
+instance, a value in a 16 bit PCM file of 20000 gets read as a floating point
+number of 0.6103515625 (20000.0 / 0x8000). Converting that back to a 16 bit
+short results in a value of 19999.3896484375 (0.6103515625 \* 0x7FFF) which then
+gets rounded down to 19999.
+
+You will notice that for this particular case, the error is 1 in 20000 or
+0.005%. Interestingly, for values of less than 16369, dividing by 0x8000
+followed by multiplying by 0x7FFF and then rounding the result, gives back the
+original value. It turns out that as long as the host operating system supplies
+the 1999 ISO C Standard functions **lrintf** and **lrint** (or a replacement has
+been supplied) then the maximum possible error is 1 in 16369 or about 0.006%.
+
+Regardless of the size of the error, the reason why this is done is rather
+subtle.
+
+In a file containing 16 bit PCM samples, the values are restricted to the range
+[-32768, 32767] while we want floating point values in the range [-1.0, 1.0].
+The only way to do this conversion is to do a floating point division by a value
+of 0x8000. Converting the other way, the only way to ensure that floating point
+values in the range [-1.0, 1.0] are within the valid range allowed by a 16 bit
+short is to multiply by 0x7FFF.
+
+Some people would say that this is a severe short-coming of libsndfile. I would
+counter that anybody who is constantly converting back and forth between 16 bit
+shorts and normalised floats is going to suffer other losses in audio quality
+that they should also be concerned about.
+
+Since this problem only occurs when converting between integer data on disk and
+normalized floats in the application, it can be avoided by using something other
+than normalized floats in the application. Alternatives to normalized floats are
+the **short** and **int** data types (ie using sf_read_short or sf_read_int) or
+using un-normalized floats (see
+[SFC_SET_NORM_FLOAT](command.html#sfc_set_norm_float)).
+
+Another way to deal with this problem is to consider 16 bit short data as a
+final destination format only, not as an intermediate storage format. All
+intermediate data (ie which is going to be processed further) should be stored
+in floating point format which is supported by all of the most common file
+formats. If floating point files are considered too large (2 times the size of a
+16 bit PCM file), it would also be possible to use 24 bit PCM as an intermediate
+storage format (and which is also supported by most common file types).
+
+## Q11 : I'm having problems with u-law encoded WAV files generated by libsndfile in Winamp. Why? {#Q011}
+
+This is actually a Winamp problem. The official Microsoft spec suggests that the
+'fmt ' chunk should be 18 bytes. Unfortunately at least one of Microsoft's own
+applications (Sound Recorder on Win98 I believe) did not accept 18 bytes 'fmt '
+chunks.
+
+Michael Lee did some experimenting and found that:
+
+> I have checked that Windows Media Player 9, QuickTime Player 6.4, RealOne
+> Player 2.0 and GoldWave 5.06 can all play u-law files with 16-byte or 18-byte
+> 'fmt ' chunk. Only Winamp (2.91) and foobar2000 are unable to play u-law files
+> with 16-byte 'fmt ' chunk.
+
+Even this is a very small sampling of all the players out there. For that reason
+it is probably not a good idea to change this now because there is the risk of
+breaking something that currently works.
+
+## Q12 : I'm looking at sf_read*. What are items? What are frames? {#Q012}
+
+An `item` is a single sample of the data type you are reading; ie a single
+`short` value for `sf_read_short` or a single `float` for `sf_read_float`.
+
+For a sound file with only one channel, a frame is the same as a item (ie a
+single sample) while for multi channel sound files, a single frame contains a
+single item for each channel.
+
+Here are two simple, correct examples, both of which are assumed to be working
+on a stereo file, first using items:
+
+```c
+#define CHANNELS 2
+short data [CHANNELS * 100] ;
+sf_count items_read = sf_read_short (file, data, 200) ;
+assert (items_read == 200) ;
+```
+
+and now reading the exact same amount of data using frames:
+
+```c
+#define CHANNELS 2
+short data [CHANNELS * 100] ;
+sf_count frames_read = sf_readf_short (file, data, 100) ;
+assert (frames_read == 100) ;
+```
+
+## Q13 : Why can't libsndfile open this Sound Designer II (SD2) file? {#Q013}
+
+This is somewhat complicated. First some background.
+
+SD2 files are native to the Apple Macintosh platform and use features of the Mac
+filesystem (file resource forks) to store the file's sample rate, number of
+channels, sample width and more. When you look at a file and its resource fork
+on Mac OS X it looks like this:
+
+    -rw-r--r--  1 erikd erikd   46512 Oct 18 22:57 file.sd2
+    -rw-r--r--  1 erikd erikd     538 Oct 18 22:57 file.sd2/rsrc
+
+Notice how the file itself looks like a directory containing a single file named
+**rsrc**. When libsndfile is compiled for MacOS X, it should open (for write and
+read) SD2 file with resource forks like this without any problems. It will also
+handle files with the resource fork in a separate file as described below.
+
+When SD2 files are moved to other platforms, the resource fork of the file can
+sometimes be dropped altogether. All that remains is the raw audio data and no
+information about the number of channels, sample rate or bit width which makes
+it a little difficult for libsndfile to open the file.
+
+However, it is possible to safely move an SD2 file to a Linux or Windows
+machine. For instance, when an SD2 file is copied from inside MacOS X to a
+windows shared directory or a Samba share (ie Linux), MacOS X is clever enough
+to store the resource fork of the file in a separate hidden file in the same
+directory like this:
+
+    -rw-r--r--  1 erikd erikd     538 Oct 18 22:57 ._file.sd2
+    -rw-r--r--  1 erikd erikd   46512 Oct 18 22:57 file.sd2
+
+Regardless of what platform it is running on, when libsndfile is asked to open a
+file named **"foo"** and it can't recognize the file type from the data in the
+file, it will attempt to open the resource fork and if that fails, it then tries
+to open a file named **"._foo"** to see if the file has a valid resource fork.
+This is the same regardless of whether the file is being opened for read or
+write.
+
+In short, libsndfile should open SD2 files with a valid resource fork on all of
+the platforms that libsndfile supports. If a file has lost its resource fork,
+the only option is the open the file using the SF_FORMAT_RAW option and guessing
+its sample rate, channel count and bit width.
+
+Occasionally, when SD2 files are moved to other systems, the file is
+[BinHexed](http://www.macdisk.com/binhexen.php3) which wraps the resource fork
+and the data fork together. For these files, it would be possible to write a
+BinHex parser but there is not a lot to gain considering how rare these BinHexed
+SD2 files are.
+
+## Q14 : I'd like to statically link libsndfile to my closed source application. Can I buy a license so that this is possible? {#Q014}
+
+Unfortunately no. libsndfile contains code written by other people who have
+agreed that their code be used under the GNU LGPL but no more. Even if they were
+to agree, there would be significant difficulties in dividing up the payments
+fairly.
+
+The **only** way you can legally use libsndfile as a statically linked library
+is if your application is released under the GNU GPL or LGPL.
+
+## Q15 : My program is crashing during a call to a function in libsndfile. Is this a bug in libsndfile? {#Q015}
+
+libsndfile is being used by large numbers of people all over the world without
+any problems like this. That means that it is much more likely that your code
+has a bug than libsndfile. However, it is still possible that there is a bug in
+libsndfile.
+
+To figure out whether it is your code or libsndfile you should do the following:
+
+- Make sure you are compiling your code with warnings switched on and that you
+  fix as many warnings as possible. With the GNU compiler (gcc) I would
+  recommend at least **-W -Wall -Werror** which will force you to fix all
+  warnings before you can run the code.
+- Try using a memory debugger. [Valgrind](http://valgrind.kde.org/) on x86 Linux
+  is excellent. [Purify](http://www.ibm.com/software/awdtools/purify/) also has
+  a good reputation.
+- If the code is clean after the above two steps and you still get a crash in
+  libsndfile, then send me a small snippet of code (no more than 30-40 lines)
+  which includes the call to sf_open() and also shows how all variables passed
+  to/returned from sf_open() are defined.
+
+## Q16 : Will you accept a fix for compiling libsndfile with compiler X? {#Q016}
+
+If compiler X is a C++ compiler then no. C and C++ are different enough to make
+writing code that compiles as valid C and valid C++ too difficult. I would
+rather spend my time fixing bugs and adding features.
+
+If compiler X is a C compiler then I will do what I can as long as that does not
+hamper the correctness, portability and maintainability of the existing code. It
+should be noted however that libsndfile uses features specified by the 1999 ISO
+C Standard. This can make compiling libsndfile with some older compilers
+difficult.
+
+## Q17 : Can libsndfile read/write files from/to UNIX pipes? {#Q017}
+
+Yes, libsndfile can read files from pipes. Unfortunately, the write case is much
+more complicated.
+
+File formats like AIFF and WAV have information at the start of the file (the
+file header) which states the length of the file, the number of sample frames
+etc. This information must be filled in correctly when the file header is
+written, but this information is not reliably known until the file is closed.
+This means that libsndfile cannot write AIFF, WAV and many other file types to a
+pipe.
+
+However, there is at least one file format (AU) which is specifically designed
+to be written to a pipe. Like AIFF and WAV, AU has a header with a sample frames
+field, but it is specifically allowable to set that frames field to 0x7FFFFFFF
+if the file length is not known when the header is written. The AU file format
+can also hold data in many of the standard formats (ie SF_FORMAT_PCM_16,
+SF_FORMAT_PCM_24, SF_FORMAT_FLOAT etc) as well as allowing data in both big and
+little endian format.
+
+See also [FAQ Q6](#Q006).
+
+## Q18 : Is it possible to build a Universal Binary on Mac OS X? {#Q018}
+
+Yes, but you must do two separate configure/build/test runs; one on PowerPC and
+one on Intel. It is then possible to merge the binaries into a single universal
+binary using one of the programs in the Apple tool chain.
+
+It is **not** possible to build a working universal binary via a single
+compile/build run on a single CPU.
+
+The problem is that the libsndfile build process detects features of the CPU its
+being built for during the configure process and when building a universal
+binary, configure is only run once and that data is then used for both CPUs.
+That configure data will be wrong for one of those CPUs. You will still be able
+to compile libsndfile, and the test suite will pass on the machine you compiled
+it on. However, if you take the universal binary test suite programs compiled on
+one CPU and run them on the other, the test suite will fail.
+
+Part of the problem is that the CPU endian-ness is detected at configure time.
+Yes, I know the Apple compiler defines one of the macros \_\_LITTLE\_ENDIAN\_\_
+and \_\_BIG\_ENDIAN\_\_, but those macros are not part of the 1999 ISO C
+Standard and they are not portable.
+
+Endian issues are not the only reason why the cross compiled binary will fail.
+The configure script also detects other CPU specific idiosyncrasies to provide
+more optimized code.
+
+Finally, the real show stopper problem with universal binaries is the problem
+with the test suite. libsndfile contains a huge, comprehensive test suite. When
+you compile a universal binary and run the test suite, you only test the native
+compile. The cross compiled binary (the one with the much higher chance of
+having problems) cannot be tested.
+
+Now, if you have read this far you're probably thinking there must be a way to
+fix this and there probably is. The problem is that its a hell of a lot of work
+and would require significant changes to the configure process, the internal
+code and the test suite. In addition, these changes must not break compilation
+on any of the platforms libsndfile is currently working on.
+
+## Q19 : I have project files for Visual Studio / XCode / Whatever. Why don't you distribute them with libsndfile? {#Q019}
+
+Use CMake project.
+
+## Q20 : Why doesn't libsndfile support MP3? {#Q020}
+
+In the past, MP3 was not supported because the technology behind MP3 was
+patented. Those patents have now expired and there is an
+[open ticket](https://github.com/libsndfile/libsndfile/issues/258) to implement
+MP3 support.
+
+## Q21 : How do I use libsndfile in a closed source or commercial program and comply with the license? {#Q021}
+
+Here is a checklist of things you need to do to make sure your use of libsndfile
+in a closed source or commercial project complies with the license libsndfile is
+released under, the GNU Lesser General Public License (LGPL):
+
+- Make sure you are linking to libsndfile as a shared library (Linux and Unix
+  systems), Dynamic Link Library (Microsoft Windows) or dynlib (Mac OS X). If
+  you are using some other operating system that doesn't allow dynamically
+  linked libraries, you will not be able to use libsndfile unless you release
+  the source code to your program.
+- In the licensing documentation for your program, add a statement that your
+  software depends on libsndfile and that libsndfile is released under the GNU
+  Lesser General Public License, either
+  [version 2.1](http://www.gnu.org/licenses/lgpl-2.1.txt) or optionally
+  [version 3](http://www.gnu.org/licenses/lgpl.txt).
+- Include the text for both versions of the license, possibly as separate files
+  named libsndfile_lgpl_v2_1.txt and libsndfile_lgpl_v3.txt.
+
+## Q22 : What versions of Windows does libsndfile work on? {#Q022}
+
+New versions of libsndfile binary releases require Wiindows Vista. If you need
+Windows XP support, you can build DLL from sources, we don't use specific WinXP
+features.
+
+## Q23 : I'm cross compiling libsndfile for another platform. How can I run the test suite? {#Q023}
+
+Since version 1.0.21 the top level Makefile has an extra make target,
+'test-tarball'. Building this target creates a tarball called called:
+
+    ` libsndfile-testsuite-${host_triplet}-${version}.tar.gz`
+
+in the top level directory. This tarball can then be copied to the target
+platform. Once untarred and test script `test_wrapper.sh` can be run from the
+top level of the extracted tarball.
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644 (file)
index 0000000..c9f19d7
--- /dev/null
@@ -0,0 +1,8 @@
+---
+author: "The libsndfile team"
+version: "1.0.31"
+
+markdown: kramdown
+plugins:
+  - jekyll-default-layout
+---
diff --git a/docs/_includes/logo.html b/docs/_includes/logo.html
new file mode 100644 (file)
index 0000000..f17a034
--- /dev/null
@@ -0,0 +1 @@
+<img src="libsndfile.jpg" class="image-logo" height=98 width=367 alt="Logo">
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
new file mode 100644 (file)
index 0000000..76c2cb8
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>{{ page.title }}</title>
+  <link rel="stylesheet" href="libsndfile.css" type="text/css" media="all">
+  <link rel="stylesheet" href="print.css" type="text/css" media="print">
+</head>
+  <body>
+    {{ content }}
+    <footer>
+      <hr>
+      <p>The libsndfile home page is <a href="http://libsndfile.github.io/libsndfile/">here</a>.</p>
+      <p>The libsndfile version: {{ site.version }}.</p>
+    </footer>
+  </body>
+</html>
diff --git a/docs/_layouts/home.html b/docs/_layouts/home.html
new file mode 100644 (file)
index 0000000..5a20c13
--- /dev/null
@@ -0,0 +1,34 @@
+---
+layout: default
+keywords: WAV AIFF AU SVX PAF NIST W64 libsndfile sound audio dsp Linux
+robots: nofollow
+title: libsndfile home page
+---
+
+<footer>
+  {% include logo.html %}
+
+  <nav>
+    <a href="#history">History</a> -+-
+    <a href="#features">Features</a> -+-
+    <a href="#similar-or-related-projects">Similar or related projects</a> -+-
+    <a href="https://github.com/libsndfile/libsndfile/blob/master/NEWS">News</a>
+    <br>
+    <a href="development.html">Development</a> -+-
+    <a href="api.html">Programming interface</a> -+-
+    <a href="bugs.html">Bug reporting</a> -+-
+    <a href="#download">Download</a>
+    <br>
+    <a href="FAQ.html">FAQ</a> -+-
+    <a href="lists.html">Mailing lists</a> -+-
+    <a href="#licensing">Licensing information</a> -+-
+    <a href="#see-also">See also</a>
+  </nav>
+  <br><br>
+</footer>
+
+<main>
+  <article>
+    {{ content }}
+  </article>
+</main>
diff --git a/docs/_layouts/page.html b/docs/_layouts/page.html
new file mode 100644 (file)
index 0000000..21c7d9b
--- /dev/null
@@ -0,0 +1,10 @@
+---
+layout: default
+---
+
+
+<main>
+  <article>
+    {{ content }}
+  </article>
+</main>
diff --git a/docs/api.md b/docs/api.md
new file mode 100644 (file)
index 0000000..f009b74
--- /dev/null
@@ -0,0 +1,736 @@
+---
+layout: page
+title: The libsndfile API
+---
+
+# libsndfile
+
+Libsndfile is a library designed to allow the reading and writing of many different sampled sound file formats (such as
+MS Windows WAV and the Apple/SGI AIFF format) through one standard library interface.
+
+During read and write operations, formats are seamlessly converted between the format the application program has
+requested or supplied and the file's data format. The application programmer can remain blissfully unaware of issues
+such as file endian-ness and data format. See [Note 1](#note-1) and [Note 2](#note-2).
+
+Every effort is made to keep these documents up-to-date, error free and unambiguous. However, since maintaining the
+documentation is the least fun part of working on libsndfile, these docs can and do fall behind the behaviour of the
+library. If any errors, omissions or ambiguities are found, please notify me (erikd) at mega-nerd dot com.
+
+To supplement this reference documentation, there are simple example programs included in the source code tarball. The
+test suite which is also part of the source code tarball is also a good place to look for the correct usage of the
+library functions.
+
+**Finally, if you think there is some feature missing from libsndfile, check that it isn't already implemented (and
+documented) [here](command.md).**
+
+## Synopsis
+
+```c
+#include <stdio.h>;
+#include <sndfile.h>;
+```
+
+| Name                                                                                                        | Description                                    |
+|:------------------------------------------------------------------------------------------------------------|:---------------------------------------        |
+| [sf_open, sf_wchar_open](#open)                                                                             | File open functions.                           |
+| [sf_open_fd](#open_fd)                                                                                      | Open sound file using file descriptor.         |
+| [sf_open_virtual](#open_virtual)                                                                            | Open sound file using virtual API.             |
+| [sf_format_check](#check)                                                                                   | Validate sound file info.                      |
+| [sf_seek](#seek)                                                                                            | Seek position in sound file.                   |
+| [sf_command](command.md)                                                                                    | Command interface.                             |
+| [sf_error, sf_strerror, sf_error_number, sf_perror, sf_error_str](#error)                                   | Error functions.                               |
+| [sf_close](#close)                                                                                          | File close function.                           |
+| [sf_write_sync](#write_sync)                                                                                | Write sync function.                           |
+| [sf_read_short, sf_read_int, sf_read_float, sf_read_double](#read)                                          | File items read functions.                     |
+| [sf_readf_short, sf_readf_int, sf_readf_float, sf_readf_double](#readf)                                     | File frames read functions.                    |
+| [sf_write_short, sf_write_int, sf_write_float, sf_write_double](#write)                                     | File items write functions.                    |
+| [sf_writef_short, sf_writef_int, sf_writef_float, sf_writef_double](#writef)                                | File frames write functions.                   |
+| [sf_read_raw, sf_write_raw](#raw)                                                                           | Raw read/write functions.                      |
+| [sf_get_string, sf_set_string](#string)                                                                     | Functions for reading and writing string data. |
+| [sf_version_string](#version_string)                                                                        | Retrive library version string.                |
+| [sf_current_byterate](#current_byterate)                                                                    | Retrieve current byterate.                     |
+| [sf_set_chunk, sf_get_chunk_iterator, sf_next_chunk_iterator, sf_get_chunk_size, sf_get_chunk_data](#chunk) | RIFF chunks API.                               |
+
+SNDFILE* is an anonymous pointer to data which is private to the library.
+
+## File Open Function {#open}
+
+```c
+SNDFILE*  sf_open    (const char *path, int mode, SF_INFO *sfinfo) ;
+```
+
+The sf_open() function opens the sound file at the specified path. The filename is byte encoded, but may be utf-8 on
+Linux, while on Mac OS X it will use the filesystem character set. On Windows, there is also a Windows specific
+sf_wchar_open() that takes a UTF16_BE encoded filename.
+
+```c
+SNDFILE*  sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
+```
+
+The SF_INFO structure is for passing data between the calling function and the library when opening a file for reading
+or writing. It is defined in sndfile.h as follows:
+
+```c
+typedef struct
+{    sf_count_t  frames ;     /* Used to be called samples. */
+        int         samplerate ;
+        int         channels ;
+        int         format ;
+        int         sections ;
+        int         seekable ;
+    } SF_INFO ;
+```
+
+The mode parameter for this function can be any one of the following three values:
+
+SFM_READ
+: read only mode
+
+SFM_WRITE
+: write only mode
+
+SFM_RDWR
+: read/write mode
+
+When opening a file for read, the **format** field should be set to zero before
+calling **sf_open**(). The only exception to this is the case of RAW files where
+the caller has to set the **samplerate**, **channels** and **format** fields to
+valid values. All other fields of the structure are filled in by the library.
+
+When opening a file for write, the caller must fill in structure members
+**samplerate**, **channels**, and **format**.
+
+The **format** field in the above **SF_INFO** structure is made up of the
+bit-wise OR of a major format type (values between 0x10000 and 0x08000000), a
+minor format type (with values less than 0x10000) and an optional endian-ness
+value. The currently understood formats are listed in *sndfile.h* as follows and
+also include bitmasks for separating major and minor file types. Not all
+combinations of endian-ness and major and minor file types are valid.
+
+| Name                   | Value      | Description                                |
+|:-----------------------|:-----------|:-------------------------------------------|
+| **Major formats.**                                                               |
+| SF_FORMAT_WAV          | 0x010000   | Microsoft WAV format (little endian).      |
+| SF_FORMAT_AIFF         | 0x020000   | Apple/SGI AIFF format (big endian).        |
+| SF_FORMAT_AU           | 0x030000   | Sun/NeXT AU format (big endian).           |
+| SF_FORMAT_RAW          | 0x040000   | RAW PCM data.                              |
+| SF_FORMAT_PAF          | 0x050000   | Ensoniq PARIS file format.                 |
+| SF_FORMAT_SVX          | 0x060000   | Amiga IFF / SVX8 / SV16 format.            |
+| SF_FORMAT_NIST         | 0x070000   | Sphere NIST format.                        |
+| SF_FORMAT_VOC          | 0x080000   | VOC files.                                 |
+| SF_FORMAT_IRCAM        | 0x0A0000   | Berkeley/IRCAM/CARL                        |
+| SF_FORMAT_W64          | 0x0B0000   | Sonic Foundry's 64 bit RIFF/WAV            |
+| SF_FORMAT_MAT4         | 0x0C0000   | Matlab (tm) V4.2 / GNU Octave 2.0          |
+| SF_FORMAT_MAT5         | 0x0D0000   | Matlab (tm) V5.0 / GNU Octave 2.1          |
+| SF_FORMAT_PVF          | 0x0E0000   | Portable Voice Format                      |
+| SF_FORMAT_XI           | 0x0F0000   | Fasttracker 2 Extended Instrument          |
+| SF_FORMAT_HTK          | 0x100000   | HMM Tool Kit format                        |
+| SF_FORMAT_SDS          | 0x110000   | Midi Sample Dump Standard                  |
+| SF_FORMAT_AVR          | 0x120000   | Audio Visual Research                      |
+| SF_FORMAT_WAVEX        | 0x130000   | MS WAVE with WAVEFORMATEX                  |
+| SF_FORMAT_SD2          | 0x160000   | Sound Designer 2                           |
+| SF_FORMAT_FLAC         | 0x170000   | FLAC lossless file format                  |
+| SF_FORMAT_CAF          | 0x180000   | Core Audio File format                     |
+| SF_FORMAT_WVE          | 0x190000   | Psion WVE format                           |
+| SF_FORMAT_OGG          | 0x200000   | Xiph OGG container                         |
+| SF_FORMAT_MPC2K        | 0x210000   | Akai MPC 2000 sampler                      |
+| SF_FORMAT_RF64         | 0x220000   | RF64 WAV file                              |
+| **Subtypes.**                                                                    |
+| SF_FORMAT_PCM_S8       | 0x0001     | Signed 8 bit data                          |
+| SF_FORMAT_PCM_16       | 0x0002     | Signed 16 bit data                         |
+| SF_FORMAT_PCM_24       | 0x0003     | Signed 24 bit data                         |
+| SF_FORMAT_PCM_32       | 0x0004     | Signed 32 bit data                         |
+| SF_FORMAT_PCM_U8       | 0x0005     | Unsigned 8 bit data (WAV and RAW only)     |
+| SF_FORMAT_FLOAT        | 0x0006     | 32 bit float data                          |
+| SF_FORMAT_DOUBLE       | 0x0007     | 64 bit float data                          |
+| SF_FORMAT_ULAW         | 0x0010     | U-Law encoded.                             |
+| SF_FORMAT_ALAW         | 0x0011     | A-Law encoded.                             |
+| SF_FORMAT_IMA_ADPCM    | 0x0012     | IMA ADPCM.                                 |
+| SF_FORMAT_MS_ADPCM     | 0x0013     | Microsoft ADPCM.                           |
+| SF_FORMAT_GSM610       | 0x0020     | GSM 6.10 encoding.                         |
+| SF_FORMAT_VOX_ADPCM    | 0x0021     | OKI / Dialogix ADPCM                       |
+| SF_FORMAT_NMS_ADPCM_16 | 0x0022     | 16kbs NMS G721-variant encoding.           |
+| SF_FORMAT_NMS_ADPCM_24 | 0x0023     | 24kbs NMS G721-variant encoding.           |
+| SF_FORMAT_NMS_ADPCM_32 | 0x0024     | 32kbs NMS G721-variant encoding.           |
+| SF_FORMAT_G721_32      | 0x0030     | 32kbs G721 ADPCM encoding.                 |
+| SF_FORMAT_G723_24      | 0x0031     | 24kbs G723 ADPCM encoding.                 |
+| SF_FORMAT_G723_40      | 0x0032     | 40kbs G723 ADPCM encoding.                 |
+| SF_FORMAT_DWVW_12      | 0x0040     | 12 bit Delta Width Variable Word encoding. |
+| SF_FORMAT_DWVW_16      | 0x0041     | 16 bit Delta Width Variable Word encoding. |
+| SF_FORMAT_DWVW_24      | 0x0042     | 24 bit Delta Width Variable Word encoding. |
+| SF_FORMAT_DWVW_N       | 0x0043     | N bit Delta Width Variable Word encoding.  |
+| SF_FORMAT_DPCM_8       | 0x0050     | 8 bit differential PCM (XI only)           |
+| SF_FORMAT_DPCM_16      | 0x0051     | 16 bit differential PCM (XI only)          |
+| SF_FORMAT_VORBIS       | 0x0060     | Xiph Vorbis encoding.                      |
+| SF_FORMAT_OPUS         | 0x0064     | Xiph/Skype Opus encoding.                  |
+| SF_FORMAT_ALAC_16      | 0x0070     | Apple Lossless Audio Codec (16 bit).       |
+| SF_FORMAT_ALAC_20      | 0x0071     | Apple Lossless Audio Codec (20 bit).       |
+| SF_FORMAT_ALAC_24      | 0x0072     | Apple Lossless Audio Codec (24 bit).       |
+| SF_FORMAT_ALAC_32      | 0x0073     | Apple Lossless Audio Codec (32 bit).       |
+| **Endian-ness options.**                                                         |
+| SF_ENDIAN_FILE         | 0x00000000 | Default file endian-ness.                  |
+| SF_ENDIAN_LITTLE       | 0x10000000 | Force little endian-ness.                  |
+| SF_ENDIAN_BIG          | 0x20000000 | Force big endian-ness.                     |
+| SF_ENDIAN_CPU          | 0x30000000 | Force CPU endian-ness.                     |
+| SF_FORMAT_SUBMASK      | 0x0000FFFF |                                            |
+| SF_FORMAT_TYPEMASK     | 0x0FFF0000 |                                            |
+| SF_FORMAT_ENDMASK      | 0x30000000 |                                            |
+
+Every call to **sf_open**() should be matched with a call to
+[**sf_close**()](#close) to free up memory allocated during the call to **sf_open**().
+
+On success, the sf_open function returns a non-NULL pointer which should be passed as the first parameter to all
+subsequent libsndfile calls dealing with that audio file. On fail, the sf_open function returns a NULL pointer. An
+explanation of the error can obtained by passing NULL to [**sf_strerror**()](#error).
+
+### File Descriptor Open {#open_fd}
+
+```c
+SNDFILE*  sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
+```
+
+**Note:** On Microsoft Windows, this function does not work if the application
+and the libsndfile DLL are linked to different versions of the Microsoft C
+runtime DLL.
+
+The second open function takes a file descriptor of a file that has already been
+opened. Care should be taken to ensure that the mode of the file represented by
+the descriptor matches the mode argument. This function is useful in the
+following circumstances:
+
+* Opening temporary files securely (ie use the **tmpfile**() to return a FILE*
+  pointer and then using fileno() to retrieve the file descriptor which is then
+  passed to libsndfile).
+* Opening files with file names using OS specific character encodings and then
+  passing the file descriptor to **sf_open_fd**().
+* Opening sound files embedded within larger files. [More info](embedded_files.md).
+
+Every call to `sf_open_fd`() should be matched with a call to sf_close() to free
+up memory allocated during the call to sf_open_fd().
+
+When sf_close() is called, the file descriptor is only closed if the
+**close_desc** parameter was TRUE when the sf_open_fd() function was called.
+
+On success, the sf_open_fd() function returns a non-NULL pointer which should be
+passed as the first parameter to all subsequent libsndfile calls dealing with
+that audio file. On fail, the sf_open_fd() function returns a NULL pointer.
+
+### Virtual File Open Function {#open_virtual}
+
+```c
+SNDFILE*    sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
+```
+
+Opens a soundfile from a virtual file I/O context which is provided by the
+caller. This is usually used to interface libsndfile to write/read from memory
+with a stream or buffer based system. Apart from the sfvirtual and the user_data
+parameters this function behaves like [sf_open()](#open).
+
+```c
+    typedef struct
+    {    sf_vio_get_filelen  get_filelen ;
+          sf_vio_seek         seek ;
+          sf_vio_read         read ;
+          sf_vio_write        write ;
+          sf_vio_tell         tell ;
+    } SF_VIRTUAL_IO ;
+```
+
+Libsndfile calls the callbacks provided by the SF_VIRTUAL_IO structure when
+opening, reading and writing to the virtual file context. The user_data pointer
+is a user defined context which will be available in the callbacks.
+
+```c
+typedef sf_count_t  (*sf_vio_get_filelen) (void *user_data) ;
+typedef sf_count_t  (*sf_vio_seek)        (sf_count_t offset, int whence, void *user_data) ;
+typedef sf_count_t  (*sf_vio_read)        (void *ptr, sf_count_t count, void *user_data) ;
+typedef sf_count_t  (*sf_vio_write)       (const void *ptr, sf_count_t count, void *user_data) ;
+typedef sf_count_t  (*sf_vio_tell)        (void *user_data) ;
+```
+
+#### sf_vio_get_filelen
+
+```c
+typedef sf_count_t  (*sf_vio_get_filelen) (void *user_data) ;
+```
+
+The virtual file contex must return the length of the virtual file in bytes.
+
+#### sf_vio_seek
+
+```c
+typedef sf_count_t  (*sf_vio_seek)        (sf_count_t offset, int whence, void *user_data) ;
+```
+
+The virtual file context must seek to offset using the seek mode provided by
+whence which is one of SEEK_CUR, SEEK_SET, SEEK_END.
+
+The return value must contain the new offset in the file.
+
+#### sf_vio_read
+
+```c
+typedef sf_count_t  (*sf_vio_read)        (void *ptr, sf_count_t count, void *user_data) ;
+```
+
+The virtual file context must copy ("read") "count" bytes into the buffer
+provided by ptr and return the count of actually copied bytes.
+
+#### sf_vio_write
+
+```c
+typedef sf_count_t  (*sf_vio_write)       (const void *ptr, sf_count_t count, void *user_data) ;
+```
+
+The virtual file context must process "count" bytes stored in the buffer passed
+with ptr and return the count of actually processed bytes.
+
+#### sf_vio_tell
+
+```c
+typedef sf_count_t  (*sf_vio_tell)        (void *user_data) ;
+```
+
+Return the current position of the virtual file context.
+
+## Format Check Function {#chek}
+
+```c
+int  sf_format_check (const SF_INFO *info) ;
+```
+
+This function allows the caller to check if a set of parameters in the SF_INFO
+struct is valid before calling [sf_open](#open) (SFM_WRITE).
+
+sf_format_check() returns TRUE if the parameters are valid and FALSE otherwise.
+
+## File Seek Functions
+
+```c
+sf_count_t  sf_seek  (SNDFILE *sndfile, sf_count_t frames, int whence) ;
+```
+
+The file seek functions work much like lseek in unistd.h with the exception that
+the non-audio data is ignored and the seek only moves within the audio data
+section of the file. In addition, seeks are defined in number of (multichannel)
+frames. Therefore, a seek in a stereo file from the current position forward
+with an offset of 1 would skip forward by one sample of both channels.
+
+like lseek(), the whence parameter can be any one of the following three values:
+
+SEEK_SET
+: The offset is set to the start of the audio data plus offset (multichannel)
+frames.
+
+SEEK_CUR
+: The offset is set to its current location plus offset (multichannel) frames.
+
+SEEK_END
+: The offset is set to the end of the data plus offset (multichannel) frames.
+
+Internally, libsndfile keeps track of the read and write locations using
+separate read and write pointers. If a file has been opened with a mode of
+SFM_RDWR, bitwise OR-ing the standard whence values above with either SFM_READ
+or SFM_WRITE allows the read and write pointers to be modified separately.
+If the SEEK_* values are used on their own, the read and write pointers are
+both modified.
+
+Note that the frames offset can be negative and in fact should be when SEEK_END
+is used for the whence parameter.
+
+sf_seek will return the offset in (multichannel) frames from the start of the
+audio data or -1 if an error occured (ie an attempt is made to seek beyond the
+start or end of the file).
+
+## Error Reporting Functions {#error}
+
+```c
+int sf_error (SNDFILE *sndfile) ;
+```
+
+This function returns the current error number for the given SNDFILE.
+
+The error number may be one of the following:
+
+| Name                        | Value |
+|:----------------------------|:------|
+| SF_ERR_NO_ERROR             | 0     |
+| SF_ERR_UNRECOGNISED_FORMAT  | 1     |
+| SF_ERR_SYSTEM               | 2     |
+| SF_ERR_MALFORMED_FILE       | 3     |
+| SF_ERR_UNSUPPORTED_ENCODING | 4     |
+
+or any one of many other internal error values.
+Applications should only test the return value against error values defined in
+\<sndfile.h\>; as the internal error values are subject to change at any time.
+For errors not in the above list, the function sf_error_number() can be used to
+convert it to an error string.
+
+```c
+const char* sf_strerror     (SNDFILE *sndfile) ;
+const char* sf_error_number (int errnum) ;
+```
+
+The error functions sf_strerror () and sf_error_number () convert the library's
+internal error enumerations into text strings.
+
+```c
+int sf_perror    (SNDFILE *sndfile) ;
+int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
+```
+
+The functions sf_perror() and sf_error_str() are deprecated and will be dropped
+from the library at some later date.
+
+## File Close Function {#close}
+
+```c
+int sf_close (SNDFILE *sndfile) ;
+```
+
+The close function closes the file, deallocates its internal buffers and returns
+0 on success or an error value otherwise.
+
+## Write Sync Function {#write_sync}
+
+```c
+void  sf_write_sync  (SNDFILE *sndfile) ;
+```
+
+If the file is opened SFM_WRITE or SFM_RDWR, call the operating system's
+function to force the writing of all file cache buffers to disk. If the file is
+opened SFM_READ no action is taken.
+
+## File Read Functions {#read}
+
+```c
+sf_count_t sf_read_short  (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
+sf_count_t sf_read_int    (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
+sf_count_t sf_read_float  (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
+sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
+```
+
+{: #readf}
+```c
+sf_count_t sf_readf_short  (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
+sf_count_t sf_readf_int    (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
+sf_count_t sf_readf_float  (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
+sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
+```
+
+The file read functions fill the array pointed to by ptr with the requested
+number of items or frames.
+
+For the frames-count functions, the frames parameter specifies the number of
+frames. A frame is just a block of samples, one for each channel.
+
+**Care must be taken to ensure that there is enough space in the array pointed
+to by ptr, to take (frames \* channels) number of items (shorts, ints, floats or
+doubles).**
+
+For the items-count functions, the items parameter must be an integer product
+of the number of channels or an error will occur. Here, an item is just a
+sample.
+
+Note: The only difference between the "items" and "frames" versions of each read
+function is the units in which the object count is specified - calling
+sf_readf_short() with a count argument of N, on a SNDFILE with C channels, is
+the same as calling sf_read_short with a count argument of N\*C. The buffer
+pointed to by "ptr" should be the same number of bytes in each case.
+
+Note: The data type used by the calling program and the data format of the file
+do not need to be the same. For instance, it is possible to open a 16 bit PCM
+encoded WAV file and read the data using sf_read_float(). The library seamlessly
+converts between the two formats on-the-fly. See [Note 1](#note-1).
+
+The sf_read_XXXX and sf_readf_XXXX functions return the number of items or
+frames read, respectively. Unless the end of the file was reached during the
+read, the return value should equal the number of objects requested. Attempts to
+read beyond the end of the file will not result in an error but will cause the
+read functions to return less than the number of objects requested or 0 if
+already at the end of the file. When the buffer is not is not completely filled,
+unused buffer space is filled by zeroes.
+
+## File Write Functions {#write}
+
+```c
+sf_count_t sf_write_short  (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
+sf_count_t sf_write_int    (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
+sf_count_t sf_write_float  (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
+sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
+```
+
+{: #writef}
+```c
+sf_count_t sf_writef_short  (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
+sf_count_t sf_writef_int    (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
+sf_count_t sf_writef_float  (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
+sf_count_t sf_writef_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
+```
+
+The file write functions write the data in the array pointed to by ptr to the
+file.
+
+For items-count functions, the items parameter specifies the size of the array
+and must be an integer product of the number of channels or an error will occur.
+
+For the frames-count functions, the array is expected to be large enough to hold
+a number of items equal to the product of frames and the number of channels.
+
+As with the read functions [above](#read), the only difference in the items and
+frames version of each write function is the units in which the buffer size is
+specified. Again, the data type used by the calling program and the data format
+of the file do not need to be the same ([Note 1](#note-1)).
+
+The sf_write_XXXX and sf_writef_XXXX functions respectively return the number of
+items or frames written (which should be the same as the items or frames
+parameter).
+
+## Raw File Read and Write Functions {#raw}
+
+```c
+sf_count_t sf_read_raw  (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
+sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
+```
+
+**Note:** Unless you are writing an external decoder/encode that uses libsndfile
+to handle the file headers, you should not be using these functions.
+
+The raw read and write functions read raw audio data from the audio file (not to
+be confused with reading RAW header-less PCM files). The number of bytes read or
+written must always be an integer multiple of the number of channels multiplied
+by the number of bytes required to represent one sample from one channel.
+
+The raw read and write functions return the number of bytes read or written
+(which should be the same as the bytes parameter).
+
+**Note : The result of using of both regular reads/writes and raw reads/writes
+on compressed file formats other than SF_FORMAT_ALAW and SF_FORMAT_ULAW is
+undefined.**
+
+See also : [SFC_RAW_NEEDS_ENDSWAP](command.md#sfc_raw_needs_endswap).
+
+## Functions for Reading and Writing String Data {#string}
+
+```c
+const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
+int         sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
+```
+
+These functions allow strings to be set on files opened for write and to be
+retrieved from files opened for read where supported by the given file type. The
+**str_type** parameter can be any one of the following string types:
+
+| Name               | Value | Description   |
+|:-------------------|:------|:--------------|
+| SF_STR_TITLE       | 0x01  | Title.        |
+| SF_STR_COPYRIGHT   | 0x02  | Copyright.    |
+| SF_STR_SOFTWARE    | 0x03  | Software.     |
+| SF_STR_ARTIST      | 0x04  | Artist.       |
+| SF_STR_COMMENT     | 0x05  | Comment.      |
+| SF_STR_DATE        | 0x06  | Date.         |
+| SF_STR_ALBUM       | 0x07  | Album.        |
+| SF_STR_LICENSE     | 0x08  | License.      |
+| SF_STR_TRACKNUMBER | 0x09  | Track number. |
+| SF_STR_GENRE       | 0x10  | Genre.        |
+
+The sf_get_string() function returns the specified string if it exists and a
+NULL pointer otherwise. In addition to the string ids above, SF_STR_FIRST (==
+SF_STR_TITLE) and SF_STR_LAST (always the same as the highest numbers string id)
+are also available to allow iteration over all the available string ids.
+
+The sf_set_string() function sets the string data. It returns zero on success
+and non-zero on error.The error code can be converted to a string using
+sf_error_number().
+
+Strings passed to and retrieved from these two functions are assumed to be
+utf-8. However, while formats like Ogg/Vorbis and FLAC fully support utf-8,
+others like WAV and AIFF officially only support ASCII. Writing utf-8 strings to
+WAV and AIF files with libsndfile will work when read back with libsndfile, but
+may not work with other programs.
+
+The suggested method of dealing with tags retrived using sf_get_string() is to
+assume they are utf-8. Similarly if you have a string in some exotic format like
+utf-16, it should be encoded to utf-8 before being written using libsndfile.
+
+## Function for retrieving library version {#version_string}
+
+```c
+const char *sf_version_string (void) ;
+```
+
+Return the library version string.
+
+## Function for retrieving current byterate {#current_byterate}
+
+```c
+int sf_current_byterate (SNDFILE *sndfile) ;
+```
+
+Return the current byterate at this point in the file. The byte rate in this
+case is the number of bytes per second of audio data. For instance, for a
+stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate
+would be 2 (stereo) \* 2 (two bytes per sample) * 16000 => 64000 bytes/sec.
+
+For some file formats the returned value will be accurate and exact, for some
+it will be a close approximation, for some it will be the average bitrate for
+the whole file and for some it will be a time varying value that was accurate
+when the file was most recently read or written.
+
+To get the bitrate, multiple this value by 8.
+
+`sf_current_byterate` returns byte per second or -1 if byterate is
+unknown.
+
+## Functions to get and set chunks from within a sound file
+
+These functions allow the getting and setting of chunks within a sound file (for
+those formats which allow it).
+
+These functions fail safely. Specifically, they will not allow you to overwrite
+existing chunks or add extra versions of format specific reserved chunks but
+should allow you to retrieve any and all chunks (may not be implemented for all
+chunks or all file formats).
+
+### sf_set_chunk
+
+```c
+int sf_set_chunk (SNDFILE *sndfile, const SF_CHUNK_INFO *chunk_info) ;
+```
+
+Set the specified chunk info (must be done before any audio data is written to
+the file). This will fail for format specific reserved chunks. The
+`chunk_info->data` pointer must be valid until the file is closed.
+
+The `SF_CHUNK_INFO` struct is documented as follows:
+
+```c
+struct SF_CHUNK_INFO
+{     char        id [64] ;   /* The chunk identifier. */
+    unsigned      id_size ;   /* The size of the chunk identifier. */
+    unsigned      datalen ;   /* The size of that data. */
+    void          *data ;     /* Pointer to the data. */
+} ;
+    typedef struct SF_CHUNK_INFO SF_CHUNK_INFO ;
+```
+
+`sf_set_chunk` returns `SF_ERR_NO_ERROR` on success or non-zero on failure.
+
+### sf_get_chunk_iterator
+
+```c
+SF_CHUNK_ITERATOR *
+sf_get_chunk_iterator (SNDFILE *sndfile, const SF_CHUNK_INFO *chunk_info) ;
+```
+
+Get an iterator for all chunks matching `chunk_info`.
+
+`SF_CHUNK_ITERATOR` is an opaque structure to an iterator over the all chunks of
+a given id and defined as follows:
+
+```c
+typedef        struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ;
+```
+
+The iterator will point to the first chunk matching `chunk_info`. Chunks are
+matching, if (`chunk_info->id`) matches the first (`chunk_info->id_size`) bytes
+of a chunk found in the `SNDFILE*` handle. If `chunk_info` is `NULL`, an
+iterator to all chunks in the `SNDFILE*` handle is returned. The values of
+`chunk_info->datalen` and `chunk_info->data` are ignored. If no matching chunks
+are found in the sndfile, `NULL` is returned.
+
+The returned iterator will stay valid until one of the following occurs:
+
+* The sndfile is closed.
+* A new chunk is added using [`sf_set_chunk()`](#sf_set_chunk).
+* Another chunk iterator function is called on the same `SNDFILE*`
+  handle that causes the iterator to be modified.
+
+The memory for the iterator belongs to the SNDFILE* handle and is freed when
+[sf_close](#close) is called.
+
+### sf_next_chunk_iterator
+
+```c
+sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ;
+```
+
+Iterate through chunks by incrementing the iterator.
+
+Increments the iterator and returns a handle to the new one. After this call,
+iterator will no longer be valid, and you must use the newly returned handle
+from now on. The returned handle can be used to access the next chunk matching
+the criteria as defined in [sf_get_chunk_iterator](#sf_get_chunk_iterator).
+If iterator points to the last chunk, this will free all resources associated
+with iterator and return `NULL`. The returned iterator will stay valid until
+`sf_get_next_chunk_iterator` is called again, the sndfile is closed or a new
+chunk us added.
+
+### sf_get_chunk_size
+
+```c
+int
+sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
+```
+
+Get the size of the specified chunk.
+
+If the specified chunk exists, the size will be returned in the `datalen` field
+of the `SF_CHUNK_INFO` struct. Additionally, the id of the chunk will be copied
+to the `id` field of the `SF_CHUNK_INFO` struct and it's `id_size` field will be
+updated accordingly.
+
+If the chunk doesn't exist `chunk_info->datalen` will be zero, and the `id` and
+`id_size` fields will be undefined.
+
+The function will return `SF_ERR_NO_ERROR` on success or non-zero on failure.
+
+### sf_get_chunk_data
+
+```c
+int
+sf_get_chunk_data (const SF_CHUNK_ITERATOR *it, SF_CHUNK_INFO *chunk_info) ;
+```
+
+Get the specified chunk data.
+
+If the specified chunk exists, up to `chunk_info->datalen` bytes of the chunk
+data will be copied into the `chunk_info->data` buffer (allocated by the caller)
+and the `chunk_info->datalen` field updated to reflect the size of the data. The
+`id` and `id_size` field will be updated according to the retrieved chunk. If
+the chunk doesn't exist `chunk_info->datalen` will be zero, and the `id` and
+`id_size` fields will be undefined.
+
+The function will return `SF_ERR_NO_ERROR` on success or non-zero on failure.
+
+## Note 1
+
+When converting between integer PCM formats of differing size (e.g. using
+sf_read_int() to read a 16 bit PCM encoded WAV file) libsndfile obeys one simple
+rule:
+
+Whenever integer data is moved from one sized container to another sized
+container, the most significant bit in the source container will become the most
+significant bit in the destination container.
+
+When converting between integer data and floating point data, different rules
+apply. The default behaviour when reading floating point data (sf_read_float()
+or sf_read_double ()) from a file with integer data is normalisation. Regardless
+of whether data in the file is 8, 16, 24 or 32 bit wide, the data will be read
+as floating point data in the range [-1.0, 1.0]. Similarly, data in the range
+[-1.0, 1.0] will be written to an integer PCM file so that a data value of 1.0
+will be the largest allowable integer for the given bit width. This
+normalisation can be turned on or off using the [sf_command](command.md)
+interface.
+
+## Note 2
+
+Reading a file containg floating point data (allowable with WAV, AIFF, AU and
+other file formats) using integer read methods (sf_read_short() or
+sf_read_int()) can produce unexpected results. For instance the data in the file
+may have a maximum absolute value &lt; 1.0 which would mean that all sample
+values read from the file will be zero. In order to read these files correctly
+using integer read methods, it is recommended that you use the
+[sf_command](command.md) interface, a command of
+[SFC_SET_SCALE_FLOAT_INT_READ](command.md#sfc_set_scale_float_int_read) and a
+parameter of SF_TRUE to force correct scaling.
diff --git a/docs/bugs.md b/docs/bugs.md
new file mode 100644 (file)
index 0000000..f788c0e
--- /dev/null
@@ -0,0 +1,47 @@
+---
+layout: page
+---
+
+# Reporting Bugs in libsndfile
+
+Before even attempting to report a bug in libsndfile please make sure you have
+read the [Frequently Asked Questions](FAQ.md). If you are having a problem
+writing code using libsndfile make sure you read the
+[Application Programming Interface](api.md) documentation.
+
+That said, I am interested in finding and fixing all genuine bugs in libsndfile.
+Bugs I want to fix include any of the following problems (and probably others):
+
+- Compilation problems on new platforms.
+- Errors being detected during the `make check` process.
+- Segmentation faults occuring inside libsndfile.
+- libsndfile hanging when opening a file.
+- Supported sound file types being incorrectly read or written.
+- Omissions, errors or spelling mistakes in the documentation.
+
+When submitting a bug report you must include:
+
+- Your system (CPU and memory size should be enough).
+- The operating system you are using.
+- Whether you are using a package provided by your distribution or you compiled
+  it youself.
+- If you compiled it yourself, the compiler you are using. (Also make sure to
+  run `make check`.)
+- A description of the problem.
+- Information generated by the sndfile-info program (see next paragraph).
+- If you are having problems with sndfile-play and ALSA on Linux, I will need
+  information about your kernel, ALSA version, compiler version, whether you
+  compiled the kernel/ALSA your self or installed from a package etc.
+
+If libsndfile compiles and installs correctly but has difficulty reading a
+particular file or type of file you should run the **sndfile-info** program
+(from the examples directory of the libsndfile distribution) on the file. See
+[here](sndfile_info.md) for an example of the use of the **sndfile-info**
+program.
+
+Please do not send me a sound file which fails to open under libsndfile unless
+I specifically ask you to. The above information should usually suffice for most
+problems.
+
+Once you have the above information you should submit a ticket on the libsndfile
+[GitHub issue tracker](https://github.com/libsndfile/libsndfile/issues).
diff --git a/docs/command.md b/docs/command.md
new file mode 100644 (file)
index 0000000..5e6606f
--- /dev/null
@@ -0,0 +1,1929 @@
+---
+layout: page
+title: libsndfile : the sf_command function.
+---
+
+# sf_command
+
+```c
+int sf_command (SNDFILE *sndfile, int cmd, void *data, int datasize) ;
+```
+
+This function allows the caller to retrieve information from or change aspects
+of the library behaviour. Examples include retrieving a string containing the
+library version or changing the scaling applied to floating point sample data
+during read and write. Most of these operations are performed on a per-file
+basis.
+
+The cmd parameter is an integer identifier which is defined in *sndfile.h*. All
+of the valid command identifiers have names beginning with "SFC_". Data is
+passed to and returned from the library by use of a void pointer. The library
+will not read or write more than datasize bytes from the void pointer. For some
+calls no data is required in which case data should be NULL and datasize may be
+used for some other purpose.
+
+The available commands are as follows:
+
+| Name                                                              | Description                                             |
+|:------------------------------------------------------------------|:--------------------------------------------------------|
+| [SFC_GET_LIB_VERSION](#sfc_get_lib_version)                       | Retrieve the version of the library as a string.        |
+| [SFC_GET_LOG_INFO](#sfc_get_log_info)                             | Retrieve the internal per-file operation log.           |
+| [SFC_GET_CURRENT_SF_INFO](#sfc_get_current_sf_info)               | Retrieve `SF_INFO` struct of opened file.               |
+| [SFC_CALC_SIGNAL_MAX](#sfc_calc_signal_max)                       | Calculate the measured maximum signal value.            |
+| [SFC_CALC_NORM_SIGNAL_MAX](#sfc_calc_norm_signal_max)             | Calculate the measured normalised maximum signal value. |
+| [SFC_CALC_MAX_ALL_CHANNELS](#sfc_calc_max_all_channels)           | Calculate the peak value for each channel.              |
+| [SFC_CALC_NORM_MAX_ALL_CHANNELS](#sfc_calc_norm_max_all_channels) | Calculate the normalised peak for each channel.         |
+| [SFC_GET_SIGNAL_MAX](#sfc_get_signal_max)                         | Retrieve the peak value for the file.                   |
+| [SFC_GET_MAX_ALL_CHANNELS](#sfc_get_max_all_channels)             | Retrieve the peak value for each channel.               |
+| [SFC_SET_NORM_FLOAT](#sfc_set_norm_float)                         | Set float normalisation behaviour.                      |
+| [SFC_SET_NORM_DOUBLE](#sfc_set_norm_double)                       | Set double normalisation behaviour.                     |
+| [SFC_GET_NORM_FLOAT](#sfc_get_norm_float)                         | Get float normalisation behaviour.                      |
+| [SFC_GET_NORM_DOUBLE](#sfc_get_norm_double)                       | Get double normalisation behaviour.                     |
+| [SFC_SET_SCALE_FLOAT_INT_READ](#sfc_set_scale_float_int_read)     | Control scale factor on read.                           |
+| [SFC_SET_SCALE_INT_FLOAT_WRITE](#sfc_set_scale_int_float_write)   | Control scale factor on write.                          |
+| [SFC_GET_SIMPLE_FORMAT_COUNT](#sfc_get_simple_format_count)       | Get simple formats count.                               |
+| [SFC_GET_SIMPLE_FORMAT](#sfc_get_simple_format)                   | Get information about a simple format.                  |
+| [SFC_GET_FORMAT_INFO](#sfc_get_format_info)                       | Get information about a major or subtype format.        |
+| [SFC_GET_FORMAT_MAJOR_COUNT](#sfc_get_format_major_count)         | Get the number of major formats.                        |
+| [SFC_GET_FORMAT_MAJOR](#sfc_get_format_major)                     | Get information about a major format type.              |
+| [SFC_GET_FORMAT_SUBTYPE_COUNT](#sfc_get_format_subtype_count)     | Get the number of subformats.                           |
+| [SFC_GET_FORMAT_SUBTYPE](#sfc_get_format_subtype)                 | Get information about a subformat.                      |
+| [SFC_SET_ADD_PEAK_CHUNK](#sfc_set_add_peak_chunk)                 | Control PEAK chunk write to WAV and AIFF.               |
+| [SFC_UPDATE_HEADER_NOW](#sfc_update_header_now)                   | Update the file header in write mode on demand.         |
+| [SFC_SET_UPDATE_HEADER_AUTO](#sfc_set_update_header_auto)         | Update the file header on each write.                   |
+| [SFC_FILE_TRUNCATE](#sfc_file_truncate)                           | Truncate a file open for write or for read/write.       |
+| [SFC_SET_RAW_START_OFFSET](#sfc_set_raw_start_offset)             | Change the data start offset for raw files.             |
+| SFC_SET_DITHER_ON_WRITE                                           | Not implemented.                                        |
+| SFC_SET_DITHER_ON_READ                                            | Not implemented.                                        |
+| SFC_GET_DITHER_INFO_COUNT                                         | Not implemented.                                        |
+| SFC_GET_DITHER_INFO                                               | Not implemented.                                        |
+| [SFC_SET_CLIPPING](#sfc_set_clipping)                             | Control automatic clipping behaviour.                   |
+| [SFC_GET_CLIPPING](#sfc_get_clipping)                             | Get current clipping setting.                           |
+| [SFC_GET_EMBED_FILE_INFO](#sfc_get_embed_file_info)               | Get information about embedded audio files.             |
+| [SFC_WAVEX_GET_AMBISONIC](#sfc_wavex_get_ambisonic)               | Test a WAVEX file for Ambisonic format.                 |
+| [SFC_WAVEX_SET_AMBISONIC](#sfc_wavex_set_ambisonic)               | Modify a WAVEX header for Ambisonic format.             |
+| [SFC_SET_VBR_ENCODING_QUALITY](#sfc_set_vbr_encoding_quality)     | Set the Variable Bit Rate encoding quality.             |
+| [SFC_SET_OGG_PAGE_LATENCY_MS](#sfc_set_ogg_page_latency_ms)       | Set Ogg page latency for Opus file.                     |
+| [SFC_SET_COMPRESSION_LEVEL](#sfc_set_compression_level)           | Set the compression level.                              |
+| [SFC_RAW_DATA_NEEDS_ENDSWAP](#sfc_raw_data_needs_endswap)         | Determine if raw data needs endswapping.                |
+| [SFC_GET_BROADCAST_INFO](#sfc_get_broadcast_info)                 | Get the Broadcast Chunk info.                           |
+| [SFC_SET_BROADCAST_INFO](#sfc_set_broadcast_info)                 | Set the Broadcast Chunk info.                           |
+| [SFC_GET_CHANNEL_MAP_INFO](#sfc_get_channel_map_info)             | Get the channel map info.                               |
+| [SFC_SET_CHANNEL_MAP_INFO](#sfc_set_channel_map_info)             | Set the channel map info.                               |
+| [SFC_SET_CART_INFO](#sfc_set_cart_info)                           | Set the Cart Chunk info.                                |
+| [SFC_GET_CART_INFO](#sfc_get_cart_info)                           | Get the Cart Chunk info.                                |
+| [SFC_GET_LOOP_INFO](#sfc_get_loop_info)                           | Get loop info.                                          |
+| [SFC_GET_INSTRUMENT](#sfc_get_instrument)                         | Get instrument info.                                    |
+| [SFC_SET_INSTRUMENT](#sfc_set_instrument)                         | Set instrument info.                                    |
+| [SFC_GET_CUE_COUNT](#sfc_get_cue_count)                           | Get the cue marker count.                               |
+| [SFC_GET_CUE](#sfc_get_cue)                                       | Get cue marker info.                                    |
+| [SFC_SET_CUE](#sfc_set_cue)                                       | Set cue marker info.                                    |
+| [SFC_RF64_AUTO_DOWNGRADE](#sfc_rf64_auto_downgrade)               | Set auto downgrade from RF64 to WAV.                    |
+| [SFC_GET_ORIGINAL_SAMPLERATE](#sfc_get_original_samplerate)       | Get original samplerate metadata.                       |
+| [SFC_SET_ORIGINAL_SAMPLERATE](#sfc_set_original_samplerate)       | Set original samplerate metadata.                       |
+
+---
+
+## SFC_GET_LIB_VERSION
+
+Retrieve the version of the library as a string.
+
+### Parameters
+
+sndfile
+: Not used
+
+cmd
+: SFC_GET_LIB_VERSION
+
+data
+: A pointer to a char buffer
+
+datasize
+: The size of the buffer
+
+### Examples
+
+```c
+char  buffer [128] ;
+sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
+```
+
+### Return value
+
+This call will return the length of the retrieved version string.
+
+### Notes
+
+The string returned in the buffer passed to this function will not overflow the
+buffer and will always be null terminated .
+
+## SFC_GET_LOG_INFO
+
+Retrieve the internal per-file operation log.
+
+This log buffer can often contain a good reason for why libsndfile failed to
+open a particular file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_LOG_INFO
+
+data
+: A pointer to a char buffer
+
+datasize
+: The size of the buffer
+
+Example:
+
+```c
+char  buffer [2048] ;
+sf_command (sndfile, SFC_GET_LOG_INFO, buffer, sizeof (buffer)) ;
+```
+
+### Return value
+
+This call will return the length of the retrieved version string.
+
+### Notes
+
+The string returned in the buffer passed to this function will not overflow the
+buffer and will always be null terminated.
+
+## SFC_GET_CURRENT_SF_INFO
+
+Retrieve `SF_INFO` struct of opened file.
+
+`SFC_GET_CURRENT_SF_INFO` command copies `SF_INFO` struct of `sndfile` object to
+provided buffer.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_CURRENT_SF_INFO
+
+data
+: A pointer to a valid SF_INFO* pointer
+
+datasize
+: sizeof (SF_INFO)
+
+### Examples
+
+```c
+SF_INFO  sfinfo ;
+sf_command (sndfile, SFC_GET_CURRENT_SF_INFO, sfinfo, sizeof (SF_INFO)) ;
+```
+
+### Return value
+
+Zero on success, non-zero otherwise.
+
+## SFC_CALC_SIGNAL_MAX
+
+Retrieve the measured maximum signal value. This involves reading through the
+whole file which can be slow on large files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_CALC_SIGNAL_MAX
+
+data
+: A pointer to a double
+
+datasize
+: sizeof (double)
+
+### Examples
+
+```c
+double   max_val ;
+sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &max_val, sizeof (max_val)) ;
+```
+
+### Return value
+
+Zero on success, non-zero otherwise.
+
+## SFC_CALC_NORM_SIGNAL_MAX
+
+Retrieve the measured normalised maximum signal value. This involves reading
+through the whole file which can be slow on large files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_CALC_NORM_SIGNAL_MAX
+
+data
+: A pointer to a double
+
+datasize
+: sizeof (double)
+
+### Examples
+
+```c
+double   max_val ;
+sf_command (sndfile, SFC_CALC_NORM_SIGNAL_MAX, &max_val, sizeof (max_val)) ;
+```
+
+### Return value
+
+Zero on success, non-zero otherwise.
+
+## SFC_CALC_MAX_ALL_CHANNELS
+
+Calculate the peak value (ie a single number) for each channel. This involves
+reading through the whole file which can be slow on large files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_CALC_MAX_ALL_CHANNELS
+
+data
+: A pointer to a double
+
+datasize
+: sizeof (double) * number_of_channels
+
+### Examples
+
+```c
+double   peaks [number_of_channels] ;
+sf_command (sndfile, SFC_CALC_MAX_ALL_CHANNELS, peaks, sizeof (peaks)) ;
+```
+
+### Return value
+
+Zero if peaks have been calculated successfully and non-zero otherwise.
+
+## SFC_CALC_NORM_MAX_ALL_CHANNELS
+
+Calculate the normalised peak for each channel. This involves reading through
+the whole file which can be slow on large files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_CALC_NORM_MAX_ALL_CHANNELS
+
+data
+: A pointer to a double
+
+datasize
+: sizeof (double) * number_of_channels
+
+### Examples
+
+```c
+double   peaks [number_of_channels] ;
+sf_command (sndfile, SFC_CALC_NORM_MAX_ALL_CHANNELS, peaks, sizeof (peaks)) ;
+```
+
+### Return value
+
+Zero if peaks have been calculated successfully and non-zero otherwise.
+
+## SFC_GET_SIGNAL_MAX
+
+Retrieve the peak value for the file as stored in the file header.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_SIGNAL_MAX
+
+data
+: A pointer to a double
+
+datasize
+: sizeof (double)
+
+### Examples
+
+```c
+double   max_peak ;
+sf_command (sndfile, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (max_peak)) ;
+```
+
+### Return value
+
+SF_TRUE if the file header contained the peak value. SF_FALSE
+otherwise.
+
+## SFC_GET_MAX_ALL_CHANNELS
+
+Retrieve the peak value for the file as stored in the file header.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_SIGNAL_MAX
+
+data
+: A pointer to an array of doubles
+
+datasize
+: sizeof (double) * number_of_channels
+
+### Example
+
+```c
+double   peaks [number_of_channels] ;
+sf_command (sndfile, SFC_GET_MAX_ALL_CHANNELS, peaks, sizeof (peaks)) ;
+```
+
+### Return value
+
+SF_TRUE if the file header contains per channel peak values for the file,
+SF_FALSE otherwise.
+
+## SFC_SET_NORM_FLOAT
+
+This command only affects data read from or written to using the
+floating point
+functions:
+
+```c
+size_t    sf_read_float    (SNDFILE *sndfile, float *ptr, size_t items) ;
+size_t    sf_readf_float   (SNDFILE *sndfile, float *ptr, size_t frames) ;
+
+size_t    sf_write_float   (SNDFILE *sndfile, float *ptr, size_t items) ;
+size_t    sf_writef_float  (SNDFILE *sndfile, float *ptr, size_t frames) ;
+```
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_NORM_FLOAT
+
+data
+: NULL
+
+datasize
+: SF_TRUE or SF_FALSE
+
+For read operations setting normalisation to SF_TRUE means that the data from
+all subsequent reads will be be normalised to the range [-1.0, 1.0].
+
+For write operations, setting normalisation to SF_TRUE means than all data
+supplied to the float write functions should be in the range [-1.0, 1.0] and
+will be scaled for the file format as necessary.
+
+For both cases, setting normalisation to SF_FALSE means that no scaling will
+take place.
+
+### Examples
+
+```c
+sf_command (sndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE) ;
+
+sf_command (sndfile, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
+```
+
+### Return value
+
+Returns the previous float normalisation mode.
+
+## SFC_SET_NORM_DOUBLE
+
+This command only affects data read from or written to using the double
+precision floating point
+functions:
+
+```c
+size_t sf_read_double  (SNDFILE *sndfile, double *ptr, size_t items) ;
+size_t sf_readf_double (SNDFILE *sndfile, double *ptr, size_t frames) ;
+
+size_t sf_write_double  (SNDFILE *sndfile, double *ptr, size_t items) ;
+size_t sf_writef_double (SNDFILE *sndfile, double *ptr, size_t frames) ;
+```
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_NORM_DOUBLE
+
+data
+: NULL
+
+datasize
+: SF_TRUE or SF_FALSE
+
+For read operations setting normalisation to SF_TRUE means that the data from
+all subsequent reads will be be normalised to the range [-1.0, 1.0].
+
+For write operations, setting normalisation to SF_TRUE means than all data
+supplied to the double write functions should be in the range [-1.0, 1.0] and
+will be scaled for the file format as necessary.
+
+For both cases, setting normalisation to SF_FALSE means that no scaling will
+take place.
+
+### Examples
+
+```c
+sf_command (sndfile, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ;
+
+sf_command (sndfile, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
+```
+
+### Return value
+
+Returns the previous double normalisation mode.
+
+## SFC_GET_NORM_FLOAT
+
+Retrieve the current float normalisation mode.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_NORM_FLOAT
+
+data
+: NULL
+
+datasize
+: anything
+
+### Examples
+
+```c
+normalisation = sf_command (sndfile, SFC_GET_NORM_FLOAT, NULL, 0) ;
+```
+
+### Return value
+
+Returns TRUE if normalisation is on and FALSE otherwise.
+
+## SFC_GET_NORM_DOUBLE
+
+Retrieve the current float normalisation mode.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_NORM_DOUBLE
+
+data
+: NULL
+
+datasize
+: anything
+
+Example:
+
+```c
+normalisation = sf_command (sndfile, SFC_GET_NORM_DOUBLE, NULL, 0) ;
+```
+
+### Return value
+
+Returns TRUE if normalisation is on and FALSE otherwise.
+
+## SFC_SET_SCALE_FLOAT_INT_READ
+
+Set/clear the scale factor when integer (short/int) data is read from a file
+containing floating point data.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd:
+SFC_SET_SCALE_FLOAT_INT_READ
+
+data
+: NULL
+
+datasize
+: TRUE or FALSE
+
+Example:
+
+```c
+sf_command (sndfile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ;
+```
+
+### Return value
+
+Returns the previous `SFC_SET_SCALE_FLOAT_INT_READ` setting for this file.
+
+## SFC_SET_SCALE_INT_FLOAT_WRITE
+
+Set/clear the scale factor when integer (short/int) data is written to a file as
+floating point data.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_SCALE_INT_FLOAT_WRITE
+
+data
+: NULL
+
+datasize
+: TRUE or FALSE
+
+### Examples
+
+```c
+sf_command (sndfile, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ;
+```
+
+### Return value
+
+Returns the previous `SFC_SET_SCALE_INT_FLOAT_WRITE` setting for this file.
+
+## SFC_GET_SIMPLE_FORMAT_COUNT
+
+Retrieve the number of simple formats supported by libsndfile.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_SIMPLE_FORMAT_COUNT
+
+data
+: a pointer to an int
+
+datasize
+: sizeof (int)
+
+### Examples
+
+```c
+int  count ;
+sf_command (sndfile, SFC_GET_SIMPLE_FORMAT_COUNT, &count, sizeof (int)) ;
+```
+
+### Return value
+
+`0`.
+
+## SFC_GET_SIMPLE_FORMAT
+
+Retrieve information about a simple format.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_SIMPLE_FORMAT
+
+data
+: a pointer to an  SF_FORMAT_INFO struct
+
+datasize
+: sizeof (SF_FORMAT_INFO)
+
+The SF_FORMAT_INFO struct is defined in *sndfile.h* as:
+
+```c
+typedef struct
+{   int         format ;
+    const char  *name ;
+    const char  *extension ;
+} SF_FORMAT_INFO ;
+```
+
+When `sf_command()` is called with `SF_GET_SIMPLE_FORMAT`, the value of the
+format field should be the format number (ie 0 \<= format \<= count value
+obtained using `SF_GET_SIMPLE_FORMAT_COUNT).
+
+### Examples
+
+```c
+SF_FORMAT_INFO  format_info ;
+int             k, count ;
+
+sf_command (sndfile, SFC_GET_SIMPLE_FORMAT_COUNT, &count, sizeof (int)) ;
+
+for (k = 0 ; k < count ; k++)
+{   format_info.format = k ;
+    sf_command (sndfile, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
+    printf ("%08x  %s %s\n", format_info.format, format_info.name, format_info.extension) ;
+    } ;
+```
+
+### Return value
+
+0 on success and non-zero otherwise.
+
+The value of the format field of the `SF_FORMAT_INFO` struct will be a value
+which can be placed in the format field of an `SF_INFO` struct when a file is to
+be opened for write. The name field will contain a char\* pointer to the name of
+the string, eg. "WAV (Microsoft 16 bit PCM)". The extension field will contain
+the most commonly used file extension for that file type.
+
+## SFC_GET_FORMAT_INFO
+
+Retrieve information about a major or subtype format.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_FORMAT_INFO
+
+data
+: a pointer to an SF_FORMAT_INFO struct
+
+datasize
+: sizeof (SF_FORMAT_INFO)
+
+The `SF_FORMAT_INFO` struct is defined in \<sndfile.h\> as:
+
+```c
+typedef struct
+{   int         format ;
+    const char  *name ;
+    const char  *extension ;
+} SF_FORMAT_INFO ;
+```
+
+When `sf_command()` is called with `SF_GET_FORMAT_INFO`, the format field is
+examined and if (format & `SF_FORMAT_TYPEMASK`) is a valid format then the
+struct is filled in with information about the given major type. If (format &
+`SF_FORMAT_TYPEMASK`) is FALSE and (format & `SF_FORMAT_SUBMASK`) is a valid
+subtype format then the struct is filled in with information about the given
+subtype.
+
+### Examples
+
+```c
+SF_FORMAT_INFO  format_info ;
+
+format_info.format = SF_FORMAT_WAV ;
+sf_command (sndfile, SFC_GET_FORMAT_INFO, &format_info, sizeof (format_info)) ;
+printf ("%08x  %s %s\n", format_info.format, format_info.name, format_info.extension) ;
+
+format_info.format = SF_FORMAT_ULAW ;
+sf_command (sndfile, SFC_GET_FORMAT_INFO, &format_info, sizeof (format_info)) ;
+printf ("%08x  %s\n", format_info.format, format_info.name) ;
+```
+
+### Return value
+
+0 on success and non-zero otherwise.
+
+## SFC_GET_FORMAT_MAJOR_COUNT
+
+Retrieve the number of major formats.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_FORMAT_MAJOR_COUNT
+
+data
+: a pointer to an int
+
+datasize
+: sizeof (int)
+
+### Examples
+
+```c
+int  count ;
+sf_command (sndfile, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int)) ;
+```
+
+### Return value
+
+0.
+
+## SFC_GET_FORMAT_MAJOR
+
+Retrieve information about a major format type.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_FORMAT_MAJOR
+
+data
+: a pointer to an  SF_FORMAT_INFO struct
+
+datasize
+: sizeof (SF_FORMAT_INFO)
+
+### Examples
+
+```c
+SF_FORMAT_INFO  format_info ;
+int             k, count ;
+
+sf_command (sndfile, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int)) ;
+
+for (k = 0 ; k < count ; k++)
+{   format_info.format = k ;
+    sf_command (sndfile, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
+    printf ("%08x  %s %s\n", format_info.format, format_info.name, format_info.extension) ;
+    } ;
+```
+
+For a more comprehensive example, see the program `list_formats.c` in the
+`examples/` directory of the libsndfile source code distribution.
+
+### Return value
+
+0 on success and non-zero otherwise.
+
+The value of the format field will be one of the major format identifiers such
+as `SF_FORMAT_WAV` or `SF_FORMAT`_AIFF. The name field will contain a char\*
+pointer to the name of the string, eg. "WAV (Microsoft)". The extension field
+will contain the most commonly used file extension for that file type.
+
+## SFC_GET_FORMAT_SUBTYPE_COUNT
+
+Retrieve the number of subformats.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_FORMAT_SUBTYPE_COUNT
+
+data
+: a pointer to an int
+
+datasize
+: sizeof (int)
+
+### Examples
+
+```c
+int   count ;
+sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ;
+```
+
+### Return value
+
+Returns zero.
+
+## SFC_GET_FORMAT_SUBTYPE
+
+Enumerate the subtypes (this function does not translate a subtype into a string
+describing that subtype). A typical use case might be retrieving a string
+description of all subtypes so that a dialog box can be filled in.
+
+### Parameters
+
+sndfile
+: Not used.
+
+cmd
+: SFC_GET_FORMAT_SUBTYPE
+
+data
+: a pointer to an SF_FORMAT_INFO struct
+
+datasize
+: sizeof (SF_FORMAT_INFO)
+
+### Examples
+
+Example 1: Retrieve all sybtypes supported by the WAV format.
+
+```c
+SF_FORMAT_INFO  format_info ;
+int             k, count ;
+
+sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ;
+
+for (k = 0 ; k < count ; k++)
+{   format_info.format = k ;
+    sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
+    if (! sf_format_check (format_info.format | SF_FORMAT_WAV))
+        continue ;
+    printf ("%08x  %s\n", format_info.format, format_info.name) ;
+    } ;
+```
+
+Example 2: Print a string describing the `SF_FORMAT_PCM_16` subtype.
+
+```c
+SF_FORMAT_INFO  format_info ;
+int             k, count ;
+
+sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ;
+
+for (k = 0 ; k < count ; k++)
+{   format_info.format = k ;
+    sf_command (sndfile, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
+    if (format_info.format == SF_FORMAT_PCM_16)
+    {   printf ("%08x  %s\n", format_info.format, format_info.name) ;
+        break ;
+        } ;
+    } ;
+```
+
+For a more comprehensive example, see the program `list_formats.c` in the
+`examples/` directory of the libsndfile source code distribution.
+
+### Return value
+
+0 on success and non-zero otherwise.
+
+The value of the format field will be one of the major format identifiers such
+as `SF_FORMAT_WAV` or `SF_FORMAT_AIFF`. The name field will contain a char\*
+pointer to the name of the string; for instance "WAV (Microsoft)" or "AIFF
+(Apple/SGI)". The extension field will be a NULL pointer.
+
+## SFC_SET_ADD_PEAK_CHUNK
+
+By default, WAV and AIFF files which contain floating point data (subtype
+`SF_FORMAT_FLOAT` or `SF_FORMAT_DOUBLE`) have a PEAK chunk. By using this
+command, the addition of a PEAK chunk can be turned on or off.
+
+**Note**: This call must be made before any data is written to the file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_ADD_PEAK_CHUNK
+
+data
+: Not used (should be NULL)
+
+datasize
+: TRUE or FALSE.
+
+### Examples
+
+```c
+/* Turn on the PEAK chunk. */
+sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
+
+/* Turn off the PEAK chunk. */
+sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
+```
+
+### Return value
+
+Returns SF_TRUE if the peak chunk will be written after this call. Returns
+SF_FALSE if the peak chunk will not be written after this call.
+
+## SFC_UPDATE_HEADER_NOW
+
+The header of an audio file is normally written by libsndfile when the file is
+closed using [**sf_close()**](api.md#file-close-function).
+
+There are however situations where large files are being generated and it would
+be nice to have valid data in the header before the file is complete. Using this
+command will update the file header to reflect the amount of data written to the
+file so far. Other programs opening the file for read (before any more data is
+written) will then read a valid sound file header.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_UPDATE_HEADER_NOW
+
+data
+: Not used (should be NULL)
+
+datasize
+: Not used.
+
+### Examples
+
+```c
+/* Update the header now. */
+sf_command (sndfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
+```
+
+### Return value
+
+Returns zero.
+
+## SFC_SET_UPDATE_HEADER_AUTO
+
+Similar to `SFC_UPDATE_HEADER_NOW` but updates the header at the end of every
+call to the [sf_write\*](api.md#write) functions.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_UPDATE_HEADER_AUTO
+
+data
+: Not used (should be NULL)
+
+datasize
+: `SF_TRUE` or `SF_FALSE`
+
+### Examples
+
+```c
+/* Turn on auto header update. */
+sf_command (sndfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+
+/* Turn off auto header update. */
+sf_command (sndfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_FALSE) ;
+```
+
+### Return value
+
+TRUE if auto update header is now on; FALSE otherwise.
+
+## SFC_FILE_TRUNCATE
+
+Truncate a file that was opened for write or read/write.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_FILE_TRUNCATE
+
+data
+: A pointer to an sf_count_t.
+
+datasize
+: sizeof (sf_count_t)
+
+Truncate the file to the number of frames specified by the sf_count_t pointed to
+by data. After this command, both the read and the write pointer will be at the
+new end of the file. This command will fail (returning non-zero) if the
+requested truncate position is beyond the end of the file.
+
+### Examples
+
+```c
+/* Truncate the file to a length of 20 frames. */
+sf_count_t  frames = 20 ;
+sf_command (sndfile, SFC_FILE_TRUNCATE, &frames, sizeof (frames)) ;
+```
+
+### Return value
+
+Zero on sucess, non-zero otherwise.
+
+## SFC_SET_RAW_START_OFFSET
+
+Change the data start offset for files opened up as `SF_FORMAT_RAW`.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_RAW_START_OFFSET
+
+data
+: A pointer to an sf_count_t.
+
+datasize
+: sizeof (sf_count_t)
+
+For a file opened as format `SF_FORMAT_RAW`, set the data offset to the value
+given by `data`.
+
+### Examples
+
+```c
+/* Reset the data offset to 5 bytes from the start of the file. */
+sf_count_t  offset = 5 ;
+sf_command (sndfile, SFC_SET_RAW_START_OFFSET, &offset, sizeof (offset)) ;
+```
+
+### Return value
+
+Zero on success, non-zero otherwise.
+
+## SFC_SET_CLIPPING
+
+Turn on/off automatic clipping when doing floating point to integer conversion.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_CLIPPING
+
+data
+: NULL
+
+datasize
+: SF_TRUE or SF_FALSE.
+
+Turn on (datasize == SF_TRUE) or off (datasize == SF_FALSE) clipping.
+
+### Examples
+
+```c
+sf_command (sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+```
+
+### Return value
+
+Clipping mode (SF_TRUE or SF_FALSE).
+
+## SFC_GET_CLIPPING
+
+Turn on/off automatic clipping when doing floating point to integer conversion.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_CLIPPING
+
+data
+: NULL
+
+datasize
+: 0
+
+Retrieve the current cliiping setting.
+
+### Examples
+
+```c
+sf_command (sndfile, SFC_GET_CLIPPING, NULL, 0) ;
+```
+
+### Return value
+
+Clipping mode (SF_TRUE or SF_FALSE).
+
+## SFC_GET_EMBED_FILE_INFO
+
+Get the file offset and file length of a file enbedded within another larger
+file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_EMBED_FILE_INFO
+
+data
+: a pointer to an  SF_EMBED_FILE_INFO struct
+
+datasize
+: sizeof (SF_EMBED_FILE_INFO)
+
+The `SF_EMBED_FILE_INFO` struct is defined in *sndfile.h* as:
+
+```c
+typedef struct
+{   sf_count_t  offset ;
+    sf_count_t  length ;
+} SF_EMBED_FILE_INFO ;
+```
+
+### Return value
+
+0 on success and non-zero otherwise.
+
+The value of the offset field of the `SF_EMBED_FILE_INFO` struct will be the
+offsets in bytes from the start of the outer file to the start of the audio
+file. The value of the offset field of the `SF_EMBED_FILE_INFO` struct will be
+the length in bytes of the embedded file.
+
+## SFC_WAVEX_GET_AMBISONIC
+
+Test if the current file has the GUID of a WAVEX file for any of the Ambisonic
+formats.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_WAVEX_GET_AMBISONIC
+
+data
+: NULL
+
+datasize
+: 0
+
+The Ambisonic WAVEX formats are defined here:
+<http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html>.
+
+### Return value
+
+`SF_AMBISONIC_NONE(0x40)` or `SF_AMBISONIC_B_FORMAT(0x41)` or zero if the file
+format does not support ambisonic formats.
+
+## SFC_WAVEX_SET_AMBISONIC
+
+Set the GUID of a new WAVEX file to indicate an Ambisonics format.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_WAVEX_SET_AMBISONIC
+
+data
+: NULL
+
+datasize
+: SF_AMBISONIC_NONE or SF_AMBISONIC_B_FORMAT
+
+Turn on (`SF_AMBISONIC_B_FORMAT(0x41)`) or off (`SF_AMBISONIC_NONE(0x40)`)
+encoding. This command is currently only supported for files with
+`SF_FORMAT_WAVEX` format.
+
+The Ambisonic WAVEX formats are defined here:
+
+<http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html>.
+
+### Return value
+
+Return the ambisonic value that has just been set or zero if the
+file format does not support ambisonic encoding.
+
+## SFC_SET_VBR_ENCODING_QUALITY
+
+Set the Variable Bit Rate encoding quality. The encoding quality value
+should be between 0.0 (lowest quality) and 1.0 (highest quality).
+Currenly this command is only implemented for FLAC and Ogg/Vorbis files.
+It has no effect on un-compressed file formats.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_VBR_ENCODING_QUALITY
+
+data
+: A pointer to a double value
+
+datasize
+: sizeof (double)
+
+The command must be sent before any audio data is written to the file.
+
+### Return value
+
+SF_TRUE if VBR encoding quality was set. SF_FALSE otherwise.
+
+## SFC_SET_OGG_PAGE_LATENCY_MS
+
+Set page latency for Ogg Opus file in milliseconds. The value should be between
+50.0 and 1600.0. This command is only implemented for Ogg Opus files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_OGG_PAGE_LATENCY_MS
+
+data
+: A pointer to a double value
+
+datasize
+: sizeof (double)
+
+### Return value
+
+0 on success and non-zero otherwise.
+
+## SFC_SET_COMPRESSION_LEVEL
+
+Set the compression level. The compression level should be between 0.0 (minimum
+compression level) and 1.0 (highest compression level). Currenly this command is
+only implemented for FLAC and Ogg/Vorbis files. It has no effect on
+uncompressed file formats.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_COMPRESSION_LEVEL
+
+data
+: A pointer to a double value
+
+datasize
+: sizeof (double)
+
+The command must be sent before any audio data is written to the file.
+
+### Return value
+
+SF_TRUE if compression level was set. SF_FALSE otherwise.
+
+## SFC_RAW_DATA_NEEDS_ENDSWAP
+
+Determine if raw data read using [sf_read_raw()](api.md#raw) needs to be end
+swapped on the host CPU.
+
+For instance, will return SF_TRUE on when reading WAV containing
+`SF_FORMAT_PCM_16` data on a big endian machine and `SF_FALSE` on a
+little endian machine.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_RAW_DATA_NEEDS_ENDSWAP
+
+data
+: NULL
+
+datasize
+: 0
+
+### Return value
+
+`SF_TRUE` or `SF_FALSE`.
+
+## SFC_GET_BROADCAST_INFO
+
+Retrieve the Broadcast Extension Chunk from WAV (and related) files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_BROADCAST_INFO
+
+data
+: a pointer to an SF_BROADCAST_INFO struct
+
+datasize
+: sizeof (SF_BROADCAST_INFO)
+
+The SF_BROADCAST_INFO struct is defined in *sndfile.h* as:
+
+```c
+typedef struct
+{   char            description [256] ;
+    char            originator [32] ;
+    char            originator_reference [32] ;
+    char            origination_date [10] ;
+    char            origination_time [8] ;
+    unsigned int    time_reference_low ;
+    unsigned int    time_reference_high ;
+    short           version ;
+    char            umid [64] ;
+    char            reserved [190] ;
+    unsigned int    coding_history_size ;
+    char            coding_history [256] ;
+} SF_BROADCAST_INFO ;
+```
+
+### Return value
+
+`SF_TRUE` if the file contained a Broadcast Extension chunk or `SF_FALSE`
+otherwise.
+
+## SFC_SET_BROADCAST_INFO
+
+Set the Broadcast Extension Chunk for WAV (and related) files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_BROADCAST_INFO
+
+data
+: a pointer to an SF_BROADCAST_INFO struct
+
+datasize
+: sizeof (SF_BROADCAST_INFO)
+
+### Return value
+
+`SF_TRUE` if setting the Broadcast Extension chunk was successful and `SF_FALSE`
+otherwise.
+
+## SFC_GET_CHANNEL_MAP_INFO
+
+Retrieve the channel map contained in an AIFF or CAF Channel Layout chunk.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_CHANNEL_MAP_INFO
+
+data
+: a pointer to an array of int, the same size as the number of channels in the
+file
+
+datasize
+: number of channels * sizeof (int)
+
+Channel map positions are defined in an enum in *sndfile.h*:
+
+| Name                                 | Value | Description                                                       |
+|:-------------------------------------|:------|:------------------------------------------------------------------|
+| SF_CHANNEL_MAP_INVALID               | 0     |                                                                   |
+| SF_CHANNEL_MAP_MONO                  | 1     |                                                                   |
+| SF_CHANNEL_MAP_LEFT                  | 2     | Apple calls this 'Left'                                           |
+| SF_CHANNEL_MAP_RIGHT                 | 3     | Apple calls this 'Right'                                          |
+| SF_CHANNEL_MAP_CENTER                | 4     | Apple calls this 'Center'                                         |
+| SF_CHANNEL_MAP_FRONT_LEFT            | 5     |                                                                   |
+| SF_CHANNEL_MAP_FRONT_RIGHT           | 6     |                                                                   |
+| SF_CHANNEL_MAP_FRONT_CENTER          | 7     |                                                                   |
+| SF_CHANNEL_MAP_REAR_CENTER           | 8     | Apple calls this 'Center Surround', Msft calls this 'Back Center' |
+| SF_CHANNEL_MAP_REAR_LEFT             | 9     | Apple calls this 'Left Surround', Msft calls this 'Back Left'     |
+| SF_CHANNEL_MAP_REAR_RIGHT            | 10    | Apple calls this 'Right Surround', Msft calls this 'Back Right'   |
+| SF_CHANNEL_MAP_LFE                   | 11    | Apple calls this 'LFEScreen', Msft calls this 'Low Frequency'     |
+| SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER  | 12    | Apple calls this 'Left Center'                                    |
+| SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER | 13    | Apple calls this 'Right Center'                                   |
+| SF_CHANNEL_MAP_SIDE_LEFT             | 14    | Apple calls this 'Left Surround Direct'                           |
+| SF_CHANNEL_MAP_SIDE_RIGHT            | 15    | Apple calls this 'Right Surround Direct'                          |
+| SF_CHANNEL_MAP_TOP_CENTER            | 16    | Apple calls this 'Top Center Surround'                            |
+| SF_CHANNEL_MAP_TOP_FRONT_LEFT        | 17    | Apple calls this 'Vertical Height Left'                           |
+| SF_CHANNEL_MAP_TOP_FRONT_RIGHT       | 18    | Apple calls this 'Vertical Height Right'                          |
+| SF_CHANNEL_MAP_TOP_FRONT_CENTER      | 19    | Apple calls this 'Vertical Height Center'                         |
+| SF_CHANNEL_MAP_TOP_REAR_LEFT         | 20    | Apple and MS call this 'Top Back Left'                            |
+| SF_CHANNEL_MAP_TOP_REAR_RIGHT        | 21    | Apple and MS call this 'Top Back Right'                           |
+| SF_CHANNEL_MAP_TOP_REAR_CENTER       | 22    | Apple and MS call this 'Top Back Center'                          |
+| SF_CHANNEL_MAP_AMBISONIC_B_W         | 23    |                                                                   |
+| SF_CHANNEL_MAP_AMBISONIC_B_X         | 24    |                                                                   | 
+| SF_CHANNEL_MAP_AMBISONIC_B_Y         | 25    |                                                                   |
+| SF_CHANNEL_MAP_AMBISONIC_B_Z         | 26    |                                                                   |
+| SF_CHANNEL_MAP_MAX                   | 27    |                                                                   |
+
+### Return value
+
+`SF_TRUE` if the file contained a Channel Layout chunk or `SF_FALSE` otherwise.
+
+## SFC_SET_CHANNEL_MAP_INFO
+
+Set the channel map contained in an AIFF or CAF Channel Layout chunk.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_CHANNEL_MAP_INFO
+
+data
+: a pointer to an array of int, the same size as the number of channels in the
+file
+
+datasize
+: number of channels * sizeof (int)
+
+### Return value
+
+`SF_TRUE` if setting the Channel Layout chunk was successful and `SF_FALSE`
+otherwise.
+
+## SFC_GET_CART_INFO
+
+Retrieve the Cart Chunk from WAV (and related) files. Based on AES46 standard
+for CartChunk (see [CartChunk.org](http://www.cartchunk.org/) for more
+information.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_CART_INFO
+
+data
+: a pointer to an SF_CART_INFO struct
+
+datasize
+: sizeof (SF_CART_INFO)
+
+The SF_CART_INFO struct is defined in *sndfile.h* as:
+
+```c
+#define SF_CART_INFO_VAR(p_tag_text_size) \
+    struct
+    {       char            version [4] ;
+            char            title [64] ;
+            char            artist [64] ;
+            char            cut_id [64] ;
+            char            client_id [64] ;
+            char            category [64] ;
+            char            classification [64] ;
+            char            out_cue [64] ;
+            char            start_date [10] ;
+            char            start_time [8] ;
+            char            end_date [10] ;
+            char            end_time [8] ;
+            char            producer_app_id [64] ;
+            char            producer_app_version [64] ;
+            char            user_def [64] ;
+            long    level_reference ;
+            SF_CART_TIMER   post_timers [8] ;
+            char            reserved [276] ;
+            char            url [1024] ;
+            unsigned int    tag_text_size ;
+            char            tag_text[p_tag_text_size] ;
+    }
+```
+
+### Return value
+
+`SF_TRUE` if the file contained a Cart chunk or `SF_FALSE` otherwise.
+
+## SFC_SET_CART_INFO
+
+Set the Cart Chunk for WAV (and related) files.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_CART_INFO
+
+data
+: a pointer to an SF_CART_INFO struct
+
+datasize
+: sizeof (SF_CART_INFO)
+
+### Return value
+
+SF_TRUE if setting the Cart chunk was successful and SF_FALSE otherwise.
+
+## SFC_GET_LOOP_INFO
+
+Retrieve loop information for file including time signature, length in beats and
+original MIDI base note
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_LOOP_INFO
+
+data
+: a pointer to an SF_LOOP_INFO struct
+
+datasize
+: sizeof (SF_LOOP_INFO)
+
+The SF_LOOP_INFO struct is defined in *sndfile.h* as:
+
+```c
+typedef struct
+{   short    time_sig_num ;   /* any positive integer    > 0  */
+    short    time_sig_den ;   /* any positive power of 2 > 0  */
+    int        loop_mode ;    /* see SF_LOOP enum             */
+
+    int        num_beats ;    /* this is NOT the amount of quarter notes !!!*/
+                              /* a full bar of 4/4 is 4 beats */
+                              /* a full bar of 7/8 is 7 beats */
+
+    float    bpm ;            /* suggestion, as it can be calculated using other fields:*/
+                              /* file's lenght, file's sampleRate and our time_sig_den*/
+                              /* -> bpms are always the amount of _quarter notes_ per minute */
+
+    int    root_key ;         /* MIDI note, or -1 for None */
+    int future [6] ;
+} SF_LOOP_INFO ;
+```
+
+### Examples
+
+```c
+SF_LOOP_INFO loop;
+sf_command (sndfile, SFC_GET_LOOP_INFO, &loop, sizeof (loop)) ;
+```
+
+### Return value
+
+`SF_TRUE` if the file header contains loop information for the file, `SF_FALSE`
+otherwise.
+
+## SFC_GET_INSTRUMENT
+
+Retrieve instrument information from file including MIDI base note, keyboard
+mapping and looping informations(start/stop and mode).
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_INSTRUMENT
+
+data
+: a pointer to an SF_INSTRUMENT struct
+
+datasize
+: sizeof (SF_INSTRUMENT)
+
+The `SF_INSTRUMENT` struct is defined in *sndfile.h* as:
+
+```c
+typedef struct
+{   int gain ;
+    char basenote, detune ;
+    char velocity_lo, velocity_hi ;
+    char key_lo, key_hi ;
+    int loop_count ;
+
+    struct
+    {   int mode ;
+        unsigned int start ;
+        unsigned int end ;
+        unsigned int count ;
+    } loops [16] ; /* make variable in a sensible way */
+} SF_INSTRUMENT ;
+```
+
+`mode` values are defined as:
+
+| Name                | Value | Description |
+|:--------------------|:------|:------------|
+| SF_LOOP_NONE        | 800   |             |
+| SF_LOOP_FORWARD     | 801   |             |
+| SF_LOOP_BACKWARD    | 802   |             |
+| SF_LOOP_ALTERNATING | 803   |             |
+
+### Examples
+
+```c
+SF_INSTRUMENT inst ;
+sf_command (sndfile, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) ;
+```
+
+### Return value
+
+`SF_TRUE` if the file header contains instrument information for the file,
+`SF_FALSE` otherwise.
+
+## SFC_SET_INSTRUMENT
+
+Set the instrument information for the file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_INSTRUMENT
+
+data
+: a pointer to an SF_INSTRUMENT struct
+
+datasize
+: sizeof (SF_INSTRUMENT)
+
+### Examples
+
+```c
+SF_INSTRUMENT inst ;
+sf_command (sndfile, SFC_SET_INSTRUMENT, &inst, sizeof (inst)) ;
+```
+
+### Return value
+
+`SF_TRUE` if the file header contains instrument information for the file,
+`SF_FALSE` otherwise.
+
+## SFC_GET_CUE_COUNT
+
+Retrieve the number of cue markers available for retrieval using the
+[SFC_GET_CUE](#sfc_get_cue) command.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_CUE_COUNT
+
+data
+: a pointer to a uint32_t
+
+datasize
+: sizeof (uint32_t)
+
+### Examples
+
+```c
+uint32_t cue_count ;
+sf_command (sndfile, SFC_GET_CUE_COUNT, &cue_count, sizeof (cue_count)) ;
+```
+
+### Return value
+
+`SF_TRUE` if the file header contains cue marker information for the file,
+`SF_FALSE` otherwise.
+
+## SFC_GET_CUE
+
+Retrieve cue marker information from file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_CUE
+
+data
+: a pointer to an SF_CUES struct
+
+datasize
+: sizeof (SF_CUES)
+
+The SF_CUES struct is defined in *sndfile.h* as:
+
+```c
+typedef struct
+{   int cue_count ;
+
+    struct
+    {   int32_t   indx ;
+        uint32_t  position ;
+        int32_t   fcc_chunk ;
+        int32_t   chunk_start ;
+        int32_t   block_start ;
+        uint32_t  sample_offset ;
+        char name [256] ;
+    } cue_points [100] ;
+} SF_CUES ;
+```
+
+There is also an SF_CUES_VAR \#define that allows reading/writing more than 100
+cue markers.
+
+### Examples
+
+```c
+SF_CUES cues ;
+sf_command (sndfile, SFC_GET_CUE, &cues, sizeof (cues)) ;
+```
+
+### Return value
+
+`SF_TRUE` if the file header contains cue marker information for the file,
+`SF_FALSE` otherwise.
+
+## SFC_SET_CUE
+
+Set the cue marker information for the file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_CUE
+
+data
+: a pointer to an SF_CUES struct
+
+datasize
+: sizeof (SF_CUES)
+
+### Examples
+
+```c
+SF_CUES cues ;
+sf_command (sndfile, SFC_SET_CUE, &cues, sizeof (cues)) ;
+```
+
+### Return value
+
+`SF_TRUE` if the file header contains cue marker information for the file,
+`SF_FALSE` otherwise.
+
+## SFC_RF64_AUTO_DOWNGRADE
+
+Enable auto downgrade from RF64 to WAV.
+
+The EBU recomendation is that when writing RF64 files and the resulting file is
+less than 4Gig in size, it should be downgraded to a WAV file (WAV files have a
+maximum size of 4Gig). libsndfile doesn't follow the EBU recommendations
+exactly, mainly because the test suite needs to be able test reading/writing
+RF64 files without having to generate files larger than 4 gigabytes.
+
+Note: This command should be issued before the first bit of audio data has been
+written to the file. Calling this command after audio data has been written will
+return the current value of this setting, but will not allow it to be changed.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_RF64_AUTO_DOWNGRADE
+
+data
+: NULL
+
+datasize
+: SF_TRUE or SF_FALSE
+
+### Examples
+
+```c
+/* Enable auto downgrade on file close. */
+sf_command (sndfile, SFC_RF64_AUTO_DOWNGRADE, NULL, SF_TRUE) ;
+```
+
+### Return value
+
+Returns `SF_TRUE` if `SFC_RF64_AUTO_DOWNGRADE` is set and `SF_FALSE` otherwise.
+
+## SFC_GET_ORIGINAL_SAMPLERATE
+
+Get original samplerate metadata.
+
+The Opus audio codec stores audio data independent of samplerate, but only
+supports encoding or decoding at 8000Hz, 12000Hz, 16000Hz, 24000Hz or 48000Hz.
+Opus includes a header field to record the original source input samplerate, and
+a samplerate converter may be used if needed.
+
+This command gets the original samplerate header field. It does not enable any
+(non-existent) samplerate conversion, nor change the current decoder samplerate.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_GET_ORIGINAL_SAMPLERATE
+
+data
+: pointer to an integer
+
+datasize
+: sizeof (int)
+
+### Examples
+
+```c
+/* Get the original sample rate */
+int original_samplerate ;
+sf_command (sndfile, SFC_GET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) ;
+```
+
+### Return value
+
+Returns `SF_TRUE` on success, `SF_FALSE` otherwise.
+
+The passed integer is set to the value of the original samplerate.
+
+## SFC_SET_ORIGINAL_SAMPLERATE
+
+Set original samplerate metadata.
+
+The Opus audio codec stores audio data independent of samplerate, but only
+supports encoding or decoding at 8000Hz, 12000Hz, 16000Hz, 24000Hz or 48000Hz.
+Opus includes a header field to record the original source input samplerate, and
+a samplerate converter may be used if needed.
+
+When writing an Opus file this command sets the original samplerate header field
+to the provided value, which is then stored in the file. This has no effect on
+the current encoder samplerate.
+
+When reading an Opus file this command overrides the original samplerate value
+as read from the file. libsndfile uses this value to choose what samplerate to
+decode at, rounding up to the nearest valid Opus samplerate. After a successful
+call, the file samplerate and frames count may have changed.
+
+Note: This command should be issued before the first bit of audio data has been
+read from or written to the file.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_ORIGINAL_SAMPLERATE
+
+data
+: pointer to an integer
+
+datasize
+: sizeof (int)
+
+### Examples
+
+```c
+/* Store the original sample rate as 44100 */
+int original_samplerate 44100;
+sf_command (sndfile, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (input_samplerate)) ;
+```
+
+### Return value
+
+Returns SF_TRUE on success, SF_FALSE otherwise.
+
+On write, can only succeed if no data has been written. On read, if successful,
+[SFC_GET_CURRENT_SF_INFO](#sfc_get_current_sf_info) should be called to
+determine the new frames count and samplerate
diff --git a/docs/development.md b/docs/development.md
new file mode 100644 (file)
index 0000000..c5b39de
--- /dev/null
@@ -0,0 +1,18 @@
+---
+layout: page
+---
+
+# libsndfile Development
+
+libsndfile is being developed by a small community of users and hackers. People
+interested in helping can raise an issue on Github.
+
+The main repository can be found on Github:
+
+<http://libsndfile.github.io/libsndfile/">
+
+and includes [instuctions](https://github.com/libsndfile/libsndfile/blob/master/README.md)
+on how to build libsndfile from the Git repo.
+
+If you are interested in how to add a new format to a libsndfile, you may find
+this [FAQ](new_file_type_howto.md) helpful.
diff --git a/docs/donate.md b/docs/donate.md
new file mode 100644 (file)
index 0000000..dd10769
--- /dev/null
@@ -0,0 +1,60 @@
+---
+layout: page
+title: libsndfile : donate.
+---
+
+{% include logo.html %}
+
+Dear libsndfile user,
+
+This library was developed on Linux for Linux. I am not a Windows user and
+maintaining this library for Windows costs me significant amounts of time above
+and beyond the time taken to make it work on Linux and Unix-like systems.
+
+I therefore ask Windows users of libsndfile to donate to ensure that
+libsndfile's support for Windows continues. As long as donations continue to
+flow in at a decentrate, I will continue to release precompiled Windows binaries
+in sync with the Linux/Unix version. If donations are poor, support for windows
+will fall behind.
+
+You are free to donate any amount you chose. As a guideline:
+
+* If you are simply a user of libsndfile that would like to ensure that the
+  development of libsndfile continues, a donation of $10US would be more than
+  adequate.
+* If you are shareware author that distributes libsndfile with your app and
+  makes more than $1000 a year from your shareware, a one off donation of $50
+  would be appropriate.
+* If your company is a commercial software house that distributes one or more
+  products that ship with libsndfile, a donation of $100 every second or third
+  year would be appropriate.
+
+Donations can be made in Bitcoin to the Bitcoin address
+**15hVWemFiH6DLJ22SBYPk9b4fgWtxBEvfQ** which can be verified by checking the
+following GPG signature.
+
+    -----BEGIN PGP SIGNED MESSAGE-----
+    Hash: SHA256
+
+    libsndfile Bitcoin address : 15hVWemFiH6DLJ22SBYPk9b4fgWtxBEvfQ
+    -----BEGIN PGP SIGNATURE-----
+    Version: GnuPG v1.4.12 (GNU/Linux)
+
+    iQIcBAEBCAAGBQJSK7MUAAoJEEXYQ7zIiotIgXEP/R8hy65tlV7TiPw9bY9BklXS
+    /Vl8FU2RhDkBt61ZmxbfDTybyQ5Vce/3wWph15L4RvpoX1OyeintQFmwwuPjOGiq
+    eIz0nT9vDorG37Xdo5NZNBu9Tp1Od9MNtxFaAsRWFrDfvKEKljBHrcfM972cYrAp
+    DaFd0Ik+bHKom9iQXFB7TFd0w2V4uszVMQDUGqb/vRNeRURZS7ypeMNwc8tZyTKR
+    waEGMTa5sxxRjs7MqGRxSovnFT7JV3TNfdkBInUliIR/XvrudFR9J4Fiv+8Dk9P8
+    WNjm6uFxvgIqiu1G9bjrwwr+DsBju93ljGNcZoayAKw5vwbX6KTcCbc31k9dP8Hf
+    p6YdmPlZVKZmva+P3nLSJBTlxNu24Jm+ha+ZM/svDXTaPFWC8l5FP17kK0Bj8wCq
+    N7pDz6RchEn10u+HdhfT1XiUjxj0zNXrr0GGj9apjl0RlT0O49eBttV0oXIdBRLi
+    nTEaOWITpCgu7ggw1kWXHIWEncuiaSuJy/iH8PgNepWVj/6PxQRMrTqG4ux2Snk8
+    Ua4vO8YHLMZX/XvSUS7eMtgfM7AO6YjJ/ac9bQif9bh6LsYEVVklysMUin6ZRS7Z
+    Cms23FnqeQKtJOzdvqSJiV06lK6fP+tYdM4WSYn+AfL4IfYl2v48xXVU8XOOK9BH
+    bJPKMDcz1ZvfYtX5mSW1
+    =WXGB
+    -----END PGP SIGNATURE-----
+
+Thanks and regards,  
+Erik de Castro Lopo  
+Main libsndfile author and maintainer
diff --git a/docs/embedded_files.md b/docs/embedded_files.md
new file mode 100644 (file)
index 0000000..e55f2ed
--- /dev/null
@@ -0,0 +1,21 @@
+---
+layout: page
+---
+
+# Embedded Sound Files
+
+By using the open SNDFILE with a file descriptor function:
+
+    SNDFILE*  sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
+
+it is possible to open sound files embedded within larger files. There are
+however a couple of caveats:
+
+* Read/Write mode (SFM_RDWR) is not supported.
+* Writing of embedded files is only supported at the end of the file.
+* Reading of embedded files is only supported at file offsets greater than zero.
+* Not all file formats are supported (currently only WAV, AIFF and AU).
+
+The test program **multi_file_test.c** in the **tests/** directory of the source
+code tarball shows how this functionality is used to read and write embedded
+files.
diff --git a/docs/formats.md b/docs/formats.md
new file mode 100644 (file)
index 0000000..13bab52
--- /dev/null
@@ -0,0 +1,52 @@
+---
+layout: page
+title: libsndfile: Supported formats
+---
+
+# libsndfile : Supported formats
+
+The following table lists the file formats and encodings that libsndfile can
+read and write. The file formats are arranged across the top and encodings along
+the left edge.
+
+{:.formats-table}
+|                    | Microsoft WAV | SGI / Apple AIFF / AIFC |Sun / DEC / NeXT AU / SND | Headerless RAW | Paris Audio File PAF | Commodore Amiga IFF / SVX | Sphere Nist WAV | IRCAM SF | Creative VOC | Soundforge W64 | GNU Octave 2.0 MAT4 | GNU Octave 2.1 MAT5 | Portable Voice Format PVF | Fasttracker 2 XI | HMM Tool Kit HTK | Apple CAF | Sound Designer II SD2 | Free Lossless Audio Codec FLAC |
+|:-------------------|:-------------:|:-----------------------:|:------------------------:|:--------------:|:--------------------:|:-------------------------:|:---------------:|:--------:|:------------:|:--------------:|:-------------------:|:-------------------:|:-------------------------:|:----------------:|:----------------:|:---------:|:---------------------:|:------------------------------:|
+| Unsigned 8 bit PCM | R/W           | R/W                     |                          | R/W            |                      |                           |                 |          | R/W          | R/W            |                     | R/W                 |                           |                  |                  |           |                       |                                |
+| Signed 8 bit PCM   |               | R/W                     | R/W                      | R/W            | R/W                  | R/W                       | R/W             |          |              |                |                     |                     | R/W                       |                  |                  | R/W       | R/W                   | R/W                            |
+| Signed 16 bit PCM  | R/W           | R/W                     | R/W                      | R/W            | R/W                  | R/W                       | R/W             | R/W      | R/W          | R/W            | R/W                 | R/W                 | R/W                       |                  | R/W              | R/W       | R/W                   | R/W                            |
+| Signed 24 bit PCM  | R/W           | R/W                     | R/W                      | R/W            | R/W                  |                           | R/W             |          |              | R/W            |                     |                     |                           |                  |                  | R/W       | R/W                   | R/W                            |
+| Signed 32 bit PCM  | R/W           | R/W                     | R/W                      | R/W            |                      |                           | R/W             | R/W      |              | R/W            | R/W                 | R/W                 | R/W                       |                  |                  | R/W       |                       |                                |
+| 32 bit float       | R/W           | R/W                     | R/W                      | R/W            |                      |                           |                 | R/W      |              | R/W            | R/W                 | R/W                 |                           |                  |                  | R/W       |                       |                                |
+| 64 bit double      | R/W           | R/W                     | R/W                      | R/W            |                      |                           |                 |          |              | R/W            | R/W                 | R/W                 |                           |                  |                  | R/W       |                       |                                |
+| u-law encoding     | R/W           | R/W                     | R/W                      | R/W            |                      |                           | R/W             | R/W      | R/W          | R/W            |                     |                     |                           |                  |                  | R/W       |                       |                                |
+| A-law encoding     | R/W           | R/W                     | R/W                      | R/W            |                      |                           | R/W             | R/W      | R/W          | R/W            |                     |                     |                           |                  |                  | R/W       |                       |                                |
+| IMA ADPCM          | R/W           |                         |                          |                |                      |                           |                 |          |              | R/W            |                     |                     |                           |                  |                  |           |                       |                                |
+| MS ADPCM           | R/W           |                         |                          |                |                      |                           |                 |          |              | R/W            |                     |                     |                           |                  |                  |           |                       |                                |
+| GSM 6.10           | R/W           | R/W                     |                          | R/W            |                      |                           |                 |          |              | R/W            |                     |                     |                           |                  |                  |           |                       |                                |
+| G721 ADPCM 32kbps  | R/W           |                         | R/W                      |                |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| G723 ADPCM 24kbps  |               |                         | R/W                      |                |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| G723 ADPCM 40kbps  |               |                         | R/W                      |                |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| 12 bit DWVW        |               | R/W                     |                          | R/W            |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| 16 bit DWVW        |               | R/W                     |                          | R/W            |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| 24 bit DWVW        |               | R/W                     |                          | R/W            |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| Ok Dialogic ADPCM  |               |                         |                          | R/W            |                      |                           |                 |          |              |                |                     |                     |                           |                  |                  |           |                       |                                |
+| 8 bit DPCM         |               |                         |                          |                |                      |                           |                 |          |              |                |                     |                     |                           | R/W              |                  |           |                       |                                |
+| 16 bit DPCM        |               |                         |                          |                |                      |                           |                 |          |              |                |                     |                     |                           | R/W              |                  |           |                       |                                |
+
+From version 1.0.18, libsndfile also reads and writes
+[FLAC](https://xiph.org/flac/) and [Ogg/Vorbis](https://xiph.org/vorbis/).
+
+From version 1.0.29, libsndfile can read and write
+[Ogg/Opus](https://opus-codec.org/).
+
+Some of the file formats I am also interested in adding are:
+
+- Kurzweil K2000 sampler files.
+- Ogg Speex.
+- MPEG Layer 3 (commonly known as MP3)
+
+Other file formats may also be added on request.
+
+If you are interested in how to add a new format to a libsndfile, you may find
+this [FAQ](new_file_type_howto.md) helpful.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644 (file)
index 0000000..3779fdf
--- /dev/null
@@ -0,0 +1,316 @@
+---
+layout: home
+title: The libsndfile Home Page
+---
+
+Libsndfile is a C library for reading and writing files containing sampled sound
+(such as MS Windows WAV and the Apple/SGI AIFF format) through one standard
+library interface. It is released in source code format under the
+[Gnu Lesser General Public License](http://www.gnu.org/copyleft/lesser.html).
+
+The library was written to compile and run on a Linux system but should compile
+and run on just about any Unix (including MacOS X).
+There are also pre-compiled binaries available for 32 and 64 bit windows.
+
+It was designed to handle both little-endian (such as WAV) and big-endian (such
+as AIFF) data, and to compile and run correctly on little-endian (such as Intel
+and DEC/Compaq Alpha) processor systems as well as big-endian processor systems
+such as Motorola 68k, Power PC, MIPS and Sparc. Hopefully the design of the
+library will also make it easy to extend for reading and writing new sound file
+formats.
+
+It has been compiled and tested (at one time or another) on the following
+systems:
+
+* Every platform supported by Debian GNU/Linux including x86_64-linux-gnu,
+  i486-linux-gnu, powerpc-linux-gnu, sparc-linux-gnu, alpha-linux-gnu,
+  mips-linux-gnu and armel-linux-gnu.
+* powerpc-apple-darwin7.0 (Mac OS X 10.3)
+* sparc-sun-solaris2.8 (using gcc)
+* mips-sgi-irix5.3 (using gcc)
+* QNX 6.0
+* i386-unknown-openbsd2.9
+* Microsoft Windows
+
+At the moment, each new release is being tested on i386 Linux, x86_64 Linux,
+PowerPC Linux, Win32 and Win64.
+
+## Features
+
+libsndfile has the following main features :
+
+* Ability to read and write a large number of [file formats](formats.html).
+* A simple, elegant and easy to use Applications Programming Interface.
+* Usable on Unix, Win32, MacOS and others.
+* On the fly format conversion, including endian-ness swapping, type conversion
+  and bitwidth scaling.
+* Optional normalisation when reading floating point data from files containing
+  integer data.
+* Ability to open files in read/write mode.
+* The ability to write the file header without closing the file (only on files
+  open for write or read/write).
+* Ability to query the library about all supported formats and retrieve text
+  strings describing each format.
+
+libsndfile has a comprehensive test suite so that each release is as bug free
+as possible.
+When new bugs are found, new tests are added to the test suite to ensure that
+these bugs don't creep back into the code.
+When new features are added, tests are added to the test suite to make sure that
+these features continue to work correctly even when they are old features.
+
+## History
+
+My first attempt at reading and writing WAV files was in 1990 or so under
+Windows 3.1. I started using Linux in early 1995 and contributed some code to
+the [wavplay](http://www.vaxxine.com/ve3wwg/gnuwave.html) program. That
+contributed code would eventually mutate into this library. As one of my
+interests is Digital Signal Processing (DSP) I decided that as well as reading
+data from an audio file in the native format (typically 16 bit short integers)
+it would also be useful to be able to have the library do the conversion to
+floating point numbers for DSP applications. It then dawned on me that whatever
+file format (anything from 8 bit unsigned chars, to 32 bit floating point
+numbers) the library should be able to convert the data to whatever format the
+library user wishes to use it in. For example, in a sound playback program, the
+library caller typically wants the sound data in 16 bit short integers to dump
+into a sound card even though the data in the file may be 32 bit floating point
+numbers (ie Microsoft's WAVE_FORMAT_IEEE_FLOAT format). Another example would be
+someone doing speech recognition research who has recorded some speech as a 16
+bit WAV file but wants to process it as double precision floating point numbers.
+
+Here is the release history for libsndfile:
+
+* Version 0.0.8 (Feb 15 1999) First official release.
+* Version 0.0.28 (Apr 26 2002) Final release of version 0 of libsndfile.
+* Version 1.0.0rc1 (Jun 24 2002) Release candidate 1 of version 1 of libsndfile.
+* Version 1.0.0rc6 (Aug 14 2002) MacOS 9 fixes.
+* Version 1.0.0 (Aug 16 2002) First 1.0.X release.
+* Version 1.0.1 (Sep 14 2002) Added MAT4 and MAT5 file formats.
+* Version 1.0.2 (Nov 24 2002) Added VOX ADPCM format.
+* Version 1.0.3 (Dec 09 2002) Fixes for Linux on ia64 CPUs.
+* Version 1.0.4 (Feb 02 2003) New file formats and functionality.
+* Version 1.0.5 (May 03 2003) One new file format and new functionality.
+* Version 1.0.6 (Feb 08 2004) Large file fix for Linux/Solaris, new
+  functionality   and Win32 improvements.
+* Version 1.0.7 (Feb 24 2004) Fix build problems on MacOS X and fix ia64/MIPS
+  etc clip mode detction.
+* Version 1.0.8 (Mar 14 2004) Minor bug fixes.
+* Version 1.0.9 (Mar 30 2004) Add AVR format. Improve handling of some WAV
+  files.
+* Version 1.0.10 (Jun 15 2004) Minor bug fixes. Fix support for Win32 MinGW
+  compiler.
+* Version 1.0.11 (Nov 15 2004) Add SD2 file support, reading of loop data in WAV
+  and AIFF. Minor bug fixes.
+* Version 1.0.12 (Sep 30 2005) Add FLAC and CAF file support, virtual I/O
+  interface. Minor bug fixes and cleanups.
+* Version 1.0.13 (Jan 21 2006) Add read/write of instrument chunks. Minor bug
+  fixes.
+* Version 1.0.14 (Feb 19 2006) Minor bug fixes. Start shipping windows
+  binary/source ZIP.
+* Version 1.0.15 (Mar 16 2006) Minor bug fixes.
+* Version 1.0.16 (Apr 30 2006) Add support for RIFX. Other minor feature
+  enhancements and bug fixes.
+* Version 1.0.17 (Aug 31 2006) Add C++ wrapper sndfile.hh. Minor bug fixes and
+  cleanups.
+* Version 1.0.18 (Feb 07 2009) Add Ogg/Vorbis suppport, remove captive
+  libraries, many new features and bug fixes. Generate Win32 and Win64
+  pre-compiled binaries.
+* Version 1.0.19 (Mar 02 2009) Fix for CVE-2009-0186. Huge number of minor fixes
+  as a result of static analysis.
+* Version 1.0.20 (May 14 2009) Fix for potential heap overflow.
+* Version 1.0.21 (December 13 2009) Bunch of minor bug fixes.
+* Version 1.0.22 (October 04 2010) Bunch of minor bug fixes.
+* Version 1.0.23 (October 10 2010) Minor bug fixes.
+* Version 1.0.24 (March 23 2011) Minor bug fixes.
+* Version 1.0.25 (July 13 2011) Fix for Secunia Advisory SA45125. Minor bug
+  fixes and improvements.
+* Version 1.0.26 (November 22 2015) Fix for CVE-2014-9496, CVE-2014-9756 and
+  CVE-2015-7805. Add ALAC/CAF support. Minor bug fixes and improvements.
+* Version 1.0.27 (June 19 2016) Fix a seek regression in 1.0.26. Add metadata
+  read/write for CAF and RF64. FIx PAF endian-ness issue.
+* Version 1.0.28 (April 2 2017) Fix buffer overruns in FLAC and ID3 handling
+  code. Reduce default header memory requirements. Fix detection of Large File
+  Support for 32 bit systems.
+* Version 1.0.29 (August 15 2020) Opus support, build system improvements and
+  bug fixes.
+* Version 1.0.30 (September 19 2020) Bugfix release. Fix file descriptor leaks
+  in sf_open_fd () function. Fix critical CMake bug leading to broken ABI on
+  Linux platforms. Other numerous fixes to CMake build system, consider it
+  stable now. Fix some memory leaks. Fix handling of some SD2 files. Update
+  documentation. Integrate GitHub Actions for faster test builds and Oss-Fuzz
+  for fuzzing tests. Move sndfile.h.in from src/ to include/ directory. To avoid
+  problems, delete old generated sndfile.h from $(top_builddir)/src.
+* Version 1.0.31 (January 24 2021) Bugfix release. Fix multiple memory leaks
+  reported by OSS-Fuzz. More SSE2-optimized functions for x86 and amd64.
+
+## Similar or Related Projects
+
+* [SoX](http://sox.sourceforge.net/) is a program for converting between sound
+  file formats.
+* [Wavplay](http://www.hitsquad.com/smm/programs/WavPlay/) started out as a
+  minimal WAV file player under Linux and has mutated into Gnuwave, a
+  client/server application for more general multimedia and games sound
+  playback.
+* [Audiofile](http://www.68k.org/~michael/audiofile/) (libaudiofile) is a
+  library similar to libsndfile but with a different programming interface. The
+  author Michael Pruett has set out to clone (and fix some bugs in) the
+  libaudiofile library which ships with SGI's IRIX OS.
+* [sndlib.tar.gz](ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz) is
+  another library written by Bill Schottstaedt of CCRMA.
+
+## Licensing
+
+libsndfile is released under the terms of the GNU Lesser General Public License,
+of which there are two versions;
+[version 2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)
+and
+[version 3](http://www.gnu.org/copyleft/lesser.html).
+To maximise the compatibility of libsndfile, the user may choose to use
+libsndfile under either of the above two licenses.
+You can also read a simple explanation of the ideas behind the GPL and the LGPL
+[here](http://www.gnu.org/copyleft/lesser.html).
+
+You can use libsndfile with
+[Free Software](http://www.gnu.org/),
+[Open Source](http://www.opensource.org/),
+proprietary, shareware or other closed source applications as long as libsndfile
+is used as a dynamically loaded library and you abide by a small number of other
+conditions (read the LGPL for more info).
+With applications released under the GNU GPL you can also use libsndfile
+statically linked to your application.
+
+I would like to see libsndfile used as widely as possible but I would prefer it
+if you released software that uses libsndfile as
+[Free Software](http://www.gnu.org/)
+or
+[Open Source](http://www.opensource.org/).
+However, if you put in a great deal of effort building a significant application
+which simply uses libsndfile for file I/O, then I have no problem with you
+releasing that as closed source and charging as much money as you want for it as
+long as you abide by [the license](http://www.gnu.org/copyleft/lesser.html).
+
+## Download
+
+Check latest version on
+[GitHub Releases page](https://github.com/libsndfile/libsndfile/releases/).
+
+Binatries and source packages are signed by current releaser David Seifert aka
+@SoapGentoo. You can verify signatures with his public GPG key:
+
+```
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQINBFppABgBEAC42ZiNvV7BTIgR6TQy0YnF54fx3mVRP1u8Mq00UZa7reAsNKh7
+1H60j0W4s6+4pVVIKGfpVGxLwUdJe+KVCYw1Cd3YW6uMf5zZrC/ZWqnJiH/n6S6o
+1l4INII2o6YbGBnzIWBPRo7PlOL+mvgKTLpBSJPnhD8XDGN5wRiV8rL2+6Dptg0F
+nJt7oxECGF3OD3gk6HMel0o82CVkIqMtNaX1L/bhcdF7K0Rp2MXPZMmpn1izW5sI
+asN1G9+w+Zwj7kMJzq1Aw3ac+rsX4SEYdvXjS2QhDHQUIr6LXri3D2WbcEqIZj2R
+JVoVwblsrG11dYXFDBbgrq4NhgTBsxHYDlkr/qF2W+kbPC/nhSqTVZeCYvTBZbOQ
++RqyN/I0izukglnWmV1jGijFA8snyP8efx732hw/24zRYmtXOtnEITUpw8WOeZCq
+6uiHaQ+eopnY2ojBg9BI7WZm0AFn58xxT9soMsyFOUFgXTqaWFZWlJ3fhZE8/0v8
+JEu/kPGE5aJReT3b34B+Bojkj74XR+h2u7iJJBHMTE8RwGoUOZHer/XsL9xlcdks
+I+7TCjiq++ShaSSt2XsJmw2BhREohrjW/2KkwmvT3b44RMpKPB4WTH+++aqJQNeM
+IqmswOMoZvzEZezInj7WVY/r0WEei1Y6wt1tBrJ/cFf1oQBM1UmphxcrfQARAQAB
+tB9EYXZpZCBTZWlmZXJ0IDxzb2FwQGdlbnRvby5vcmc+iQJUBBMBCgA+BQsJCAcD
+BRUKCQgLBRYCAwEAAh4BAheAAhsBFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/V
+CvoFCQkuceIACgkQpHYg6AHkfpXYxA//aiJW1NwunpmzEc62id8lRMnoLHWVjISZ
+b+xSlm+hk4LYq+ZbthJDzKcT86/3DJOSE1zQw9wLuCao9IW2UfFJQBtR+TAfbagG
+0Yyk/kMcLoFJxnG1ywdJWypCAauuIhia52Z7PmmjsBbFwr6LygDwSQmZAyACMAs7
+TLQe+yERc2RNDsIEsquLSxxRF0Spk9gagWtKgrPc2XBjuNtQDwW7JgsOUoEeHyxC
+29fRUjC3o/pG2I6iAZp17OROZI5yl4TSORrSBDGIi2sayxyxP0x+IPKtrCUcBGNx
+wGp+56bP/V0hA6sgCPh/iwvqLoeibso6l/Kd4ltVAEQnHTd6fr8g+wLEUXfbJVTR
+7aeFUoaFmWjSPlQrNr6HlxSLV/kRx9kVJp1Pn16vkfVBF7fG7iDLiqphwEeQg5ND
+nmGeKAbRRNxFHyBHf0XRsaYiFZQckguO+71XSRtVx8/YP5nyNbtl9y1h/4JlT6Gy
+t7hb5twYFQyQrKss83E/Bo1sRdHpj0ibtqb4ZbYANbh482E6yFhAkuo8YjVTJipI
+1Ve8EBKnX3R+pDt147uyysNvtPVXML+sWpGSMVSm4NA8uT3F5nqxVwj+SeXy3Wq/
+CHQ2VBKGBC655G+wFD5C6O7cTx2MwH+2H8tzhWm+gFlI3MFKEXa/PC+YUC/diYcb
+BrApavriTRa5Ag0EWmkAZgEQAPXMD3mZI+ChvBysXZWksC88/uSEwFeb3XkcRm7v
+04GN7hcz+bfrmnUTB3tuE/ZQgv+u7ZjetvH1aEKieznn/GjnWoOBoJusOYvfAQeF
+0mQVi118QiOZRCnEZpkz+RY9TiXVgrZJg+AGqHZ3Ol4GkInEV2NWgH37Xal+HkFl
+rwI2U7mL0kZRG+LAVCQHKzqU0R0HE1XyJ4qf0awtG5Qi/TZvgXBdZPDXgr8i9Vlf
+UUu10c2XnXM0Av/YAlZmBFjVYrSOUCFenqSVqL+s9sTCVdWlJrGjrr3Ja4uT3kl2
+rLva0AR4oSQoxt8adKohmFz0vzOkQtCoRzhrCwoo3JvNjKdSNoOP1nSsxlO5ji8r
+ih5d+ajPgi580XyHLnrvG7vobR48qqscv1hizKuCgTacOTe6Db2Gqc8xF6v8HhJa
+KwWJtmFllIfN/tIvZ6BbbgHQn0IGf4CYnWf0SksPZqpBmTRpD2jfBxcj2UEg+AR3
+LARjuyUVpFJScyu6ExQG+6O+ByLL31iWP5MgUrza1rIpriPa3NT3rZ3DG2pvQrS3
+ySsrPzH7VRX8L1ThSMSzjwF96aMsd14s7XzR4EzNuWwZDukfs0yavZk6l4o1M0mb
+tbJi7hE4cz13KRHYvIkKMdZGYUnzRzZUDlsj2imakk3BR6GXnxZ1ST6062g+QxiL
+AJFLABEBAAGJBHIEGAEKACYCGwIWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9UL
+DQUJCS5xpwJAwXQgBBkBCgAdFiEEuNUxXaAAcsCoYIifzjbhFyAuOEIFAlppAGYA
+CgkQzjbhFyAuOELmrQ/9H9wrWsWa21STZdxUmyU2sh9VXAWEHl1Ey0fVTznDM0Fl
+zx5YSR/TmmnE36rpaz31Ttkx8SP914oV+mMgseecdya9Bf6uZL9Cv7V3KEsJBRL/
+ncrOWQBHP/Xy1X+mLD6A19xq7H4RihSLj0LeK2YVjrJzJ7wMf4mKXuBayQeAHImU
+WRCRTbmK3umh2nB5V0iPd/XZEIiYtiTPe+7E/va6+0bBvOumF3a+Z0iui7eU4hFC
+7Jk71D0dcg09SlIaNoMOrw7cMC3j2pMdKtsj8+0I6WBv14PhhqPAsnjdf7I/4NfK
+L7Jav8T/gDS01uA2Jxm72d+wr+eSjOBXa6x8CEbTqfkjAGxsWENThCp6zDkaXSDd
+JsV0va47vjzG8+wTDAvPy5IxIM/KZZdl4uWM+mF5K+q+eSTOHe7aLF2OdcussoBA
+A18zm994dAkG1COX/qpxanxx2bv/2IvCGPg+x6JtAN8ji2kncWu3dWGQdE5XbVjc
+fDwgsUPpp04G27Mr/x+HpEbgZ5SdA0dAqJktlNvCcHALhlblCWrsh/1QNjT/2iG8
+wsjcpEy/s4tWAuV4PTa4xvZ1JPS7Z7Eo5aBy9ZGOWG9SrHEiHnhkUsiswbHBOEjd
+pBSkmNElDcv9fRUahVCTPfvWBATFDrQyMjJBSm+cV8c/iFQM7isVSu8W7E0eetsJ
+EKR2IOgB5H6Vv9sP/1dxTvH0N0UoEoxIG/hnirEkbRpljdvqy4/uikYBKyQgSbo8
+VITTjea7gIhDztil9WZYt35jbOmoaGM2Z6TP2LEDOWgljYUNq9pl9Sc2GS8cNtEO
+WxExzGOc1Flo730dX3A85Ks3+0WPXZjLDcRRcPVkFd5WLQQDV1YVYopWkuQBC+Br
+4q3uv+sk+bw6gDa9+zFBbDuegdsYuTXrFHoxHz2GRv9Yb7ULCMgpFeNKDgtQq91u
+RqewoTwQp9tlp91LH/hh7R0Q4DRgeFDkLnVRXwSKjVvCrT5cBgImGwtFTGS4egoy
+MDKd/KKjZllp1ahRCln1XfmFQyQVMVvuF/JTtt31n6KwXwK2yxIlXB01xvRH+Ees
+AWeRYWKWXydaAY/9Ve0/PLFlgsr/XUGvt0GoEKe7odD3nZgg6015+/8JTroKw19L
+NZkhdfFMl11Zi0j5k3UbyzjYVpFSd8K2o0VoOG1LFsPp8tlRxNoVzpId0CX1au/p
+y1H7Wy/39mzriRG3rw+mJAQbBjN09putCltXFXpOEWk08n/N3vufCVQUoSu/2Bqw
+2HYj8VtToQp+O5dG3XxvDHINtInP1yr2Wcw2plna0KoXLwv/lZgDm3LN+eCWpG6d
+N/xk25DTSqTHArUQIEkhcHYK6GnyxUcvoKtG88hXtqEPYXiK08FZYAUPTnDYuQIN
+BFppAIkBEADDjvQZUs1NoqJpxkD2QDBudU1DBCaeI1D6CancMtb5FebPUxgFlDMd
+CBGOun48dY5i87gDhT/qS3gP/Mv9rjKJmcG9JHfhpXdW73owxrcsQ96nxxVJNEVl
+UHJw00z8C9eGWqr0SzSoE33K/PkzSkgtsaotF6+3uCerWulweulmGa5dpVfV0mbS
+aVw8VmrhZ5NmCeodyy/lR85rPik5pb32NT6v7xBkgkfS0VYtPB2E5gW1pXX/jEOi
+Mfq9idOEP9lxrNXV9j49Lr0JQCwAcrYbQ2+VPe6eacJEjzJ/6HiUqhPrYdnvydmb
+hU+xmv2NjGp2UnDZDEhzQfwm6fMx+8Nx2uPzCnXQGoyRBwiC/KcdW0F1ZPKdSXqH
+NKoOF62pLvIMSmfI3ZVOrTohArfr1kFEYVDv9Nl7oY+qg2rZEc2srOF74a9Z46bR
+TDPsEQzE2UMCvu3+rofhSD7aRotlKeDCvbe2s0yE4Man457Xc3LXh8Gva8CzCOLE
+2eMhNTsHIZk68WgXp3/uvE4Xy42myrk1AV8XXDdlWgx0Kc/I6tE59O5NVPSfuGvH
+1a15KKx0F6euEnYDKKpQ5PDR6dSn61po0tfbt96m044G/xQFjrfhHei4jji9Ogd9
+vlXVAi2vn3+NCSHFP5l3igLByBHy9iLIdmz7yQuus/1nwRmxOHOf2QARAQABiQI8
+BBgBCgAmAhsMFiEEMdlcq22A0mIkShdQpHYg6AHkfpUFAl/VCxkFCQkucZAACgkQ
+pHYg6AHkfpVPSRAAmheYkYJmtDbkzPBBnj5mbCIQN1/G5PI9eixc/TXWFOXtcjU1
+mJlJpSidHJyLRrx7r0c+N+s8vnY/JuUBsNoMJMER+Mv/CFW4iFi59V534SyAb2S0
+7NINJnFNkXBY62CDz9KsMuv/MdSv2yLhPH2Tfrm/eDRQesj1PanE4U1cgjWyJRc/
+IOlaRHvTasWDLgwbQi8ykt+4xUWzL/YKHzB+KyyzBK7vPBXqySX8ka4BOw7SDwG5
+lX2gtmhk4AGBwVChLXKflqVx1WXj4DPOt0kmOKVnKFyvUijK58M0A2FMgFMXDTIS
+DRtoZPdx/rkODXxgS+W+27NcYAnxJiM0cQqizEnQh7PQ1KzgdChPejYXMKe9lwdn
+ssMUxrBpbuAuagEf+pebNjD2eaNR4p8kfaDdGn53q55ysDvoyxKvnVQGSk1FAR9Q
+s4N5a4f02U7dzlyEhEfIcuUlRCfnlpn4n725YIhHheDig5zKWoEZCkNIfiRcGzDl
+8Drj+tlZiUR+gDkIoWSBaCkKbIQlc8qCYy6Hm7oZBaol6xKlUnTMK2rjK8fR4i8r
+bVDWBAaWj3jcDHJ0Jg3fS/qBpeya/JXMp89TR8NK5Ys7PZpWbor+puXBYyXDAVx3
+rXQ7JBA5klHPxrgjso1S/LqwscKLENtrVjdjhryLBmPifrmofJRnrpiHIEa5Ag0E
+WmkAswEQAL0hKwsRybQzkNGpJP+ElLSwFHd7XQhr+qIwLllpumWtnIK/DHmv8SpW
+FqAYajmRTXipFcBHH25x2jIIliZidn0a9826l+sMzrFadMC6/W4pitP71TeqZzwn
+pAuHs14YL7Wiy0aJQnfbCpRzPq3kYyOXmhmY7lPWO0WdUpR6W8wUbleK5XOVDDRx
+aIC/M3hhDOxZOMzQ+pdn4BaOFQQ0ygsRkqOudbuc0R1giYRt1i6gMeT8gfzL9jlw
+HcJ+aVnxdUQQ4uC47oKo/+lg7qh7LsiW79pQC1Bcdm8lhRmqtxe6ub60ecjax3XU
+1ILIEfIFCv6M7LRUAwz0bqk35spgkJqrGGKkdeWEKAFHg2QWR2F0zy+HdlPLfKxO
+uhaccpwc9EJtf744GS0SXa2AXr32j56n7CFcEjFcIQPBC6OJn6eA3hOVUYGZ7SrT
+4fsmZiFAdGEkvLKFuNhju1Hj2EJQUY1pm4GSBco7BR8x+QqoYrt5clU3WxRMNfTR
+0Rtuzsh4xskXNVMMgvKOahAtxENv2M2Cx6zJPVL5dmaysP7d6QRVeOQA5PwkcZ5Q
+qK6JtDZj2jpaKQH4Za715kiIcdqMDSkwxa6avc0kARHvfFcBR4hwDm1GAlaKG7eH
+8TOGGQIk8x2F3s4l8mTJVLWTP/uJYnkYBdqANYo5t1NIQLvwLFV3ABEBAAGJAjwE
+GAEKACYCGyAWIQQx2VyrbYDSYiRKF1CkdiDoAeR+lQUCX9ULIwUJCS5xcAAKCRCk
+diDoAeR+leekD/sF7aHH0W35ckWrXZlfSp0qHPWrBUaLBI9OAUHenRhgs4SbK0D4
+wqEiu0C5iDQojpXAeALQ8g/1pUsZ1yuFqYbGYWrHkA0Pm+P3tAGB4LMZ41YfvROP
+uaiW/+IMJbWllgRtaDt8/NtCgs30WI9I+az5M29HcGfvEwEUykrBx3dE9T+1ui3O
+capdd+GMvdAAsX5PyVkjWgZ7GrZeH8mG7UysYfT4qthxEtQfZ/u8ceSduKA46ugh
+C2eafIDNvluqn7BU4oKxME61u6C8BN2yHLI6LV0Tr4z5H8joVbM4BSFMwLVGlsXf
+HhB8kLiErN6bXolxsjARlmYiD9S9H2AcYidr6RYXf2EVFSpBG59xn1WTDN+DsHQf
+7btNPEPl/OPxa3OQjG+xn8USddiP0N0B4xsyzMNCCKDgvXXcIhX55KG9eh3Tc98S
+fEyhxu8ybZBIGmTJysPKxijfvSgQF+RPNTsz9lvXqkoK7RTgeYMschpjJEznCLbt
+M6eTDb5z0G5uLXh6+dYxtDOlPogI5OHd+G51LwCjvrQ+AtIUCgafuemwA9mpFT2b
+svb/qcxSVUb44bVaNHn1JHebX2YbokGtBOm1x2PI5fT8n6YIIYz3jKYOZAYdUT7x
+6qURyNjOfG4aPJIATwuh4GSNuxUG40+yuT+XfQF24mu1esS1J3wzRloJ7w==
+=K3x+
+-----END PGP PUBLIC KEY BLOCK-----
+```
+
+## See Also
+
+* [sndfile-tools](https://github.com/libsndfile/sndfile-tools): a small
+collection of programs which use libsndfile.
similarity index 63%
rename from doc/libsndfile.css.in
rename to docs/libsndfile.css
index 40fca0f..3386bc3 100644 (file)
@@ -1,13 +1,15 @@
 body {
-       background : @HTML_BGCOLOUR@ ;
-       color : @HTML_FGCOLOUR@ ;
+       background : black ;
+       color : white ;
        font-family : arial, helvetica, sans-serif ;
        line-height: 1.5 ;
+       margin-left: 6%;
+       margin-right: 6%;
 }
 td {
        font-family : arial, helvetica, sans-serif ;
-       background : @HTML_BGCOLOUR@ ;
-       color : @HTML_FGCOLOUR@ ;
+       background : black ;
+       color : white ;
 }
 center {
        font-family : arial, helvetica, sans-serif ;
@@ -15,14 +17,10 @@ center {
 p {
        font-family : arial, helvetica, sans-serif ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 3% ;
 }
 .indent_block {
        font-family : arial, helvetica, sans-serif ;
        text-align : left ;
-       margin-left : 10% ;
-       margin-right : 10% ;
 }
 br {
        font-family : arial, helvetica, sans-serif ;
@@ -33,60 +31,71 @@ form {
 ul {
        font-family : arial, helvetica, sans-serif ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 6% ;
 }
 ol {
        font-family : arial, helvetica, sans-serif ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 6% ;
 }
 dl {
        font-family : arial, helvetica, sans-serif ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 3% ;
 }
 h1 {
        font-size : xx-large ;
-       background : @HTML_BGCOLOUR@ ;
+       background : black ;
        color : #5050FF ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 3% ;
 }
 h2 {
        font-size : x-large ;
-       background : @HTML_BGCOLOUR@ ;
+       background : black ;
        color : #5050FF ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 3% ;
 }
 h3 {
        font-size : large ;
-       background : @HTML_BGCOLOUR@ ;
+       background : black ;
        color : #5050FF ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 3% ;
 }
 h4 {
        font-size : medium ;
-       background : @HTML_BGCOLOUR@ ;
+       background : black ;
        color : #5050FF ;
        text-align : left ;
-       margin-left : 3% ;
-       margin-right : 3% ;
 }
 pre {
        font-family : courier, monospace ;
        font-size : medium ;
-       margin-left : 6% ;
-       margin-right : 6% ;
+}
+code,
+kbd,
+samp,
+var {
+       font-family: "Courier New", monospace, serif;
+       font-size: 1em;
 }
 a:link { color : #9090FF ; }
 a:visited { color : #5050FF ; }
 a:active { color : #FF00FF ; }
 a:hover { background-color : #202080 ; }
+
+table.formats-table {
+       text-align: center;
+       font-size: small;
+       border-collapse: collapse;
+}
+
+table.formats-table, table.formats-table th, table.formats-table td {
+       border: 1px solid white;
+}
+
+.image-logo {
+       display: block;
+       margin-left: auto;
+       margin-right: auto;
+}
+
+nav {
+       text-align: center;
+}
similarity index 100%
rename from doc/libsndfile.jpg
rename to docs/libsndfile.jpg
diff --git a/docs/lists.md b/docs/lists.md
new file mode 100644 (file)
index 0000000..31a0962
--- /dev/null
@@ -0,0 +1,27 @@
+---
+layout: page
+title: libsndfile Mailing Lists
+---
+
+# libsndfile Mailing Lists
+
+**Note**: These mailing lists are not maintained by the libsndfile team anymore.
+Use [GitHub issues and pull requests instead](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests).
+
+There are three mailing lists for libsndfile:
+
+ - **libsndfile-announce@mega-nerd.com**  
+  [Subscribe](mailto:libsndfile-announce-request@mega-nerd.com?subject=subscribe)  
+  A list which will announce each new release of libsndfile. Noone can
+  post to this list except the author.  
+- **libsndfile-devel@mega-nerd.com**  
+  [Subscribe](mailto:libsndfile-devel-request@mega-nerd.com?subject=subscribe)  
+  A list for discussing bugs, porting issues and feature requests.
+  Posting is restricted to subscribers.  
+- **libsndfile-users@mega-nerd.com**  
+  [Subscribe](mailto:libsndfile-users-request@mega-nerd.com?subject=subscribe)  
+  A list for discussing the use of libsndfile in other programs.
+  Posting is restricted to subscribers.  
+
+The libsndfile-devel and libsndfile-users list will automatically receive a copy
+of all emails to the libsndfile-announce list.
similarity index 72%
rename from doc/new_file_type.HOWTO
rename to docs/new_file_type_howto.md
index a6da80a..0585394 100644 (file)
@@ -1,55 +1,58 @@
-new_file_type.HOWTO
-===================
+---
+layout: page
+---
+
+# How to add new file format
 
    Original : Wed May 23 19:05:07 EST 2001
    Update 1 : Fri Jul 11 22:12:38 EST 2003
 
-This document will attempt to explain as fully as possible how to add code to 
+This document will attempt to explain as fully as possible how to add code to
 libsndfile to allow the reading and writing of new file types. By new file
 type I particularly mean a new header type rather than a new encoding method
 for an existing file type.
 
-This HOWTO will take the form of a step by step guide. It will assume that you 
+This HOWTO will take the form of a step by step guide. It will assume that you
 have all required tools including :
 
-       - gcc
-       - make (should really be the GNU version)
-       - autoconf
-       - automake 
-       - libtool
-       
-These should all be available on the GNU ftp site: ftp://ftp.gnu.org/pub/gnu/.
+- gcc
+- make (should really be the GNU version)
+- autoconf
+- automake
+- libtool
+
+These should all be available on the GNU ftp site: <ftp://ftp.gnu.org/pub/gnu/>.
 
 To help make these steps clearer let's suppose we are adding support for the
 Whacky file format whose files contain 'W','A','C' and 'K' as the first four
 bytes of the file format. Lets also assume that Whacky files contain PCM encoded
-data. 
+data.
+
+## Step 1
 
-Step 1
-------
-Create a new .c file in the src/ directory of the libsndfile source tree. The 
-file name should be reasonable descriptive so that is is obvious that files of 
+Create a new .c file in the src/ directory of the libsndfile source tree. The
+file name should be reasonable descriptive so that is is obvious that files of
 the new type are handled by this file. In this particular case the file might
 be named 'whacky.c'.
-       
-Step 2
-------
+
+## Step 2
+
 Add your new source code file to the build process.
 
-Edit the file src/Makefile.am and add the name of your file handler to the 
+Edit the file src/Makefile.am and add the name of your file handler to the
 FILESPECIFIC list of handlers. This list looks something like this:  
 
-FILESPECIFIC = aiff.c au.c au_g72x.c nist.c paf.c raw.c samplitude.c \
-                               svx.c wav.c wav_float.c wav_gsm610.c wav_ima_adpcm.c \
-                               wav_ms_adpcm.c
+    FILESPECIFIC = aiff.c au.c au_g72x.c nist.c paf.c raw.c samplitude.c \
+                    svx.c wav.c wav_float.c wav_gsm610.c wav_ima_adpcm.c \
+                    wav_ms_adpcm.c
 
 Then, run the script named 'reconf' in the libsndfile top level directory,
 which will run autoconf and other associated tools. Finally run "./configure"
 in the top level directory. You may want to use the "--disable-gcc-opt" option
 to disable gcc optimisations and make debugging with gdb/ddd easier.
 
-Step 3
-------
+## Step 3
+
 Add a unique identifier for the new file type.
 
 Edit src/sndfile.h.in and find the enum containing the SF_FORMAT_XXX identifiers.
@@ -59,77 +62,73 @@ way to do this is to find the largest value in the list, add 0x10000 to it and
 make that your new identifier value. The identifier should be something like
 SF_FORMAT_WACK.
 
-Step 4
-------
+## Step 4
+
 Add code to the file type recogniser function.
 
-Edit src/sndfile.c and find the function guess_file_type (). This function 
-reads the first 3 ints of the file and from that makes a guess at the file 
+Edit src/sndfile.c and find the function guess_file_type (). This function
+reads the first 3 ints of the file and from that makes a guess at the file
 type. In our case we would add:
 
+    if (buffer [0] == MAKE_MARKER ('W','A','C','K'))
+        return SF_FORMAT_WACK ;
+
+The use of the MAKE_MARKER macro should be pretty obvious and it is defined at
+the top of file should you need to have a look at it.
 
-       if (buffer [0] == MAKE_MARKER ('W','A','C','K'))
-               return SF_FORMAT_WACK ;
-               
-The use of the MAKE_MARKER macro should be pretty obvious and it is defined at the 
-top of file should you need to have a look at it.
+## Step 5
 
-Step 5
-------
 Add a call to your open function from psf_open_file ().
 
 Edit src/sndfile.c and find the switch statement in psf_open_file (). It starts
 like this:
 
-       switch (filetype)
-       {       case    SF_FORMAT_WAV :
-                               error = wav_open (psf) ;
-                               break ;
+    switch (filetype)
+    {   case SF_FORMAT_WAV :
+                error = wav_open (psf) ;
+                break ;
 
-               case    SF_FORMAT_AIFF :
-                               error = aiff_open (psf) ;
-                               break ;
+        case SF_FORMAT_AIFF :
+                error = aiff_open (psf) ;
+                break ;
 
 Towards the bottom of this switch statement your should add one for the new file
 type. Something like:
 
-               case    SF_FORMAT_WACK :
-                               sf_errno = whacky_open (psf) ;
-                               break ;
+        case    SF_FORMAT_WACK :
+                sf_errno = whacky_open (psf) ;
+                break ;
+
+## Step 6
 
-Setp 6
-------
 Add prototypes for new open read and open write functions.
 
 Edit src/common.h, go to the bottom of the file and add something like
 
-       int             whacky_open       (SF_PRIVATE *psf) ;
+    int     whacky_open   (SF_PRIVATE *psf) ;
 
-Step 7
-------
+## Step 7
 
-Implement your open read function. The best way to do this is by coding 
-something much like one of the other file formats. The file src/au.c might be 
-good place to start.
+Implement your open read function. The best way to do this is by coding
+something much like one of the other file formats. The file src/au.c might be a
+good place to start.
 
-In src/whacky.c you should now implement the function whacky_open() which 
-was prototyped in src/common.h. This function should return 0 on success and 
-a non-zero number on error. 
+In src/whacky.c you should now implement the function whacky_open() which
+was prototyped in src/common.h. This function should return 0 on success and
+a non-zero number on error.
 
 Error values are defined in src/common.h in a enum which starts at SFE_NO_ERROR.
-When adding a new error value, you also need to add an error string to the 
+When adding a new error value, you also need to add an error string to the
 SndfileErrors array in src/sndfile.c.
 
 To parse the header of your new file type you should avoid using standard read/
-write/seek functions (and the fread/fwrite/fseek etc) and instead use 
+write/seek functions (and the fread/fwrite/fseek etc) and instead use
 psf_binheader_readf () which is implemented and documented in src/common.h.
 
-During the parsing process, you should also print logging information to 
+During the parsing process, you should also print logging information to
 libsndfile's internal log buffer using the psf_log_printf() function.
 
-At the end of the open read process, you should have set a number of fields in the
-SF_PRIVATE structure pointed to by psf.
-
-
+At the end of the open read process, you should have set a number of fields in
+the SF_PRIVATE structure pointed to by psf.
 
-*** THIS FILE IS INCOMPLETE ***
+**THIS FILE IS INCOMPLETE**
diff --git a/docs/octave.md b/docs/octave.md
new file mode 100644 (file)
index 0000000..f619ca6
--- /dev/null
@@ -0,0 +1,71 @@
+---
+layout: page
+---
+
+# libsndfile and GNU Octave
+
+[GNU Octave](http://www.octave.org/) is a high-level interactive language for
+numerical computations. There are currently two development streams, a stable
+2.0.X series and a development 2.1.X series. Octave reads and writes data in
+binary formats that were originally developed for
+[MATLAB](http://www.mathworks.com/). Version 2.0.X of Octave uses binary data
+files compatible with MATLAB version 4.2 while Octave 2.1.X uses binary data
+files compatible with MATLAB version 5.0 as well as being able to read the older
+MATLAB 4.2 format.
+
+From version 1.0.1 of libsndfile onwards, libsndfile has the ability of reading
+and writing a small subset of the binary data files used by both versions of GNU
+Octave. This gives people using GNU Octave for audio based work an easy method
+of moving audio data between GNU Octave and other programs which use libsndfile.
+
+For instance it is now possible to do the following:
+
+* Load a WAV file into a sound file editor such as
+  [Sweep](http://www.metadecks.org/software/sweep/).
+* Save it as a MAT4 file.
+* Load the data into Octave for manipulation.
+* Save the modified data.
+* Reload it in Sweep.
+
+Another example would be using the MAT4 or MAT5 file formats as a format which
+can be easily loaded into Octave for viewing/analyzing as well as a format which
+can be played with command line players such as the one included with
+libsndfile.
+
+## Details
+
+Octave, like most programming languages, uses variables to store data, and
+Octave variables can contain both arrays and matrices. It is also able to store
+one or more of these variables in a file. When reading Octave files, libsndfile
+expects a file to contain two variables and their associated data. The first
+variable should contain a variable holding the file sample rate while the second
+variable contains the audio data.
+
+For example, to generate a sine wave and store it as a binary file which is
+compatible with libsndfile, do the following:
+
+    octave:1 > samplerate = 44100 ;
+    octave:2 > wavedata = sin ((0:1023)*2*pi/1024) ;
+    octave:3 > save sine.mat samplerate wavedata
+
+The process of reading and writing files compatible with libsndfile can be made
+easier by use of two Octave script files:
+
+    octave:4 > [data fs] = sndfile_load ("sine.mat") ;
+    octave:5 > sndfile_save ("sine2.mat", data, fs) ;
+
+In addition, libsndfile contains a command line program which which is able to
+play the correct types of Octave files. Using this command line player
+**sndfile-play** and a third Octave script file allows Octave data to be played
+from within Octave on any of the platforms which **sndfile-play** supports (at
+the moment: Linux, MacOS X, Solaris and Win32).
+
+    octave:6 > sndfile_play (data, fs) ;
+
+These three Octave scripts are installed automatically in Octave's site script
+directory when libsndfile is installed (except on Win32) ie when libsndfile is
+being installed into /usr/local, the Octave scripts will be installed in
+/usr/local/share/octave/site/m/.
+
+There are some other Octave scripts for audio to be found
+[here](http://octave.sourceforge.net/audio/index.html).
similarity index 100%
rename from doc/print.css
rename to docs/print.css
diff --git a/docs/sndfile_info.md b/docs/sndfile_info.md
new file mode 100644 (file)
index 0000000..78d3548
--- /dev/null
@@ -0,0 +1,36 @@
+---
+layout: page
+title: sndfile-info
+---
+
+Here is an example of the output from the **sndfile-info** program
+distributed with libsndfile.
+
+This file was opened and parsed correctly but had been truncated so that
+the values in the **FORM** and **SSND** chunks were incorrect.
+
+```
+        erikd@hendrix > examples/sndfile-info truncated.aiff
+        truncated.aiff
+        size : 200000
+        FORM : 307474 (should be 199992)
+         AIFF
+         COMM : 18
+          Sample Rate : 16000
+          Samples     : 76857
+          Channels    : 2
+          Sample Size : 16
+         SSND : 307436 (should be 199946)
+          Offset     : 0
+          Block Size : 0
+
+        --------------------------------
+        Sample Rate : 16000
+        Frames      : 76857
+        Channels    : 2
+        Bit Width   : 16
+        Format      : 0x00020001
+        Sections    : 1
+        Seekable    : TRUE
+        Signal Max  : 32766
+```
diff --git a/docs/tutorial.md b/docs/tutorial.md
new file mode 100644 (file)
index 0000000..848c175
--- /dev/null
@@ -0,0 +1,10 @@
+---
+layout: page
+---
+
+# libsndfile Tutorial
+
+**More coming soon.**
+
+For now, the best place to look for example code is the `examples/` directory of the source code distribution and the
+libsndfile test suite which is located in the `tests/` directory of the source code distribution.
diff --git a/docs/win32.md b/docs/win32.md
new file mode 100644 (file)
index 0000000..6106517
--- /dev/null
@@ -0,0 +1,18 @@
+---
+layout: page
+---
+
+# Building libsndfile on Win32
+
+**Note : For pre-compiled binaries for windows, both for win32 and win64, see
+the main web page.**
+
+There are currently two build systems; the official GNU autotool based one and
+a more limited and experimental CMake based build system.
+
+libsndfile is written to be compiled by a compiler which supports large chunks
+of the 1999 ISO C Standard (tested with GCC, Clang and Visual Studio 2015).
+
+It is recommended to use CMake and Visual Studio to build libsndfile on Windows
+but you can try the [MinGW](http://www.mingw.org/) compiler suite with Autotools
+or CMake buildsystem.
diff --git a/echo-install-dirs.in b/echo-install-dirs.in
deleted file mode 100644 (file)
index 48d54b4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-# @configure_input@
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-bindir=@bindir@
-pkgconfigdir=@pkgconfigdir@
-datadir=@datadir@
-datarootdir=@datarootdir@
-docdir=@docdir@
-htmldir=@htmldir@
-
-echo "
-  Installation directories :
-
-    Library directory : ................... $libdir
-    Program directory : ................... $bindir
-    Pkgconfig directory : ................. $pkgconfigdir
-    HTML docs directory : ................. $htmldir
-"
-echo "Compiling some other packages against libsndfile may require"
-echo "the addition of '$pkgconfigdir' to the"
-echo "PKG_CONFIG_PATH environment variable."
-echo
diff --git a/examples/Makefile.am b/examples/Makefile.am
deleted file mode 100644 (file)
index f342c78..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-check_PROGRAMS = make_sine sfprocess list_formats generate sndfilehandle \
-       sndfile-to-text sndfile-loopify
-
-AM_CPPFLAGS = -I$(top_srcdir)/src
-
-sndfile_to_text_SOURCES = sndfile-to-text.c
-sndfile_to_text_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_loopify_SOURCES = sndfile-loopify.c
-sndfile_loopify_LDADD = $(top_builddir)/src/libsndfile.la
-
-make_sine_SOURCES = make_sine.c
-make_sine_LDADD = $(top_builddir)/src/libsndfile.la
-
-sfprocess_SOURCES = sfprocess.c
-sfprocess_LDADD = $(top_builddir)/src/libsndfile.la
-
-list_formats_SOURCES = list_formats.c
-list_formats_LDADD = $(top_builddir)/src/libsndfile.la
-
-generate_SOURCES = generate.c
-generate_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfilehandle_SOURCES = sndfilehandle.cc
-sndfilehandle_LDADD = $(top_builddir)/src/libsndfile.la
-
-CLEANFILES = *~ *.exe
index 884e8d7..dade7d9 100644 (file)
@@ -30,8 +30,6 @@
 ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#include "sfconfig.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index 69d4dbf..76f35b0 100644 (file)
@@ -55,8 +55,8 @@ main (void)
        int     *buffer ;
 
        if (! (buffer = malloc (2 * SAMPLE_COUNT * sizeof (int))))
-       {       printf ("Malloc failed.\n") ;
-               exit (0) ;
+       {       printf ("Error : Malloc failed.\n") ;
+               return 1 ;
                } ;
 
        memset (&sfinfo, 0, sizeof (sfinfo)) ;
@@ -83,8 +83,10 @@ main (void)
                        } ;
                }
        else
-       {       printf ("makesine can only generate mono or stereo files.\n") ;
-               exit (1) ;
+       {       printf ("Error : make_sine can only generate mono or stereo files.\n") ;
+               sf_close (file) ;
+               free (buffer) ;
+               return 1 ;
                } ;
 
        if (sf_write_int (file, buffer, sfinfo.channels * SAMPLE_COUNT) !=
index f0ceb6d..b0aded4 100644 (file)
@@ -44,8 +44,6 @@
 
 #include <sndfile.h>
 
-#include "common.h"
-
 #define BUFFER_LEN             (1 << 14)
 
 
similarity index 96%
rename from src/sndfile.h.in
rename to include/sndfile.h.in
index 3983118..917ff4b 100644 (file)
@@ -20,7 +20,7 @@
 ** sndfile.h -- system-wide definitions
 **
 ** API documentation is in the doc/ directory of the source code tarball
-** and at http://www.mega-nerd.com/libsndfile/api.html.
+** and at http://libsndfile.github.io/libsndfile/api.html.
 */
 
 #ifndef SNDFILE_H
@@ -92,6 +92,10 @@ enum
        SF_FORMAT_GSM610                = 0x0020,               /* GSM 6.10 encoding. */
        SF_FORMAT_VOX_ADPCM             = 0x0021,               /* OKI / Dialogix ADPCM */
 
+       SF_FORMAT_NMS_ADPCM_16  = 0x0022,               /* 16kbs NMS G721-variant encoding. */
+       SF_FORMAT_NMS_ADPCM_24  = 0x0023,               /* 24kbs NMS G721-variant encoding. */
+       SF_FORMAT_NMS_ADPCM_32  = 0x0024,               /* 32kbs NMS G721-variant encoding. */
+
        SF_FORMAT_G721_32               = 0x0030,               /* 32kbs G721 ADPCM encoding. */
        SF_FORMAT_G723_24               = 0x0031,               /* 24kbs G723 ADPCM encoding. */
        SF_FORMAT_G723_40               = 0x0032,               /* 40kbs G723 ADPCM encoding. */
@@ -105,6 +109,7 @@ enum
        SF_FORMAT_DPCM_16               = 0x0051,               /* 16 bit differential PCM (XI only) */
 
        SF_FORMAT_VORBIS                = 0x0060,               /* Xiph Vorbis encoding. */
+       SF_FORMAT_OPUS                  = 0x0064,               /* Xiph/Skype Opus encoding. */
 
        SF_FORMAT_ALAC_16               = 0x0070,               /* Apple Lossless Audio Codec (16 bit). */
        SF_FORMAT_ALAC_20               = 0x0071,               /* Apple Lossless Audio Codec (20 bit). */
@@ -160,7 +165,6 @@ enum
        SFC_GET_MAX_ALL_CHANNELS                = 0x1045,
 
        SFC_SET_ADD_PEAK_CHUNK                  = 0x1050,
-       SFC_SET_ADD_HEADER_PAD_CHUNK    = 0x1051,
 
        SFC_UPDATE_HEADER_NOW                   = 0x1060,
        SFC_SET_UPDATE_HEADER_AUTO              = 0x1061,
@@ -210,20 +214,28 @@ enum
 
        SFC_SET_VBR_ENCODING_QUALITY    = 0x1300,
        SFC_SET_COMPRESSION_LEVEL               = 0x1301,
+       SFC_SET_OGG_PAGE_LATENCY_MS             = 0x1302,
+       SFC_SET_OGG_PAGE_LATENCY                = 0x1303,
 
        /* Cart Chunk support */
        SFC_SET_CART_INFO                               = 0x1400,
        SFC_GET_CART_INFO                               = 0x1401,
 
+       /* Opus files original samplerate metadata */
+       SFC_SET_ORIGINAL_SAMPLERATE             = 0x1500,
+       SFC_GET_ORIGINAL_SAMPLERATE             = 0x1501,
+
        /* Following commands for testing only. */
        SFC_TEST_IEEE_FLOAT_REPLACE             = 0x6001,
 
        /*
-       ** SFC_SET_ADD_* values are deprecated and will disappear at some
+       ** These SFC_SET_ADD_* values are deprecated and will disappear at some
        ** time in the future. They are guaranteed to be here up to and
        ** including version 1.0.8 to avoid breakage of existing software.
        ** They currently do nothing and will continue to do nothing.
        */
+       SFC_SET_ADD_HEADER_PAD_CHUNK    = 0x1051,
+
        SFC_SET_ADD_DITHER_ON_WRITE             = 0x1070,
        SFC_SET_ADD_DITHER_ON_READ              = 0x1071
 } ;
@@ -333,11 +345,8 @@ typedef    struct SNDFILE_tag      SNDFILE ;
 ** and the Microsoft compiler.
 */
 
-#if (defined (_MSCVER) || defined (_MSC_VER) && (_MSC_VER < 1310))
-typedef __int64                sf_count_t ;
-#define SF_COUNT_MAX           0x7fffffffffffffffi64
-#else
 typedef @TYPEOF_SF_COUNT_T@    sf_count_t ;
+#ifndef SF_COUNT_MAX
 #define SF_COUNT_MAX           @SF_COUNT_MAX@
 #endif
 
@@ -492,7 +501,12 @@ typedef struct
                                uint32_t        time_reference_high ; \
                                short           version ; \
                                char            umid [64] ; \
-                               char            reserved [190] ; \
+                               int16_t loudness_value ; \
+                               int16_t loudness_range ; \
+                               int16_t max_true_peak_level ; \
+                               int16_t max_momentary_loudness ; \
+                               int16_t max_shortterm_loudness ; \
+                               char            reserved [180] ; \
                                uint32_t        coding_history_size ; \
                                char            coding_history [coding_hist_size] ; \
                        }
@@ -610,7 +624,9 @@ int         sf_perror               (SNDFILE *sndfile) ;
 int            sf_error_str    (SNDFILE *sndfile, char* str, size_t len) ;
 
 
-/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
+/* Allow the caller to retrieve information from or change aspects of the
+** library behaviour.
+*/
 
 int            sf_command      (SNDFILE *sndfile, int command, void *data, int datasize) ;
 
@@ -854,4 +870,3 @@ sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
 #endif /* __cplusplus */
 
 #endif /* SNDFILE_H */
-
similarity index 93%
rename from src/sndfile.hh
rename to include/sndfile.hh
index 0e1c1c2..ae9af3f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2005-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2005-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** All rights reserved.
 **
@@ -46,7 +46,7 @@
 ** file. There is no separate implementation file.
 **
 ** API documentation is in the doc/ directory of the source code tarball
-** and at http://www.mega-nerd.com/libsndfile/api.html.
+** and at http://libsndfile.github.io/libsndfile/api.html.
 */
 
 #ifndef SNDFILE_HH
 #include <string>
 #include <new> // for std::nothrow
 
+#if __cplusplus < 201100
+#ifndef nullptr
+#define nullptr NULL
+#endif
+#endif
+
 class SndfileHandle
 {      private :
                struct SNDFILE_ref
@@ -72,7 +78,7 @@ class SndfileHandle
 
        public :
                        /* Default constructor */
-                       SndfileHandle (void) : p (NULL) {} ;
+                       SndfileHandle (void) : p (nullptr) {} ;
                        SndfileHandle (const char *path, int mode = SFM_READ,
                                                        int format = 0, int channels = 0, int samplerate = 0) ;
                        SndfileHandle (std::string const & path, int mode = SFM_READ,
@@ -93,9 +99,9 @@ class SndfileHandle
                        SndfileHandle & operator = (const SndfileHandle &rhs) ;
 
                /* Mainly for debugging/testing. */
-               int refCount (void) const { return (p == NULL) ? 0 : p->ref ; }
+               int refCount (void) const { return (p == nullptr) ? 0 : p->ref ; }
 
-               operator bool () const { return (p != NULL) ; }
+               operator bool () const { return (p != nullptr) ; }
 
                bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
 
@@ -155,20 +161,20 @@ class SndfileHandle
 
 inline
 SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
-: sf (NULL), sfinfo (), ref (1)
+: sf (nullptr), sfinfo (), ref (1)
 {}
 
 inline
 SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
-{      if (sf != NULL) sf_close (sf) ; }
+{      if (sf != nullptr) sf_close (sf) ; }
 
 inline
 SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
-: p (NULL)
+: p (nullptr)
 {
        p = new (std::nothrow) SNDFILE_ref () ;
 
-       if (p != NULL)
+       if (p != nullptr)
        {       p->ref = 1 ;
 
                p->sfinfo.frames = 0 ;
@@ -186,11 +192,11 @@ SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, in
 
 inline
 SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)
-: p (NULL)
+: p (nullptr)
 {
        p = new (std::nothrow) SNDFILE_ref () ;
 
-       if (p != NULL)
+       if (p != nullptr)
        {       p->ref = 1 ;
 
                p->sfinfo.frames = 0 ;
@@ -208,14 +214,14 @@ SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int c
 
 inline
 SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
-: p (NULL)
+: p (nullptr)
 {
        if (fd < 0)
                return ;
 
        p = new (std::nothrow) SNDFILE_ref () ;
 
-       if (p != NULL)
+       if (p != nullptr)
        {       p->ref = 1 ;
 
                p->sfinfo.frames = 0 ;
@@ -233,11 +239,11 @@ SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int ch
 
 inline
 SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate)
-: p (NULL)
+: p (nullptr)
 {
        p = new (std::nothrow) SNDFILE_ref () ;
 
-       if (p != NULL)
+       if (p != nullptr)
        {       p->ref = 1 ;
 
                p->sfinfo.frames = 0 ;
@@ -255,7 +261,7 @@ SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mod
 
 inline
 SndfileHandle::~SndfileHandle (void)
-{      if (p != NULL && --p->ref == 0)
+{      if (p != nullptr && -- p->ref == 0)
                delete p ;
 } /* SndfileHandle destructor */
 
@@ -263,8 +269,8 @@ SndfileHandle::~SndfileHandle (void)
 inline
 SndfileHandle::SndfileHandle (const SndfileHandle &orig)
 : p (orig.p)
-{      if (p != NULL)
-               ++p->ref ;
+{      if (p != nullptr)
+               ++ p->ref ;
 } /* SndfileHandle copy constructor */
 
 inline SndfileHandle &
@@ -272,12 +278,12 @@ SndfileHandle::operator = (const SndfileHandle &rhs)
 {
        if (&rhs == this)
                return *this ;
-       if (p != NULL && --p->ref == 0)
+       if (p != nullptr && -- p->ref == 0)
                delete p ;
 
        p = rhs.p ;
-       if (p != NULL)
-               ++p->ref ;
+       if (p != nullptr)
+               ++ p->ref ;
 
        return *this ;
 } /* SndfileHandle assignment operator */
@@ -401,18 +407,18 @@ SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
 
 inline SNDFILE *
 SndfileHandle::rawHandle (void)
-{      return (p ? p->sf : NULL) ; }
+{      return (p ? p->sf : nullptr) ; }
 
 inline SNDFILE *
 SndfileHandle::takeOwnership (void)
 {
-       if (p == NULL || (p->ref != 1))
-               return NULL ;
+       if (p == nullptr || (p->ref != 1))
+               return nullptr ;
 
        SNDFILE * sf = p->sf ;
-       p->sf = NULL ;
+       p->sf = nullptr ;
        delete p ;
-       p = NULL ;
+       p = nullptr ;
        return sf ;
 }
 
@@ -420,11 +426,11 @@ SndfileHandle::takeOwnership (void)
 
 inline
 SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)
-: p (NULL)
+: p (nullptr)
 {
        p = new (std::nothrow) SNDFILE_ref () ;
 
-       if (p != NULL)
+       if (p != nullptr)
        {       p->ref = 1 ;
 
                p->sfinfo.frames = 0 ;
diff --git a/m4/ax_append_compile_flags.m4 b/m4/ax_append_compile_flags.m4
new file mode 100644 (file)
index 0000000..5b6f1af
--- /dev/null
@@ -0,0 +1,67 @@
+# ============================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   For every FLAG1, FLAG2 it is checked whether the compiler works with the
+#   flag.  If it does, the flag is added FLAGS-VARIABLE
+#
+#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+#   CFLAGS) is used.  During the check the flag is always added to the
+#   current language's flags.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: This macro depends on the AX_APPEND_FLAG and
+#   AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
+#   AX_APPEND_LINK_FLAGS.
+#
+# LICENSE
+#
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 6
+
+AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+  AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
+done
+])dnl AX_APPEND_COMPILE_FLAGS
diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4
new file mode 100644 (file)
index 0000000..e8c5312
--- /dev/null
@@ -0,0 +1,71 @@
+# ===========================================================================
+#      https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+#   FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+#   added in between.
+#
+#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+#   CFLAGS) is used.  FLAGS-VARIABLE is not changed if it already contains
+#   FLAG.  If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+#   FLAG.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 7
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+  AS_CASE([" AS_VAR_GET(FLAGS) "],
+    [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+    [
+     AS_VAR_APPEND(FLAGS,[" $1"])
+     AC_RUN_LOG([: FLAGS="$FLAGS"])
+    ])
+  ],
+  [
+  AS_VAR_SET(FLAGS,[$1])
+  AC_RUN_LOG([: FLAGS="$FLAGS"])
+  ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
diff --git a/m4/ax_append_link_flags.m4 b/m4/ax_append_link_flags.m4
new file mode 100644 (file)
index 0000000..6f7f174
--- /dev/null
@@ -0,0 +1,65 @@
+# ===========================================================================
+#   https://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   For every FLAG1, FLAG2 it is checked whether the linker works with the
+#   flag.  If it does, the flag is added FLAGS-VARIABLE
+#
+#   If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is
+#   used. During the check the flag is always added to the linker's flags.
+#
+#   If EXTRA-FLAGS is defined, it is added to the linker's default flags
+#   when the check is done.  The check is thus made with the flags: "LDFLAGS
+#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to
+#   issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
+#   Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
+#
+# LICENSE
+#
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 6
+
+AC_DEFUN([AX_APPEND_LINK_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+  AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4])
+done
+])dnl AX_APPEND_LINK_FLAGS
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644 (file)
index 0000000..dcabb92
--- /dev/null
@@ -0,0 +1,74 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the current language's compiler
+#   or gives an error.  (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
new file mode 100644 (file)
index 0000000..819409a
--- /dev/null
@@ -0,0 +1,74 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the linker or gives an error.
+#   (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the linker's default flags
+#   when the check is done.  The check is thus made with the flags: "LDFLAGS
+#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to
+#   issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+  ax_check_save_flags=$LDFLAGS
+  LDFLAGS="$LDFLAGS $4 $1"
+  AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  LDFLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4
new file mode 100644 (file)
index 0000000..4ca8089
--- /dev/null
@@ -0,0 +1,87 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_VENDOR
+#
+# DESCRIPTION
+#
+#   Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
+#   hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
+#   watcom, etc. The vendor is returned in the cache variable
+#   $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+#   Copyright (c) 2008 Matteo Frigo
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 16
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+  dnl Please add if possible support to ax_compiler_version.m4
+  [# note: don't check for gcc first since some other compilers define __GNUC__
+  vendors="intel:     __ICC,__ECC,__INTEL_COMPILER
+           ibm:       __xlc__,__xlC__,__IBMC__,__IBMCPP__
+           pathscale: __PATHCC__,__PATHSCALE__
+           clang:     __clang__
+           cray:      _CRAYC
+           fujitsu:   __FUJITSU
+           gnu:       __GNUC__
+           sun:       __SUNPRO_C,__SUNPRO_CC
+           hp:        __HP_cc,__HP_aCC
+           dec:       __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
+           borland:   __BORLANDC__,__CODEGEARC__,__TURBOC__
+           comeau:    __COMO__
+           kai:       __KCC
+           lcc:       __LCC__
+           sgi:       __sgi,sgi
+           microsoft: _MSC_VER
+           metrowerks: __MWERKS__
+           watcom:    __WATCOMC__
+           portland:  __PGI
+          tcc:       __TINYC__
+           unknown:   UNKNOWN"
+  for ventest in $vendors; do
+    case $ventest in
+      *:) vendor=$ventest; continue ;;
+      *)  vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
+    esac
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+      #if !($vencpp)
+        thisisanerror;
+      #endif
+    ])], [break])
+  done
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
+ ])
+])
diff --git a/m4/ax_compiler_version.m4 b/m4/ax_compiler_version.m4
new file mode 100644 (file)
index 0000000..8a8e28a
--- /dev/null
@@ -0,0 +1,492 @@
+# ===========================================================================
+#   https://www.gnu.org/software/autoconf-archive/ax_compiler_version.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_VERSION
+#
+# DESCRIPTION
+#
+#   This macro retrieves the compiler version and returns it in the cache
+#   variable $ax_cv_c_compiler_version for C and $ax_cv_cxx_compiler_version
+#   for C++.
+#
+#   Version is returned as epoch:major.minor.patchversion
+#
+#   Epoch is used in order to have an increasing version number in case of
+#   marketing change.
+#
+#   Epoch use: * borland compiler use chronologically 0turboc for turboc
+#   era,
+#
+#     1borlanc BORLANDC++ before 5, 2cppbuilder for cppbuilder era,
+#     3borlancpp for return of BORLANDC++ (after version 5.5),
+#     4cppbuilder for cppbuilder with year version,
+#     and 5xe for XE era.
+#
+#   An empty string is returned otherwise.
+#
+# LICENSE
+#
+#   Copyright (c) 2014 Bastien ROUCARIES <roucaries.bastien+autoconf@gmail.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 9
+
+# for intel
+AC_DEFUN([_AX_COMPILER_VERSION_INTEL],
+  [ dnl
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    [__INTEL_COMPILER/100],,
+    AC_MSG_FAILURE([[[$0]] unknown intel compiler version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    [(__INTEL_COMPILER%100)/10],,
+    AC_MSG_FAILURE([[[$0]] unknown intel compiler version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [(__INTEL_COMPILER%10)],,
+    AC_MSG_FAILURE([[[$0]] unknown intel compiler version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# for IBM
+AC_DEFUN([_AX_COMPILER_VERSION_IBM],
+  [ dnl
+  dnl check between z/OS C/C++  and XL C/C++
+  AC_COMPILE_IFELSE([
+    AC_LANG_PROGRAM([],
+      [
+        #if defined(__COMPILER_VER__)
+        choke me;
+        #endif
+      ])],
+    [
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+        [__xlC__/100],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler major version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+        [__xlC__%100],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler minor version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+        [__xlC_ver__/0x100],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler patch version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_build,
+        [__xlC_ver__%0x100],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler build version]))
+      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_build"
+    ],
+    [
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+        [__xlC__%1000],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler patch version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+        [(__xlC__/10000)%10],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler minor version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+        [(__xlC__/100000)%10],,
+       AC_MSG_FAILURE([[[$0]] unknown IBM compiler major version]))
+      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+    ])
+])
+
+# for pathscale
+AC_DEFUN([_AX_COMPILER_VERSION_PATHSCALE],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    __PATHCC__,,
+    AC_MSG_FAILURE([[[$0]] unknown pathscale major]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    __PATHCC_MINOR__,,
+    AC_MSG_FAILURE([[[$0]] unknown pathscale minor]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [__PATHCC_PATCHLEVEL__],,
+    AC_MSG_FAILURE([[[$0]] unknown pathscale patch level]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# for clang
+AC_DEFUN([_AX_COMPILER_VERSION_CLANG],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    __clang_major__,,
+    AC_MSG_FAILURE([[[$0]] unknown clang major]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    __clang_minor__,,
+    AC_MSG_FAILURE([[[$0]] unknown clang minor]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [__clang_patchlevel__],,0)
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# for crayc
+AC_DEFUN([_AX_COMPILER_VERSION_CRAY],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    _RELEASE,,
+    AC_MSG_FAILURE([[[$0]] unknown crayc release]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    _RELEASE_MINOR,,
+    AC_MSG_FAILURE([[[$0]] unknown crayc minor]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor"
+  ])
+
+# for fujitsu
+AC_DEFUN([_AX_COMPILER_VERSION_FUJITSU],[
+  AC_COMPUTE_INT(ax_cv_[]_AC_LANG_ABBREV[]_compiler_version,
+                 __FCC_VERSION,,
+                AC_MSG_FAILURE([[[$0]]unknown fujitsu release]))
+  ])
+
+# for GNU
+AC_DEFUN([_AX_COMPILER_VERSION_GNU],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    __GNUC__,,
+    AC_MSG_FAILURE([[[$0]] unknown gcc major]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    __GNUC_MINOR__,,
+    AC_MSG_FAILURE([[[$0]] unknown gcc minor]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [__GNUC_PATCHLEVEL__],,
+    AC_MSG_FAILURE([[[$0]] unknown gcc patch level]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# For sun
+AC_DEFUN([_AX_COMPILER_VERSION_SUN],[
+  m4_define([_AX_COMPILER_VERSION_SUN_NUMBER],
+            [
+            #if defined(__SUNPRO_CC)
+            __SUNPRO_CC
+            #else
+            __SUNPRO_C
+            #endif
+           ])
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_until59,
+    !!(_AX_COMPILER_VERSION_SUN_NUMBER < 0x1000),,
+    AC_MSG_FAILURE([[[$0]] unknown sun release version]))
+  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_until59" = X1],
+    [dnl
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+        _AX_COMPILER_VERSION_SUN_NUMBER % 0x10,,
+       AC_MSG_FAILURE([[[$0]] unknown sun patch version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x10) % 0x10,,
+        AC_MSG_FAILURE([[[$0]] unknown sun minor version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x100),,
+        AC_MSG_FAILURE([[[$0]] unknown sun major version]))
+    ],
+    [dnl
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+        _AX_COMPILER_VERSION_SUN_NUMBER % 0x10,,
+        AC_MSG_FAILURE([[[$0]] unknown sun patch version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x100) % 0x100,,
+        AC_MSG_FAILURE([[[$0]] unknown sun minor version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+        (_AX_COMPILER_VERSION_SUN_NUMBER / 0x1000),,
+        AC_MSG_FAILURE([[[$0]] unknown sun major version]))
+    ])
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+])
+
+AC_DEFUN([_AX_COMPILER_VERSION_HP],[
+  m4_define([_AX_COMPILER_VERSION_HP_NUMBER],
+            [
+            #if defined(__HP_cc)
+            __HP_cc
+            #else
+            __HP_aCC
+            #endif
+           ])
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_untilA0121,
+    !!(_AX_COMPILER_VERSION_HP_NUMBER <= 1),,
+    AC_MSG_FAILURE([[[$0]] unknown hp release version]))
+  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_untilA0121" = X1],
+    [dnl By default output last version with this behavior.
+     dnl it is so old
+      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="01.21.00"
+    ],
+    [dnl
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+        (_AX_COMPILER_VERSION_HP_NUMBER % 100),,
+        AC_MSG_FAILURE([[[$0]] unknown hp release version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+        ((_AX_COMPILER_VERSION_HP_NUMBER / 100)%100),,
+        AC_MSG_FAILURE([[[$0]] unknown hp minor version]))
+      AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+        ((_AX_COMPILER_VERSION_HP_NUMBER / 10000)%100),,
+        AC_MSG_FAILURE([[[$0]] unknown hp major version]))
+      ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+    ])
+])
+
+AC_DEFUN([_AX_COMPILER_VERSION_DEC],[dnl
+  m4_define([_AX_COMPILER_VERSION_DEC_NUMBER],
+            [
+            #if defined(__DECC_VER)
+            __DECC_VER
+            #else
+            __DECCXX_VER
+            #endif
+           ])
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    (_AX_COMPILER_VERSION_DEC_NUMBER % 10000),,
+    AC_MSG_FAILURE([[[$0]] unknown dec release version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    ((_AX_COMPILER_VERSION_DEC_NUMBER / 100000UL)%100),,
+    AC_MSG_FAILURE([[[$0]] unknown dec minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    ((_AX_COMPILER_VERSION_DEC_NUMBER / 10000000UL)%100),,
+    AC_MSG_FAILURE([[[$0]] unknown dec major version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# borland
+AC_DEFUN([_AX_COMPILER_VERSION_BORLAND],[dnl
+  m4_define([_AX_COMPILER_VERSION_TURBOC_NUMBER],
+            [
+            #if defined(__TURBOC__)
+            __TURBOC__
+            #else
+            choke me
+            #endif
+           ])
+  m4_define([_AX_COMPILER_VERSION_BORLANDC_NUMBER],
+            [
+            #if defined(__BORLANDC__)
+            __BORLANDC__
+            #else
+            __CODEGEARC__
+            #endif
+           ])
+ AC_COMPILE_IFELSE(
+   [AC_LANG_PROGRAM(,
+     _AX_COMPILER_VERSION_TURBOC_NUMBER)],
+   [dnl TURBOC
+     AC_COMPUTE_INT(
+       _ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw,
+       _AX_COMPILER_VERSION_TURBOC_NUMBER,,
+       AC_MSG_FAILURE([[[$0]] unknown turboc version]))
+     AS_IF(
+       [test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw -lt 661 || test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw -gt 1023],
+       [dnl compute normal version
+        AC_COMPUTE_INT(
+         _ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+         _AX_COMPILER_VERSION_TURBOC_NUMBER % 0x100,,
+         AC_MSG_FAILURE([[[$0]] unknown turboc minor version]))
+       AC_COMPUTE_INT(
+         _ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+         (_AX_COMPILER_VERSION_TURBOC_NUMBER/0x100)%0x100,,
+         AC_MSG_FAILURE([[[$0]] unknown turboc major version]))
+       ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor"],
+      [dnl special version
+       AS_CASE([$_ax_[]_AC_LANG_ABBREV[]_compiler_version_turboc_raw],
+         [661],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:1.00"],
+        [662],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:1.01"],
+         [663],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="0turboc:2.00"],
+        [
+        AC_MSG_WARN([[[$0]] unknown turboc version between 0x295 and 0x400 please report bug])
+        ax_cv_[]_AC_LANG_ABBREV[]_compiler_version=""
+        ])
+      ])
+    ],
+    # borlandc
+    [
+    AC_COMPUTE_INT(
+      _ax_[]_AC_LANG_ABBREV[]_compiler_version_borlandc_raw,
+      _AX_COMPILER_VERSION_BORLANDC_NUMBER,,
+      AC_MSG_FAILURE([[[$0]] unknown borlandc version]))
+    AS_CASE([$_ax_[]_AC_LANG_ABBREV[]_compiler_version_borlandc_raw],
+      dnl BORLANDC++ before 5.5
+      [512] ,[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:2.00"],
+      [1024],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:3.00"],
+      [1024],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:3.00"],
+      [1040],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:3.1"],
+      [1106],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:4.0"],
+      [1280],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:5.0"],
+      [1312],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="1borlanc:5.02"],
+      dnl C++ Builder era
+      [1328],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="2cppbuilder:3.0"],
+      [1344],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="2cppbuilder:4.0"],
+      dnl BORLANDC++ after 5.5
+      [1360],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="3borlancpp:5.5"],
+      [1361],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="3borlancpp:5.51"],
+      [1378],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="3borlancpp:5.6.4"],
+      dnl C++ Builder with year number
+      [1392],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2006"],
+      [1424],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2007"],
+      [1555],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2009"],
+      [1569],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="4cppbuilder:2010"],
+      dnl XE version
+      [1584],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe"],
+      [1600],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe:2"],
+      [1616],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe:3"],
+      [1632],[ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="5xe:4"],
+      [
+      AC_MSG_WARN([[[$0]] Unknown borlandc compiler version $_ax_[]_AC_LANG_ABBREV[]_compiler_version_borlandc_raw please report bug])
+      ])
+    ])
+  ])
+
+# COMO
+AC_DEFUN([_AX_COMPILER_VERSION_COMEAU],
+  [ dnl
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    [__COMO_VERSION__%100],,
+    AC_MSG_FAILURE([[[$0]] unknown comeau compiler minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    [(__COMO_VERSION__/100)%10],,
+    AC_MSG_FAILURE([[[$0]] unknown comeau compiler major version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor"
+  ])
+
+# KAI
+AC_DEFUN([_AX_COMPILER_VERSION_KAI],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [__KCC_VERSION%100],,
+    AC_MSG_FAILURE([[[$0]] unknown kay compiler patch version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    [(__KCC_VERSION/100)%10],,
+    AC_MSG_FAILURE([[[$0]] unknown kay compiler minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    [(__KCC_VERSION/1000)%10],,
+    AC_MSG_FAILURE([[[$0]] unknown kay compiler major version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+dnl LCC
+dnl LCC does not output version...
+
+# SGI
+AC_DEFUN([_AX_COMPILER_VERSION_SGI],[
+   m4_define([_AX_COMPILER_VERSION_SGI_NUMBER],
+            [
+            #if defined(_COMPILER_VERSION)
+            _COMPILER_VERSION
+            #else
+            _SGI_COMPILER_VERSION
+            #endif
+           ])
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [_AX_COMPILER_VERSION_SGI_NUMBER%10],,
+    AC_MSG_FAILURE([[[$0]] unknown SGI compiler patch version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    [(_AX_COMPILER_VERSION_SGI_NUMBER/10)%10],,
+    AC_MSG_FAILURE([[[$0]] unknown SGI compiler minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    [(_AX_COMPILER_VERSION_SGI_NUMBER/100)%10],,
+    AC_MSG_FAILURE([[[$0]] unknown SGI compiler major version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# microsoft
+AC_DEFUN([_AX_COMPILER_VERSION_MICROSOFT],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    _MSC_VER%100,,
+    AC_MSG_FAILURE([[[$0]] unknown microsoft compiler minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    (_MSC_VER/100)%100,,
+    AC_MSG_FAILURE([[[$0]] unknown microsoft compiler major version]))
+  dnl could be overridden
+  _ax_[]_AC_LANG_ABBREV[]_compiler_version_patch=0
+  _ax_[]_AC_LANG_ABBREV[]_compiler_version_build=0
+  # special case for version 6
+  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major" = "X12"],
+    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+       _MSC_FULL_VER%1000,,
+       _ax_[]_AC_LANG_ABBREV[]_compiler_version_patch=0)])
+  # for version 7
+  AS_IF([test "X$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major" = "X13"],
+    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+       _MSC_FULL_VER%1000,,
+       AC_MSG_FAILURE([[[$0]] unknown microsoft compiler patch version]))
+    ])
+  # for version > 8
+ AS_IF([test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_major -ge 14],
+    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+       _MSC_FULL_VER%10000,,
+       AC_MSG_FAILURE([[[$0]] unknown microsoft compiler patch version]))
+    ])
+ AS_IF([test $_ax_[]_AC_LANG_ABBREV[]_compiler_version_major -ge 15],
+    [AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_build,
+       _MSC_BUILD,,
+       AC_MSG_FAILURE([[[$0]] unknown microsoft compiler build version]))
+    ])
+ ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_build"
+ ])
+
+# for metrowerks
+AC_DEFUN([_AX_COMPILER_VERSION_METROWERKS],[dnl
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    __MWERKS__%0x100,,
+    AC_MSG_FAILURE([[[$0]] unknown metrowerks compiler patch version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    (__MWERKS__/0x100)%0x10,,
+    AC_MSG_FAILURE([[[$0]] unknown metrowerks compiler minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    (__MWERKS__/0x1000)%0x10,,
+    AC_MSG_FAILURE([[[$0]] unknown metrowerks compiler major version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# for watcom
+AC_DEFUN([_AX_COMPILER_VERSION_WATCOM],[dnl
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    __WATCOMC__%100,,
+    AC_MSG_FAILURE([[[$0]] unknown watcom compiler minor version]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    (__WATCOMC__/100)%100,,
+    AC_MSG_FAILURE([[[$0]] unknown watcom compiler major version]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor"
+  ])
+
+# for PGI
+AC_DEFUN([_AX_COMPILER_VERSION_PORTLAND],[
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_major,
+    __PGIC__,,
+    AC_MSG_FAILURE([[[$0]] unknown pgi major]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor,
+    __PGIC_MINOR__,,
+    AC_MSG_FAILURE([[[$0]] unknown pgi minor]))
+  AC_COMPUTE_INT(_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch,
+    [__PGIC_PATCHLEVEL__],,
+    AC_MSG_FAILURE([[[$0]] unknown pgi patch level]))
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version="$_ax_[]_AC_LANG_ABBREV[]_compiler_version_major.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_minor.$_ax_[]_AC_LANG_ABBREV[]_compiler_version_patch"
+  ])
+
+# tcc
+AC_DEFUN([_AX_COMPILER_VERSION_TCC],[
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_version=[`tcc -v | $SED 's/^[ ]*tcc[ ]\+version[ ]\+\([0-9.]\+\).*/\1/g'`]
+  ])
+# main entry point
+AC_DEFUN([AX_COMPILER_VERSION],[dnl
+  AC_REQUIRE([AX_COMPILER_VENDOR])
+  AC_REQUIRE([AC_PROG_SED])
+  AC_CACHE_CHECK([for _AC_LANG compiler version],
+    ax_cv_[]_AC_LANG_ABBREV[]_compiler_version,
+    [ dnl
+      AS_CASE([$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor],
+        [intel],[_AX_COMPILER_VERSION_INTEL],
+       [ibm],[_AX_COMPILER_VERSION_IBM],
+       [pathscale],[_AX_COMPILER_VERSION_PATHSCALE],
+       [clang],[_AX_COMPILER_VERSION_CLANG],
+       [cray],[_AX_COMPILER_VERSION_CRAY],
+       [fujitsu],[_AX_COMPILER_VERSION_FUJITSU],
+        [gnu],[_AX_COMPILER_VERSION_GNU],
+       [sun],[_AX_COMPILER_VERSION_SUN],
+       [hp],[_AX_COMPILER_VERSION_HP],
+       [dec],[_AX_COMPILER_VERSION_DEC],
+       [borland],[_AX_COMPILER_VERSION_BORLAND],
+       [comeau],[_AX_COMPILER_VERSION_COMEAU],
+       [kai],[_AX_COMPILER_VERSION_KAI],
+       [sgi],[_AX_COMPILER_VERSION_SGI],
+       [microsoft],[_AX_COMPILER_VERSION_MICROSOFT],
+       [metrowerks],[_AX_COMPILER_VERSION_METROWERKS],
+       [watcom],[_AX_COMPILER_VERSION_WATCOM],
+       [portland],[_AX_COMPILER_VERSION_PORTLAND],
+       [tcc],[_AX_COMPILER_VERSION_TCC],
+       [ax_cv_[]_AC_LANG_ABBREV[]_compiler_version=""])
+    ])
+])
diff --git a/m4/ax_recursive_eval.m4 b/m4/ax_recursive_eval.m4
new file mode 100644 (file)
index 0000000..0625aca
--- /dev/null
@@ -0,0 +1,56 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_recursive_eval.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_RECURSIVE_EVAL(VALUE, RESULT)
+#
+# DESCRIPTION
+#
+#   Interpolate the VALUE in loop until it doesn't change, and set the
+#   result to $RESULT. WARNING: It's easy to get an infinite loop with some
+#   unsane input.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Alexandre Duret-Lutz <adl@gnu.org>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 1
+
+AC_DEFUN([AX_RECURSIVE_EVAL],
+[_lcl_receval="$1"
+$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+     test "x$exec_prefix" = xNONE && exec_prefix="${prefix}"
+     _lcl_receval_old=''
+     while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do
+       _lcl_receval_old="[$]_lcl_receval"
+       eval _lcl_receval="\"[$]_lcl_receval\""
+     done
+     echo "[$]_lcl_receval")`])
diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4
new file mode 100644 (file)
index 0000000..17c3eab
--- /dev/null
@@ -0,0 +1,37 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+#   AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+#   been defined and thus are available for use.  This avoids random issues
+#   where a macro isn't expanded.  Instead the configure script emits a
+#   non-fatal:
+#
+#     ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+#   It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+#   Here's an example:
+#
+#     AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+#   Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 2
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+  m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
similarity index 100%
rename from M4/clip_mode.m4
rename to m4/clip_mode.m4
similarity index 97%
rename from M4/extra_pkg.m4
rename to m4/extra_pkg.m4
index afe474e..ce4ecb8 100644 (file)
@@ -50,7 +50,7 @@ eval "pkg_LIBS=\${pkg_cv_[]$1[]_LIBS}"
 CFLAGS="$CFLAGS $pkg_CFLAGS"
 LIBS="$LIBS $pkg_LIBS"
 
-AC_TRY_LINK([], puts ("");, pkg_link=yes, pkg_link=no)
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [puts ("")])], pkg_link=yes, pkg_link=no)
 
 CFLAGS=$pkg_link_saved_CFLAGS
 LIBS=$pkg_link_saved_LIBS
similarity index 100%
rename from M4/flexible_array.m4
rename to m4/flexible_array.m4
similarity index 100%
rename from M4/octave.m4
rename to m4/octave.m4
similarity index 100%
rename from M4/stack_protect.m4
rename to m4/stack_protect.m4
diff --git a/man/Makefile.am b/man/Makefile.am
deleted file mode 100644 (file)
index 4964336..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-man_MANS = sndfile-info.1 sndfile-play.1 sndfile-convert.1 sndfile-cmp.1 \
-       sndfile-metadata-get.1 sndfile-metadata-set.1 sndfile-concat.1 \
-       sndfile-interleave.1 sndfile-deinterleave.1 sndfile-salvage.1
-
-EXTRA_DIST = sndfile-info.1 sndfile-play.1 sndfile-convert.1 sndfile-cmp.1 \
-       sndfile-metadata-get.1 sndfile-concat.1 sndfile-interleave.1 \
-       sndfile-salvage.1
-
-# Same manpage for both programs.
-sndfile-metadata-set.1 : sndfile-metadata-get.1
-       $(LN_S) $(srcdir)/sndfile-metadata-get.1 $@
-
-sndfile-deinterleave.1 : sndfile-interleave.1
-       $(LN_S) $(srcdir)/sndfile-interleave.1 $@
index d346e2c..88aaafe 100644 (file)
@@ -23,7 +23,7 @@ The audio data is the same.
 The audio data differs.
 .El
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile
+.Lk http://libsndfile.github.io/libsndfile/
 .Sh AUTHORS
 .An Conrad Parker Aq Mt conrad@metadecks.org
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com
index 2110401..3ba34c7 100644 (file)
@@ -23,6 +23,6 @@ The output file is overwritten if it already exists.
 .Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com
index d34edcd..e7156ee 100644 (file)
@@ -155,6 +155,6 @@ This will not always work as most container formats
 .Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com .
index 68c6a1e..a8c3749 100644 (file)
@@ -29,6 +29,6 @@ Display instrument info:
 a base note, gain, velocity, key, and loop points.
 .El
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com .
index 31723a1..0cf7076 100644 (file)
@@ -57,6 +57,6 @@ Output files :
     multi_03.wav
 .Ed
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com
index 90aac3a..61dfae7 100644 (file)
@@ -110,7 +110,7 @@ Set the string date to current.
 .Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .Lk http://tech.ebu.ch/docs/tech/tech3285.pdf
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com
index 1d161b3..f36d131 100644 (file)
@@ -29,6 +29,6 @@ AudioToolbox
 waveOut
 .El
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com
index 87e0408..b2010f1 100644 (file)
@@ -19,7 +19,7 @@ This file is overwritten if it already exists.
 .Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
-.Lk http://www.mega-nerd.com/libsndfile/
+.Lk http://libsndfile.github.io/libsndfile/
 .\".Lk http://en.wikipedia.org/wiki/RF64
 .Sh AUTHORS
 .An Erik de Castro Lopo Aq Mt erikd@mega-nerd.com
diff --git a/ossfuzz/ci_oss.sh b/ossfuzz/ci_oss.sh
new file mode 100755 (executable)
index 0000000..408b00d
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+set -ex
+
+PROJECT_NAME=libsndfile
+
+# Clone the oss-fuzz repository
+git clone https://github.com/google/oss-fuzz.git /tmp/ossfuzz
+
+if [[ ! -d /tmp/ossfuzz/projects/${PROJECT_NAME} ]]
+then
+    echo "Could not find the ${PROJECT_NAME} project in ossfuzz"
+
+    # Exit with a success code while the libsndfile project is not expected to exist
+    # on oss-fuzz.
+    exit 0
+fi
+
+# Work out which branch to clone from, inside Docker
+BRANCH=${GITHUB_REF}
+
+# Modify the oss-fuzz Dockerfile so that we're checking out the current reference on CI.
+sed -i "s@RUN.*@RUN git config --global remote.origin.fetch '+refs/pull/*:refs/remotes/origin/pull/*' \&\& git clone https://github.com/libsndfile/libsndfile.git /src/libsndfile \&\& cd /src/libsndfile \&\& git checkout -b ${BRANCH}@" /tmp/ossfuzz/projects/${PROJECT_NAME}/Dockerfile
+
+# Try and build the fuzzers
+pushd /tmp/ossfuzz
+python3 infra/helper.py build_image --pull ${PROJECT_NAME}
+python3 infra/helper.py build_fuzzers ${PROJECT_NAME}
+python3 infra/helper.py check_build ${PROJECT_NAME} --engine libfuzzer --sanitizer address --architecture x86_64
+popd
diff --git a/ossfuzz/ossfuzz.sh b/ossfuzz/ossfuzz.sh
new file mode 100755 (executable)
index 0000000..b93d4fc
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash -eu
+
+# This script is called by the oss-fuzz main project when compiling the fuzz
+# targets. This script is regression tested by ci_oss.sh.
+
+# Save off the current folder as the build root.
+export BUILD_ROOT=$PWD
+
+echo "CC: ${CC:-}"
+echo "CXX: ${CXX:-}"
+echo "LIB_FUZZING_ENGINE: ${LIB_FUZZING_ENGINE:-}"
+echo "CFLAGS: ${CFLAGS:-}"
+echo "CXXFLAGS: ${CXXFLAGS:-}"
+echo "OUT: ${OUT:-}"
+
+export MAKEFLAGS+="-j$(nproc)"
+
+# Install dependencies
+apt-get -y install autoconf autogen automake libtool pkg-config python
+
+# For now, do not install the following libraries (as they won't be in the
+# final image):
+# libasound2-dev libflac-dev libogg-dev libopus-dev libvorbis-dev
+
+# Compile the fuzzer.
+./autogen.sh
+./configure --disable-shared --enable-ossfuzzers
+make V=1
+
+# Copy the fuzzer to the output directory.
+cp -v ossfuzz/sndfile_fuzzer $OUT/
diff --git a/ossfuzz/sndfile_fuzzer.cc b/ossfuzz/sndfile_fuzzer.cc
new file mode 100644 (file)
index 0000000..3c85073
--- /dev/null
@@ -0,0 +1,155 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sndfile.h>
+#include <inttypes.h>
+
+typedef struct
+{
+  sf_count_t offset;
+  sf_count_t length;
+  const unsigned char *data;
+} VIO_DATA;
+
+static sf_count_t vfget_filelen (void *user_data)
+{
+  VIO_DATA *vf = (VIO_DATA *)user_data;
+  return vf->length;
+}
+
+static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
+{
+  VIO_DATA *vf = (VIO_DATA *)user_data;
+  sf_count_t new_offset;
+
+  switch (whence)
+  {
+    case SEEK_SET:
+      new_offset = offset;
+      break ;
+
+    case SEEK_CUR:
+      new_offset = vf->offset + offset;
+      break ;
+
+    case SEEK_END:
+      new_offset = vf->length + offset;
+      break;
+
+    default:
+      break;
+  }
+
+  /* Ensure you can't seek outside the data */
+  if (new_offset > vf->length)
+  {
+    /* Trying to seek past the end of the data */
+    printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");"
+           "  whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n",
+           new_offset, vf->length, whence, vf->offset, offset);
+    new_offset = vf->length;
+  }
+  else if (new_offset < 0)
+  {
+    /* Trying to seek before the start of the data */
+    printf("vf underseek: new_offset(%" PRId64 ") < 0;  whence(%d), vf->offset"
+           "(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n",
+           new_offset, whence, vf->offset, vf->length, offset);
+    new_offset = 0;
+  }
+  vf->offset = new_offset;
+
+  return vf->offset;
+}
+
+static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
+{
+  VIO_DATA *vf = (VIO_DATA *)user_data;
+
+  if (vf->offset + count > vf->length)
+  {
+    count = vf->length - vf->offset;
+  }
+
+  memcpy(ptr, vf->data + vf->offset, count);
+  vf->offset += count;
+
+  return count;
+}
+
+static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
+{
+  (void)ptr;
+  (void)count;
+  (void)user_data;
+
+  // Cannot write to this virtual file.
+  return 0;
+}
+
+static sf_count_t vftell (void *user_data)
+{ VIO_DATA *vf = (VIO_DATA *)user_data;
+
+  return vf->offset;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+  VIO_DATA vio_data;
+  SF_VIRTUAL_IO vio;
+  SF_INFO sndfile_info;
+  SNDFILE *sndfile = NULL;
+  float* read_buffer = NULL;
+
+  // Initialize the virtual IO structure.
+  vio.get_filelen = vfget_filelen;
+  vio.seek = vfseek;
+  vio.read = vfread;
+  vio.write = vfwrite;
+  vio.tell = vftell;
+
+  // Initialize the VIO user data.
+  vio_data.data = data;
+  vio_data.length = size;
+  vio_data.offset = 0;
+
+  memset(&sndfile_info, 0, sizeof(SF_INFO));
+
+  // Try and open the virtual file.
+  sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data);
+
+  if (sndfile_info.channels == 0)
+  {
+    // No sound channels in file.
+    goto EXIT_LABEL;
+  }
+  else if (sndfile_info.channels > 1024 * 1024)
+  {
+    // Too many channels to handle.
+    goto EXIT_LABEL;
+  }
+
+  // Just the right number of channels. Create some buffer space for reading.
+  read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
+  if (read_buffer == NULL)
+  {
+    abort();
+  }
+
+  while (sf_readf_float(sndfile, read_buffer, 1))
+  {
+    // Do nothing with the data.
+  }
+
+EXIT_LABEL:
+
+  if (sndfile != NULL)
+  {
+    sf_close(sndfile);
+  }
+
+  free(read_buffer);
+
+  return 0;
+}
diff --git a/ossfuzz/standaloneengine.cc b/ossfuzz/standaloneengine.cc
new file mode 100644 (file)
index 0000000..ab6408d
--- /dev/null
@@ -0,0 +1,86 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testinput.h"
+
+/**
+ * Main procedure for standalone fuzzing engine.
+ *
+ * Reads filenames from the argument array. For each filename, read the file
+ * into memory and then call the fuzzing interface with the data.
+ */
+int main(int argc, char **argv)
+{
+  int ii;
+  for(ii = 1; ii < argc; ii++)
+  {
+    FILE *infile;
+    printf("[%s] ", argv[ii]);
+
+    /* Try and open the file. */
+    infile = fopen(argv[ii], "rb");
+    if(infile)
+    {
+      uint8_t *buffer = NULL;
+      size_t buffer_len;
+
+      printf("Opened.. ");
+
+      /* Get the length of the file. */
+      fseek(infile, 0L, SEEK_END);
+      buffer_len = ftell(infile);
+
+      /* Reset the file indicator to the beginning of the file. */
+      fseek(infile, 0L, SEEK_SET);
+
+      /* Allocate a buffer for the file contents. */
+      buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t));
+      if(buffer)
+      {
+        size_t result;
+
+        /* Read all the text from the file into the buffer. */
+        result = fread(buffer, sizeof(uint8_t), buffer_len, infile);
+
+        if (result == buffer_len)
+        {
+          printf("Read %zu bytes, fuzzing.. ", buffer_len);
+          /* Call the fuzzer with the data. */
+          LLVMFuzzerTestOneInput(buffer, buffer_len);
+
+          printf("complete !!");
+        }
+        else
+        {
+          fprintf(stderr,
+                  "Failed to read %zu bytes (result %zu)\n",
+                  buffer_len,
+                  result);
+        }
+
+        /* Free the buffer as it's no longer needed. */
+        free(buffer);
+        buffer = NULL;
+      }
+      else
+      {
+        fprintf(stderr,
+                "[%s] Failed to allocate %zu bytes \n",
+                argv[ii],
+                buffer_len);
+      }
+
+      /* Close the file as it's no longer needed. */
+      fclose(infile);
+      infile = NULL;
+    }
+    else
+    {
+      /* Failed to open the file. Maybe wrong name or wrong permissions? */
+      fprintf(stderr, "[%s] Open failed. \n", argv[ii]);
+    }
+
+    printf("\n");
+  }
+}
diff --git a/ossfuzz/testinput.h b/ossfuzz/testinput.h
new file mode 100644 (file)
index 0000000..6ab9b51
--- /dev/null
@@ -0,0 +1,3 @@
+#include <inttypes.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
diff --git a/programs/Makefile.am b/programs/Makefile.am
deleted file mode 100644 (file)
index 6764c11..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-bin_PROGRAMS = sndfile-info sndfile-play sndfile-convert sndfile-cmp \
-                               sndfile-metadata-set sndfile-metadata-get sndfile-interleave \
-                               sndfile-deinterleave sndfile-concat sndfile-salvage
-
-OS_SPECIFIC_CFLAGS = @OS_SPECIFIC_CFLAGS@
-OS_SPECIFIC_LINKS = @OS_SPECIFIC_LINKS@
-
-AM_CPPFLAGS = -I$(top_srcdir)/src $(OS_SPECIFIC_CFLAGS)
-
-CLEANFILES = *~ sndfile-*.exe *.wav
-
-# This is the BeOS version of sndfile-play. It needs to be compiled with the C++
-# compiler.
-EXTRA_DIST = sndfile-play-beos.cpp test-sndfile-metadata-set.py
-
-sndfile_info_SOURCES = sndfile-info.c common.c common.h
-sndfile_info_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_play_SOURCES = sndfile-play.c common.c common.h
-sndfile_play_LDADD = $(top_builddir)/src/libsndfile.la $(OS_SPECIFIC_LINKS) $(ALSA_LIBS) $(SNDIO_LIBS)
-
-sndfile_convert_SOURCES = sndfile-convert.c common.c common.h
-sndfile_convert_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_cmp_SOURCES = sndfile-cmp.c common.c common.h
-sndfile_cmp_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_metadata_set_SOURCES = sndfile-metadata-set.c common.c common.h
-sndfile_metadata_set_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_metadata_get_SOURCES = sndfile-metadata-get.c common.c common.h
-sndfile_metadata_get_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_interleave_SOURCES = sndfile-interleave.c common.c common.h
-sndfile_interleave_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_deinterleave_SOURCES = sndfile-deinterleave.c common.c common.h
-sndfile_deinterleave_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_concat_SOURCES = sndfile-concat.c common.c common.h
-sndfile_concat_LDADD = $(top_builddir)/src/libsndfile.la
-
-sndfile_salvage_SOURCES = sndfile-salvage.c common.c common.h
-sndfile_salvage_LDADD = $(top_builddir)/src/libsndfile.la
-
-check :
-       @if [ -x /usr/bin/python ]; then $(top_srcdir)/programs/test-sndfile-metadata-set.py @HOST_TRIPLET@ ; fi
index 3fc4e3d..fb479f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2008 George Blood Audio
 **
 ** All rights reserved.
@@ -36,6 +36,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <stdint.h>
+#include <math.h>
 
 #include <sndfile.h>
 
 
 #define        MIN(x, y)       ((x) < (y) ? (x) : (y))
 
-void
+int
 sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize)
 {      static double   data [BUFFER_LEN], max ;
-       int             frames, readcount, k ;
+       sf_count_t              frames, readcount, k ;
 
        frames = BUFFER_LEN / channels ;
        readcount = frames ;
 
        sf_command (infile, SFC_CALC_SIGNAL_MAX, &max, sizeof (max)) ;
+       if (!isnormal (max)) /* neither zero, subnormal, infinite, nor NaN */
+               return 1 ;
 
        if (!normalize && max < 1.0)
        {       while (readcount > 0)
@@ -67,12 +70,16 @@ sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize
                while (readcount > 0)
                {       readcount = sf_readf_double (infile, data, frames) ;
                        for (k = 0 ; k < readcount * channels ; k++)
-                               data [k] /= max ;
+                       {       data [k] /= max ;
+
+                               if (!isfinite (data [k])) /* infinite or NaN */
+                                       return 1;
+                               }
                        sf_writef_double (outfile, data, readcount) ;
                        } ;
                } ;
 
-       return ;
+       return ;
 } /* sfe_copy_data_fp */
 
 void
@@ -147,6 +154,18 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET
        REPLACE_IF_NEW (origination_time) ;
        REPLACE_IF_NEW (umid) ;
 
+       /* Special case loudness values */
+#define REPLACE_IF_NEW_INT(x) \
+               if (info->x != NULL) \
+               {       binfo.x = round (atof (info->x) * 100.0) ; \
+                       } ;
+
+       REPLACE_IF_NEW_INT (loudness_value) ;
+       REPLACE_IF_NEW_INT (loudness_range) ;
+       REPLACE_IF_NEW_INT (max_true_peak_level) ;
+       REPLACE_IF_NEW_INT (max_momentary_loudness) ;
+       REPLACE_IF_NEW_INT (max_shortterm_loudness) ;
+
        /* Special case for Time Ref. */
        if (info->time_ref != NULL)
        {       uint64_t ts = atoll (info->time_ref) ;
@@ -252,7 +271,12 @@ sfe_apply_metadata_changes (const char * filenames [2], const METADATA_INFO * in
 
                /* If the input file is not the same as the output file, copy the data. */
                if ((infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT))
-                       sfe_copy_data_fp (outfile, infile, sfinfo.channels, SF_FALSE) ;
+               {       if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, SF_FALSE) != 0)
+                       {       printf ("Error : Not able to decode input file '%s'\n", filenames [0]) ;
+                               error_code = 1 ;
+                               goto cleanup_exit ;
+                               } ;
+                       }
                else
                        sfe_copy_data_int (outfile, infile, sfinfo.channels) ;
                } ;
@@ -282,6 +306,7 @@ typedef struct
        int                     format ;
 } OUTPUT_FORMAT_MAP ;
 
+/* Map a file name extension to a container format. */
 static OUTPUT_FORMAT_MAP format_map [] =
 {
        {       "wav",          0,      SF_FORMAT_WAV   },
@@ -289,8 +314,8 @@ static OUTPUT_FORMAT_MAP format_map [] =
        {       "au",           0,      SF_FORMAT_AU    },
        {       "snd",          0,      SF_FORMAT_AU    },
        {       "raw",          0,      SF_FORMAT_RAW   },
-       {       "gsm",          0,      SF_FORMAT_RAW   },
-       {       "vox",          0,      SF_FORMAT_RAW   },
+       {       "gsm",          0,      SF_FORMAT_RAW | SF_FORMAT_GSM610 },
+       {       "vox",          0,      SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM },
        {       "paf",          0,      SF_FORMAT_PAF | SF_ENDIAN_BIG },
        {       "fap",          0,      SF_FORMAT_PAF | SF_ENDIAN_LITTLE },
        {       "svx",          0,      SF_FORMAT_SVX   },
@@ -316,6 +341,7 @@ static OUTPUT_FORMAT_MAP format_map [] =
        {       "prc",          0,      SF_FORMAT_WVE   },
        {       "ogg",          0,      SF_FORMAT_OGG   },
        {       "oga",          0,      SF_FORMAT_OGG   },
+       {       "opus",         0,      SF_FORMAT_OGG | SF_FORMAT_OPUS },
        {       "mpc",          0,      SF_FORMAT_MPC2K },
        {       "rf64",         0,      SF_FORMAT_RF64  },
 } ; /* format_map */
@@ -336,17 +362,14 @@ sfe_file_type_of_ext (const char *str, int format)
        for (k = 0 ; buffer [k] ; k++)
                buffer [k] = tolower ((buffer [k])) ;
 
-       if (strcmp (buffer, "gsm") == 0)
-               return SF_FORMAT_RAW | SF_FORMAT_GSM610 ;
-
-       if (strcmp (buffer, "vox") == 0)
-               return SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM ;
-
        for (k = 0 ; k < (int) (sizeof (format_map) / sizeof (format_map [0])) ; k++)
-       {       if (format_map [k].len > 0 && strncmp (buffer, format_map [k].ext, format_map [k].len) == 0)
-                       return format_map [k].format | format ;
-               else if (strcmp (buffer, format_map [k].ext) == 0)
-                       return format_map [k].format | format ;
+       {       if ((format_map [k].len > 0 && strncmp (buffer, format_map [k].ext, format_map [k].len) == 0) ||
+                       (strcmp (buffer, format_map [k].ext) == 0))
+               {       if (format_map [k].format & SF_FORMAT_SUBMASK)
+                               return format_map [k].format ;
+                       else
+                               return format_map [k].format | format ;
+                       } ;
                } ;
 
        /* Default if all the above fails. */
@@ -361,7 +384,14 @@ sfe_dump_format_map (void)
        for (k = 0 ; k < ARRAY_LEN (format_map) ; k++)
        {       info.format = format_map [k].format ;
                sf_command (NULL, SFC_GET_FORMAT_INFO, &info, sizeof (info)) ;
-               printf ("        %-10s : %s\n", format_map [k].ext, info.name == NULL ? "????" : info.name) ;
+               printf ("        %-10s : %s", format_map [k].ext, info.name == NULL ? "????" : info.name) ;
+               if (format_map [k].format & SF_FORMAT_SUBMASK)
+               {       info.format = format_map [k].format & SF_FORMAT_SUBMASK ;
+                       sf_command (NULL, SFC_GET_FORMAT_INFO, &info, sizeof (info)) ;
+                       printf (" %s", info.name == NULL ? "????" : info.name) ;
+                       } ;
+               putchar ('\n') ;
+
                } ;
 
 } /* sfe_dump_format_map */
@@ -460,8 +490,8 @@ sfe_codec_name (int format)
                case SF_FORMAT_ALAC_20 : return "20 bit ALAC" ;
                case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ;
                case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ;
+               case SF_FORMAT_OPUS : return "Opus" ;
                default : break ;
                } ;
        return "unknown" ;
 } /* sfe_codec_name */
-
index eda2d7d..5ed36db 100644 (file)
@@ -54,6 +54,11 @@ typedef struct
        const char * origination_date ;
        const char * origination_time ;
        const char * umid ;
+       const char * loudness_value ;
+       const char * loudness_range ;
+       const char * max_true_peak_level ;
+       const char * max_momentary_loudness ;
+       const char * max_shortterm_loudness ;
        const char * coding_history ;
        const char * time_ref ;
 } METADATA_INFO ;
@@ -62,7 +67,7 @@ typedef SF_BROADCAST_INFO_VAR (2048) SF_BROADCAST_INFO_2K ;
 
 void sfe_apply_metadata_changes (const char * filenames [2], const METADATA_INFO * info) ;
 
-void sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize) ;
+int sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize) ;
 
 void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ;
 
@@ -75,4 +80,3 @@ const char * program_name (const char * argv0) ;
 const char * sfe_endian_name (int format) ;
 const char * sfe_container_name (int format) ;
 const char * sfe_codec_name (int format) ;
-
index dff7f79..5aa4fdf 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** All rights reserved.
 **
@@ -68,6 +68,7 @@ usage_exit (const char *progname)
                "        -pcm24     : 24 bit pcm\n"
                "        -pcm32     : 32 bit pcm\n"
                "        -float32   : 32 bit floating point\n"
+               "        -float64   : 64 bit floating point\n"
                "        -ulaw      : ULAW\n"
                "        -alaw      : ALAW\n"
                "        -alac16    : 16 bit ALAC (CAF only)\n"
@@ -81,6 +82,7 @@ usage_exit (const char *progname)
                "        -dwvw16    : 16 bit DWVW (AIFF only)\n"
                "        -dwvw24    : 24 bit DWVW (AIFF only)\n"
                "        -vorbis    : Vorbis (OGG only)\n"
+               "        -opus      : Opus (OGG only)\n"
                ) ;
 
        puts (
@@ -105,6 +107,7 @@ static void
 report_format_error_exit (const char * argv0, SF_INFO * sfinfo)
 {      int old_format = sfinfo->format ;
        int endian = sfinfo->format & SF_FORMAT_ENDMASK ;
+       int channels = sfinfo->channels ;
 
        sfinfo->format = old_format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
 
@@ -113,6 +116,12 @@ report_format_error_exit (const char * argv0, SF_INFO * sfinfo)
                exit (1) ;
                } ;
 
+       sfinfo->channels = 1 ;
+       if (sf_format_check (sfinfo))
+       {       printf ("Error : output file format does not support %d channels.\n", channels) ;
+               exit (1) ;
+               } ;
+
        printf ("\n"
                        "Error : output file format is invalid.\n"
                        "The '%s' container does not support '%s' codec data.\n"
@@ -178,6 +187,10 @@ main (int argc, char * argv [])
                {       outfileminor = SF_FORMAT_FLOAT ;
                        continue ;
                        } ;
+               if (! strcmp (argv [k], "-float64"))
+               {       outfileminor = SF_FORMAT_DOUBLE ;
+                       continue ;
+                       } ;
                if (! strcmp (argv [k], "-ulaw"))
                {       outfileminor = SF_FORMAT_ULAW ;
                        continue ;
@@ -230,6 +243,10 @@ main (int argc, char * argv [])
                {       outfileminor = SF_FORMAT_VORBIS ;
                        continue ;
                        } ;
+               if (! strcmp (argv [k], "-opus"))
+               {       outfileminor = SF_FORMAT_OPUS ;
+                       continue ;
+                       } ;
 
                if (strstr (argv [k], "-override-sample-rate=") == argv [k])
                {       const char *ptr ;
@@ -312,7 +329,9 @@ main (int argc, char * argv [])
                        } ;
 
        if (sf_format_check (&sfinfo) == 0)
+       {       sf_close (infile) ;
                report_format_error_exit (argv [0], &sfinfo) ;
+               } ;
 
        if ((sfinfo.format & SF_FORMAT_SUBMASK) == SF_FORMAT_GSM610 && sfinfo.samplerate != 8000)
        {       printf (
@@ -334,8 +353,13 @@ main (int argc, char * argv [])
        if (normalize
                        || (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT)
                        || (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT)
+                       || (infileminor == SF_FORMAT_OPUS) || (outfileminor == SF_FORMAT_OPUS)
                        || (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS))
-               sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) ;
+       {       if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0)
+               {       printf ("Error : Not able to decode input file %s.\n", infilename) ;
+                       return 1 ;
+                       } ;
+               }
        else
                sfe_copy_data_int (outfile, infile, sfinfo.channels) ;
 
index e27593e..616761e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2009-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2009-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** All rights reserved.
 **
@@ -89,10 +89,21 @@ main (int argc, char **argv)
                exit (1) ;
                } ;
 
+       if (sfinfo.channels > MAX_CHANNELS)
+       {       printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n",
+                       argv [1], sfinfo.channels, MAX_CHANNELS) ;
+               exit (1) ;
+               } ;
+
+
        state.channels = sfinfo.channels ;
        sfinfo.channels = 1 ;
 
-       snprintf (pathname, sizeof (pathname), "%s", argv [1]) ;
+       if (snprintf (pathname, sizeof (pathname), "%s", argv [1]) > (int) sizeof (pathname))
+       {       printf ("\nError : Length of provided filename '%s' exceeds MAX_PATH (%d).\n", argv [1], (int) sizeof (pathname)) ;
+               exit (1) ;
+               } ;
+
        if ((cptr = strrchr (pathname, '.')) == NULL)
                ext [0] = 0 ;
        else
@@ -105,8 +116,13 @@ main (int argc, char **argv)
 
        for (ch = 0 ; ch < state.channels ; ch++)
        {       char filename [520] ;
+               size_t count ;
 
-               snprintf (filename, sizeof (filename), "%s_%02d%s", pathname, ch, ext) ;
+               count = snprintf (filename, sizeof (filename), "%s_%02d%s", pathname, ch, ext) ;
+
+               if (count >= sizeof (filename))
+               {       printf ("File name truncated to %s\n", filename) ;
+                       } ;
 
                if ((state.outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
                {       printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ;
index 87b3d42..e0e4882 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** All rights reserved.
 **
@@ -357,20 +357,35 @@ broadcast_dump (const char *filename)
 
        time_ref_sec = ((pow (2.0, 32) * bext.time_reference_high) + (1.0 * bext.time_reference_low)) / sfinfo.samplerate ;
 
-       printf ("Description      : %.*s\n", (int) sizeof (bext.description), bext.description) ;
-       printf ("Originator       : %.*s\n", (int) sizeof (bext.originator), bext.originator) ;
-       printf ("Origination ref  : %.*s\n", (int) sizeof (bext.originator_reference), bext.originator_reference) ;
-       printf ("Origination date : %.*s\n", (int) sizeof (bext.origination_date), bext.origination_date) ;
-       printf ("Origination time : %.*s\n", (int) sizeof (bext.origination_time), bext.origination_time) ;
+       printf ("Description              : %.*s\n", (int) sizeof (bext.description), bext.description) ;
+       printf ("Originator               : %.*s\n", (int) sizeof (bext.originator), bext.originator) ;
+       printf ("Origination ref          : %.*s\n", (int) sizeof (bext.originator_reference), bext.originator_reference) ;
+       printf ("Origination date         : %.*s\n", (int) sizeof (bext.origination_date), bext.origination_date) ;
+       printf ("Origination time         : %.*s\n", (int) sizeof (bext.origination_time), bext.origination_time) ;
 
        if (bext.time_reference_high == 0 && bext.time_reference_low == 0)
-               printf ("Time ref         : 0\n") ;
+               printf ("Time ref                 : 0\n") ;
        else
-               printf ("Time ref         : 0x%x%08x (%.6f seconds)\n", bext.time_reference_high, bext.time_reference_low, time_ref_sec) ;
+               printf ("Time ref                 : 0x%x%08x (%.6f seconds)\n", bext.time_reference_high, bext.time_reference_low, time_ref_sec) ;
+
+       printf ("BWF version              : %d\n", bext.version) ;
+
+       if (bext.version >= 1)
+               printf ("UMID                     : %.*s\n", (int) sizeof (bext.umid), bext.umid) ;
+
+       if (bext.version >= 2)
+       {       /* 0x7fff shall be used to designate an unused value */
+               /* valid range: -99.99 .. 99.99 */
+               printf ("Loudness value           : %6.2f LUFS\n", bext.loudness_value / 100.0) ;
+               /* valid range: 0.00 .. 99.99 */
+               printf ("Loudness range           : %6.2f LU\n", bext.loudness_range / 100.0) ;
+               /* valid range: -99.99 .. 99.99 */
+               printf ("Max. true peak level     : %6.2f dBTP\n", bext.max_true_peak_level / 100.0) ;
+               printf ("Max. momentary loudness  : %6.2f LUFS\n", bext.max_momentary_loudness / 100.0) ;
+               printf ("Max. short term loudness : %6.2f LUFS\n", bext.max_shortterm_loudness / 100.0) ;
+               } ;
 
-       printf ("BWF version      : %d\n", bext.version) ;
-       printf ("UMID             : %.*s\n", (int) sizeof (bext.umid), bext.umid) ;
-       printf ("Coding history   : %.*s\n", bext.coding_history_size, bext.coding_history) ;
+       printf ("Coding history           : %.*s\n", bext.coding_history_size, bext.coding_history) ;
 
        return 0 ;
 } /* broadcast_dump */
index fa1522e..9a09638 100644 (file)
@@ -102,23 +102,28 @@ usage_exit (const char *progname, int exit_code)
 {      printf ("\nUsage :\n  %s [options] <file>\n\nOptions:\n", progname) ;
 
        puts (
-               "    --bext-description    Print the 'bext' description.\n"
-               "    --bext-originator     Print the 'bext' originator info.\n"
-               "    --bext-orig-ref       Print the 'bext' origination reference.\n"
-               "    --bext-umid           Print the 'bext' UMID.\n"
-               "    --bext-orig-date      Print the 'bext' origination date.\n"
-               "    --bext-orig-time      Print the 'bext' origination time.\n"
-               "    --bext-coding-hist    Print the 'bext' coding history.\n"
+               "    --bext-description     Print the 'bext' description.\n"
+               "    --bext-originator      Print the 'bext' originator info.\n"
+               "    --bext-orig-ref        Print the 'bext' origination reference.\n"
+               "    --bext-umid            Print the 'bext' UMID.\n"
+               "    --bext-orig-date       Print the 'bext' origination date.\n"
+               "    --bext-orig-time       Print the 'bext' origination time.\n"
+               "    --bext-loudness-value  Print the 'bext' loudness value.\n"
+               "    --bext-loudness-range  Print the 'bext' loudness range.\n"
+               "    --bext-max-truepeak    Print the 'bext' max. true peak level\n"
+               "    --bext-max-momentary   Print the 'bext' max. momentary loudness\n"
+               "    --bext-max-shortterm   Print the 'bext' max. short term loudness\n"
+               "    --bext-coding-hist     Print the 'bext' coding history.\n"
                ) ;
 
        puts (
-               "    --str-title           Print the title metadata.\n"
-               "    --str-copyright       Print the copyright metadata.\n"
-               "    --str-artist          Print the artist metadata.\n"
-               "    --str-comment         Print the comment metadata.\n"
-               "    --str-date            Print the creation date metadata.\n"
-               "    --str-album           Print the album metadata.\n"
-               "    --str-license         Print the license metadata.\n"
+               "    --str-title            Print the title metadata.\n"
+               "    --str-copyright        Print the copyright metadata.\n"
+               "    --str-artist           Print the artist metadata.\n"
+               "    --str-comment          Print the comment metadata.\n"
+               "    --str-date             Print the creation date metadata.\n"
+               "    --str-album            Print the album metadata.\n"
+               "    --str-license          Print the license metadata.\n"
                ) ;
 
        printf ("Using %s.\n\n", sf_version_string ()) ;
@@ -132,7 +137,14 @@ process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char
 
 #define HANDLE_BEXT_ARG(cmd, name, field) \
                if (do_all || strcmp (argv [k], cmd) == 0) \
-               {       printf ("%-20s : %.*s\n", name, (int) sizeof (binfo->field), binfo->field) ; \
+               {       printf ("%-22s : %.*s\n", name, (int) sizeof (binfo->field), binfo->field) ; \
+                       if (! do_all) \
+                               continue ; \
+                       } ;
+
+#define HANDLE_BEXT_ARG_INT(cmd, name, field) \
+               if (do_all || strcmp (argv [k], cmd) == 0) \
+               {       printf ("%-22s : %6.2f\n", name, binfo->field / 100.0) ; \
                        if (! do_all) \
                                continue ; \
                        } ;
@@ -140,7 +152,7 @@ process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char
 #define HANDLE_STR_ARG(cmd, name, id) \
                if (do_all || strcmp (argv [k], cmd) == 0) \
                {       str = sf_get_string (file, id) ; \
-                       printf ("%-20s : %s\n", name, str ? str : "") ; \
+                       printf ("%-22s : %s\n", name, str ? str : "") ; \
                        if (! do_all) continue ; \
                        } ;
 
@@ -159,6 +171,11 @@ process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char
                HANDLE_BEXT_ARG ("--bext-umid", "UMID", umid) ;
                HANDLE_BEXT_ARG ("--bext-orig-date", "Origination date", origination_date) ;
                HANDLE_BEXT_ARG ("--bext-orig-time", "Origination time", origination_time) ;
+               HANDLE_BEXT_ARG_INT ("--bext-loudness-value", "Loudness value", loudness_value) ;
+               HANDLE_BEXT_ARG_INT ("--bext-loudness-range", "Loudness range", loudness_range) ;
+               HANDLE_BEXT_ARG_INT ("--bext-max-truepeak", "Max. true peak level", max_true_peak_level) ;
+               HANDLE_BEXT_ARG_INT ("--bext-max-momentary", "Max. momentary level", max_momentary_loudness) ;
+               HANDLE_BEXT_ARG_INT ("--bext-max-shortterm", "Max. short term level", max_shortterm_loudness) ;
                HANDLE_BEXT_ARG ("--bext-coding-hist", "Coding history", coding_history) ;
 
                HANDLE_STR_ARG ("--str-title", "Name", SF_STR_TITLE) ;
index bd7a33f..b1ed640 100644 (file)
@@ -100,6 +100,11 @@ main (int argc, char *argv [])
                HANDLE_BEXT_ARG ("--bext-umid", umid) ;
                HANDLE_BEXT_ARG ("--bext-orig-date", origination_date) ;
                HANDLE_BEXT_ARG ("--bext-orig-time", origination_time) ;
+               HANDLE_BEXT_ARG ("--bext-loudness-value", loudness_value) ;
+               HANDLE_BEXT_ARG ("--bext-loudness-range", loudness_range) ;
+               HANDLE_BEXT_ARG ("--bext-max-truepeak", max_true_peak_level) ;
+               HANDLE_BEXT_ARG ("--bext-max-momentary", max_momentary_loudness) ;
+               HANDLE_BEXT_ARG ("--bext-max-shortterm", max_shortterm_loudness) ;
                HANDLE_BEXT_ARG ("--bext-coding-hist", coding_history) ;
                HANDLE_BEXT_ARG ("--bext-time-ref", time_ref) ;
 
@@ -206,6 +211,11 @@ usage_exit (const char *progname, int exit_code)
                "    --bext-umid              Set the 'bext' UMID.\n"
                "    --bext-orig-date         Set the 'bext' origination date.\n"
                "    --bext-orig-time         Set the 'bext' origination time.\n"
+               "    --bext-loudness-value    Set the 'bext' loudness value.\n"
+               "    --bext-loudness-range    Set the 'bext' loudness range.\n"
+               "    --bext-max-truepeak      Set the 'bext' max. true peak level\n"
+               "    --bext-max-momentary     Set the 'bext' max. momentary loudness\n"
+               "    --bext-max-shortterm     Set the 'bext' max. short term loudness\n"
                "    --bext-coding-hist       Set the 'bext' coding history.\n"
                "    --bext-time-ref          Set the 'bext' Time ref.\n"
                "\n"
@@ -256,6 +266,9 @@ has_bext_fields_set (const METADATA_INFO * info)
        if (info->origination_date || info->origination_time || info->umid || info->coding_history || info->time_ref)
                return 1 ;
 
+       if (info->loudness_value || info->loudness_range || info->max_true_peak_level || info->max_momentary_loudness || info->max_shortterm_loudness)
+               return 1 ;
+
        return 0 ;
 } /* has_bext_fields_set */
 
@@ -280,4 +293,3 @@ read_localtime (struct tm * timedata)
 
        return ;
 } /* read_localtime */
-
diff --git a/programs/sndfile-play-beos.cpp b/programs/sndfile-play-beos.cpp
deleted file mode 100644 (file)
index fb3fde4..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
-** Copyright (C) 2001 Marcus Overhagen <marcus@overhagen.de>
-**  
-** 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       <Application.h>
-#include       <SoundPlayer.h>
-#include       <string.h>
-
-#include       <sndfile.h>
-
-#define        BUFFER_LEN              1024
-
-/*------------------------------------------------------------------------------
-**     BeOS functions for playing a sound.
-*/
-
-#if defined (__BEOS__)
-
-struct shared_data
-{
-       BSoundPlayer *player;
-       SNDFILE *sndfile;
-       SF_INFO sfinfo; 
-       sem_id finished;
-};
-
-static void 
-buffer_callback(void *theCookie, void *buf, size_t size, const media_raw_audio_format &format) 
-{
-       shared_data *data = (shared_data *)theCookie;
-       short *buffer = (short *)buf;
-       int count = size / sizeof(short);
-       int m, readcount;
-
-       if (!data->player->HasData())
-               return;
-
-       readcount = sf_read_short(data->sndfile, buffer, count);
-       if (readcount == 0) 
-       {       data->player->SetHasData(false);                
-               release_sem(data->finished);
-               }
-       if (readcount < count) 
-       {       for (m = readcount ; m < count ; m++)
-                       buffer [m] = 0 ;
-               }
-       if (data->sfinfo.pcmbitwidth < 16) 
-       {       for (m = 0 ; m < count ; m++)
-                       buffer [m] *= 256 ;
-               }
-}
-
-static void
-beos_play (int argc, char *argv [])
-{
-       shared_data data;
-       status_t status;
-       int     k;
-
-       /* BSoundPlayer requires a BApplication object */
-       BApplication app("application/x-vnd.MarcusOverhagen-sfplay");
-
-       for (k = 1 ; k < argc ; k++)
-       {       printf ("Playing %s\n", argv [k]) ;     
-               if (! (data.sndfile = sf_open_read (argv [k], &data.sfinfo)))
-               {       sf_perror (NULL) ;
-                       continue ;
-                       } ;
-                       
-               if (data.sfinfo.channels < 1 || data.sfinfo.channels > 2)
-               {       printf ("Error : channels = %d.\n", data.sfinfo.channels) ;
-                       sf_close (data.sndfile) ;
-                       continue ;
-                       } ;             
-
-               data.finished = create_sem(0,"finished");                       
-
-               media_raw_audio_format format = 
-               {       data.sfinfo.samplerate,
-                       data.sfinfo.channels,
-                       media_raw_audio_format::B_AUDIO_SHORT,
-                       B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN,
-                       BUFFER_LEN * sizeof(short)
-                       };
-
-               BSoundPlayer player(&format,"player",buffer_callback,NULL,&data);
-               data.player = &player;
-               
-               if ((status = player.InitCheck()) != B_OK) 
-               {
-                       printf ("Error : BSoundPlayer init failed, %s.\n", strerror(status)) ;
-                       delete_sem(data.finished);
-                       sf_close (data.sndfile) ;
-                       continue ;
-                       }
-
-               player.SetVolume(1.0);
-               player.Start();
-               player.SetHasData(true);
-               acquire_sem(data.finished);
-               player.Stop();
-               delete_sem(data.finished);
-               
-               sf_close (data.sndfile) ;
-
-               } ;
-
-} /* beos_play */
-
-#endif
-
-/*==============================================================================
-**     Main function.
-*/
-
-int 
-main (int argc, char *argv [])
-{
-       if (argc < 2)
-       {       printf ("Usage : %s <input sound file>\n\n", argv [0]) ;
-               return 1 ;
-               } ;
-       
-       beos_play (argc, argv) ;
-
-       return 0 ;
-} /* main */
-               
index 1fc96fa..cd5cc27 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** All rights reserved.
 **
@@ -39,6 +39,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
        #include        <sys/ioctl.h>
        #include        <sys/soundcard.h>
 
-#elif (defined (__MACH__) && defined (__APPLE__))
-       #include <AvailabilityMacros.h>
-       #include <Availability.h>
-
 #elif HAVE_SNDIO_H
        #include <sndio.h>
 
@@ -121,10 +119,10 @@ alsa_play (int argc, char *argv [])
                        int     m ;
 
                        sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
-                       if (scale < 1e-10)
-                               scale = 1.0 ;
+                       if (scale > 1.0)
+                               scale = 1.0 / scale ;
                        else
-                               scale = 32700.0 / scale ;
+                               scale = 1.0 ;
 
                        while ((readcount = sf_read_float (sndfile, buffer, BUFFER_LEN)))
                        {       for (m = 0 ; m < readcount ; m++)
@@ -511,7 +509,8 @@ win32_play_data (Win32_Audio_Data *audio_data)
        /* fill a buffer if there is more data and we can read it sucessfully */
        readcount = (audio_data->remaining > audio_data->bufferlen) ? audio_data->bufferlen : (int) audio_data->remaining ;
 
-       thisread = (int) sf_read_short (audio_data->sndfile, (short *) (audio_data->whdr [audio_data->current].lpData), readcount) ;
+       short *lpData = (short *) (void *) audio_data->whdr [audio_data->current].lpData ;
+       thisread = (int) sf_read_short (audio_data->sndfile, lpData, readcount) ;
 
        audio_data->remaining -= thisread ;
 
@@ -850,16 +849,8 @@ main (int argc, char *argv [])
        solaris_play (argc, argv) ;
 #elif (OS_IS_WIN32 == 1)
        win32_play (argc, argv) ;
-#elif (defined (__MACH__) && defined (__APPLE__))
-       printf ("OS X 10.8 and later have a new Audio API.\n") ;
-       printf ("Someone needs to write code to use that API.\n") ;
-       return 1 ;
-#elif defined (__BEOS__)
-       printf ("This program cannot be compiled on BeOS.\n") ;
-       printf ("Instead, compile the file sfplay_beos.cpp.\n") ;
-       return 1 ;
 #else
-       puts ("*** Playing sound not yet supported on this platform.") ;
+       puts ("*** Playing sound not supported on this platform.") ;
        puts ("*** Please feel free to submit a patch.") ;
        return 1 ;
 #endif
index d6200a6..9c21d52 100644 (file)
@@ -30,6 +30,8 @@
 ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include       "sfconfig.h"
+
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
 #include       <ctype.h>
 #include       <math.h>
 #include       <errno.h>
+#if HAVE_UNISTD_H
 #include       <unistd.h>
+#else
+#include       "sf_unistd.h"
+#endif
 #include       <fcntl.h>
 #include       <sys/stat.h>
 #include       <sys/types.h>
@@ -157,7 +163,7 @@ salvage_file (const char * broken_wav, const char * fixed_w64)
        read_size *= sfinfo.channels ;
 
        if ((sndfile = sf_open (fixed_w64, SFM_WRITE, &sfinfo)) == NULL)
-       {       printf ("sf_open ('%s') failed : %s\n", broken_wav, sf_strerror (NULL)) ;
+       {       printf ("sf_open ('%s') failed : %s\n", fixed_w64, sf_strerror (NULL)) ;
                exit (1) ;
                } ;
 
diff --git a/regtest/Makefile.am b/regtest/Makefile.am
deleted file mode 100644 (file)
index cc335aa..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-if HAVE_SQLITE3
-bin_PROGRAMS = sndfile-regtest
-endif
-
-noinst_HEADERS = regtest.h
-
-AM_CPPFLAGS = -I$(top_srcdir)/src $(SQLITE3_CFLAGS) $(OS_SPECIFIC_CFLAGS)
-
-sndfile_regtest_SOURCES = sndfile-regtest.c database.c checksum.c
-sndfile_regtest_LDADD = $(top_builddir)/src/libsndfile.la $(SQLITE3_LIBS)
-
-CLEANFILES = *~ *.exe
index 7f433a4..5714144 100644 (file)
@@ -108,7 +108,7 @@ float_checksum (SNDFILE * file, int start)
        do
        {       count = (int) sf_read_float (file, data.f, ARRAY_LEN (data.f)) ;
                for (k = 0 ; k < count ; k++)
-                       start = start * BIG_PRIME + lrintf (0x7FFFFFFF * data.f [k]) ;
+                       start = start * BIG_PRIME + lrintf (2147483648.0f * data.f [k]) ;
                }
        while (count > 0) ;
 
index f800a2c..1048ebb 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
+#endif
 #include <string.h>
 #include <fcntl.h>
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
 #include <sys/stat.h>
 
 #include <sndfile.h>
@@ -31,6 +38,7 @@
 
 #if HAVE_SQLITE3
 
+#include <ctype.h>
 #include <sqlite3.h>
 
 typedef struct
@@ -64,6 +72,16 @@ static int check_file_by_ekey (REGTEST_DB * db, int ekey) ;
 static int count_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ;
 static int ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ;
 static int callback (void *unused, int argc, char **argv, char **colname) ;
+static const char *db_basename (const char *fname);
+
+/* Windows accepts both '\\' and '/' in paths */
+#ifdef _WIN32
+  #define IS_SLASH(c)                  ((c) == '\\' || (c) == '/')
+  #define HAS_DRIVELETTER(path)        (isalpha ((int)(path[0])) && path[1] == ':' && IS_SLASH(path[2]))
+#else
+  #define IS_SLASH(c)                  ((c) == '/')
+  #define HAS_DRIVELETTER(path)        0
+#endif
 
 REG_DB *
 db_open (const char * db_name)
@@ -133,14 +151,12 @@ db_close (REG_DB * db_handle)
 int
 db_file_exists (REG_DB * db_handle, const char * filename)
 {      REGTEST_DB * db ;
-       const char * cptr ;
        char * errmsg ;
        int err ;
 
        db = (REGTEST_DB *) db_handle ;
 
-       if ((cptr = strrchr (filename, '/')) != NULL)
-               filename = cptr + 1 ;
+       filename = db_basename (filename);
 
        snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname from sndfile where fname='%s'", filename) ;
 
@@ -176,7 +192,7 @@ db_add_file (REG_DB * db_handle, const char * filepath)
        sf_close (sndfile) ;
 
        if (sndfile == NULL)
-       {       printf ("    %s : could not open : %s\n", db->filename, sf_strerror (NULL)) ;
+       {       printf ("    %s : could not open : %s, filepath: '%s'\n", db->filename, sf_strerror (NULL), filepath) ;
                puts (db->logbuf) ;
                return 1 ;
                } ;
@@ -410,10 +426,13 @@ check_file_by_ekey (REGTEST_DB * db, int ekey)
 
 static void
 get_filename_pathname (REGTEST_DB * db, const char *filepath)
-{      const char * cptr ;
+{
+       const char * basename = db_basename (filepath) ;
        int slen ;
 
-       if (filepath [0] != '/')
+       /* Test for a relative path
+        */
+       if (!IS_SLASH(filepath [0]) && !HAS_DRIVELETTER(filepath))
        {       memset (db->pathname, 0, sizeof (db->pathname)) ;
                if (getcwd (db->pathname, sizeof (db->pathname)) == NULL)
                {       perror ("\ngetcwd failed") ;
@@ -421,18 +440,19 @@ get_filename_pathname (REGTEST_DB * db, const char *filepath)
                        } ;
 
                slen = strlen (db->pathname) ;
-               db->pathname [slen ++] = '/' ;
-               snprintf (db->pathname + slen, sizeof (db->pathname) - slen, "%s", filepath) ;
+               /* a '/' is fine for Windows too */
+               snprintf (db->pathname + slen, sizeof (db->pathname) - slen, "/%s", filepath) ;
                }
        else
                snprintf (db->pathname, sizeof (db->pathname), "%s", filepath) ;
 
-       if ((cptr = strrchr (db->pathname, '/')) == NULL)
+       snprintf (db->filename, sizeof (db->filename), "%s", basename) ;
+
+       basename = db_basename (db->pathname) ;
+       if (basename == db->pathname)
        {       printf ("\nError : bad pathname %s\n", filepath) ;
                exit (1) ;
                } ;
-
-       snprintf (db->filename, sizeof (db->filename), "%s", cptr + 1) ;
 } /* get filename_pathname */
 
 static void
@@ -479,6 +499,33 @@ callback (void *unused, int argc, char **argv, char **colname)
        return 0 ;
 } /* callback */
 
+/*
+ * Win32:     Strip drive-letter and directory from a filename.
+ * non-Win32: Strip directory from a filename.
+ */
+static const char *db_basename (const char *fname)
+{
+  const char *base = fname;
+
+#if !defined(_WIN32)
+  const char *slash = strrchr (base, '/');
+
+  if (slash)
+               base = slash + 1 ;
+#else
+       if (fname[0] && fname[1] == ':')  {
+               fname += 2;
+               base = fname;
+       }
+       while (*fname) {
+               if (IS_SLASH(*fname))
+                       base = fname + 1;
+               fname++;
+       }
+#endif
+       return base ;
+}
+
 #else
 
 int dummy (void) ;
index 5e77ebc..961cf93 100644 (file)
@@ -5,8 +5,8 @@ includedir=@includedir@
 
 Name: sndfile
 Description: A library for reading and writing audio files
-Requires: 
+Requires:
+Requires.private: @EXTERNAL_XIPH_REQUIRE@
 Version: @VERSION@
 Libs: -L${libdir} -lsndfile
-Libs.private: @EXTERNAL_XIPH_LIBS@
-Cflags: -I${includedir} 
+Cflags: -I${includedir}
index de91be3..e8a9767 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 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
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+#include "sfconfig.h"
+
 #include <stdio.h>
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
+#endif
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
index 9e650cc..dc95e3a 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef        PRIVATE_H
 #define        PRIVATE_H
 
+#include <stdint.h>
+
 /* Added by Erik de Castro Lopo */
 #define        USE_FLOAT_MUL
 #define        FAST
 #endif
 /* Added by Erik de Castro Lopo */
 
-
-
-typedef short                          int16_t ;               /* 16 bit signed int    */
-typedef int                                    int32_t ;       /* 32 bit signed int    */
-
-typedef unsigned short         uint16_t ;              /* unsigned int16_t     */
-typedef unsigned int           uint32_t ;      /* unsigned int32_t     */
-
 struct gsm_state
 {      int16_t                 dp0 [280] ;
 
index f492eab..922421e 100644 (file)
@@ -159,7 +159,7 @@ static void Fast_Autocorrelation (
                for (i = k ; i < 160 ; ++i) L_temp2 += sf [i] * sfl [i] ;
                f_L_ACF [k] = L_temp2 ;
                }
-       scale = MAX_LONGWORD / f_L_ACF [0] ;
+       scale = 2147483648.0f / f_L_ACF [0] ;
 
        for (k = 0 ; k <= 8 ; k++)
                L_ACF [k] = f_L_ACF [k] * scale ;
index 4514cab..d9e90f2 100644 (file)
@@ -387,9 +387,12 @@ static void RPE_grid_positioning (
 
        switch (Mc)
        {       case 3: *ep++ = 0 ;
+                               /* Falls through. */
                case 2: do
                                {       *ep++ = 0 ;
+                               /* Falls through. */
                case 1:         *ep++ = 0 ;
+                               /* Falls through. */
                case 0:         *ep++ = *xMp++ ;
                                        } while (--i) ;
        }
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644 (file)
index e7640cd..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-AUTOMAKE_OPTIONS = subdir-objects
-
-AM_CPPFLAGS = $(EXTERNAL_XIPH_CFLAGS)
-
-lib_LTLIBRARIES = libsndfile.la
-include_HEADERS = sndfile.hh
-nodist_include_HEADERS = sndfile.h
-
-noinst_LTLIBRARIES =  GSM610/libgsm.la G72x/libg72x.la ALAC/libalac.la libcommon.la
-
-SYMBOL_FILES = Symbols.gnu-binutils Symbols.darwin libsndfile-1.def Symbols.os2 Symbols.static
-
-EXTRA_DIST = sndfile.h.in config.h.in test_endswap.c test_endswap.tpl test_endswap.def \
-                       $(SYMBOL_FILES) create_symbols_file.py binheader_writef_check.py \
-                       GSM610/README GSM610/COPYRIGHT GSM610/ChangeLog \
-                       G72x/README G72x/README.original G72x/ChangeLog \
-                       make-static-lib-hidden-privates.sh
-
-noinst_HEADERS = common.h sfconfig.h sfendian.h wavlike.h sf_unistd.h ogg.h chanmap.h
-
-check_PROGRAMS = test_main G72x/g72x_test
-
-FILESPECIFIC = sndfile.c aiff.c au.c avr.c caf.c dwd.c flac.c g72x.c htk.c ircam.c \
-               macos.c mat4.c mat5.c nist.c paf.c pvf.c raw.c rx2.c sd2.c \
-               sds.c svx.c txw.c voc.c wve.c w64.c wavlike.c wav.c xi.c mpc2k.c rf64.c \
-               ogg_vorbis.c ogg_speex.c ogg_pcm.c ogg_opus.c
-
-CLEANFILES = *~ *.exe G72x/*.exe error.dat
-
-if USE_WIN_VERSION_FILE
-WIN_VERSION_FILE = version-metadata.rc
-else
-WIN_VERSION_FILE =
-endif
-
-libsndfile_la_CFLAGS = $(CFLAG_VISIBILITY)
-libsndfile_la_CPPFLAGS = -DSNDFILE_EXPORTS
-
-#===============================================================================
-# MinGW requires -no-undefined if a DLL is to be built.
-libsndfile_la_LDFLAGS = -no-undefined -version-info  $(SHARED_VERSION_INFO) $(SHLIB_VERSION_ARG)
-libsndfile_la_SOURCES = $(FILESPECIFIC) $(noinst_HEADERS)
-nodist_libsndfile_la_SOURCES = $(nodist_include_HEADERS)
-libsndfile_la_LIBADD = GSM610/libgsm.la G72x/libg72x.la ALAC/libalac.la \
-               libcommon.la $(EXTERNAL_XIPH_LIBS) -lm
-
-EXTRA_libsndfile_la_DEPENDENCIES = $(SYMBOL_FILES)
-
-libcommon_la_SOURCES = common.c file_io.c command.c pcm.c ulaw.c alaw.c \
-               float32.c double64.c ima_adpcm.c ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c \
-               interleave.c strings.c dither.c cart.c broadcast.c audio_detect.c \
-               ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \
-               windows.c id3.c $(WIN_VERSION_FILE)
-
-
-#======================================================================
-# Subdir libraries.
-
-GSM610_libgsm_la_SOURCES = GSM610/config.h GSM610/gsm.h GSM610/gsm610_priv.h \
-               GSM610/add.c GSM610/code.c GSM610/decode.c GSM610/gsm_create.c \
-               GSM610/gsm_decode.c GSM610/gsm_destroy.c GSM610/gsm_encode.c \
-               GSM610/gsm_option.c GSM610/long_term.c GSM610/lpc.c GSM610/preprocess.c \
-               GSM610/rpe.c GSM610/short_term.c GSM610/table.c
-
-G72x_libg72x_la_SOURCES = G72x/g72x.h G72x/g72x_priv.h \
-               G72x/g721.c G72x/g723_16.c G72x/g723_24.c G72x/g723_40.c G72x/g72x.c
-
-ALAC_libalac_la_SOURCES = ALAC/ALACAudioTypes.h ALAC/ALACBitUtilities.h \
-               ALAC/EndianPortable.h ALAC/aglib.h ALAC/dplib.h ALAC/matrixlib.h \
-               ALAC/alac_codec.h ALAC/shift.h \
-               ALAC/ALACBitUtilities.c ALAC/ag_dec.c \
-               ALAC/ag_enc.c ALAC/dp_dec.c ALAC/dp_enc.c ALAC/matrix_dec.c \
-               ALAC/matrix_enc.c ALAC/alac_decoder.c ALAC/alac_encoder.c
-
-#===============================================================================
-# Test programs.
-
-test_main_SOURCES = test_main.c test_main.h test_conversions.c test_float.c test_endswap.c \
-                                       test_audio_detect.c test_log_printf.c test_file_io.c test_ima_oki_adpcm.c \
-                                       test_strncpy_crlf.c test_broadcast_var.c test_cart_var.c \
-                                       test_binheader_writef.c
-test_main_LDADD = libcommon.la
-
-G72x_g72x_test_SOURCES = G72x/g72x_test.c
-G72x_g72x_test_LDADD = G72x/libg72x.la
-
-SUFFIXES = .def .tpl
-
-.def.c:
-       autogen --writable $<
-
-check :
-       @if [ -x /usr/bin/python ]; then $(srcdir)/binheader_writef_check.py $(srcdir)/*.c ; fi
-       G72x/g72x_test$(EXEEXT) all
-       ./test_main$(EXEEXT)
-
-# Need this target to force building of test programs.
-checkprograms : $(check_PROGRAMS)
-
-#======================================================================
-# Generate an OS specific Symbols files. This is done when the author
-# builds the distribution tarball. There should be not need for the
-# end user to create these files.
-
-Symbols.gnu-binutils: create_symbols_file.py
-       python $(srcdir)/create_symbols_file.py linux $(VERSION) > $@
-
-Symbols.darwin: create_symbols_file.py
-       python $(srcdir)/create_symbols_file.py darwin $(VERSION) > $@
-
-libsndfile-1.def: create_symbols_file.py
-       python $(srcdir)/create_symbols_file.py win32 $(VERSION) > $@
-
-Symbols.os2: create_symbols_file.py
-       python $(srcdir)/create_symbols_file.py os2 $(VERSION) > $@
-
-Symbols.static: create_symbols_file.py
-       python $(srcdir)/create_symbols_file.py static $(VERSION) > $@
-
-#======================================================================
-# Building windows resource files (if needed).
-
-.rc.lo:
-       $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) $< -o $@
-
-#======================================================================
-# Disable autoheader.
-AUTOHEADER=echo
-
-
-
index 6352247..d872a89 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2005 David Viens <davidv@plogue.com>
 **
 ** This program is free software; you can redistribute it and/or modify
@@ -243,6 +243,8 @@ aiff_open (SF_PRIVATE *psf)
        if ((psf->container_data = calloc (1, sizeof (AIFF_PRIVATE))) == NULL)
                return SFE_MALLOC_FAILED ;
 
+       psf->container_close = aiff_close ;
+
        if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
        {       if ((error = aiff_read_header (psf, &comm_fmt)))
                        return error ;
@@ -283,7 +285,6 @@ aiff_open (SF_PRIVATE *psf)
                psf->set_chunk          = aiff_set_chunk ;
                } ;
 
-       psf->container_close = aiff_close ;
        psf->command = aiff_command ;
 
        switch (SF_CODEC (psf->sf.format))
@@ -498,6 +499,11 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
                                                return SFE_WAV_BAD_PEAK ;
                                                } ;
 
+                                       if (psf->peak_info)
+                                       {       psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ;
+                                               free (psf->peak_info) ;
+                                               psf->peak_info = NULL ;
+                                               } ;
                                        if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
                                                return SFE_MALLOC_FAILED ;
 
@@ -794,12 +800,16 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
                                                if (paiff->markstr == NULL)
                                                        return SFE_MALLOC_FAILED ;
 
-                                               if (mark_count > 1000)
-                                               {       psf_log_printf (psf, "  More than 1000 markers, skipping!\n") ;
+                                               if (mark_count > 2500) /* 2500 is close to the largest number of cues possible because of block sizes */
+                                               {       psf_log_printf (psf, "  More than 2500 markers, skipping!\n") ;
                                                        psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
                                                        break ;
                                                } ;
 
+                                               if (psf->cues)
+                                               {       free (psf->cues) ;
+                                                       psf->cues = NULL ;
+                                                       } ;
                                                if ((psf->cues = psf_cues_alloc (mark_count)) == NULL)
                                                        return SFE_MALLOC_FAILED ;
 
@@ -849,7 +859,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
 
                        case FVER_MARKER :
                                        found_chunk |= HAVE_FVER ;
-                                       /* Fall through to next case. */
+                                       /* Falls through. */
 
                        case SFX_MARKER :
                                        psf_log_printf (psf, " %M : %d\n", marker, chunk_size) ;
@@ -950,7 +960,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
        if (psf->sf.channels < 1)
                return SFE_CHANNEL_COUNT_ZERO ;
 
-       if (psf->sf.channels >= SF_MAX_CHANNELS)
+       if (psf->sf.channels > SF_MAX_CHANNELS)
                return SFE_CHANNEL_COUNT ;
 
        if (! (found_chunk & HAVE_FORM))
@@ -1030,7 +1040,7 @@ aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
        psf_log_printf (psf, "  Sample Rate : %d\n", samplerate) ;
        psf_log_printf (psf, "  Frames      : %u%s\n", comm_fmt->numSampleFrames, (comm_fmt->numSampleFrames == 0 && psf->filelength > 104) ? " (Should not be 0)" : "") ;
 
-       if (comm_fmt->numChannels < 1 || comm_fmt->numChannels >= SF_MAX_CHANNELS)
+       if (comm_fmt->numChannels < 1 || comm_fmt->numChannels > SF_MAX_CHANNELS)
        {       psf_log_printf (psf, "  Channels    : %d (should be >= 1 and < %d)\n", comm_fmt->numChannels, SF_MAX_CHANNELS) ;
                return SFE_CHANNEL_COUNT_BAD ;
                } ;
@@ -1120,7 +1130,6 @@ aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
                                break ;
 
                case GSM_MARKER :
-                               psf->sf.format = SF_FORMAT_AIFF ;
                                psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_GSM610) ;
                                break ;
 
@@ -1163,30 +1172,30 @@ aiff_rewrite_header (SF_PRIVATE *psf)
        psf->header.indx = 0 ;
 
        /* FORM chunk. */
-       psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ;
+       psf_binheader_writef (psf, "Etm8", BHWm (FORM_MARKER), BHW8 (psf->filelength - 8)) ;
 
        /* COMM chunk. */
        if ((k = psf_find_read_chunk_m32 (&psf->rchunks, COMM_MARKER)) >= 0)
        {       psf->header.indx = psf->rchunks.chunks [k].offset - 8 ;
                comm_frames = psf->sf.frames ;
                comm_size = psf->rchunks.chunks [k].len ;
-               psf_binheader_writef (psf, "Em42t4", COMM_MARKER, comm_size, psf->sf.channels, comm_frames) ;
+               psf_binheader_writef (psf, "Em42t4", BHWm (COMM_MARKER), BHW4 (comm_size), BHW2 (psf->sf.channels), BHW4 (comm_frames)) ;
                } ;
 
        /* PEAK chunk. */
        if ((k = psf_find_read_chunk_m32 (&psf->rchunks, PEAK_MARKER)) >= 0)
        {       psf->header.indx = psf->rchunks.chunks [k].offset - 8 ;
-               psf_binheader_writef (psf, "Em4", PEAK_MARKER, AIFF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
-               psf_binheader_writef (psf, "E44", 1, time (NULL)) ;
+               psf_binheader_writef (psf, "Em4", BHWm (PEAK_MARKER), BHW4 (AIFF_PEAK_CHUNK_SIZE (psf->sf.channels))) ;
+               psf_binheader_writef (psf, "E44", BHW4 (1), BHW4 (time (NULL))) ;
                for (ch = 0 ; ch < psf->sf.channels ; ch++)
-                       psf_binheader_writef (psf, "Eft8", (float) psf->peak_info->peaks [ch].value, psf->peak_info->peaks [ch].position) ;
+                       psf_binheader_writef (psf, "Eft8", BHWf ((float) psf->peak_info->peaks [ch].value), BHW8 (psf->peak_info->peaks [ch].position)) ;
                } ;
 
 
        /* SSND chunk. */
        if ((k = psf_find_read_chunk_m32 (&psf->rchunks, SSND_MARKER)) >= 0)
        {       psf->header.indx = psf->rchunks.chunks [k].offset - 8 ;
-               psf_binheader_writef (psf, "Etm8", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK) ;
+               psf_binheader_writef (psf, "Etm8", BHWm (SSND_MARKER), BHW8 (psf->datalength + SIZEOF_SSND_CHUNK)) ;
                } ;
 
        /* Header mangling complete so write it out. */
@@ -1196,21 +1205,6 @@ aiff_rewrite_header (SF_PRIVATE *psf)
        return ;
 } /* aiff_rewrite_header */
 
-static uint16_t
-convert_loop_mode (int type_mode)
-{      switch (type_mode)
-       {       case SF_LOOP_NONE:
-                       return 0 ;
-               case SF_LOOP_FORWARD :
-                       return 1 ;
-               case SF_LOOP_ALTERNATING :
-                       return 2 ;
-               default : break ;
-               } ;
-
-       return 0 ;
-} /* convert_loop_mode */
-
 static int
 aiff_write_header (SF_PRIVATE *psf, int calc_length)
 {      sf_count_t              current ;
@@ -1415,167 +1409,36 @@ aiff_write_header (SF_PRIVATE *psf, int calc_length)
        psf->header.indx = 0 ;
        psf_fseek (psf, 0, SEEK_SET) ;
 
-       psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ;
+       psf_binheader_writef (psf, "Etm8", BHWm (FORM_MARKER), BHW8 (psf->filelength - 8)) ;
 
        /* Write AIFF/AIFC marker and COM chunk. */
        if (comm_type == AIFC_MARKER)
                /* AIFC must have an FVER chunk. */
-               psf_binheader_writef (psf, "Emm44", comm_type, FVER_MARKER, 4, 0xA2805140) ;
+               psf_binheader_writef (psf, "Emm44", BHWm (comm_type), BHWm (FVER_MARKER), BHW4 (4), BHW4 (0xA2805140)) ;
        else
-               psf_binheader_writef (psf, "Em", comm_type) ;
+               psf_binheader_writef (psf, "Em", BHWm (comm_type)) ;
 
        paiff->comm_offset = psf->header.indx - 8 ;
 
        memset (comm_sample_rate, 0, sizeof (comm_sample_rate)) ;
        uint2tenbytefloat (psf->sf.samplerate, comm_sample_rate) ;
 
-       psf_binheader_writef (psf, "Em42t42", COMM_MARKER, comm_size, psf->sf.channels, comm_frames, bit_width) ;
-       psf_binheader_writef (psf, "b", comm_sample_rate, sizeof (comm_sample_rate)) ;
+       psf_binheader_writef (psf, "Em42t42", BHWm (COMM_MARKER), BHW4 (comm_size), BHW2 (psf->sf.channels), BHW4 (comm_frames), BHW2 (bit_width)) ;
+       psf_binheader_writef (psf, "b", BHWv (comm_sample_rate), BHWz (sizeof (comm_sample_rate))) ;
 
        /* AIFC chunks have some extra data. */
        if (comm_type == AIFC_MARKER)
-               psf_binheader_writef (psf, "mb", comm_encoding, comm_zero_bytes, sizeof (comm_zero_bytes)) ;
+               psf_binheader_writef (psf, "mb", BHWm (comm_encoding), BHWv (comm_zero_bytes), BHWz (sizeof (comm_zero_bytes))) ;
 
        if (psf->channel_map && paiff->chanmap_tag)
-               psf_binheader_writef (psf, "Em4444", CHAN_MARKER, 12, paiff->chanmap_tag, 0, 0) ;
+               psf_binheader_writef (psf, "Em4444", BHWm (CHAN_MARKER), BHW4 (12), BHW4 (paiff->chanmap_tag), BHW4 (0), BHW4 (0)) ;
 
        /* Check if there's a INST chunk to write */
        if (psf->instrument != NULL && psf->cues != NULL)
-       {       /* Both loops and cues exist */
-               uint16_t sustainLoopMode, releaseLoopMode ;
-               uint32_t idx, sLoopStart = 0, sLoopEnd = 0, rLoopStart = 0, rLoopEnd = 0 ;
-               int totalStringLength = 0, stringLength ;
-
-               /* Here we count how many bytes will the pascal strings need */
-               for (idx = 0 ; idx < psf->cues->cue_count ; idx++)
-               {       stringLength = strlen (psf->cues->cue_points [idx].name) + 1 ; /* We'll count the first byte also of every pascal string */
-                       if (stringLength % 2 == 0)
-                               totalStringLength += stringLength ;
-                       else
-                               totalStringLength += (stringLength + 1) ; /* The pascal string must have an even count */
-                       }
-
-               /* First we check which loops are active and create the necessary MARK chunk for markers */
-               /* The first written markers will be references from loop points then comes the real markers */
-               if (psf->instrument->loops [0].mode != SF_LOOP_NONE && psf->instrument->loops [1].mode != SF_LOOP_NONE)
-               {       /* There's both a sustain loop and a release loop */
-                       psf_binheader_writef (psf, "Em42 241b 241b 241b 241b",
-                                       MARK_MARKER, 2 + 2 * (2 + 4 + 1 + 19) + 2 * (2 + 4 + 1 + 17) + psf->cues->cue_count * (2 + 4) + totalStringLength, 4 + psf->cues->cue_count,
-                                       1, psf->instrument->loops [0].start, 18, "sustain loop start", make_size_t (19),
-                                       2, psf->instrument->loops [0].end, 16, "sustain loop end", make_size_t (17),
-                                       3, psf->instrument->loops [1].start, 18, "release loop start", make_size_t (19),
-                                       4, psf->instrument->loops [1].end, 16, "release loop end", make_size_t (17)) ;
-                       /* Now comes true markers from cues struct */
-                       for (idx = 0 ; idx < psf->cues->cue_count ; idx++)
-                               psf_binheader_writef (psf, "E24p", 5 + idx, psf->cues->cue_points [idx].sample_offset, psf->cues->cue_points [idx].name) ;
-
-                       /* Change the loops to be references to the markers */
-                       sLoopStart = 1 ;
-                       sLoopEnd = 2 ;
-                       rLoopStart = 3 ;
-                       rLoopEnd = 4 ;
-                       }
-               else if (psf->instrument->loops [0].mode != SF_LOOP_NONE && psf->instrument->loops [1].mode == SF_LOOP_NONE)
-               {       /* There's a sustain loop but no release loop */
-                       psf_binheader_writef (psf, "Em42241b241b",
-                                       MARK_MARKER, 2 + (2 + 4 + 1 + 19) + (2 + 4 + 1 + 17) + psf->cues->cue_count * (2 + 4) + totalStringLength, 2 + psf->cues->cue_count,
-                                       1, psf->instrument->loops [0].start, 18, "sustain loop start", make_size_t (19),
-                                       2, psf->instrument->loops [0].end, 16, "sustain loop end", make_size_t (17)) ;
-                       /* Now comes true markers from cues struct */
-                       for (idx = 0 ; idx < psf->cues->cue_count ; idx++)
-                               psf_binheader_writef (psf, "E24p", 3 + idx, psf->cues->cue_points [idx].sample_offset, psf->cues->cue_points [idx].name) ;
-
-                       /* Change the loops to be references to the markers */
-                       sLoopStart = 1 ;
-                       sLoopEnd = 2 ;
-                       rLoopStart = 0 ;
-                       rLoopEnd = 0 ;
-                       }
-               else if (psf->instrument->loops [0].mode == SF_LOOP_NONE && psf->instrument->loops [1].mode != SF_LOOP_NONE)
-               {       /* There's a release loop but no sustain loop! Strange indeed! */
-                       psf_binheader_writef (psf, "Em42241b241b",
-                                       MARK_MARKER, 2 + (2 + 4 + 1 + 19) + (2 + 4 + 1 + 17) + psf->cues->cue_count * (2 + 4) + totalStringLength, 2 + psf->cues->cue_count,
-                                       1, psf->instrument->loops [1].start, 18, "release loop start", make_size_t (19),
-                                       2, psf->instrument->loops [1].end, 16, "release loop end", make_size_t (17)) ;
-                       /* Now comes true markers from cues struct */
-                       for (idx = 0 ; idx < psf->cues->cue_count ; idx++)
-                               psf_binheader_writef (psf, "E24p", 3 + idx, psf->cues->cue_points [idx].sample_offset, psf->cues->cue_points [idx].name) ;
-
-                       /* Change the loops to be references to the markers */
-                       sLoopStart = 0 ;
-                       sLoopEnd = 0 ;
-                       rLoopStart = 1 ;
-                       rLoopEnd = 2 ;
-                       } ;
-
-               /* First convert loop modes to aiff standard */
-               sustainLoopMode = convert_loop_mode (psf->instrument->loops [0].mode) ;
-               releaseLoopMode = convert_loop_mode (psf->instrument->loops [1].mode) ;
-
-               /* Now we finally write the actual INST chunk */
-               psf_binheader_writef (psf, "Em4111111", INST_MARKER, SIZEOF_INST_CHUNK, psf->instrument->basenote, psf->instrument->detune,
-                       psf->instrument->key_lo, psf->instrument->key_hi, psf->instrument->velocity_lo, psf->instrument->velocity_hi) ;
-               psf_binheader_writef (psf, "E2222222", (short) psf->instrument->gain,
-                       sustainLoopMode, sLoopStart, sLoopEnd,
-                       releaseLoopMode, rLoopStart, rLoopEnd) ;
-
-               }
-       else if (psf->instrument != NULL && psf->cues == NULL)
-       {       /* There are loops but no cues */
-               uint16_t sustainLoopMode, releaseLoopMode ;
-               uint32_t sLoopStart = 0, sLoopEnd = 0, rLoopStart = 0, rLoopEnd = 0 ;
-
-               /* First we check which loops are active and create the necessary MARK chunk for markers */
-               if (psf->instrument->loops [0].mode != SF_LOOP_NONE && psf->instrument->loops [1].mode != SF_LOOP_NONE)
-               {       /* There's both a sustain loop and a release loop */
-                       psf_binheader_writef (psf, "Em42 241b 241b 241b 241b",
-                                       MARK_MARKER, 2 + 2 * (2 + 4 + 1 + 19) + 2 * (2 + 4 + 1 + 17), 4,
-                                       1, psf->instrument->loops [0].start, 18, "sustain loop start", make_size_t (19),
-                                       2, psf->instrument->loops [0].end, 16, "sustain loop end", make_size_t (17),
-                                       3, psf->instrument->loops [1].start, 18, "release loop start", make_size_t (19),
-                                       4, psf->instrument->loops [1].end, 16, "release loop end", make_size_t (17)) ;
-                       /* Change the loops to be references to the markers */
-                       sLoopStart = 1 ;
-                       sLoopEnd = 2 ;
-                       rLoopStart = 3 ;
-                       rLoopEnd = 4 ;
-                       }
-               else if (psf->instrument->loops [0].mode != SF_LOOP_NONE && psf->instrument->loops [1].mode == SF_LOOP_NONE)
-               {       /* There's a sustain loop but no release loop */
-                       psf_binheader_writef (psf, "Em42241b241b",
-                                       MARK_MARKER, 2 + (2 + 4 + 1 + 19) + (2 + 4 + 1 + 17), 2,
-                                       1, psf->instrument->loops [0].start, 18, "sustain loop start", make_size_t (19),
-                                       2, psf->instrument->loops [0].end, 16, "sustain loop end", make_size_t (17)) ;
-                       /* Change the loops to be references to the markers */
-                       sLoopStart = 1 ;
-                       sLoopEnd = 2 ;
-                       rLoopStart = 0 ;
-                       rLoopEnd = 0 ;
-                       }
-               else if (psf->instrument->loops [0].mode == SF_LOOP_NONE && psf->instrument->loops [1].mode != SF_LOOP_NONE)
-               {       /* There's a release loop but no sustain loop! Strange indeed! */
-                       psf_binheader_writef (psf, "Em42241b241b",
-                                       MARK_MARKER, 2 + (2 + 4 + 1 + 19) + (2 + 4 + 1 + 17), 2,
-                                       1, psf->instrument->loops [1].start, 18, "release loop start", make_size_t (19),
-                                       2, psf->instrument->loops [1].end, 16, "release loop end", make_size_t (17)) ;
-                       /* Change the loops to be references to the markers */
-                       sLoopStart = 0 ;
-                       sLoopEnd = 0 ;
-                       rLoopStart = 1 ;
-                       rLoopEnd = 2 ;
-                       } ;
-
-               /* First convert loop modes to aiff standard */
-               sustainLoopMode = convert_loop_mode (psf->instrument->loops [0].mode) ;
-               releaseLoopMode = convert_loop_mode (psf->instrument->loops [1].mode) ;
-
-               /* Now we finally write the actual INST chunk */
-               psf_binheader_writef (psf, "Em4111111", INST_MARKER, SIZEOF_INST_CHUNK, psf->instrument->basenote, psf->instrument->detune,
-                       psf->instrument->key_lo, psf->instrument->key_hi, psf->instrument->velocity_lo, psf->instrument->velocity_hi) ;
-               psf_binheader_writef (psf, "E2222222", (short) psf->instrument->gain,
-                       sustainLoopMode, sLoopStart, sLoopEnd,
-                       releaseLoopMode, rLoopStart, rLoopEnd) ;
-
+       {       /* Huge chunk of code removed here because it had egregious errors that were
+               ** not detected by either the compiler or the tests. It was found when updating
+               ** the way psf_binheader_writef works.
+               */
                }
        else if (psf->instrument == NULL && psf->cues != NULL)
        {       /* There are cues but no loops */
@@ -1589,29 +1452,29 @@ aiff_write_header (SF_PRIVATE *psf, int calc_length)
                        } ;
 
                psf_binheader_writef (psf, "Em42",
-                       MARK_MARKER, 2 + psf->cues->cue_count * (2 + 4) + totalStringLength, psf->cues->cue_count) ;
+                       BHWm (MARK_MARKER), BHW4 (2 + psf->cues->cue_count * (2 + 4) + totalStringLength), BHW2 (psf->cues->cue_count)) ;
 
                for (idx = 0 ; idx < psf->cues->cue_count ; idx++)
-                       psf_binheader_writef (psf, "E24p", psf->cues->cue_points [idx].indx, psf->cues->cue_points [idx].sample_offset, psf->cues->cue_points [idx].name) ;
+                       psf_binheader_writef (psf, "E24p", BHW2 (psf->cues->cue_points [idx].indx), BHW4 (psf->cues->cue_points [idx].sample_offset), BHWp (psf->cues->cue_points [idx].name)) ;
                } ;
 
        if (psf->strings.flags & SF_STR_LOCATE_START)
                aiff_write_strings (psf, SF_STR_LOCATE_START) ;
 
        if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START)
-       {       psf_binheader_writef (psf, "Em4", PEAK_MARKER, AIFF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
-               psf_binheader_writef (psf, "E44", 1, time (NULL)) ;
+       {       psf_binheader_writef (psf, "Em4", BHWm (PEAK_MARKER), BHW4 (AIFF_PEAK_CHUNK_SIZE (psf->sf.channels))) ;
+               psf_binheader_writef (psf, "E44", BHW4 (1), BHW4 (time (NULL))) ;
                for (k = 0 ; k < psf->sf.channels ; k++)
-                       psf_binheader_writef (psf, "Eft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
+                       psf_binheader_writef (psf, "Eft8", BHWf ((float) psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ;
                } ;
 
        /* Write custom headers. */
        for (uk = 0 ; uk < psf->wchunks.used ; uk++)
-               psf_binheader_writef (psf, "Em4b", psf->wchunks.chunks [uk].mark32, psf->wchunks.chunks [uk].len, psf->wchunks.chunks [uk].data, make_size_t (psf->wchunks.chunks [uk].len)) ;
+               psf_binheader_writef (psf, "Em4b", BHWm (psf->wchunks.chunks [uk].mark32), BHW4 (psf->wchunks.chunks [uk].len), BHWv (psf->wchunks.chunks [uk].data), BHWz (psf->wchunks.chunks [uk].len)) ;
 
        /* Write SSND chunk. */
        paiff->ssnd_offset = psf->header.indx ;
-       psf_binheader_writef (psf, "Etm844", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK, 0, 0) ;
+       psf_binheader_writef (psf, "Etm844", BHWm (SSND_MARKER), BHW8 (psf->datalength + SIZEOF_SSND_CHUNK), BHW4 (0), BHW4 (0)) ;
 
        /* Header construction complete so write it out. */
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
@@ -1649,10 +1512,10 @@ aiff_write_tailer (SF_PRIVATE *psf)
                } ;
 
        if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_END)
-       {       psf_binheader_writef (psf, "Em4", PEAK_MARKER, AIFF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
-               psf_binheader_writef (psf, "E44", 1, time (NULL)) ;
+       {       psf_binheader_writef (psf, "Em4", BHWm (PEAK_MARKER), BHW4 (AIFF_PEAK_CHUNK_SIZE (psf->sf.channels))) ;
+               psf_binheader_writef (psf, "E44", BHW4 (1), BHW4 (time (NULL))) ;
                for (k = 0 ; k < psf->sf.channels ; k++)
-                       psf_binheader_writef (psf, "Eft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
+                       psf_binheader_writef (psf, "Eft8", BHWf ((float) psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ;
                } ;
 
        if (psf->strings.flags & SF_STR_LOCATE_END)
@@ -1679,28 +1542,28 @@ aiff_write_strings (SF_PRIVATE *psf, int location)
                switch (psf->strings.data [k].type)
                {       case SF_STR_SOFTWARE :
                                slen = strlen (psf->strings.storage + psf->strings.data [k].offset) ;
-                               psf_binheader_writef (psf, "Em4mb", APPL_MARKER, slen + 4, m3ga_MARKER, psf->strings.storage + psf->strings.data [k].offset, make_size_t (slen + (slen & 1))) ;
+                               psf_binheader_writef (psf, "Em4mb", BHWm (APPL_MARKER), BHW4 (slen + 4), BHWm (m3ga_MARKER), BHWv (psf->strings.storage + psf->strings.data [k].offset), BHWz (slen + (slen & 1))) ;
                                break ;
 
                        case SF_STR_TITLE :
-                               psf_binheader_writef (psf, "EmS", NAME_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "EmS", BHWm (NAME_MARKER), BHWS (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_COPYRIGHT :
-                               psf_binheader_writef (psf, "EmS", c_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "EmS", BHWm (c_MARKER), BHWS (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_ARTIST :
-                               psf_binheader_writef (psf, "EmS", AUTH_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "EmS", BHWm (AUTH_MARKER), BHWS (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_COMMENT :
-                               psf_binheader_writef (psf, "EmS", ANNO_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "EmS", BHWm (ANNO_MARKER), BHWS (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        /*
                        case SF_STR_DATE :
-                               psf_binheader_writef (psf, "Ems", ICRD_MARKER, psf->strings.data [k].str) ;
+                               psf_binheader_writef (psf, "Ems", BHWm (ICRD_MARKER), BHWs (psf->strings.data [k].str)) ;
                                break ;
                        */
                        } ;
@@ -1866,6 +1729,11 @@ aiff_read_basc_chunk (SF_PRIVATE * psf, int datasize)
 
        psf_log_printf (psf, "  Loop Type : 0x%x (%s)\n", bc.loopType, type_str) ;
 
+       if (psf->loop_info)
+       {       psf_log_printf (psf, "  Found existing loop info, using last one.\n") ;
+               free (psf->loop_info) ;
+               psf->loop_info = NULL ;
+               } ;
        if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL)
                return SFE_MALLOC_FAILED ;
 
@@ -1905,7 +1773,7 @@ aiff_read_chanmap (SF_PRIVATE * psf, unsigned dword)
                psf_binheader_readf (psf, "j", dword - bytesread) ;
 
        if (map_info->channel_map != NULL)
-       {       size_t chanmap_size = psf->sf.channels * sizeof (psf->channel_map [0]) ;
+       {       size_t chanmap_size = SF_MIN (psf->sf.channels, layout_tag & 0xffff) * sizeof (psf->channel_map [0]) ;
 
                free (psf->channel_map) ;
 
index 063fd1a..6e0a794 100644 (file)
@@ -19,6 +19,7 @@
 #include       "sfconfig.h"
 
 #include       <math.h>
+#include       <limits.h>
 
 #include       "sndfile.h"
 #include       "common.h"
@@ -326,7 +327,9 @@ s2alaw_array (const short *ptr, int count, unsigned char *buffer)
 static inline void
 i2alaw_array (const int *ptr, int count, unsigned char *buffer)
 {      while (--count >= 0)
-       {       if (ptr [count] >= 0)
+       {       if (ptr [count] == INT_MIN)
+                       buffer [count] = alaw_encode [INT_MAX >> (16 + 4)] ;
+               else if (ptr [count] >= 0)
                        buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ;
                else
                        buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ;
@@ -337,19 +340,21 @@ static inline void
 f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact)
 {      while (--count >= 0)
        {       if (ptr [count] >= 0)
-                       buffer [count] = alaw_encode [lrintf (normfact * ptr [count])] ;
+                       buffer [count] = alaw_encode [psf_lrintf (normfact * ptr [count])] ;
                else
-                       buffer [count] = 0x7F & alaw_encode [- lrintf (normfact * ptr [count])] ;
+                       buffer [count] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [count])] ;
                } ;
 } /* f2alaw_array */
 
 static inline void
 d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact)
 {      while (--count >= 0)
-       {       if (ptr [count] >= 0)
-                       buffer [count] = alaw_encode [lrint (normfact * ptr [count])] ;
+       {       if (!isfinite (ptr [count]))
+                       buffer [count] = 0 ;
+               else if (ptr [count] >= 0)
+                       buffer [count] = alaw_encode [psf_lrint (normfact * ptr [count])] ;
                else
-                       buffer [count] = 0x7F & alaw_encode [- lrint (normfact * ptr [count])] ;
+                       buffer [count] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [count])] ;
                } ;
 } /* d2alaw_array */
 
index 57b8b5f..62bd691 100644 (file)
--- a/src/au.c
+++ b/src/au.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -239,12 +239,12 @@ au_write_header (SF_PRIVATE *psf, int calc_length)
                datalength = (int) (psf->datalength & 0x7FFFFFFF) ;
 
        if (psf->endian == SF_ENDIAN_BIG)
-       {       psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ;
-               psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
+       {       psf_binheader_writef (psf, "Em4", BHWm (DOTSND_MARKER), BHW4 (AU_DATA_OFFSET)) ;
+               psf_binheader_writef (psf, "E4444", BHW4 (datalength), BHW4 (encoding), BHW4 (psf->sf.samplerate), BHW4 (psf->sf.channels)) ;
                }
        else if (psf->endian == SF_ENDIAN_LITTLE)
-       {       psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ;
-               psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
+       {       psf_binheader_writef (psf, "em4", BHWm (DNSDOT_MARKER), BHW4 (AU_DATA_OFFSET)) ;
+               psf_binheader_writef (psf, "e4444", BHW4 (datalength), BHW4 (encoding), BHW4 (psf->sf.samplerate), BHW4 (psf->sf.channels)) ;
                }
        else
                return (psf->error = SFE_BAD_OPEN_FORMAT) ;
index 9cac83b..b2671e8 100644 (file)
@@ -24,6 +24,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <string.h>
index a66bb47..bd6b00f 100644 (file)
--- a/src/avr.c
+++ b/src/avr.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2004-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2004-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -127,7 +127,7 @@ avr_read_header (SF_PRIVATE *psf)
        psf_log_printf (psf, "  Channels    : %d\n  Bit width   : %d\n  Signed      : %s\n",
                        (hdr.mono & 1) + 1, hdr.rez, hdr.sign ? "yes" : "no") ;
 
-       switch ((hdr.rez << 16) + (hdr.sign & 1))
+       switch (arith_shift_left (hdr.rez, 16) + (hdr.sign & 1))
        {       case ((8 << 16) + 0) :
                        psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_U8 ;
                        psf->bytewidth = 1 ;
@@ -211,15 +211,15 @@ avr_write_header (SF_PRIVATE *psf, int calc_length)
        if (psf->is_pipe == SF_FALSE)
                psf_fseek (psf, 0, SEEK_SET) ;
 
-       psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, make_size_t (8),
-                       psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ;
+       psf_binheader_writef (psf, "Emz22", BHWm (TWOBIT_MARKER), BHWz (8),
+                       BHW2 (psf->sf.channels == 2 ? 0xFFFF : 0), BHW2 (psf->bytewidth * 8)) ;
 
        sign = ((SF_CODEC (psf->sf.format)) == SF_FORMAT_PCM_U8) ? 0 : 0xFFFF ;
 
-       psf_binheader_writef (psf, "E222", sign, 0, 0xFFFF) ;
-       psf_binheader_writef (psf, "E4444", psf->sf.samplerate, psf->sf.frames, 0, 0) ;
+       psf_binheader_writef (psf, "E222", BHW2 (sign), BHW2 (0), BHW2 (0xFFFF)) ;
+       psf_binheader_writef (psf, "E4444", BHW4 (psf->sf.samplerate), BHW4 (psf->sf.frames), BHW4 (0), BHW4 (0)) ;
 
-       psf_binheader_writef (psf, "E222zz", 0, 0, 0, make_size_t (20), make_size_t (64)) ;
+       psf_binheader_writef (psf, "E222zz", BHW2 (0), BHW2 (0), BHW2 (0), BHWz (20), BHWz (64)) ;
 
        /* Header construction complete so write it out. */
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
index 6ee609e..09ebc92 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 
-# Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+# Copyright (C) 2006-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 #
 # All rights reserved.
 #
@@ -42,76 +42,73 @@ import re, string, sys
 _whitespace_re = re.compile ("\s+", re.MULTILINE)
 
 def find_binheader_writefs (data):
-       lst = re.findall ('psf_binheader_writef\s*\(\s*[a-zA-Z_]+\s*,\s*\"[^;]+;', data, re.MULTILINE)
-       return [_whitespace_re.sub (" ", x) for x in lst]
+    lst = re.findall ('psf_binheader_writef\s*\(\s*[a-zA-Z_]+\s*,\s*\"[^;]+;', data, re.MULTILINE)
+    return [_whitespace_re.sub (" ", x) for x in lst]
 
 def find_format_string (s):
-       fmt = re.search ('"([^"]+)"', s)
-       if not fmt:
-               print ("Bad format in :\n\n\t%s\n\n" % s)
-               sys.exit (1)
-       fmt = fmt.groups ()
-       if len (fmt) != 1:
-               print ("Bad format in :\n\n\t%s\n\n" % s)
-               sys.exit (1)
-       return _whitespace_re.sub ("", fmt [0])
+    fmt = re.search ('"([^"]+)"', s)
+    if not fmt:
+        print ("Bad format in :\n\n\t%s\n\n" % s)
+        sys.exit (1)
+    fmt = fmt.groups ()
+    if len (fmt) != 1:
+        print ("Bad format in :\n\n\t%s\n\n" % s)
+        sys.exit (1)
+    return _whitespace_re.sub ("", fmt [0])
 
 def get_param_list (data):
-       dlist = re.search ("\((.+)\)\s*;", data)
-       dlist = dlist.groups ()[0]
-       dlist = dlist.split(",")
-       dlist = [x.strip() for x in dlist]
-       return dlist [2:]
+    dlist = re.search ("\((.+)\)\s*;", data)
+    dlist = dlist.groups ()[0]
+    dlist = dlist.split(",")
+    dlist = [x.strip() for x in dlist]
+    return dlist [2:]
 
 def handle_file (fname):
-       errors = 0
-       data = open (fname, "r").read ()
+    errors = 0
+    data = open (fname, "r").read ()
 
-       writefs = find_binheader_writefs (data)
-       for item in writefs:
-               fmt = find_format_string (item)
-               params = get_param_list (item)
-               param_index = 0
+    # return errors
 
-               # print item
+    writefs = find_binheader_writefs (data)
+    for item in writefs:
+        fmt = find_format_string (item)
+        params = get_param_list (item)
+        param_index = 0
 
-               for ch in fmt:
-                       if ch in 'Eet ':
-                               continue
+        # print item
 
-                       # print "    param [%d] %c : %s" % (param_index, ch, params [param_index])
+        for ch in fmt:
+            if ch in 'Eet ':
+                continue
 
-                       if ch != 'b':
-                               param_index += 1
-                               continue
+            if ch == 'b':
+                if params [param_index][:4] == "BHWv" and params [param_index + 1][:4] == "BHWz":
+                    param_index += 2
+                    continue
 
-                       # print item
-                       # print "    param [%d] %c : %s <-> %s" % (param_index, ch, params [param_index], params [param_index + 1])
+            if "BHW" + ch == params [param_index][:4]:
+                param_index += 1
+                continue
 
-                       # print (params [param_index + 1])
-                       if params [param_index + 1].find ("sizeof") < 0 \
-                                               and params [param_index + 1].find ("make_size_t") < 0 \
-                                               and params [param_index + 1].find ("strlen") < 0:
-                               if errors == 0: sys.stdout.write ("\n")
-                               print ("\n%s :" % fname)
-                               print ("    param [%d] %c : %s <-> %s" % (param_index, ch, params [param_index], params [param_index + 1]))
-                               print ("    %s" % item)
-                               errors += 1
-                       param_index += 2
+            if errors == 0: sys.stdout.write ("\n")
+            print ("\n%s: error for format specifier '%c' (index %d) in:\n    %s\n" % (fname, ch, param_index, item))
+            errors += 1
+            # Break out of 'for ch in fmt' loop
+            break
 
-       return errors
+    return errors
 
 #===============================================================================
 
 if len (sys.argv) > 1:
-       sys.stdout.write ("\n    binheader_writef_check                   :")
-       sys.stdout.flush ()
-       errors = 0
-       for fname in sys.argv [1:]:
-               errors += handle_file (fname)
-       if errors > 0:
-               print ("\nErrors : %d\n" % errors)
-               sys.exit (1)
+    sys.stdout.write ("\n    binheader_writef_check                   : ")
+    sys.stdout.flush ()
+    errors = 0
+    for fname in sys.argv [1:]:
+        errors += handle_file (fname)
+    if errors > 0:
+        print ("\nErrors : %d\n" % errors)
+        sys.exit (1)
 
 print ("ok\n")
 
index d2a7a76..16575bb 100644 (file)
@@ -87,7 +87,7 @@ broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datas
        psf->broadcast_16k->coding_history_size = len ;
 
        /* Currently writing this version. */
-       psf->broadcast_16k->version = 1 ;
+       psf->broadcast_16k->version = 2 ;
 
        return SF_TRUE ;
 } /* broadcast_var_set */
@@ -188,4 +188,3 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
 
        return count ;
 } /* gen_coding_history */
-
index 6546d6d..45b1dba 100644 (file)
--- a/src/caf.c
+++ b/src/caf.c
@@ -370,7 +370,7 @@ caf_read_header (SF_PRIVATE *psf)
                return SFE_MALFORMED_FILE ;
                } ;
 
-       psf->sf.samplerate = lrint (srate) ;
+       psf->sf.samplerate = psf_lrint (srate) ;
 
        psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.frames_per_packet,
                        &desc.channels_per_frame, &desc.bits_per_chan) ;
@@ -608,13 +608,13 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
        psf_fseek (psf, 0, SEEK_SET) ;
 
        /* 'caff' marker, version and flags. */
-       psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ;
+       psf_binheader_writef (psf, "Em22", BHWm (caff_MARKER), BHW2 (1), BHW2 (0)) ;
 
        /* 'desc' marker and chunk size. */
-       psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ;
+       psf_binheader_writef (psf, "Em8", BHWm (desc_MARKER), BHW8 ((sf_count_t) (sizeof (DESC_CHUNK)))) ;
 
        double64_be_write (1.0 * psf->sf.samplerate, ubuf.ucbuf) ;
-       psf_binheader_writef (psf, "b", ubuf.ucbuf, make_size_t (8)) ;
+       psf_binheader_writef (psf, "b", BHWv (ubuf.ucbuf), BHWz (8)) ;
 
        subformat = SF_CODEC (psf->sf.format) ;
 
@@ -721,33 +721,33 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
                        return SFE_UNIMPLEMENTED ;
                } ;
 
-       psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ;
+       psf_binheader_writef (psf, "mE44444", BHWm (desc.fmt_id), BHW4 (desc.fmt_flags), BHW4 (desc.pkt_bytes), BHW4 (desc.frames_per_packet), BHW4 (desc.channels_per_frame), BHW4 (desc.bits_per_chan)) ;
 
        caf_write_strings (psf, SF_STR_LOCATE_START) ;
 
        if (psf->peak_info != NULL)
        {       int k ;
-               psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ;
+               psf_binheader_writef (psf, "Em84", BHWm (peak_MARKER), BHW8 ((sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels)), BHW4 (psf->peak_info->edit_number)) ;
                for (k = 0 ; k < psf->sf.channels ; k++)
-                       psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
+                       psf_binheader_writef (psf, "Ef8", BHWf ((float) psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ;
                } ;
 
        if (psf->channel_map && pcaf->chanmap_tag)
-               psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ;
+               psf_binheader_writef (psf, "Em8444", BHWm (chan_MARKER), BHW8 ((sf_count_t) 12), BHW4 (pcaf->chanmap_tag), BHW4 (0), BHW4 (0)) ;
 
        /* Write custom headers. */
        for (uk = 0 ; uk < psf->wchunks.used ; uk++)
-               psf_binheader_writef (psf, "m44b", (int) psf->wchunks.chunks [uk].mark32, 0, psf->wchunks.chunks [uk].len, psf->wchunks.chunks [uk].data, make_size_t (psf->wchunks.chunks [uk].len)) ;
+               psf_binheader_writef (psf, "m44b", BHWm ((int) psf->wchunks.chunks [uk].mark32), BHW4 (0), BHW4 (psf->wchunks.chunks [uk].len), BHWv (psf->wchunks.chunks [uk].data), BHWz (psf->wchunks.chunks [uk].len)) ;
 
        if (append_free_block)
        {       /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
                sf_count_t free_len = 0x1000 - psf->header.indx - 16 - 12 ;
                while (free_len < 0)
                        free_len += 0x1000 ;
-               psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, make_size_t (free_len)) ;
+               psf_binheader_writef (psf, "Em8z", BHWm (free_MARKER), BHW8 (free_len), BHWz (free_len)) ;
                } ;
 
-       psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ;
+       psf_binheader_writef (psf, "Em84", BHWm (data_MARKER), BHW8 (psf->datalength + 4), BHW4 (0)) ;
 
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
        if (psf->error)
@@ -780,7 +780,7 @@ caf_write_tailer (SF_PRIVATE *psf)
                psf->dataend = psf_fseek (psf, 0, SEEK_END) ;
 
        if (psf->dataend & 1)
-               psf_binheader_writef (psf, "z", 1) ;
+               psf_binheader_writef (psf, "z", BHWz (1)) ;
 
        if (psf->strings.flags & SF_STR_LOCATE_END)
                caf_write_strings (psf, SF_STR_LOCATE_END) ;
@@ -982,7 +982,7 @@ caf_write_strings (SF_PRIVATE * psf, int location)
        if (string_count == 0 || buf.index == 0)
                return ;
 
-       psf_binheader_writef (psf, "Em84b", info_MARKER, make_size_8 (buf.index + 4), string_count, buf.s, make_size_t (buf.index)) ;
+       psf_binheader_writef (psf, "Em84b", BHWm (info_MARKER), BHW8 (buf.index + 4), BHW4 (string_count), BHWv (buf.s), BHWz (buf.index)) ;
 } /* caf_write_strings */
 
 /*==============================================================================
index d8b6555..471c5a4 100644 (file)
@@ -219,6 +219,7 @@ psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info)
 {      union
        {       uint32_t marker ;
                char str [5] ;
+               /* Update snprintf() format string below when changing this */
        } u ;
        uint32_t len ;
 
@@ -241,7 +242,7 @@ psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info)
        len = chunk_info->datalen ;
        while (len & 3) len ++ ;
 
-       snprintf (u.str, sizeof (u.str), "%s", chunk_info->id) ;
+       snprintf (u.str, sizeof (u.str), "%.4s", chunk_info->id) ;
 
        pchk->chunks [pchk->used].hash = strlen (chunk_info->id) > 4 ? hash_of_str (chunk_info->id) : u.marker ;
        pchk->chunks [pchk->used].mark32 = u.marker ;
index 3204e56..15037ab 100644 (file)
@@ -66,8 +66,12 @@ static SF_FORMAT_INFO const simple_formats [] =
                },
 
 #if HAVE_EXTERNAL_XIPH_LIBS
+       {       SF_FORMAT_OGG | SF_FORMAT_OPUS,
+               "Ogg Opus (Xiph Foundation)", "opus"
+               },
+
        {       SF_FORMAT_OGG | SF_FORMAT_VORBIS,
-               "Ogg Vorbis (Xiph Foundation)", "oga"
+               "Ogg Vorbis (Xiph Foundation)", "ogg"
                },
 #endif
 
@@ -192,17 +196,23 @@ static SF_FORMAT_INFO subtype_formats [] =
 
        {       SF_FORMAT_G721_32,              "32kbs G721 ADPCM",             NULL    },
        {       SF_FORMAT_G723_24,              "24kbs G723 ADPCM",             NULL    },
+       {       SF_FORMAT_G723_40,              "40kbs G723 ADPCM",             NULL    },
 
        {       SF_FORMAT_DWVW_12,              "12 bit DWVW",                  NULL    },
        {       SF_FORMAT_DWVW_16,              "16 bit DWVW",                  NULL    },
        {       SF_FORMAT_DWVW_24,              "24 bit DWVW",                  NULL    },
        {       SF_FORMAT_VOX_ADPCM,    "VOX ADPCM",                    "vox"   },
 
+       {       SF_FORMAT_NMS_ADPCM_16, "16kbs NMS ADPCM",              NULL    },
+       {       SF_FORMAT_NMS_ADPCM_24, "24kbs NMS ADPCM",              NULL    },
+       {       SF_FORMAT_NMS_ADPCM_32, "32kbs NMS ADPCM",              NULL    },
+
        {       SF_FORMAT_DPCM_16,              "16 bit DPCM",                  NULL    },
        {       SF_FORMAT_DPCM_8,               "8 bit DPCM",                   NULL    },
 
 #if HAVE_EXTERNAL_XIPH_LIBS
        {       SF_FORMAT_VORBIS,               "Vorbis",                               NULL    },
+       {       SF_FORMAT_OPUS,                 "Opus",                                 NULL    },
 #endif
 
        {       SF_FORMAT_ALAC_16,              "16 bit ALAC",                  NULL    },
index b9f3223..c9737a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -22,6 +22,8 @@
 #include <string.h>
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 #include <ctype.h>
 #include <math.h>
@@ -33,7 +35,7 @@
 #include "sfendian.h"
 #include "common.h"
 
-#define        INITAL_HEADER_SIZE      256
+#define        INITIAL_HEADER_SIZE     256
 
 /* Allocate and initialize the SF_PRIVATE struct. */
 SF_PRIVATE *
@@ -43,11 +45,11 @@ psf_allocate (void)
        if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL)
                return  NULL ;
 
-       if ((psf->header.ptr = calloc (1, INITAL_HEADER_SIZE)) == NULL)
+       if ((psf->header.ptr = calloc (1, INITIAL_HEADER_SIZE)) == NULL)
        {       free (psf) ;
                return  NULL ;
                } ;
-       psf->header.len = INITAL_HEADER_SIZE ;
+       psf->header.len = INITIAL_HEADER_SIZE ;
 
        return psf ;
 } /* psf_allocate */
@@ -55,13 +57,13 @@ psf_allocate (void)
 static int
 psf_bump_header_allocation (SF_PRIVATE * psf, sf_count_t needed)
 {
-       sf_count_t newlen, smallest = INITAL_HEADER_SIZE ;
+       sf_count_t newlen, smallest = INITIAL_HEADER_SIZE ;
        void * ptr ;
 
        newlen = (needed > psf->header.len) ? 2 * SF_MAX (needed, smallest) : 2 * psf->header.len ;
 
        if (newlen > 100 * 1024)
-       {       psf_log_printf (psf, "Request for header allocation of %D denined.\n", newlen) ;
+       {       psf_log_printf (psf, "Request for header allocation of %D denied.\n", newlen) ;
                return 1 ;
                }
 
@@ -71,6 +73,10 @@ psf_bump_header_allocation (SF_PRIVATE * psf, sf_count_t needed)
                return 1 ;
                } ;
 
+       /* Always zero-out new header memory to avoid un-initializer memory accesses. */
+       if (newlen > psf->header.len)
+               memset ((char *) ptr + psf->header.len, 0, newlen - psf->header.len) ;
+
        psf->header.ptr = ptr ;
        psf->header.len = newlen ;
        return 0 ;
@@ -379,6 +385,9 @@ psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...)
        int             maxlen ;
        char    *start ;
 
+       if (! format)
+               return ;
+
        maxlen = strlen ((char*) psf->header.ptr) ;
        start   = ((char*) psf->header.ptr) + maxlen ;
        maxlen  = psf->header.len - maxlen ;
@@ -552,9 +561,10 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
        void                    *bindata ;
        size_t                  size ;
        char                    c, *strptr ;
-       int                             count = 0, trunc_8to4 ;
+       int                             count = 0, trunc_8to4 = SF_FALSE ;
 
-       trunc_8to4 = SF_FALSE ;
+       if (! format)
+               return psf_ftell (psf) ;
 
        va_start (argptr, format) ;
 
@@ -675,16 +685,16 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
                                        /* Write a C string (guaranteed to have a zero terminator). */
                                        strptr = va_arg (argptr, char *) ;
                                        size = strlen (strptr) + 1 ;
-                                       size += (size & 1) ;
 
-                                       if (psf->header.indx + (sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, 16))
+                                       if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
                                                return count ;
 
                                        if (psf->rwf_endian == SF_ENDIAN_BIG)
-                                               header_put_be_int (psf, size) ;
+                                               header_put_be_int (psf, size + (size & 1)) ;
                                        else
-                                               header_put_le_int (psf, size) ;
+                                               header_put_le_int (psf, size + (size & 1)) ;
                                        memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
+                                       size += (size & 1) ;
                                        psf->header.indx += size ;
                                        psf->header.ptr [psf->header.indx - 1] = 0 ;
                                        count += 4 + size ;
@@ -697,16 +707,15 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
                                        */
                                        strptr = va_arg (argptr, char *) ;
                                        size = strlen (strptr) ;
-                                       if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
+                                       if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
                                                return count ;
                                        if (psf->rwf_endian == SF_ENDIAN_BIG)
                                                header_put_be_int (psf, size) ;
                                        else
                                                header_put_le_int (psf, size) ;
-                                       memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + 1) ;
+                                       memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + (size & 1)) ;
                                        size += (size & 1) ;
                                        psf->header.indx += size ;
-                                       psf->header.ptr [psf->header.indx] = 0 ;
                                        count += 4 + size ;
                                        break ;
 
@@ -718,7 +727,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
                                        size = (size & 1) ? size : size + 1 ;
                                        size = (size > 254) ? 254 : size ;
 
-                                       if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
+                                       if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size))
                                                return count ;
 
                                        header_put_byte (psf, size) ;
@@ -868,6 +877,7 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
                                psf_bump_header_allocation (psf, position) ;
                        if (position > psf->header.len)
                        {       /* Too much header to cache so just seek instead. */
+                               psf->header.indx = psf->header.end ;
                                psf_fseek (psf, position, whence) ;
                                return ;
                                } ;
@@ -1238,8 +1248,12 @@ psf_memset (void *s, int c, sf_count_t len)
 
 typedef SF_CUES_VAR (0) SF_CUES_0 ;
 
+/* calculate size of SF_CUES struct given number of cues */
 #define SF_CUES_VAR_SIZE(count)        (sizeof (SF_CUES_0) + count * sizeof (SF_CUE_POINT))
 
+/* calculate number of cues in SF_CUES struct given data size */
+#define SF_CUES_COUNT(datasize) (((datasize) - sizeof (uint32_t)) / sizeof (SF_CUE_POINT))
+
 SF_CUES *
 psf_cues_alloc (uint32_t cue_count)
 {      SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ;
@@ -1249,11 +1263,16 @@ psf_cues_alloc (uint32_t cue_count)
 } /* psf_cues_alloc */
 
 SF_CUES *
-psf_cues_dup (const void * ptr)
+psf_cues_dup (const void * ptr, size_t datasize)
 {      const SF_CUES *pcues = ptr ;
-       SF_CUES *pnew = psf_cues_alloc (pcues->cue_count) ;
+       SF_CUES *pnew = NULL ;
+
+       if (pcues->cue_count <= SF_CUES_COUNT (datasize))
+       {       /* check that passed-in datasize is consistent with cue_count in passed-in SF_CUES struct */
+               pnew = psf_cues_alloc (pcues->cue_count) ;
+               memcpy (pnew, pcues, SF_CUES_VAR_SIZE (pcues->cue_count)) ;
+       }
 
-       memcpy (pnew, pcues, SF_CUES_VAR_SIZE (pcues->cue_count)) ;
        return pnew ;
 } /* psf_cues_dup */
 
@@ -1261,7 +1280,7 @@ void
 psf_get_cues (SF_PRIVATE * psf, void * data, size_t datasize)
 {
        if (psf->cues)
-       {       uint32_t cue_count = (datasize - sizeof (uint32_t)) / sizeof (SF_CUE_POINT) ;
+       {       uint32_t cue_count = SF_CUES_COUNT (datasize) ;
 
                cue_count = SF_MIN (cue_count, psf->cues->cue_count) ;
                memcpy (data, psf->cues, SF_CUES_VAR_SIZE (cue_count)) ;
@@ -1531,6 +1550,9 @@ str_of_minor_format (int format)
                CASE_NAME (SF_FORMAT_MS_ADPCM) ;
                CASE_NAME (SF_FORMAT_GSM610) ;
                CASE_NAME (SF_FORMAT_VOX_ADPCM) ;
+               CASE_NAME (SF_FORMAT_NMS_ADPCM_16) ;
+               CASE_NAME (SF_FORMAT_NMS_ADPCM_24) ;
+               CASE_NAME (SF_FORMAT_NMS_ADPCM_32) ;
                CASE_NAME (SF_FORMAT_G721_32) ;
                CASE_NAME (SF_FORMAT_G723_24) ;
                CASE_NAME (SF_FORMAT_G723_40) ;
@@ -1585,7 +1607,7 @@ psf_f2s_array (const float *src, short *dest, int count, int normalize)
 
        normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
        while (--count >= 0)
-               dest [count] = lrintf (src [count] * normfact) ;
+               dest [count] = psf_lrintf (src [count] * normfact) ;
 
        return ;
 } /* psf_f2s_array */
@@ -1607,7 +1629,7 @@ psf_f2s_clip_array (const float *src, short *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               dest [count] = lrintf (scaled_value) ;
+               dest [count] = psf_lrintf (scaled_value) ;
                } ;
 
        return ;
@@ -1619,7 +1641,7 @@ psf_d2s_array (const double *src, short *dest, int count, int normalize)
 
        normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
        while (--count >= 0)
-               dest [count] = lrint (src [count] * normfact) ;
+               dest [count] = psf_lrint (src [count] * normfact) ;
 
        return ;
 } /* psf_f2s_array */
@@ -1641,7 +1663,7 @@ psf_d2s_clip_array (const double *src, short *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               dest [count] = lrint (scaled_value) ;
+               dest [count] = psf_lrint (scaled_value) ;
                } ;
 
        return ;
@@ -1654,7 +1676,7 @@ psf_f2i_array (const float *src, int *dest, int count, int normalize)
 
        normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
        while (--count >= 0)
-               dest [count] = lrintf (src [count] * normfact) ;
+               dest [count] = psf_lrintf (src [count] * normfact) ;
 
        return ;
 } /* psf_f2i_array */
@@ -1676,7 +1698,7 @@ psf_f2i_clip_array (const float *src, int *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               dest [count] = lrintf (scaled_value) ;
+               dest [count] = psf_lrintf (scaled_value) ;
                } ;
 
        return ;
@@ -1688,7 +1710,7 @@ psf_d2i_array (const double *src, int *dest, int count, int normalize)
 
        normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
        while (--count >= 0)
-               dest [count] = lrint (src [count] * normfact) ;
+               dest [count] = psf_lrint (src [count] * normfact) ;
 
        return ;
 } /* psf_f2i_array */
@@ -1710,7 +1732,7 @@ psf_d2i_clip_array (const double *src, int *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               dest [count] = lrint (scaled_value) ;
+               dest [count] = psf_lrint (scaled_value) ;
                } ;
 
        return ;
index 0bd810c..08360d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 #include <stdlib.h>
 #include <string.h>
 
-#if HAVE_STDINT_H
-#include <stdint.h>
-#elif HAVE_INTTYPES_H
+#if HAVE_INTTYPES_H
 #include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
 #endif
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #include "sndfile.h"
 #endif
 
+#include <math.h>
+
+#ifdef USE_SSE2
+#include <immintrin.h>
+#endif
+
 #ifdef __cplusplus
 #error "This code is not designed to be compiled with a C++ compiler."
 #endif
 
 #ifdef INT64_C
-#      define  SF_PLATFORM_S64(x)              INT64_C(x)
+#      define  SF_PLATFORM_S64(x)              INT64_C (x)
 #elif (SIZEOF_LONG == 8)
 #      define  SF_PLATFORM_S64(x)              x##l
 #elif (SIZEOF_LONG_LONG == 8)
 #      define WARN_UNUSED
 #endif
 
-/*
-** Visibility control
-*/
-
-#if defined (SNDFILE_EXPORTS) && !defined (_WIN32)
-#      define SNDFILE_API      __attribute__ ((visibility ("default")))
-#else
-#      define SNDFILE_API
-#endif
-
-
 #define        SF_BUFFER_LEN                   (8192)
 #define        SF_FILENAME_LEN                 (1024)
 #define SF_SYSERR_LEN                  (256)
 #define SF_CODEC(x)                    ((x) & SF_FORMAT_SUBMASK)
 #define SF_ENDIAN(x)           ((x) & SF_FORMAT_ENDMASK)
 
+/*
+**     Binheader cast macros.
+*/
+
+#define BHW1(x) ((uint8_t) (x))
+#define BHW2(x) ((uint16_t) (x))
+#define BHW3(x) ((uint32_t) (x))
+#define BHW4(x) ((uint32_t) (x))
+#define BHW8(x) ((uint64_t) (x))
+
+#define BHWm(x) ((uint32_t) (x))
+#define BHWS(x) ((char *) (x))
+
+#define BHWf(x) ((double) (x))
+#define BHWd(x) ((double) (x))
+
+#define BHWh(x) ((void *) (x))
+#define BHWj(x) ((size_t) (x))
+#define BHWp(x) ((char *) (x))
+#define BHWo(x) ((size_t) (x))
+#define BHWs(x) ((char *) (x))
+#define BHWv(x) ((const void *) (x))
+#define BHWz(x) ((size_t) (x))
+
+/*------------------------------------------------------------------------------
+*/
+
 enum
 {      /* PEAK chunk location. */
        SF_PEAK_START           = 42,
@@ -281,11 +303,6 @@ make_size_t (int x)
 {      return (size_t) x ;
 } /* make_size_t */
 
-static inline uint64_t
-make_size_8 (int x)
-{      return (uint64_t) x ;
-} /* make_size_8 */
-
 typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ;
 
 typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ;
@@ -535,6 +552,8 @@ typedef struct sf_private_tag
        SF_CHUNK_ITERATOR *     (*next_chunk_iterator)  (struct sf_private_tag*, SF_CHUNK_ITERATOR * iterator) ;
        int                                     (*get_chunk_size)       (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
        int                                     (*get_chunk_data)       (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
+
+       int cpu_flags ;
 } SF_PRIVATE ;
 
 
@@ -562,7 +581,6 @@ enum
        SFE_UNIMPLEMENTED,
        SFE_BAD_READ_ALIGN,
        SFE_BAD_WRITE_ALIGN,
-       SFE_UNKNOWN_FORMAT,
        SFE_NOT_READMODE,
        SFE_NOT_WRITEMODE,
        SFE_BAD_MODE_RW,
@@ -628,6 +646,7 @@ enum
        SFE_WAV_GSM610_FORMAT,
        SFE_WAV_UNKNOWN_CHUNK,
        SFE_WAV_WVPK_DATA,
+       SFE_WAV_NMS_FORMAT,
 
        SFE_AIFF_NO_FORM,
        SFE_AIFF_AIFF_NO_FORM,
@@ -702,6 +721,7 @@ enum
 
        SFE_DWVW_BAD_BITWIDTH,
        SFE_G72X_NOT_MONO,
+       SFE_NMS_ADPCM_NOT_MONO,
 
        SFE_XI_BAD_HEADER,
        SFE_XI_EXCESS_SAMPLES,
@@ -725,6 +745,7 @@ enum
        SFE_FLAC_INIT_DECODER,
        SFE_FLAC_LOST_SYNC,
        SFE_FLAC_BAD_SAMPLE_RATE,
+       SFE_FLAC_CHANNEL_COUNT_CHANGED,
        SFE_FLAC_UNKOWN_ERROR,
 
        SFE_WVE_NOT_WVE,
@@ -745,6 +766,8 @@ enum
        SFE_FILENAME_TOO_LONG,
        SFE_NEGATIVE_RW_LEN,
 
+       SFE_OPUS_BAD_SAMPLERATE,
+
        SFE_MAX_ERROR                   /* This must be last in list. */
 } ;
 
@@ -918,6 +941,7 @@ int         float32_init    (SF_PRIVATE *psf) ;
 int            double64_init   (SF_PRIVATE *psf) ;
 int            dwvw_init               (SF_PRIVATE *psf, int bitwidth) ;
 int            gsm610_init             (SF_PRIVATE *psf) ;
+int            nms_adpcm_init  (SF_PRIVATE *psf) ;
 int            vox_adpcm_init  (SF_PRIVATE *psf) ;
 int            flac_init               (SF_PRIVATE *psf) ;
 int            g72x_init               (SF_PRIVATE * psf) ;
@@ -983,12 +1007,34 @@ psf_strlcpy (char *dest, size_t n, const char *src)
 } /* psf_strlcpy */
 
 /*------------------------------------------------------------------------------------
+** SIMD optimized math functions.
+*/
+
+static inline int psf_lrintf (float x)
+{
+       #ifdef USE_SSE2
+               return _mm_cvtss_si32 (_mm_load_ss (&x)) ;
+       #else
+               return lrintf (x) ;
+       #endif
+} /* psf_lrintf */
+
+static inline int psf_lrint (double x)
+{
+       #ifdef USE_SSE2
+               return _mm_cvtsd_si32 (_mm_load_sd (&x)) ;
+       #else
+               return lrint (x) ;
+       #endif
+} /* psf_lrintf */
+
+/*------------------------------------------------------------------------------------
 ** Other helper functions.
 */
 
 void   *psf_memset (void *s, int c, sf_count_t n) ;
 
-SF_CUES * psf_cues_dup (const void * ptr) ;
+SF_CUES * psf_cues_dup (const void * ptr, size_t datasize) ;
 SF_CUES * psf_cues_alloc (uint32_t cue_count) ;
 void psf_get_cues (SF_PRIVATE * psf, void * data, size_t datasize) ;
 
diff --git a/src/config.h.cmake b/src/config.h.cmake
new file mode 100644 (file)
index 0000000..c33bcbc
--- /dev/null
@@ -0,0 +1,314 @@
+/* Set to 1 if the compile is GNU GCC. */
+#cmakedefine01 COMPILER_IS_GCC
+
+/* Target processor clips on negative float to int conversion. */
+#cmakedefine01 CPU_CLIPS_NEGATIVE
+
+/* Target processor clips on positive float to int conversion. */
+#cmakedefine01 CPU_CLIPS_POSITIVE
+
+/* Target processor is big endian. */
+#cmakedefine01 CPU_IS_BIG_ENDIAN
+
+/* Target processor is little endian. */
+#cmakedefine01 CPU_IS_LITTLE_ENDIAN
+
+/* Set to 1 to enable experimental code. */
+#cmakedefine01 ENABLE_EXPERIMENTAL_CODE
+
+/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
+#cmakedefine01 HAVE_ALSA_ASOUNDLIB_H
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#cmakedefine01 HAVE_BYTESWAP_H
+
+/* Define to 1 if you have the `calloc' function. */
+#cmakedefine01 HAVE_CALLOC
+
+/* Define to 1 if you have the `ceil' function. */
+#cmakedefine01 HAVE_CEIL
+
+/* Set to 1 if S_IRGRP is defined. */
+#cmakedefine01 HAVE_DECL_S_IRGRP
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#cmakedefine01 HAVE_DLFCN_H
+
+/* Define to 1 if you have the <direct.h> header file. */
+#cmakedefine HAVE_DIRECT_H
+
+/* Define to 1 if you have the <endian.h> header file. */
+#cmakedefine01 HAVE_ENDIAN_H
+
+/* Will be set to 1 if flac, ogg and vorbis are available. */
+#cmakedefine01 HAVE_EXTERNAL_XIPH_LIBS
+
+/* Define to 1 if you have the `floor' function. */
+#cmakedefine01 HAVE_FLOOR
+
+/* Define to 1 if you have the `fmod' function. */
+#cmakedefine01 HAVE_FMOD
+
+/* Define to 1 if you have the `free' function. */
+#cmakedefine01 HAVE_FREE
+
+/* Define to 1 if you have the `fstat' function. */
+#cmakedefine01 HAVE_FSTAT
+
+/* Define to 1 if you have the `fstat64' function. */
+#cmakedefine01 HAVE_FSTAT64
+
+/* Define to 1 if you have the `fsync' function. */
+#cmakedefine01 HAVE_FSYNC
+
+/* Define to 1 if you have the `ftruncate' function. */
+#cmakedefine01 HAVE_FTRUNCATE
+
+/* Define to 1 if you have the `getpagesize' function. */
+#cmakedefine01 HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#cmakedefine01 HAVE_GETTIMEOFDAY
+
+/* Define if you have the `gmtime' function. */
+#cmakedefine HAVE_GMTIME
+
+/* Define if you have the `gmtime_r' function. */
+#cmakedefine HAVE_GMTIME_R
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine01 HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <io.h> header file. */
+#cmakedefine HAVE_IO_H
+
+/* Define to 1 if you have the `m' library (-lm). */
+#cmakedefine01 HAVE_LIBM
+
+/* Define to 1 if you have the <locale.h> header file. */
+#cmakedefine01 HAVE_LOCALE_H
+
+/* Define if you have the `localtime' function. */
+#cmakedefine HAVE_LOCALTIME
+
+/* Define if you have the `localtime_r' function. */
+#cmakedefine HAVE_LOCALTIME_R
+
+/* Define if you have C99's lrint function. */
+#cmakedefine01 HAVE_LRINT
+
+/* Define if you have C99's lrintf function. */
+#cmakedefine01 HAVE_LRINTF
+
+/* Define to 1 if you have the `lround' function. */
+#cmakedefine01 HAVE_LROUND
+
+/* Define to 1 if you have the `lseek' function. */
+#cmakedefine01 HAVE_LSEEK
+
+/* Define to 1 if you have the `lseek64' function. */
+#cmakedefine01 HAVE_LSEEK64
+
+/* Define to 1 if you have the `malloc' function. */
+#cmakedefine01 HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine01 HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mmap' function. */
+#cmakedefine01 HAVE_MMAP
+
+/* Define to 1 if you have the `open' function. */
+#cmakedefine01 HAVE_OPEN
+
+/* Define to 1 if you have the `pipe' function. */
+#cmakedefine01 HAVE_PIPE
+
+/* Define to 1 if you have the `read' function. */
+#cmakedefine01 HAVE_READ
+
+/* Define to 1 if you have the `realloc' function. */
+#cmakedefine01 HAVE_REALLOC
+
+/* Define to 1 if you have the `setlocale' function. */
+#cmakedefine01 HAVE_SETLOCALE
+
+/* Set to 1 if <sndio.h> is available. */
+#cmakedefine01 HAVE_SNDIO_H
+
+/* Define to 1 if you have the `snprintf' function. */
+#cmakedefine01 HAVE_SNPRINTF
+
+/* Set to 1 if you have libsqlite3. */
+#cmakedefine01 HAVE_SQLITE3
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#cmakedefine01 HAVE_SSIZE_T
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine01 HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine01 HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine01 HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine01 HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine01 HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#cmakedefine01 HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine01 HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#cmakedefine01 HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine01 HAVE_UNISTD_H
+
+/* Define to 1 if you have the <immintrin.h> header file. */
+#cmakedefine01 HAVE_IMMINTRIN_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#cmakedefine01 HAVE_VSNPRINTF
+
+/* Define to 1 if you have the `waitpid' function. */
+#cmakedefine01 HAVE_WAITPID
+
+/* Define to 1 if you have the `write' function. */
+#cmakedefine01 HAVE_WRITE
+
+/* The darwin version, no-zero is valid */
+#cmakedefine01 OSX_DARWIN_VERSION
+
+/* Set to 1 if compiling for OpenBSD */
+#cmakedefine01 OS_IS_OPENBSD
+
+/* Set to 1 if compiling for Win32 */
+#cmakedefine01 OS_IS_WIN32
+
+/* Set to 1 if SSE2 is enabled */
+#cmakedefine USE_SSE2
+
+/* Name of package */
+#define PACKAGE "@PACKAGE_NAME@"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "@PACKAGE_NAME@"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "@PACKAGE_NAME@ @CPACK_PACKAGE_VERSION_FULL@"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "@PACKAGE_NAME@"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "@PACKAGE_URL@"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "@CPACK_PACKAGE_VERSION_FULL@"
+
+/* Set to maximum allowed value of sf_count_t type. */
+#define SF_COUNT_MAX @SF_COUNT_MAX@
+
+/* The size of `double', as computed by sizeof. */
+@SIZEOF_DOUBLE_CODE@
+
+/* The size of `float', as computed by sizeof. */
+@SIZEOF_FLOAT_CODE@
+
+/* The size of `int', as computed by sizeof. */
+@SIZEOF_INT_CODE@
+
+/* The size of `int64_t', as computed by sizeof. */
+@SIZEOF_INT64_T_CODE@
+
+/* The size of `loff_t', as computed by sizeof. */
+@SIZEOF_LOFF_T_CODE@
+
+/* The size of `long', as computed by sizeof. */
+@SIZEOF_LONG_CODE@
+
+/* The size of `long long', as computed by sizeof. */
+@SIZEOF_LONG_LONG_CODE@
+
+/* The size of `off64_t', as computed by sizeof. */
+@SIZEOF_OFF64_T_CODE@
+
+/* The size of `off_t', as computed by sizeof. */
+@SIZEOF_OFF_T_CODE@
+
+/* Set to sizeof (long) if unknown. */
+@SIZEOF_SF_COUNT_T_CODE@
+
+/* The size of `short', as computed by sizeof. */
+@SIZEOF_SHORT_CODE@
+
+/* The size of `size_t', as computed by sizeof. */
+@SIZEOF_SIZE_T_CODE@
+
+/* The size of `ssize_t', as computed by sizeof. */
+@SIZEOF_SSIZE_T_CODE@
+
+/* The size of `void*', as computed by sizeof. */
+@SIZEOF_VOIDP_CODE@
+
+/* The size of `wchar_t', as computed by sizeof. */
+@SIZEOF_WCHAR_T_CODE@
+
+/* Set to long if unknown. */
+#define TYPEOF_SF_COUNT_T @TYPEOF_SF_COUNT_T@
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Set to 1 to use the native windows API */
+#cmakedefine01 USE_WINDOWS_API
+
+/* Version number of package */
+#define VERSION "@PROJECT_VERSION@"
+
+/* Set to 1 if windows DLL is being built. */
+#cmakedefine01 WIN32_TARGET_DLL
+
+/* Target processor is big endian. */
+#cmakedefine01 WORDS_BIGENDIAN
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Define to 1 if on MINIX. */
+#cmakedefine01 _MINIX
+
+/* Define as `__inline' or '__inline__' if that's what the C compiler calls it, or to nothing if it is not supported. */
+@INLINE_CODE@
diff --git a/src/create_symbols_file.c b/src/create_symbols_file.c
deleted file mode 100755 (executable)
index 851f00d..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (C) 2003-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//      * 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.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-//----------------------------------------------------------------
-// These are all of the public functions exported from libsndfile.
-//
-// Its important not to change the order they are listed in or
-// the ordinal values in the second column.
-
-typedef struct
-{      const char * name ;
-       int                     ordinal ;
-} SYMBOL ;
-
-static SYMBOL all_symbols [] =
-{
-       {       "sf_command",                           1       },
-       {       "sf_open",                                      2       },
-       {       "sf_close",                                     3       },
-       {       "sf_seek",                                      4       },
-       {       "sf_error",                                     7       },
-       {       "sf_perror",                            8       },
-       {       "sf_error_str",                         9       },
-       {       "sf_error_number",                      10      },
-       {       "sf_format_check",                      11      },
-       {       "sf_read_raw",                          16      },
-       {       "sf_readf_short",                       17      },
-       {       "sf_readf_int",                         18      },
-       {       "sf_readf_float",                       19      },
-       {       "sf_readf_double",                      20      },
-       {       "sf_read_short",                        21      },
-       {       "sf_read_int",                          22      },
-       {       "sf_read_float",                        23      },
-       {       "sf_read_double",                       24      },
-       {       "sf_write_raw",                         32      },
-       {       "sf_writef_short",                      33      },
-       {       "sf_writef_int",                        34      },
-       {       "sf_writef_float",                      35      },
-       {       "sf_writef_double",                     36      },
-       {       "sf_write_short",                       37      },
-       {       "sf_write_int",                         38      },
-       {       "sf_write_float",                       39      },
-       {       "sf_write_double",                      40      },
-       {       "sf_strerror",                          50      },
-       {       "sf_get_string",                        60      },
-       {       "sf_set_string",                        61      },
-       {       "sf_version_string",            68      },
-       {       "sf_open_fd",                           70      },
-       {       "sf_wchar_open",                        71      },
-       {       "sf_open_virtual",                      80      },
-       {       "sf_write_sync",                        90      },
-       {       "sf_set_chunk",                         100     },
-       {       "sf_get_chunk_size",            101 },
-       {       "sf_get_chunk_data",            102 },
-       {       "sf_get_chunk_iterator",        103 },
-       {       "sf_next_chunk_iterator",       104 },
-       {       "sf_current_byterate",          110 },
-       {       NULL,                                           0 }
-} ;
-
-//-------------------------------------------------------------------------------
-
-static void
-linux_symbols (FILE * file, const char * progname, const char * version)
-{      unsigned k ;
-
-       fprintf (file, "# Auto-generated by %s\n", progname) ;
-       fprintf (file, "libsndfile.so.%s\n", version) ;
-       fprintf (file, "{\n") ;
-       fprintf (file, "  global:\n") ;
-
-       for (k = 0 ; all_symbols [k].name != NULL ; k++)
-       {       if (strcmp (all_symbols [k].name, "sf_wchar_open") == 0)
-                       continue ;
-               fprintf (file, "        %s ;\n", all_symbols [k].name) ;
-               } ;
-
-       fprintf (file, "  local:\n") ;
-       fprintf (file, "        * ;\n") ;
-       fprintf (file, "} ;\n\n") ;
-} /* linux_symbols */
-
-static void
-darwin_symbols (FILE * file, const char * progname)
-{      unsigned k ;
-
-       fprintf (file, "// Auto-generated by %s\n", progname) ;
-
-       for (k = 0 ; all_symbols [k].name != NULL ; k++)
-       {       if (strcmp (all_symbols [k].name, "sf_wchar_open") == 0)
-                       continue ;
-               fprintf (file, "_%s\n", all_symbols [k].name) ;
-               } ;
-       fprintf (file, "\n") ;
-} /* darwin_symbols */
-
-static void
-win32_symbols (FILE * file, const char * progname, const char * major_version, const char * libname)
-{      unsigned k ;
-
-       fprintf (file, "; Auto-generated by %s\n\n", progname) ;
-       fprintf (file, "LIBRARY %s-%s.dll\n", libname, major_version) ;
-       fprintf (file, "EXPORTS\n\n") ;
-
-       for (k = 0 ; all_symbols [k].name != NULL ; k++)
-               fprintf (file, "%-24s @%d\n", all_symbols [k].name, all_symbols [k].ordinal) ;
-       fprintf (file, "\n") ;
-} /* win32_symbols */
-
-static void
-os2_symbols (FILE * file, const char * progname, const char * major_version, const char * libname)
-{      unsigned k ;
-
-       fprintf (file, "; Auto-generated by %s\n\n", progname) ;
-       fprintf (file, "LIBRARY %s%s\n", libname, major_version) ;
-       fprintf (file, "INITINSTANCE TERMINSTANCE\n") ;
-       fprintf (file, "CODE PRELOAD MOVEABLE DISCARDABLE\n") ;
-       fprintf (file, "DATA PRELOAD MOVEABLE MULTIPLE NONSHARED\n") ;
-       fprintf (file, "EXPORTS\n\n") ;
-
-       for (k = 0 ; all_symbols [k].name != NULL ; k++)
-       {       if (strcmp (all_symbols [k].name, "sf_wchar_open") == 0)
-                       continue ;
-               fprintf (file, "_%-24s @%d\n", all_symbols [k].name, all_symbols [k].ordinal) ;
-               } ;
-       fprintf (file, "\n") ;
-} /* os2_symbols */
-
-static void
-plain_symbols (FILE * file)
-{      unsigned k ;
-
-       for (k = 0 ; all_symbols [k].name != NULL ; k++)
-               fprintf (file, "%s\n", all_symbols [k].name) ;
-} /* plain_symbols */
-
-static void
-no_symbols (const char * os_name)
-{      printf ("\n") ;
-       printf ("No known way of restricting exported symbols on '%s'.\n", os_name) ;
-       printf ("If you know a way, please contact the author.\n\n") ;
-       exit (1) ;
-} /* no_symbols */
-
-//-------------------------------------------------------------------------------
-
-int
-main (int argc, char *argv [])
-{
-       FILE * file ;
-       const char *cptr, *progname, *os_name, *version ;
-       char major_version [256] ;
-       unsigned k ;
-
-       if ((cptr = strrchr (argv [0], '/')) != NULL)
-               progname = cptr + 1 ;
-       else if ((cptr = strrchr (argv [0], '\\')) != NULL)
-               progname = cptr + 1 ;
-       else
-               progname = argv [0] ;
-
-       if (argc != 4)
-       {       printf (
-                       "\n"
-                       "Usage : %s <target OS name> <libsndfile version> <output file>.\n"
-                       "\n"
-                       "       Currently supported values for target OS are:\n"
-                       "                 linux\n"
-                       "                 darwin         (ie MacOSX)\n"
-                       "                 win32   (ie wintendo)\n"
-                       "                 cygwin         (Cygwin on wintendo)\n"
-                       "                 os2           (OS/2)\n"
-                       "                 plain   (plain list of symbols)\n"
-                       "\n", progname) ;
-               exit (1) ;
-               } ;
-
-       os_name = argv [1] ;
-       version = argv [2] ;
-
-       strncpy (major_version, argv [2], sizeof (major_version)) ;
-       for (k = 0 ; k < sizeof (major_version) ; k++)
-               if (! isdigit (major_version [k]))
-               {       major_version [k] = 0 ;
-                       break ;
-                       } ;
-
-       if ((file = fopen (argv [3], "w")) == NULL)
-       {       printf ("Error: Not able to open output file '%s'.\n", argv [3]) ;
-               exit (1) ;
-               }
-
-       if (strcmp (os_name, "linux") == 0 || strcmp (os_name, "gnu") == 0 || strcmp (os_name, "binutils") == 0)
-               linux_symbols (file, progname, version) ;
-       else if (strcmp (os_name, "darwin") == 0)
-               darwin_symbols (file, progname) ;
-       else if (strcmp (os_name, "win32") == 0)
-               win32_symbols (file, progname, major_version, "libsndfile") ;
-       else if (strcmp (os_name, "os2") == 0)
-               os2_symbols (file, progname, major_version, "sndfile") ;
-       else if (strcmp (os_name, "static") == 0)
-               plain_symbols (file) ;
-       else
-       {       no_symbols (os_name) ;
-               fclose (file) ;
-               exit (1) ;
-               } ;
-
-       fclose (file) ;
-
-       return 0 ;
-} /* main */
-
old mode 100755 (executable)
new mode 100644 (file)
index 28503f3..8271746
@@ -110,7 +110,6 @@ def darwin_symbols (progname, version):
 
 def win32_symbols (progname, version, name):
        print ("; Auto-generated by %s\n" %progname)
-       print ("LIBRARY %s-%s.dll" % (name, re.sub ("\..*", "", version)))
        print ("EXPORTS\n")
        for name, ordinal in ALL_SYMBOLS:
                print ("%-20s @%s" % (name, ordinal))
index d149bc1..a36705e 100644 (file)
@@ -233,7 +233,7 @@ dither_write_short  (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
                        return pdither->write_short (psf, ptr, len) ;
                } ;
 
-       bufferlen = sizeof (pdither->buffer) / sizeof (short) ;
+       bufferlen = sizeof (pdither->buffer) / (sizeof (short)) ;
 
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
@@ -279,7 +279,7 @@ dither_write_int    (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
                } ;
 
 
-       bufferlen = sizeof (pdither->buffer) / sizeof (int) ;
+       bufferlen = sizeof (pdither->buffer) / (sizeof (int)) ;
 
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
@@ -324,7 +324,7 @@ dither_write_float  (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
                        return pdither->write_float (psf, ptr, len) ;
                } ;
 
-       bufferlen = sizeof (pdither->buffer) / sizeof (float) ;
+       bufferlen = sizeof (pdither->buffer) / (sizeof (float)) ;
 
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (float) len ;
index b318ea8..fb6d468 100644 (file)
@@ -91,7 +91,7 @@ int
 double64_init  (SF_PRIVATE *psf)
 {      static int double64_caps ;
 
-       if (psf->sf.channels < 1)
+       if (psf->sf.channels < 1 || psf->sf.channels > SF_MAX_CHANNELS)
        {       psf_log_printf (psf, "double64_init : internal error : channels = %d\n", psf->sf.channels) ;
                return SFE_INTERNAL ;
                } ;
@@ -368,7 +368,7 @@ double64_be_write (double in, unsigned char *out)
        out [1] |= (exponent << 4) & 0xF0 ;
 
        in *= 0x20000000 ;
-       mantissa = lrint (floor (in)) ;
+       mantissa = psf_lrint (floor (in)) ;
 
        out [1] |= (mantissa >> 24) & 0xF ;
        out [2] = (mantissa >> 16) & 0xFF ;
@@ -377,7 +377,7 @@ double64_be_write (double in, unsigned char *out)
 
        in = fmod (in, 1.0) ;
        in *= 0x1000000 ;
-       mantissa = lrint (floor (in)) ;
+       mantissa = psf_lrint (floor (in)) ;
 
        out [5] = (mantissa >> 16) & 0xFF ;
        out [6] = (mantissa >> 8) & 0xFF ;
@@ -408,7 +408,7 @@ double64_le_write (double in, unsigned char *out)
        out [6] |= (exponent << 4) & 0xF0 ;
 
        in *= 0x20000000 ;
-       mantissa = lrint (floor (in)) ;
+       mantissa = psf_lrint (floor (in)) ;
 
        out [6] |= (mantissa >> 24) & 0xF ;
        out [5] = (mantissa >> 16) & 0xFF ;
@@ -417,7 +417,7 @@ double64_le_write (double in, unsigned char *out)
 
        in = fmod (in, 1.0) ;
        in *= 0x1000000 ;
-       mantissa = lrint (floor (in)) ;
+       mantissa = psf_lrint (floor (in)) ;
 
        out [2] = (mantissa >> 16) & 0xFF ;
        out [1] = (mantissa >> 8) & 0xFF ;
@@ -487,7 +487,7 @@ double64_get_capability     (SF_PRIVATE *psf)
 static void
 d2s_array (const double *src, int count, short *dest, double scale)
 {      while (--count >= 0)
-       {       dest [count] = lrint (scale * src [count]) ;
+       {       dest [count] = psf_lrint (scale * src [count]) ;
                } ;
 } /* d2s_array */
 
@@ -501,14 +501,14 @@ d2s_clip_array (const double *src, int count, short *dest, double scale)
                else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
                        dest [count] = SHRT_MIN ;
                else
-                       dest [count] = lrint (tmp) ;
+                       dest [count] = psf_lrint (tmp) ;
                } ;
 } /* d2s_clip_array */
 
 static void
 d2i_array (const double *src, int count, int *dest, double scale)
 {      while (--count >= 0)
-       {       dest [count] = lrint (scale * src [count]) ;
+       {       dest [count] = psf_lrint (scale * src [count]) ;
                } ;
 } /* d2i_array */
 
@@ -522,7 +522,7 @@ d2i_clip_array (const double *src, int count, int *dest, double scale)
                else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
                        dest [count] = INT_MIN ;
                else
-                       dest [count] = lrint (tmp) ;
+                       dest [count] = psf_lrint (tmp) ;
                } ;
 } /* d2i_clip_array */
 
@@ -597,7 +597,7 @@ host_read_d2i       (SF_PRIVATE *psf, int *ptr, sf_count_t len)
 
        convert = (psf->add_clipping) ? d2i_clip_array : d2i_array ;
        bufferlen = ARRAY_LEN (ubuf.dbuf) ;
-       scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
+       scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
 
        while (len > 0)
        {       if (len < bufferlen)
@@ -631,7 +631,7 @@ host_read_d2f       (SF_PRIVATE *psf, float *ptr, sf_count_t len)
                readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
 
                if (psf->data_endswap == SF_TRUE)
-                       endswap_double_array (ubuf.dbuf, bufferlen) ;
+                       endswap_double_array (ubuf.dbuf, readcount) ;
 
                d2f_array (ubuf.dbuf, readcount, ptr + total) ;
                total += readcount ;
@@ -836,7 +836,7 @@ replace_read_d2i    (SF_PRIVATE *psf, int *ptr, sf_count_t len)
        double          scale ;
 
        bufferlen = ARRAY_LEN (ubuf.dbuf) ;
-       scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
+       scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
 
        while (len > 0)
        {       if (len < bufferlen)
index 0da1326..13985ad 100644 (file)
@@ -628,7 +628,7 @@ dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       iptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       iptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
 
                total += count ;
@@ -660,7 +660,7 @@ dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       iptr [k] = lrint (normfact * ptr [total + k]) ;
+                       iptr [k] = psf_lrint (normfact * ptr [total + k]) ;
                count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
 
                total += count ;
index 7cf8f0c..9cd9379 100644 (file)
 
 #include "sfconfig.h"
 
+#if USE_WINDOWS_API
+
+/* Don't include rarely used headers, speed up build */
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include <io.h>
 #endif
 
 #if (HAVE_DECL_S_IRGRP == 0)
@@ -116,33 +126,36 @@ psf_fclose (SF_PRIVATE *psf)
 
 int
 psf_open_rsrc (SF_PRIVATE *psf)
-{
+{      size_t count ;
+
        if (psf->rsrc.filedes > 0)
                return 0 ;
 
        /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
-       snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/..namedfork/rsrc", psf->file.path.c) ;
+       count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/..namedfork/rsrc", psf->file.path.c) ;
        psf->error = SFE_NO_ERROR ;
-       if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
-       {       psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
-               if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE))
-                       return SFE_NO_ERROR ;
-               psf_close_fd (psf->rsrc.filedes) ;
-               psf->rsrc.filedes = -1 ;
-               } ;
+       if (count < sizeof (psf->rsrc.path.c))
+       {       if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
+               {       psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
+                       if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE))
+                               return SFE_NO_ERROR ;
+                       psf_close_fd (psf->rsrc.filedes) ;
+                       psf->rsrc.filedes = -1 ;
+                       } ;
 
-       if (psf->rsrc.filedes == - SFE_BAD_OPEN_MODE)
-       {       psf->error = SFE_BAD_OPEN_MODE ;
-               return psf->error ;
+               if (psf->rsrc.filedes == - SFE_BAD_OPEN_MODE)
+               {       psf->error = SFE_BAD_OPEN_MODE ;
+                       return psf->error ;
+                       } ;
                } ;
 
        /*
        ** Now try for a resource fork stored as a separate file in the same
        ** directory, but preceded with a dot underscore.
        */
-       snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
+       count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
        psf->error = SFE_NO_ERROR ;
-       if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
+       if (count < sizeof (psf->rsrc.path.c) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
        {       psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
                return SFE_NO_ERROR ;
                } ;
@@ -151,16 +164,21 @@ psf_open_rsrc (SF_PRIVATE *psf)
        ** Now try for a resource fork stored in a separate file in the
        ** .AppleDouble/ directory.
        */
-       snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
+       count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
        psf->error = SFE_NO_ERROR ;
-       if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
-       {       psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
-               return SFE_NO_ERROR ;
-               } ;
+       if (count < sizeof (psf->rsrc.path.c))
+       {       if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
+               {       psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
+                       return SFE_NO_ERROR ;
+                       } ;
 
-       /* No resource file found. */
-       if (psf->rsrc.filedes == -1)
-               psf_log_syserr (psf, errno) ;
+               /* No resource file found. */
+               if (psf->rsrc.filedes == -1)
+                       psf_log_syserr (psf, errno) ;
+               }
+       else
+       {       psf->error = SFE_OPEN_FAILED ;
+               } ;
 
        psf->rsrc.filedes = -1 ;
 
@@ -257,12 +275,17 @@ psf_file_valid (SF_PRIVATE *psf)
 
 sf_count_t
 psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
-{      sf_count_t      current_pos, new_position ;
+{      sf_count_t      absolute_position ;
 
        if (psf->virtual_io)
                return psf->vio.seek (offset, whence, psf->vio_user_data) ;
 
-       current_pos = psf_ftell (psf) ;
+       /* When decoding from pipes sometimes see seeks to the pipeoffset, which appears to mean do nothing. */
+       if (psf->is_pipe)
+       {       if (whence != SEEK_SET || offset != psf->pipeoffset)
+                       psf_log_printf (psf, "psf_fseek : pipe seek to value other than pipeoffset\n") ;
+               return offset ;
+               }
 
        switch (whence)
        {       case SEEK_SET :
@@ -270,27 +293,9 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
                                break ;
 
                case SEEK_END :
-                               if (psf->file.mode == SFM_WRITE)
-                               {       new_position = lseek (psf->file.filedes, offset, whence) ;
-
-                                       if (new_position < 0)
-                                               psf_log_syserr (psf, errno) ;
-
-                                       return new_position - psf->fileoffset ;
-                                       } ;
-
-                               /* Transform SEEK_END into a SEEK_SET, ie find the file
-                               ** length add the requested offset (should be <= 0) to
-                               ** get the offset wrt the start of file.
-                               */
-                               whence = SEEK_SET ;
-                               offset = lseek (psf->file.filedes, 0, SEEK_END) + offset ;
                                break ;
 
                case SEEK_CUR :
-                               /* Translate a SEEK_CUR into a SEEK_SET. */
-                               offset += current_pos ;
-                               whence = SEEK_SET ;
                                break ;
 
                default :
@@ -299,17 +304,12 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
                                return 0 ;
                } ;
 
-       if (current_pos != offset)
-               new_position = lseek (psf->file.filedes, offset, whence) ;
-       else
-               new_position = offset ;
+       absolute_position = lseek (psf->file.filedes, offset, whence) ;
 
-       if (new_position < 0)
+       if (absolute_position < 0)
                psf_log_syserr (psf, errno) ;
 
-       new_position -= psf->fileoffset ;
-
-       return new_position ;
+       return absolute_position - psf->fileoffset ;
 } /* psf_fseek */
 
 sf_count_t
@@ -606,8 +606,9 @@ psf_fsync (SF_PRIVATE *psf)
 
 /* Win32 file i/o functions implemented using native Win32 API */
 
-#include <windows.h>
-#include <io.h>
+#ifndef WINAPI_PARTITION_SYSTEM
+#define WINAPI_PARTITION_SYSTEM 0
+#endif
 
 static int psf_close_handle (HANDLE handle) ;
 static HANDLE psf_open_handle (PSF_FILE * pfile) ;
@@ -787,6 +788,21 @@ psf_open_handle (PSF_FILE * pfile)
                                return NULL ;
                } ;
 
+#if defined (WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
+       if (!pfile->use_wchar)
+               return NULL ;
+
+       CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ;
+       cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ;
+       cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ;
+
+       handle = CreateFile2 (pfile->path.wc, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ;
+
+       if (handle == INVALID_HANDLE_VALUE)
+               return NULL ;
+
+       return handle ;
+#else
        if (pfile->use_wchar)
                handle = CreateFileW (
                                        pfile->path.wc,                         /* pointer to name of the file */
@@ -798,7 +814,7 @@ psf_open_handle (PSF_FILE * pfile)
                                        NULL                                            /* handle to file with attributes to copy */
                                        ) ;
        else
-               handle = CreateFile (
+               handle = CreateFileA (
                                        pfile->path.c,                          /* pointer to name of the file */
                                        dwDesiredAccess,                        /* access (read-write) mode */
                                        dwShareMode,                            /* share mode */
@@ -812,6 +828,7 @@ psf_open_handle (PSF_FILE * pfile)
                return NULL ;
 
        return handle ;
+#endif
 } /* psf_open_handle */
 
 /* USE_WINDOWS_API */ static void
@@ -902,9 +919,10 @@ psf_file_valid (SF_PRIVATE *psf)
 /* USE_WINDOWS_API */ sf_count_t
 psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
 {      sf_count_t new_position ;
-       LONG lDistanceToMove, lDistanceToMoveHigh ;
+       LARGE_INTEGER liDistanceToMove, liNewFilePointer ;
        DWORD dwMoveMethod ;
-       DWORD dwResult, dwError ;
+       BOOL fResult ;
+       DWORD dwError ;
 
        if (psf->virtual_io)
                return psf->vio.seek (offset, whence, psf->vio_user_data) ;
@@ -924,12 +942,11 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
                                break ;
                } ;
 
-       lDistanceToMove = (DWORD) (offset & 0xFFFFFFFF) ;
-       lDistanceToMoveHigh = (DWORD) ((offset >> 32) & 0xFFFFFFFF) ;
+       liDistanceToMove.QuadPart = offset ;
 
-       dwResult = SetFilePointer (psf->file.handle, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ;
+       fResult = SetFilePointerEx (psf->file.handle, liDistanceToMove, &liNewFilePointer, dwMoveMethod) ;
 
-       if (dwResult == 0xFFFFFFFF)
+       if (fResult == FALSE)
                dwError = GetLastError () ;
        else
                dwError = NO_ERROR ;
@@ -939,7 +956,7 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
                return -1 ;
                } ;
 
-       new_position = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) - psf->fileoffset ;
+       new_position = liNewFilePointer.QuadPart - psf->fileoffset ;
 
        return new_position ;
 } /* psf_fseek */
@@ -1025,8 +1042,9 @@ psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf
 /* USE_WINDOWS_API */ sf_count_t
 psf_ftell (SF_PRIVATE *psf)
 {      sf_count_t pos ;
-       LONG lDistanceToMoveLow, lDistanceToMoveHigh ;
-       DWORD dwResult, dwError ;
+       LARGE_INTEGER liDistanceToMove, liNewFilePointer ;
+       BOOL fResult ;
+       DWORD dwError ;
 
        if (psf->virtual_io)
                return psf->vio.tell (psf->vio_user_data) ;
@@ -1034,12 +1052,11 @@ psf_ftell (SF_PRIVATE *psf)
        if (psf->is_pipe)
                return psf->pipeoffset ;
 
-       lDistanceToMoveLow = 0 ;
-       lDistanceToMoveHigh = 0 ;
+       liDistanceToMove.QuadPart = 0 ;
 
-       dwResult = SetFilePointer (psf->file.handle, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_CURRENT) ;
+       fResult = SetFilePointerEx (psf->file.handle, liDistanceToMove, &liNewFilePointer, FILE_CURRENT) ;
 
-       if (dwResult == 0xFFFFFFFF)
+       if (fResult == FALSE)
                dwError = GetLastError () ;
        else
                dwError = NO_ERROR ;
@@ -1049,7 +1066,7 @@ psf_ftell (SF_PRIVATE *psf)
                return -1 ;
                } ;
 
-       pos = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) ;
+       pos = liNewFilePointer.QuadPart ;
 
        return pos - psf->fileoffset ;
 } /* psf_ftell */
@@ -1105,17 +1122,19 @@ psf_is_pipe (SF_PRIVATE *psf)
 /* USE_WINDOWS_API */ sf_count_t
 psf_get_filelen_handle (HANDLE handle)
 {      sf_count_t filelen ;
-       DWORD dwFileSizeLow, dwFileSizeHigh, dwError = NO_ERROR ;
+       LARGE_INTEGER liFileSize ;
+       BOOL fResult ;
+       DWORD dwError = NO_ERROR ;
 
-       dwFileSizeLow = GetFileSize (handle, &dwFileSizeHigh) ;
+       fResult = GetFileSizeEx (handle, &liFileSize) ;
 
-       if (dwFileSizeLow == 0xFFFFFFFF)
+       if (fResult == FALSE)
                dwError = GetLastError () ;
 
        if (dwError != NO_ERROR)
                return (sf_count_t) -1 ;
 
-       filelen = dwFileSizeLow + ((__int64) dwFileSizeHigh << 32) ;
+       filelen = liFileSize.QuadPart ;
 
        return filelen ;
 } /* psf_get_filelen_handle */
@@ -1129,8 +1148,9 @@ psf_fsync (SF_PRIVATE *psf)
 /* USE_WINDOWS_API */ int
 psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
 {      int retval = 0 ;
-       LONG lDistanceToMoveLow, lDistanceToMoveHigh ;
-       DWORD dwResult, dwError = NO_ERROR ;
+       LARGE_INTEGER liDistanceToMove ;
+       BOOL fResult ;
+       DWORD dwError = NO_ERROR ;
 
        /* This implementation trashes the current file position.
        ** should it save and restore it? what if the current position is past
@@ -1141,12 +1161,11 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
        if (len < 0)
                return 1 ;
 
-       lDistanceToMoveLow = (DWORD) (len & 0xFFFFFFFF) ;
-       lDistanceToMoveHigh = (DWORD) ((len >> 32) & 0xFFFFFFFF) ;
+       liDistanceToMove.QuadPart = (sf_count_t) len ;
 
-       dwResult = SetFilePointer (psf->file.handle, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ;
+       fResult = SetFilePointerEx (psf->file.handle, liDistanceToMove, NULL, FILE_BEGIN) ;
 
-       if (dwResult == 0xFFFFFFFF)
+       if (fResult == FALSE)
                dwError = GetLastError () ;
 
        if (dwError != NO_ERROR)
index 40629c7..64d0172 100644 (file)
@@ -169,6 +169,14 @@ flac_buffer_copy (SF_PRIVATE *psf)
        const int32_t* const *buffer = pflac->wbuffer ;
        unsigned i = 0, j, offset, channels, len ;
 
+       if (psf->sf.channels != (int) frame->header.channels)
+       {       psf_log_printf (psf, "Error: FLAC frame changed from %d to %d channels\n"
+                                                                       "Nothing to do but to error out.\n" ,
+                                                                       psf->sf.channels, frame->header.channels) ;
+               psf->error = SFE_FLAC_CHANNEL_COUNT_CHANGED ;
+               return 0 ;
+               } ;
+
        /*
        **      frame->header.blocksize is variable and we're using a constant blocksize
        **      of FLAC__MAX_BLOCK_SIZE.
@@ -202,7 +210,6 @@ flac_buffer_copy (SF_PRIVATE *psf)
                return 0 ;
                } ;
 
-
        len = SF_MIN (pflac->len, frame->header.blocksize) ;
 
        if (pflac->remain % channels != 0)
@@ -228,7 +235,7 @@ flac_buffer_copy (SF_PRIVATE *psf)
                                                for (j = 0 ; j < channels ; j++)
                                                        retpcm [offset + j] = buffer [j][pflac->bufferpos] >> shift ;
                                                pflac->remain -= channels ;
-                                               pflac->bufferpos++ ;
+                                               pflac->bufferpos ++ ;
                                                }
                                        }
                                else
@@ -245,7 +252,7 @@ flac_buffer_copy (SF_PRIVATE *psf)
                                                        retpcm [offset + j] = ((uint16_t) buffer [j][pflac->bufferpos]) << shift ;
 
                                                pflac->remain -= channels ;
-                                               pflac->bufferpos++ ;
+                                               pflac->bufferpos ++ ;
                                                } ;
                                        } ;
                                } ;
@@ -430,11 +437,23 @@ sf_flac_meta_get_vorbiscomments (SF_PRIVATE *psf, const FLAC__StreamMetadata *me
 static void
 sf_flac_meta_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC__StreamMetadata *metadata, void *client_data)
 {      SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
-       FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
-       int bitwidth = 0, i ;
+       int bitwidth = 0 ;
 
        switch (metadata->type)
        {       case FLAC__METADATA_TYPE_STREAMINFO :
+                       if (psf->sf.channels > 0 && psf->sf.channels != (int) metadata->data.stream_info.channels)
+                       {       psf_log_printf (psf, "Error: FLAC stream changed from %d to %d channels\n"
+                                                                       "Nothing to do but to error out.\n" ,
+                                                                       psf->sf.channels, metadata->data.stream_info.channels) ;
+                               psf->error = SFE_FLAC_CHANNEL_COUNT_CHANGED ;
+                               return ;
+                               } ;
+
+                       if (psf->sf.channels > 0 && psf->sf.samplerate != (int) metadata->data.stream_info.sample_rate)
+                       {       psf_log_printf (psf, "Warning: FLAC stream changed sample rates from %d to %d.\n"
+                                                                       "Carrying on as if nothing happened.",
+                                                                       psf->sf.samplerate, metadata->data.stream_info.sample_rate) ;
+                               } ;
                        psf->sf.channels = metadata->data.stream_info.channels ;
                        psf->sf.samplerate = metadata->data.stream_info.sample_rate ;
                        psf->sf.frames = metadata->data.stream_info.total_samples ;
@@ -468,12 +487,6 @@ sf_flac_meta_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC_
 
                        if (bitwidth > 0)
                                psf_log_printf (psf, "  Bit width   : %d\n", bitwidth) ;
-
-
-                       for (i = 0 ; i < psf->sf.channels ; i++)
-                               pflac->rbuffer [i] = calloc (FLAC__MAX_BLOCK_SIZE, sizeof (int32_t)) ;
-
-                       pflac->wbuffer = (const int32_t* const*) pflac->rbuffer ;
                        break ;
 
                case FLAC__METADATA_TYPE_VORBIS_COMMENT :
@@ -652,6 +665,9 @@ flac_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
                psf->dataoffset = psf_ftell (psf) ;
        pflac->encbuffer = calloc (ENC_BUFFER_SIZE, sizeof (int32_t)) ;
 
+       /* can only call init_stream once */
+       psf->write_header = NULL ;
+
        return psf->error ;
 } /* flac_write_header */
 
@@ -835,7 +851,9 @@ flac_read_header (SF_PRIVATE *psf)
 
        psf_log_printf (psf, "End\n") ;
 
-       if (psf->error == 0)
+       if (psf->error != 0)
+               FLAC__stream_decoder_delete (pflac->fsd) ;
+       else
        {       FLAC__uint64 position ;
 
                FLAC__stream_decoder_get_decode_position (pflac->fsd, &position) ;
@@ -863,7 +881,7 @@ flac_command (SF_PRIVATE * psf, int command, void * data, int datasize)
                        */
                        quality = (*((double *) data)) * 8.0 ;
                        /* Clip range. */
-                       pflac->compression = lrint (SF_MAX (0.0, SF_MIN (8.0, quality))) ;
+                       pflac->compression = psf_lrint (SF_MAX (0.0, SF_MIN (8.0, quality))) ;
 
                        psf_log_printf (psf, "%s : Setting SFC_SET_COMPRESSION_LEVEL to %u.\n", __func__, pflac->compression) ;
 
@@ -1041,7 +1059,7 @@ flac_write_s2flac (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
                case SF_FORMAT_PCM_16 :
                        convert = s2flac16_array ;
                        break ;
-                       case SF_FORMAT_PCM_24 :
+               case SF_FORMAT_PCM_24 :
                        convert = s2flac24_array ;
                        break ;
                default :
@@ -1165,10 +1183,10 @@ f2flac8_clip_array (const float *src, int32_t *dest, int count, int normalize)
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10))
-               {       dest [count] = 0x80 ;
+               {       dest [count] = -0x80 ;
                        continue ;
                        } ;
-               dest [count] = lrintf (scaled_value) ;
+               dest [count] = psf_lrintf (scaled_value) ;
                } ;
 
        return ;
@@ -1187,10 +1205,10 @@ f2flac16_clip_array (const float *src, int32_t *dest, int count, int normalize)
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
-               {       dest [count] = 0x8000 ;
+               {       dest [count] = -0x8000 ;
                        continue ;
                        } ;
-               dest [count] = lrintf (scaled_value) ;
+               dest [count] = psf_lrintf (scaled_value) ;
                } ;
 } /* f2flac16_clip_array */
 
@@ -1208,10 +1226,10 @@ f2flac24_clip_array (const float *src, int32_t *dest, int count, int normalize)
                        } ;
 
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000))
-               {       dest [count] = 0x800000 ;
+               {       dest [count] = -0x800000 ;
                        continue ;
                        }
-               dest [count] = lrintf (scaled_value) ;
+               dest [count] = psf_lrintf (scaled_value) ;
                } ;
 
        return ;
@@ -1222,7 +1240,7 @@ f2flac8_array (const float *src, int32_t *dest, int count, int normalize)
 {      float normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
 
        while (--count >= 0)
-               dest [count] = lrintf (src [count] * normfact) ;
+               dest [count] = psf_lrintf (src [count] * normfact) ;
 } /* f2flac8_array */
 
 static void
@@ -1230,7 +1248,7 @@ f2flac16_array (const float *src, int32_t *dest, int count, int normalize)
 {      float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
 
        while (--count >= 0)
-               dest [count] = lrintf (src [count] * normfact) ;
+               dest [count] = psf_lrintf (src [count] * normfact) ;
 } /* f2flac16_array */
 
 static void
@@ -1238,7 +1256,7 @@ f2flac24_array (const float *src, int32_t *dest, int count, int normalize)
 {      float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
 
        while (--count >= 0)
-               dest [count] = lrintf (src [count] * normfact) ;
+               dest [count] = psf_lrintf (src [count] * normfact) ;
 } /* f2flac24_array */
 
 static sf_count_t
@@ -1296,10 +1314,10 @@ d2flac8_clip_array (const double *src, int32_t *dest, int count, int normalize)
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10))
-               {       dest [count] = 0x80 ;
+               {       dest [count] = -0x80 ;
                        continue ;
                        } ;
-               dest [count] = lrint (scaled_value) ;
+               dest [count] = psf_lrint (scaled_value) ;
                } ;
 
        return ;
@@ -1318,10 +1336,10 @@ d2flac16_clip_array (const double *src, int32_t *dest, int count, int normalize)
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
-               {       dest [count] = 0x8000 ;
+               {       dest [count] = -0x8000 ;
                        continue ;
                        } ;
-               dest [count] = lrint (scaled_value) ;
+               dest [count] = psf_lrint (scaled_value) ;
                } ;
 
        return ;
@@ -1340,10 +1358,10 @@ d2flac24_clip_array (const double *src, int32_t *dest, int count, int normalize)
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000))
-               {       dest [count] = 0x800000 ;
+               {       dest [count] = -0x800000 ;
                        continue ;
                        } ;
-               dest [count] = lrint (scaled_value) ;
+               dest [count] = psf_lrint (scaled_value) ;
                } ;
 
        return ;
@@ -1354,7 +1372,7 @@ d2flac8_array (const double *src, int32_t *dest, int count, int normalize)
 {      double normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
 
        while (--count >= 0)
-               dest [count] = lrint (src [count] * normfact) ;
+               dest [count] = psf_lrint (src [count] * normfact) ;
 } /* d2flac8_array */
 
 static void
@@ -1362,7 +1380,7 @@ d2flac16_array (const double *src, int32_t *dest, int count, int normalize)
 {      double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
 
        while (--count >= 0)
-               dest [count] = lrint (src [count] * normfact) ;
+               dest [count] = psf_lrint (src [count] * normfact) ;
 } /* d2flac16_array */
 
 static void
@@ -1370,7 +1388,7 @@ d2flac24_array (const double *src, int32_t *dest, int count, int normalize)
 {      double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
 
        while (--count >= 0)
-               dest [count] = lrint (src [count] * normfact) ;
+               dest [count] = psf_lrint (src [count] * normfact) ;
 } /* d2flac24_array */
 
 static sf_count_t
index 100c149..a63413d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -438,7 +438,7 @@ static void
 f2s_array (const float *src, int count, short *dest, float scale)
 {
        while (--count >= 0)
-       {       dest [count] = lrintf (scale * src [count]) ;
+       {       dest [count] = psf_lrintf (scale * src [count]) ;
                } ;
 } /* f2s_array */
 
@@ -452,14 +452,14 @@ f2s_clip_array (const float *src, int count, short *dest, float scale)
                else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
                        dest [count] = SHRT_MIN ;
                else
-                       dest [count] = lrintf (tmp) ;
+                       dest [count] = psf_lrintf (tmp) ;
                } ;
 } /* f2s_clip_array */
 
 static inline void
 f2i_array (const float *src, int count, int *dest, float scale)
 {      while (--count >= 0)
-       {       dest [count] = lrintf (scale * src [count]) ;
+       {       dest [count] = psf_lrintf (scale * src [count]) ;
                } ;
 } /* f2i_array */
 
@@ -473,7 +473,7 @@ f2i_clip_array (const float *src, int count, int *dest, float scale)
                else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
                        dest [count] = INT_MIN ;
                else
-                       dest [count] = lrintf (tmp) ;
+                       dest [count] = psf_lrintf (tmp) ;
                } ;
 } /* f2i_clip_array */
 
@@ -527,7 +527,7 @@ host_read_f2s       (SF_PRIVATE *psf, short *ptr, sf_count_t len)
 
 /* Fix me : Need lef2s_array */
                if (psf->data_endswap == SF_TRUE)
-                       endswap_int_array (ubuf.ibuf, bufferlen) ;
+                       endswap_int_array (ubuf.ibuf, readcount) ;
 
                convert (ubuf.fbuf, readcount, ptr + total, scale) ;
                total += readcount ;
@@ -549,7 +549,7 @@ host_read_f2i       (SF_PRIVATE *psf, int *ptr, sf_count_t len)
 
        convert = (psf->add_clipping) ? f2i_clip_array : f2i_array ;
        bufferlen = ARRAY_LEN (ubuf.fbuf) ;
-       scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
+       scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
 
        while (len > 0)
        {       if (len < bufferlen)
index 7b77b4f..563a909 100644 (file)
@@ -538,7 +538,7 @@ g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = g72x_write_block (psf, pg72x, sptr, writecount) ;
 
                total += count ;
@@ -570,7 +570,7 @@ g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrint (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
                count = g72x_write_block (psf, pg72x, sptr, writecount) ;
 
                total += count ;
index 4474598..06519bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -563,11 +563,13 @@ gsm610_write_f    (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
 
                total += count ;
                len -= writecount ;
+               if (count != writecount)
+                       break ;
                } ;
        return total ;
 } /* gsm610_write_f */
@@ -592,7 +594,7 @@ gsm610_write_d      (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrint (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
                count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
 
                total += count ;
index 32d392e..1041a84 100644 (file)
--- a/src/htk.c
+++ b/src/htk.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -123,7 +123,7 @@ htk_write_header (SF_PRIVATE *psf, int calc_length)
 
        sample_period = 10000000 / psf->sf.samplerate ;
 
-       psf_binheader_writef (psf, "E444", sample_count, sample_period, 0x20000) ;
+       psf_binheader_writef (psf, "E444", BHW4 (sample_count), BHW4 (sample_period), BHW4 (0x20000)) ;
 
        /* Header construction complete so write it out. */
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
index 095b989..2b82d0f 100644 (file)
--- a/src/id3.c
+++ b/src/id3.c
@@ -47,10 +47,10 @@ id3_skip (SF_PRIVATE * psf)
                        return 0 ;
 
                /* Calculate new file offset and position ourselves there. */
-               psf->fileoffset += offset + 10 ;
-
-               if (psf->fileoffset < psf->filelength)
-               {       psf_binheader_readf (psf, "p", psf->fileoffset) ;
+               offset += 10 ;
+               if (psf->fileoffset + offset < psf->filelength)
+               {       psf_binheader_readf (psf, "p", offset) ;
+                       psf->fileoffset += offset ;
                        return 1 ;
                        } ;
                } ;
index 33c5e1b..8c9bbff 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2020 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -325,73 +325,58 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
 {      int             chan, k, step, diff, vpdiff, blockindx, indx ;
        short   bytecode, mask ;
 
-       /* Encode the block header. */
+       k = 0 ;
        for (chan = 0 ; chan < pima->channels ; chan ++)
        {       blockindx = chan * pima->blocksize ;
-
-               pima->block [blockindx] = (pima->samples [chan] >> 8) & 0xFF ;
-               pima->block [blockindx + 1] = (pima->samples [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ;
-
-               pima->previous [chan] = pima->samples [chan] ;
-               } ;
-
-       /* Encode second and later samples for every block as a 4 bit value. */
-       for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
-       {       chan = (pima->channels > 1) ? (k % 2) : 0 ;
-
-               diff = pima->samples [k] - pima->previous [chan] ;
-
-               bytecode = 0 ;
-               step = ima_step_size [pima->stepindx [chan]] ;
-               vpdiff = step >> 3 ;
-               if (diff < 0)
-               {       bytecode = 8 ;
-                       diff = -diff ;
-                       } ;
-               mask = 4 ;
-               while (mask)
-               {       if (diff >= step)
-                       {       bytecode |= mask ;
-                               diff -= step ;
-                               vpdiff += step ;
+               /* Encode the block header. */
+               pima->block [blockindx++] = (pima->previous [chan] >> 8) & 0xFF ;
+               pima->block [blockindx++] = (pima->previous [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ;
+
+               /* Encode the samples as 4 bit. */
+               for (indx = chan ; indx < pima->samplesperblock * pima->channels ; indx += pima->channels)
+               {       diff = pima->samples [indx] - pima->previous [chan] ;
+
+                       bytecode = 0 ;
+                       step = ima_step_size [pima->stepindx [chan]] ;
+                       vpdiff = step >> 3 ;
+                       if (diff < 0)
+                       {       bytecode = 8 ;
+                               diff = -diff ;
+                               } ;
+                       mask = 4 ;
+                       while (mask)
+                       {       if (diff >= step)
+                               {       bytecode |= mask ;
+                                       diff -= step ;
+                                       vpdiff += step ;
+                                       } ;
+                               step >>= 1 ;
+                               mask >>= 1 ;
                                } ;
-                       step >>= 1 ;
-                       mask >>= 1 ;
-                       } ;
 
-               if (bytecode & 8)
-                       pima->previous [chan] -= vpdiff ;
-               else
+                       if (bytecode & 8)
+                               vpdiff = -vpdiff ;
                        pima->previous [chan] += vpdiff ;
 
-               if (pima->previous [chan] > 32767)
-                       pima->previous [chan] = 32767 ;
-               else if (pima->previous [chan] < -32768)
-                       pima->previous [chan] = -32768 ;
-
-               pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
+                       if (pima->previous [chan] > 32767)
+                               pima->previous [chan] = 32767 ;
+                       else if (pima->previous [chan] < -32768)
+                               pima->previous [chan] = -32768 ;
 
-               pima->stepindx [chan] = clamp_ima_step_index (pima->stepindx [chan]) ;
-               pima->samples [k] = bytecode ;
-               } ;
-
-       /* Pack the 4 bit encoded samples. */
-
-       for (chan = 0 ; chan < pima->channels ; chan ++)
-       {       for (indx = pima->channels ; indx < pima->channels * pima->samplesperblock ; indx += 2 * pima->channels)
-               {       blockindx = chan * pima->blocksize + 2 + indx / 2 ;
+                       pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
 
-                       pima->block [blockindx] = pima->samples [indx] & 0x0F ;
-                       pima->block [blockindx] |= (pima->samples [indx + chan] << 4) & 0xF0 ;
+                       pima->stepindx [chan] = clamp_ima_step_index (pima->stepindx [chan]) ;
+                       pima->block [blockindx] = (bytecode << (4 * k)) | pima->block [blockindx] ;
+                       blockindx += k ;
+                       k = 1 - k ;
                        } ;
                } ;
 
        /* Write the block to disk. */
-
        if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize)
                psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ;
 
-       memset (pima->samples, 0, pima->channels * pima->samplesperblock * sizeof (short)) ;
+       memset (pima->block, 0, pima->channels * pima->blocksize) ;
        pima->samplecount = 0 ;
        pima->blockcount ++ ;
 
@@ -779,6 +764,9 @@ wavlike_ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
        if (offset == 0)
        {       psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
                pima->blockcount = 0 ;
+               if (!pima->decode_block)
+                       return PSF_SEEK_ERROR ;
+
                pima->decode_block (psf, pima) ;
                pima->samplecount = 0 ;
                return 0 ;
@@ -820,7 +808,20 @@ ima_writer_init (SF_PRIVATE *psf, int blockalign)
        if (psf->file.mode != SFM_WRITE)
                return SFE_BAD_MODE_RW ;
 
-       samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
+       switch (SF_CONTAINER (psf->sf.format))
+       {       case SF_FORMAT_WAV :
+               case SF_FORMAT_W64 :
+                               samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
+                               break ;
+
+               case SF_FORMAT_AIFF :
+                               samplesperblock = 2 * ((blockalign - 2) * psf->sf.channels) / psf->sf.channels ;
+                               break ;
+
+               default :
+                               psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
+                               return SFE_INTERNAL ;
+               } ;
 
        pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
 
@@ -958,7 +959,7 @@ ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = ima_write_block (psf, pima, sptr, writecount) ;
                total += count ;
                len -= writecount ;
@@ -989,7 +990,7 @@ ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrint (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
                count = ima_write_block (psf, pima, sptr, writecount) ;
                total += count ;
                len -= writecount ;
index 7c3e924..8e7cdba 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -266,19 +266,19 @@ ircam_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
 
        switch (psf->endian)
        {       case SF_ENDIAN_BIG :
-                       psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ;
-                       psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ;
+                       psf_binheader_writef (psf, "Emf", BHWm (IRCAM_02B_MARKER), BHWf (samplerate)) ;
+                       psf_binheader_writef (psf, "E44", BHW4 (psf->sf.channels), BHW4 (encoding)) ;
                        break ;
 
                case SF_ENDIAN_LITTLE :
-                       psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ;
-                       psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ;
+                       psf_binheader_writef (psf, "emf", BHWm (IRCAM_03L_MARKER), BHWf (samplerate)) ;
+                       psf_binheader_writef (psf, "e44", BHW4 (psf->sf.channels), BHW4 (encoding)) ;
                        break ;
 
                default : return SFE_BAD_OPEN_FORMAT ;
                } ;
 
-       psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->header.indx)) ;
+       psf_binheader_writef (psf, "z", BHWz ((size_t) (IRCAM_DATA_OFFSET - psf->header.indx))) ;
 
        /* Header construction complete so write it out. */
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
index 3c73680..0b1b414 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -173,16 +173,16 @@ mat4_write_header (SF_PRIVATE *psf, int calc_length)
        samplerate = psf->sf.samplerate ;
 
        if (psf->endian == SF_ENDIAN_BIG)
-       {       psf_binheader_writef (psf, "Em444", MAT4_BE_DOUBLE, 1, 1, 0) ;
-               psf_binheader_writef (psf, "E4bd", 11, "samplerate", make_size_t (11), samplerate) ;
-               psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
-               psf_binheader_writef (psf, "E4b", 9, "wavedata", make_size_t (9)) ;
+       {       psf_binheader_writef (psf, "Em444", BHWm (MAT4_BE_DOUBLE), BHW4 (1), BHW4 (1), BHW4 (0)) ;
+               psf_binheader_writef (psf, "E4bd", BHW4 (11), BHWv ("samplerate"), BHWz (11), BHWd (samplerate)) ;
+               psf_binheader_writef (psf, "tEm484", BHWm (encoding), BHW4 (psf->sf.channels), BHW8 (psf->sf.frames), BHW4 (0)) ;
+               psf_binheader_writef (psf, "E4b", BHW4 (9), BHWv ("wavedata"), BHWz (9)) ;
                }
        else if (psf->endian == SF_ENDIAN_LITTLE)
-       {       psf_binheader_writef (psf, "em444", MAT4_LE_DOUBLE, 1, 1, 0) ;
-               psf_binheader_writef (psf, "e4bd", 11, "samplerate", make_size_t (11), samplerate) ;
-               psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
-               psf_binheader_writef (psf, "e4b", 9, "wavedata", make_size_t (9)) ;
+       {       psf_binheader_writef (psf, "em444", BHWm (MAT4_LE_DOUBLE), BHW4 (1), BHW4 (1), BHW4 (0)) ;
+               psf_binheader_writef (psf, "e4bd", BHW4 (11), BHWv ("samplerate"), BHWz (11), BHWd (samplerate)) ;
+               psf_binheader_writef (psf, "tem484", BHWm (encoding), BHW4 (psf->sf.channels), BHW8 (psf->sf.frames), BHW4 (0)) ;
+               psf_binheader_writef (psf, "e4b", BHW4 (9), BHWv ("wavedata"), BHWz (9)) ;
                }
        else
                return SFE_BAD_OPEN_FORMAT ;
@@ -248,7 +248,7 @@ mat4_read_header (SF_PRIVATE *psf)
        if ((rows != 1) || (cols != 1))
                return SFE_MAT4_NO_SAMPLERATE ;
 
-       psf->sf.samplerate = lrint (value) ;
+       psf->sf.samplerate = psf_lrint (value) ;
 
        /* Now write out the audio data. */
 
index 11a57f4..da5a6ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -206,41 +206,41 @@ mat5_write_header (SF_PRIVATE *psf, int calc_length)
        psf_fseek (psf, 0, SEEK_SET) ;
 
        psf_get_date_str (buffer, sizeof (buffer)) ;
-       psf_binheader_writef (psf, "bb", filename, strlen (filename), buffer, strlen (buffer) + 1) ;
+       psf_binheader_writef (psf, "bb", BHWv (filename), BHWz (strlen (filename)), BHWv (buffer), BHWz (strlen (buffer) + 1)) ;
 
        memset (buffer, ' ', 124 - psf->header.indx) ;
-       psf_binheader_writef (psf, "b", buffer, make_size_t (124 - psf->header.indx)) ;
+       psf_binheader_writef (psf, "b", BHWv (buffer), BHWz (124 - psf->header.indx)) ;
 
        psf->rwf_endian = psf->endian ;
 
        if (psf->rwf_endian == SF_ENDIAN_BIG)
-               psf_binheader_writef (psf, "2b", 0x0100, "MI", make_size_t (2)) ;
+               psf_binheader_writef (psf, "2b", BHW2 (0x0100), BHWv ("MI"), BHWz (2)) ;
        else
-               psf_binheader_writef (psf, "2b", 0x0100, "IM", make_size_t (2)) ;
+               psf_binheader_writef (psf, "2b", BHW2 (0x0100), BHWv ("IM"), BHWz (2)) ;
 
-       psf_binheader_writef (psf, "444444", MAT5_TYPE_ARRAY, 64, MAT5_TYPE_UINT32, 8, 6, 0) ;
-       psf_binheader_writef (psf, "4444", MAT5_TYPE_INT32, 8, 1, 1) ;
-       psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (sr_name), sr_name, make_size_t (16)) ;
+       psf_binheader_writef (psf, "444444", BHW4 (MAT5_TYPE_ARRAY), BHW4 (64), BHW4 (MAT5_TYPE_UINT32), BHW4 (8), BHW4 (6), BHW4 (0)) ;
+       psf_binheader_writef (psf, "4444", BHW4 (MAT5_TYPE_INT32), BHW4 (8), BHW4 (1), BHW4 (1)) ;
+       psf_binheader_writef (psf, "44b", BHW4 (MAT5_TYPE_SCHAR), BHW4 (strlen (sr_name)), BHWv (sr_name), BHWz (16)) ;
 
        if (psf->sf.samplerate > 0xFFFF)
-               psf_binheader_writef (psf, "44", MAT5_TYPE_COMP_UINT, psf->sf.samplerate) ;
+               psf_binheader_writef (psf, "44", BHW4 (MAT5_TYPE_COMP_UINT), BHW4 (psf->sf.samplerate)) ;
        else
        {       unsigned short samplerate = psf->sf.samplerate ;
 
-               psf_binheader_writef (psf, "422", MAT5_TYPE_COMP_USHORT, samplerate, 0) ;
+               psf_binheader_writef (psf, "422", BHW4 (MAT5_TYPE_COMP_USHORT), BHW2 (samplerate), BHW2 (0)) ;
                } ;
 
        datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ;
 
-       psf_binheader_writef (psf, "t484444", MAT5_TYPE_ARRAY, datasize + 64, MAT5_TYPE_UINT32, 8, 6, 0) ;
-       psf_binheader_writef (psf, "t4448", MAT5_TYPE_INT32, 8, psf->sf.channels, psf->sf.frames) ;
-       psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (wd_name), wd_name, strlen (wd_name)) ;
+       psf_binheader_writef (psf, "t484444", BHW4 (MAT5_TYPE_ARRAY), BHW8 (datasize + 64), BHW4 (MAT5_TYPE_UINT32), BHW4 (8), BHW4 (6), BHW4 (0)) ;
+       psf_binheader_writef (psf, "t4448", BHW4 (MAT5_TYPE_INT32), BHW4 (8), BHW4 (psf->sf.channels), BHW8 (psf->sf.frames)) ;
+       psf_binheader_writef (psf, "44b", BHW4 (MAT5_TYPE_SCHAR), BHW4 (strlen (wd_name)), BHWv (wd_name), BHWz (strlen (wd_name))) ;
 
        datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ;
        if (datasize > 0x7FFFFFFF)
                datasize = 0x7FFFFFFF ;
 
-       psf_binheader_writef (psf, "t48", encoding, datasize) ;
+       psf_binheader_writef (psf, "t48", BHW4 (encoding), BHW8 (datasize)) ;
 
        /* Header construction complete so write it out. */
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
@@ -370,7 +370,7 @@ mat5_read_header (SF_PRIVATE *psf)
                                        snprintf (name, sizeof (name), "%f\n", samplerate) ;
                                        psf_log_printf (psf, "    Val  : %s\n", name) ;
 
-                                       psf->sf.samplerate = lrint (samplerate) ;
+                                       psf->sf.samplerate = psf_lrint (samplerate) ;
                                        } ;
                                break ;
 
index f004ca1..aef21ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2008-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -131,12 +131,12 @@ mpc2k_write_header (SF_PRIVATE *psf, int calc_length)
        if (psf->is_pipe == SF_FALSE)
                psf_fseek (psf, 0, SEEK_SET) ;
 
-       snprintf (sample_name, sizeof (sample_name), "%s                    ", psf->file.name.c) ;
+       snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name.c) ;
 
-       psf_binheader_writef (psf, "e11b", 1, 4, sample_name, make_size_t (HEADER_NAME_LEN)) ;
-       psf_binheader_writef (psf, "e111", 100, 0, (psf->sf.channels - 1) & 1) ;
-       psf_binheader_writef (psf, "et4888", 0, psf->sf.frames, psf->sf.frames, psf->sf.frames) ;
-       psf_binheader_writef (psf, "e112", 0, 1, (uint16_t) psf->sf.samplerate) ;
+       psf_binheader_writef (psf, "e11b", BHW1 (1), BHW1 (4), BHWv (sample_name), BHWz (HEADER_NAME_LEN)) ;
+       psf_binheader_writef (psf, "e111", BHW1 (100), BHW1 (0), BHW1 ((psf->sf.channels - 1) & 1)) ;
+       psf_binheader_writef (psf, "et4888", BHW4 (0), BHW8 (psf->sf.frames), BHW8 (psf->sf.frames), BHW8 (psf->sf.frames)) ;
+       psf_binheader_writef (psf, "e112", BHW1 (0), BHW1 (1), BHW2 ((uint16_t) psf->sf.samplerate)) ;
 
        /* Always 16 bit little endian data. */
        psf->bytewidth = 2 ;
index bbc3002..5e8f1a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -510,7 +510,7 @@ wavlike_msadpcm_write_adapt_coeffs  (SF_PRIVATE *psf)
 {      int k ;
 
        for (k = 0 ; k < WAVLIKE_MSADPCM_ADAPT_COEFF_COUNT ; k++)
-               psf_binheader_writef (psf, "22", AdaptCoeff1 [k], AdaptCoeff2 [k]) ;
+               psf_binheader_writef (psf, "22", BHW2 (AdaptCoeff1 [k]), BHW2 (AdaptCoeff2 [k])) ;
 } /* wavlike_msadpcm_write_adapt_coeffs */
 
 /*==========================================================================================
@@ -520,7 +520,8 @@ static int
 msadpcm_encode_block   (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
 {      unsigned int    blockindx ;
        unsigned char   byte ;
-       int                             chan, k, predict, bpred [2], idelta [2], errordelta, newsamp ;
+       int                             chan, k, predict, bpred [2] = { 0 }, idelta [2] = { 0 },
+                                       errordelta, newsamp ;
 
        choose_predictor (pms->channels, pms->samples, bpred, idelta) ;
 
@@ -730,7 +731,7 @@ msadpcm_write_f     (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = msadpcm_write_block (psf, pms, sptr, writecount) ;
                total += count ;
                len -= writecount ;
@@ -760,7 +761,7 @@ msadpcm_write_d     (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrint (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
                count = msadpcm_write_block (psf, pms, sptr, writecount) ;
                total += count ;
                len -= writecount ;
index b6e2ff3..657c4d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -357,7 +357,7 @@ nist_write_header (SF_PRIVATE *psf, int calc_length)
        psf_asciiheader_printf (psf, "end_head\n") ;
 
        /* Zero fill to dataoffset. */
-       psf_binheader_writef (psf, "z", (size_t) (NIST_HEADER_LENGTH - psf->header.indx)) ;
+       psf_binheader_writef (psf, "z", BHWz ((size_t) (NIST_HEADER_LENGTH - psf->header.indx))) ;
 
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
 
diff --git a/src/nms_adpcm.c b/src/nms_adpcm.c
new file mode 100644 (file)
index 0000000..40f56f5
--- /dev/null
@@ -0,0 +1,1156 @@
+/*
+** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2017 Arthur Taylor <art@ified.ca>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+** This is a Natural MicroSystems ADPCM encoder/decoder. It converts 14 bit linear
+** PCM to and from either a 2, 3, or 4 bit ADPCM. NMS-ADPCM does not have appeared
+** to have ever been publicly documented, and appears to have debuted in the early
+** 90s in the Natural Access suite of PC-based telephony products. Raw NMS ADPCM
+** files usually have a .vce extension, although this does not encode what bitrate
+** is used.
+**
+** NMS-ADPCM is an 'optimised variation' of the ITU G.726 ADPCM scheme. The dominant
+** variation is that it removes the tone (modem) operation mode, and it's associated
+** voice/modem transition detection. This simplifies the computation of the step
+** size multiplier, as all operations on it remain in a log domain.
+*/
+
+#include       "sfconfig.h"
+
+#include       <math.h>
+
+#include       "sndfile.h"
+#include       "sfendian.h"
+#include       "common.h"
+
+
+#define NMS_SAMPLES_PER_BLOCK 160
+#define NMS_BLOCK_SHORTS_32 41
+#define NMS_BLOCK_SHORTS_24 31
+#define NMS_BLOCK_SHORTS_16 21
+
+/* Variable names from ITU G.726 spec */
+struct nms_adpcm_state
+{      /* Log of the step size multiplier. Operated on by codewords. */
+       int yl ;
+
+       /* Quantizer step size multiplier. Generated from yl. */
+       int y ;
+
+       /* Coefficents of the pole predictor */
+       int a [2] ;
+
+       /* Coefficents of the zero predictor  */
+       int b [6] ;
+
+       /* Previous quantized deltas (multiplied by 2^14) */
+       int d_q [7] ;
+
+       /* d_q [x] + s_ez [x], used by the pole-predictor for signs only. */
+       int p [3] ;
+
+       /* Previous reconstructed signal values. */
+       int s_r [2] ;
+
+       /* Zero predictor components of the signal estimate. */
+       int s_ez ;
+
+       /* Signal estimate, (including s_ez). */
+       int s_e ;
+
+       /* The most recent codeword (enc:generated, dec:inputted) */
+       int Ik ;
+
+       int parity ;
+
+       /*
+       ** Offset into code tables for the bitrate.
+       ** 2-bit words: +0
+       ** 3-bit words: +8
+       ** 4-bit words: +16
+       */
+       int t_off ;
+} ;
+
+enum nms_enc_type
+{      NMS16,
+       NMS24,
+       NMS32
+} ;
+
+typedef struct
+{      struct nms_adpcm_state state ;
+
+       /* The encoding type */
+       enum nms_enc_type type ;
+
+       int shortsperblock ;
+       int     blocks_total ;
+       int block_curr, sample_curr ;
+
+       unsigned short block [NMS_BLOCK_SHORTS_32] ;
+       short samples [NMS_SAMPLES_PER_BLOCK] ;
+} NMS_ADPCM_PRIVATE ;
+
+/* Pre-computed exponential interval used in the antilog approximation. */
+static unsigned int table_expn [] =
+{      0x4000, 0x4167, 0x42d5, 0x444c, 0x45cb, 0x4752, 0x48e2, 0x4a7a,
+       0x4c1b, 0x4dc7, 0x4f7a, 0x5138, 0x52ff, 0x54d1, 0x56ac, 0x5892,
+       0x5a82, 0x5c7e, 0x5e84, 0x6096, 0x62b4, 0x64dd, 0x6712, 0x6954,
+       0x6ba2, 0x6dfe, 0x7066, 0x72dc, 0x7560, 0x77f2, 0x7a93, 0x7d42,
+} ;
+
+/* Table mapping codewords to scale factor deltas. */
+static int table_scale_factor_step [] =
+{      0x0,    0x0,    0x0,    0x0,    0x4b0,  0x0,    0x0,    0x0,    /* 2-bit */
+       -0x3c,  0x0,    0x90,   0x0,    0x2ee,  0x0,    0x898,  0x0,    /* 3-bit */
+       -0x30,  0x12,   0x6b,   0xc8,   0x188,  0x2e0,  0x551,  0x1150, /* 4-bit */
+} ;
+
+/* Table mapping codewords to quantized delta interval steps. */
+static unsigned int table_step [] =
+{      0x73F,  0,              0,              0,              0x1829, 0,              0,              0,              /* 2-bit */
+       0x3EB,  0,              0xC18,  0,              0x1581, 0,              0x226E, 0,              /* 3-bit */
+       0x20C,  0x635,  0xA83,  0xF12,  0x1418, 0x19E3, 0x211A, 0x2BBA, /* 4-bit */
+} ;
+
+/* Binary search lookup table for quantizing using table_step. */
+static int table_step_search [] =
+{      0,              0x1F6D, 0,              -0x1F6D,        0,              0,                      0,                      0, /* 2-bit */
+       0x1008, 0x1192, 0,              -0x219A,        0x1656, -0x1656,        0,                      0, /* 3-bit */
+       0x872,  0x1277, -0x8E6, -0x232B,        0xD06,  -0x17D7,        -0x11D3,        0, /* 4-bit */
+} ;
+
+
+/*============================================================================================
+** Static functions.
+*/
+
+static void nms_adpcm_update (struct nms_adpcm_state *s) ;
+static void nms_adpcm_codec_init (struct nms_adpcm_state *s, enum nms_enc_type type) ;
+
+static int16_t nms_adpcm_reconstruct_sample (struct nms_adpcm_state *s, uint8_t I) ;
+static uint8_t nms_adpcm_encode_sample (struct nms_adpcm_state *s, int16_t sl) ;
+static int16_t nms_adpcm_decode_sample (struct nms_adpcm_state *s, uint8_t code) ;
+
+static void nms_adpcm_block_pack_16 (const int16_t codewords [], uint16_t block [], int16_t rms) ;
+static void nms_adpcm_block_pack_24 (const int16_t codewords [], uint16_t block [], int16_t rms) ;
+static void nms_adpcm_block_pack_32 (const int16_t codewords [], uint16_t block [], int16_t rms) ;
+
+static void nms_adpcm_block_unpack_16 (const uint16_t block [], int16_t codewords [], int16_t *rms) ;
+static void nms_adpcm_block_unpack_24 (const uint16_t block [], int16_t codewords [], int16_t *rms) ;
+static void nms_adpcm_block_unpack_32 (const uint16_t block [], int16_t codewords [], int16_t *rms) ;
+
+static int nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, uint16_t block [], int16_t samples []) ;
+static int nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, int16_t samples [], uint16_t block []) ;
+
+static sf_count_t nms_adpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
+static sf_count_t nms_adpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
+static sf_count_t nms_adpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
+static sf_count_t nms_adpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
+
+static sf_count_t nms_adpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
+static sf_count_t nms_adpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
+static sf_count_t nms_adpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
+static sf_count_t nms_adpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
+
+static int nms_adpcm_close (SF_PRIVATE *psf) ;
+static sf_count_t nms_adpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
+
+/*
+** An exponential function (antilog) approximation.
+**
+** Maps [1,20480] to [1,1024] in an exponential relationship. This is
+** approximately ret = b^exp where b = e^(ln(1024)/ln(20480)) ~= 1.0003385
+*/
+static inline int
+nms_adpcm_antilog (int exp)
+{      int ret ;
+
+       ret = 0x1000 ;
+       ret += (((exp & 0x3f) * 0x166b) >> 12) ;
+       ret *= table_expn [(exp & 0x7c0) >> 6] ;
+       ret >>= (26 - (exp >> 11)) ;
+
+       return ret ;
+} /* nms_adpcm_antilog */
+
+static void
+nms_adpcm_update (struct nms_adpcm_state *s)
+{      /* Variable names from ITU G.726 spec */
+       int a1ul ;
+       int fa1 ;
+       int i ;
+
+       /* Decay and Modify the scale factor in the log domain based on the codeword. */
+       s->yl = ((s->yl *0xf8) >> 8) + table_scale_factor_step [s->t_off + (s->Ik & 7)] ;
+       if (s->yl < 2171)
+               s->yl = 2171 ;
+       else if (s->yl > 20480)
+               s->yl = 20480 ;
+       s->y = nms_adpcm_antilog (s->yl) ;
+
+       /* Update the zero predictor coefficents. */
+       for (i = 0 ; i < 6 ; i++)
+       {       s->b [i] = (s->b [i] * 0xff) >> 8 ;
+               if ((s->d_q [0] ^ s->d_q [i + 1]) >= 0)
+                       s->b [i] += 128 ;
+               else
+                       s->b [i] -= 128 ;
+               }
+
+       /* Update the pole predictor coefficents. */
+       fa1 = s->a [0] >> 5 ;
+       if (fa1 < -256)
+               fa1 = -256 ;
+       else if (fa1 > 256)
+               fa1 = 256 ;
+
+       s->a [0] = (0xff * s->a [0]) >> 8 ;
+       if (s->p [0] != 0 && s->p [1] != 0 && ((s->p [0] ^ s->p [1]) < 0))
+               s->a [0] -= 192 ;
+       else
+       {       s->a [0] += 192 ;
+               fa1 = -fa1 ;
+               }
+
+       s->a [1] = fa1 + ((0xfe * s->a [1]) >> 8) ;
+       if (s->p [0] != 0 && s->p [2] != 0 && ((s->p [0] ^ s->p [2]) < 0))
+               s->a [1] -= 128 ;
+       else
+               s->a [1] += 128 ;
+
+       /* Stability constraints. */
+       if (s->a [1] < -12288)
+               s->a [1] = -12288 ;
+       else if (s->a [1] > 12288)
+               s->a [1] = 12288 ;
+       a1ul = 15360 - s->a [1] ;
+       if (s->a [0] >= a1ul)
+               s->a [0] = a1ul ;
+       else
+       {       a1ul = -a1ul ;
+               if (s->a [0] < a1ul)
+                       s->a [0] = a1ul ;
+               } ;
+
+       /* Compute the zero predictor estimate. Rotate past deltas too. */
+       s->s_ez = 0 ;
+       for (i = 5 ; i >= 0 ; i--)
+       {       s->s_ez += s->d_q [i] * s->b [i] ;
+               s->d_q [i + 1] = s->d_q [i] ;
+               } ;
+
+       /* Compute the signal estimate. */
+       s->s_e = s->a [0] * s->s_r [0] + s->a [1] * s->s_r [1] + s->s_ez ;
+
+       /* Return to scale */
+       s->s_ez >>= 14 ;
+       s->s_e >>= 14 ;
+
+       /* Rotate members to prepare for next iteration. */
+       s->s_r [1] = s->s_r [0] ;
+       s->p [2] = s->p [1] ;
+       s->p [1] = s->p [0] ;
+} /* nms_adpcm_update */
+
+
+static int16_t
+nms_adpcm_reconstruct_sample (struct nms_adpcm_state *s, uint8_t I)
+{      /* Variable names from ITU G.726 spec */
+       int dqx ;
+
+       /*
+       ** The ordering of the 12-bit right-shift is a precision loss. It agrees
+       ** with the output of a 16-bit NMSVCE.DLL, but disagrees with the output
+       ** of a CG6565 board.
+       */
+
+       /* Look up the delta, scale and sign it. */
+       dqx = table_step [s->t_off + (I & 7)] * s->y ;
+       if (I & 8)
+               dqx = -dqx ;
+
+       /* Take from delta scale to actual scale. */
+       dqx >>= 12 ;
+
+       /* Set variables used as input for the next predictor update. */
+       s->d_q [0] = dqx ;
+       s->s_r [0] = s->s_e + dqx ;
+       s->Ik = I & 0xf ;
+       s->p [0] = s->s_ez + dqx ;
+
+       return s->s_r [0] ;
+} /* nms_adpcm_reconstruct_sample */
+
+static void
+nms_adpcm_codec_init (struct nms_adpcm_state *s, enum nms_enc_type type)
+{      memset (s, 0, sizeof (struct nms_adpcm_state)) ;
+       s->t_off = (type == NMS32) ? 16 : (type == NMS24) ? 8 : 0 ;
+} /* nms_adpcm_codec_init */
+
+/*
+** nms_adpcm_encode_sample()
+**
+** Encode a linear 16-bit pcm sample into a 2,3, or 4 bit NMS-ADPCM codeword
+** using and updating the predictor state.
+*/
+static uint8_t
+nms_adpcm_encode_sample (struct nms_adpcm_state *s, int16_t sl)
+{      /* Variable names from ITU G.726 spec */
+       int d ;
+       uint8_t I ;
+
+       /* Down scale the sample from 16 => ~14 bits. */
+       sl = (sl * 0x1fdf) / 0x7fff ;
+
+       /* Compute estimate, and delta from actual value */
+       nms_adpcm_update (s) ;
+       d = sl - s->s_e ;
+
+       /*
+       ** Vary the input signal. Not sure why. It agrees with NMSVCE.DLL and
+       ** a CG6565 board.
+       */
+       if (s->parity ^= 1)
+               d -= 2 ;
+
+       /* Encode the delta signed-ness (Codeword bit 4) */
+       if (d < 0)
+       {       d = -d ;
+               I = 8 ;
+               }
+       else
+               I = 0 ;
+
+       /* Increase magnitude to be in the range of the delta steps */
+       d <<= 13 ;
+
+       /* Quantize the delta using a binary search. */
+       d += table_step_search [s->t_off + 3] * s->y ;
+       /* Codeword bit 3 */
+       if (d >= 0)
+       {       d += table_step_search [s->t_off + 5] * s->y ;
+               /* Codeword bit 2 */
+               if (d >= 0)
+               {       d += table_step_search [s->t_off + 6] * s->y ;
+                       /* Codeword bit 1 */
+                       if (d >= 0)
+                               I |= 7 ;
+                       else
+                               I |= 6 ;
+                       }
+               else
+               {       d += table_step_search [s->t_off + 4] * s->y ;
+                       /* Codeword bit 1 */
+                       if (d >= 0)
+                               I |= 5 ;
+                       else
+                               I |= 4 ;
+                       } ;
+               }
+       else {
+               d += table_step_search [s->t_off + 1] * s->y ;
+               /* Codeword bit 2 */
+               if (d >= 0)
+               {       d += table_step_search [s->t_off + 2] * s->y ;
+                       /* Codeword bit 1 */
+                       if (d >= 0)
+                               I |= 3 ;
+                       else
+                               I |= 2 ;
+                       }
+               else {
+                       d += table_step_search [s->t_off + 0] * s->y ;
+                       /* Codeword bit 1 */
+                       if (d >= 0)
+                               I |= 1 ;
+                       else
+                               I |= 0 ;
+                       } ;
+               } ;
+       /* What's left in d is actually our quantizer noise. */
+
+       /* Reduce the codeword size for the bitrate accordingly. */
+       if (s->t_off == 8)
+               I &= 0xe ;
+       else if (s->t_off == 0)
+               I &= 0xc ;
+
+       /* Call reconstruct for side effects preparing for the next update. */
+       nms_adpcm_reconstruct_sample (s, I) ;
+
+       return I ;
+} /* nms_adpcm_encode_sample */
+
+/*
+** nms_adpcm_decode_sample()
+**
+** Given a 2,3 or 4-bit NMS-ADPCM codeword, decode the next 16-bit linear PCM
+** sample using and updating the predictor state.
+*/
+static int16_t
+nms_adpcm_decode_sample (struct nms_adpcm_state *s, uint8_t I)
+{      int sl ;
+
+       nms_adpcm_update (s) ;
+       sl = nms_adpcm_reconstruct_sample (s, I) ;
+
+       /* Clamp to [-0x1fdf, 0x1fdf] (just under 14 bits resolution) */
+       if (sl < -0x1fdf)
+               sl = -0x1fdf ;
+       else if (sl > 0x1fdf)
+               sl = 0x1fdf ;
+
+       /* Expand from 14 to 16 bits */
+       sl = (sl * 0x7fff) / 0x1fdf ;
+
+       return (int16_t) sl ;
+} /* nms_adpcm_decode_sample */
+
+/**
+** NMS ADPCM Codeword packing scheme.
+**
+** The serialized form of NMS-ADPCM operates on blocks of 160 mono samples
+** (20ms at 8000Hz.) Blocks are 42, 62 and 82 bytes in size for the 2, 3, and
+** 4 bit codeword sizes respectively. The data is treated as an array of
+** little-endian 2-byte shorts, and the data is packed into the first 20, 30
+** or 40 shorts. The last short represents the block's root-mean-square
+** average. This is apparently an optimization so that energy/silence
+** detection processes can avoid decoding a block.
+**
+** All codewords are nibbles, with the least significant bits dropped as
+** required for the 3 and 2 bit codeword sizes.
+**
+** Nibbles are packed into shorts in order of most significant to least. The
+** 4-bit scheme is trivial. The three bit scheme reconstructs a fourth sample
+** from the leftover bits of the proceeding three samples. The 2-bit scheme
+** uses a two-pass, left two bit shift.
+*/
+
+/*
+** Reads 21 shorts from block, unpacks 160 codewords of 2-bits each, writing
+** each to its sequential array index of codewords. If rms is non-null, the
+** read block rms is copied to its location.
+*/
+static void
+nms_adpcm_block_unpack_16 (const uint16_t block [], int16_t codewords [], int16_t *rms)
+{      int k ;
+       uint16_t w = 0 ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; )
+       {       /*
+               ** k % 8 == [0-3]: Top 2-bits of a nibble
+               ** k % 8 == [4-7]: Bottom 2-bits of a nibble
+               */
+               if ((k & 4) == 0)
+                       w = *(block++) ;
+               else
+                       w <<= 2 ;
+               codewords [k++] = (w >> 12) & 0xc ;
+               codewords [k++] = (w >> 8) & 0xc ;
+               codewords [k++] = (w >> 4) & 0xc ;
+               codewords [k++] = w & 0xc ;
+               } ;
+
+       /*
+       ** Every block ends with a short representing a RMS-approximation for the
+       ** block.
+       **/
+       if (rms)
+               *rms = *block ;
+} /* nms_adpcm_unpack_16 */
+
+/*
+** Reads 31 shorts from block, unpacks 160 codewords of 3-bits each, writing
+** each to its sequential array index of codewords. If rms is non-null, the
+** read block rms is copied to its location.
+*/
+static void
+nms_adpcm_block_unpack_24 (const uint16_t block [], int16_t codewords [], int16_t *rms)
+{      int k ;
+       uint16_t w = 0, residual = 0 ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; )
+       {               /*
+               ** k % 16 == [0, 11]: Unpack new nibble, build residual
+               ** k % 16 == [12, 15]: Unpack residual
+               */
+               if ((k & 12) != 12)
+               {       w = *(block++) ;
+                       residual = (residual << 1) | (w & 0x1111) ;
+                       }
+               else
+               {       w = residual << 1 ;
+                       residual = 0 ;
+                       } ;
+               codewords [k++] = (w >> 12) & 0xe ;
+               codewords [k++] = (w >> 8) & 0xe ;
+               codewords [k++] = (w >> 4) & 0xe ;
+               codewords [k++] = w & 0xe ;
+               } ;
+
+       /*
+       ** Every block ends with a short representing a RMS-approximation for the
+       ** block.
+       **/
+       if (rms)
+               *rms = *block ;
+} /* nms_adpcm_unpack_24 */
+
+/*
+** Reads 41 shorts from block, unpacks 160 codewords of 4-bits each, writing
+** each to its sequential array index of codewords. If rms is non-null, the
+** read block rms is copied to its location.
+*/
+static void
+nms_adpcm_block_unpack_32 (const uint16_t block [], int16_t codewords [], int16_t *rms)
+{      int k ;
+       uint16_t w = 0 ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; )
+       {       w = *(block++) ;
+               codewords [k++] = (w >> 12) & 0xf ;
+               codewords [k++] = (w >> 8) & 0xf ;
+               codewords [k++] = (w >> 4) & 0xf ;
+               codewords [k++] = w & 0xf ;
+               } ;
+       /*
+       ** Every block ends with a short representing a RMS-approximation for the
+       ** block.
+       **/
+       if (rms)
+               *rms = *block ;
+} /* nms_adpcm_unpack_32 */
+
+/*
+** Reads 160 indicies of codewords for one 2-bit codeword each, packing them
+** into 20 shorts of block, and writes the short rms for a total of 42 bytes.
+*/
+static void
+nms_adpcm_block_pack_16 (const int16_t codewords [], uint16_t block [], int16_t rms)
+{      int k ;
+       uint16_t w ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; )
+       {       w = codewords [k++] << 12 ;
+               w |= codewords [k++] << 8 ;
+               w |= codewords [k++] << 4 ;
+               w |= codewords [k++] ;
+               w |= codewords [k++] << 10 ;
+               w |= codewords [k++] << 6 ;
+               w |= codewords [k++] << 2 ;
+               w |= codewords [k++] >> 2 ;
+
+               *(block++) = w ;
+               } ;
+
+       /* Every block ends with a short representing the blocks RMS */
+       *block = rms ;
+} /* nms_adpcm_pack_16 */
+
+/*
+** Reads 160 indicies of codewords for one 3-bit codeword each, packing them
+** into 30 shorts of block, and writes the short rms for a total of 62 bytes.
+*/
+static void
+nms_adpcm_block_pack_24 (const int16_t codewords [], uint16_t block [], int16_t rms)
+{      int k ;
+       uint16_t w [3] ;
+       uint16_t residual ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; )
+       {       w [0] = codewords [k++] << 12 ;
+               w [0] |= codewords [k++] << 8 ;
+               w [0] |= codewords [k++] << 4 ;
+               w [0] |= codewords [k++] ;
+
+               w [1] = codewords [k++] << 12 ;
+               w [1] |= codewords [k++] << 8 ;
+               w [1] |= codewords [k++] << 4 ;
+               w [1] |= codewords [k++] ;
+
+               w [2] = codewords [k++] << 12 ;
+               w [2] |= codewords [k++] << 8 ;
+               w [2] |= codewords [k++] << 4 ;
+               w [2] |= codewords [k++] ;
+
+               residual = codewords [k++] << 12 ;
+               residual |= codewords [k++] << 8 ;
+               residual |= codewords [k++] << 4 ;
+               residual |= codewords [k++] ;
+
+               residual >>= 1 ;
+               w [2] |= (residual & 0x1111) ;
+               residual >>= 1 ;
+               w [1] |= (residual & 0x1111) ;
+               residual >>= 1 ;
+               w [0] |= (residual & 0x1111) ;
+
+               *(block++) = w [0] ;
+               *(block++) = w [1] ;
+               *(block++) = w [2] ;
+               } ;
+
+       /* Every block ends with a short representing the blocks RMS */
+       *block = rms ;
+} /* nms_adpcm_pack_24 */
+
+/*
+** Reads 160 indicies of codewords for one 4-bit codeword each, packing them
+** into 40 shorts of block, and writes the short rms for a total of 82 bytes.
+*/
+static void
+nms_adpcm_block_pack_32 (const int16_t codewords [], uint16_t block [], int16_t rms)
+{      int k ;
+       uint16_t w ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; )
+       {       w = codewords [k++] << 12 ;
+               w |= codewords [k++] << 8 ;
+               w |= codewords [k++] << 4 ;
+               w |= codewords [k++] ;
+
+               *(block++) = w ;
+               } ;
+
+       /* Every block ends with a short representing the blocks RMS */
+       *block = rms ;
+} /*nms_adpcm_block_pack_32 */
+
+static int
+nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, uint16_t block [], int16_t samples [])
+{      int k ;
+
+       switch (pnms->type)
+       {       case NMS16 :
+                       nms_adpcm_block_unpack_16 (block, samples, NULL) ;
+                       break ;
+               case NMS24 :
+                       nms_adpcm_block_unpack_24 (block, samples, NULL) ;
+                       break ;
+               case NMS32 :
+                       nms_adpcm_block_unpack_32 (block, samples, NULL) ;
+                       break ;
+
+               default :
+                       psf_log_printf (psf, "*** Error : Unhandled NMS ADPCM type %d.\n", pnms->type) ;
+                       return 0 ;
+               } ;
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; k++)
+               samples [k] = nms_adpcm_decode_sample (&pnms->state, samples [k]) ;
+
+       return NMS_SAMPLES_PER_BLOCK ;
+} /* nms_adpcm_decode_block */
+
+static int
+nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, int16_t samples [], uint16_t block [])
+{      int k ;
+       unsigned int rms = 0 ;
+
+       /*
+       ** The rms we write is a complete lie. Considering that the various
+       ** other implementations I've tested don't completely agree, that this data
+       ** is usually ignored, and except for some weird offloading of "energy
+       ** detection", so long as we don't write zeros for non-zero data, I don't
+       ** think it really matters.
+       */
+
+       for (k = 0 ; k < NMS_SAMPLES_PER_BLOCK ; k++)
+       {       rms += (samples [k] * samples [k]) >> 2 ;
+               samples [k] = nms_adpcm_encode_sample (&pnms->state, samples [k]) ;
+               } ;
+
+       rms <<= 12 ;
+       switch (pnms->type)
+       {       case NMS16 :
+                       nms_adpcm_block_pack_16 (samples, block, rms) ;
+                       break ;
+               case NMS24 :
+                       nms_adpcm_block_pack_24 (samples, block, rms) ;
+                       break ;
+               case NMS32 :
+                       nms_adpcm_block_pack_32 (samples, block, rms) ;
+                       break ;
+
+               default :
+                       psf_log_printf (psf, "*** Error : Unhandled NMS ADPCM type %d.\n", pnms->type) ;
+                       return 0 ;
+               } ;
+
+       return NMS_SAMPLES_PER_BLOCK ;
+} /* nms_adpcm_encode_block */
+
+static int
+psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms)
+{      int k ;
+
+       if ((k = psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock)
+       {       psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pnms->shortsperblock) ;
+               memset (pnms->block + (k * sizeof (short)), 0, (pnms->shortsperblock - k) * sizeof (short)) ;
+               } ;
+
+       if (CPU_IS_BIG_ENDIAN)
+               endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ;
+
+       nms_adpcm_decode_block (psf, pnms, pnms->block, pnms->samples) ;
+
+       return 1 ;
+} /* nms_adpcm_decode_block */
+
+static int
+nms_adpcm_read_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, short *ptr, int len)
+{      int     count, indx = 0 ;
+
+       while (indx < len)
+       {       if (pnms->sample_curr >= NMS_SAMPLES_PER_BLOCK)
+               {       pnms->block_curr ++ ;
+                       pnms->sample_curr = 0 ;
+                       } ;
+
+               if (pnms->block_curr > pnms->blocks_total)
+               {       memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
+                       return indx ;
+                       } ;
+
+               if (pnms->sample_curr == 0)
+                       psf_nms_adpcm_decode_block (psf, pnms) ;
+
+               count = NMS_SAMPLES_PER_BLOCK - pnms->sample_curr ;
+               if (len - indx < count)
+                       count = len - indx ;
+
+               memcpy (&(ptr [indx]), &(pnms->samples [pnms->sample_curr]), count * sizeof (short)) ;
+               indx += count ;
+               pnms->sample_curr += count ;
+               } ;
+
+       return indx ;
+} /* nms_adpcm_read_block */
+
+static sf_count_t
+nms_adpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
+{      NMS_ADPCM_PRIVATE       *pnms ;
+       int                                     readcount, count ;
+       sf_count_t                      total = 0 ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       while (len > 0)
+       {       readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
+
+               count = nms_adpcm_read_block (psf, pnms, ptr, readcount) ;
+
+               total += count ;
+               len -= count ;
+
+               if (count != readcount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_read_s */
+
+static sf_count_t
+nms_adpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
+{      BUF_UNION       ubuf ;
+       NMS_ADPCM_PRIVATE *pnms ;
+       short           *sptr ;
+       int                     k, bufferlen, readcount = 0, count ;
+       sf_count_t      total = 0 ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE *) psf->codec_data ;
+
+       sptr = ubuf.sbuf ;
+       bufferlen = SF_BUFFER_LEN / sizeof (short) ;
+       while (len > 0)
+       {       readcount = (len >= bufferlen) ? bufferlen : len ;
+               count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
+
+               for (k = 0 ; k < readcount ; k++)
+                       ptr [total + k] = arith_shift_left (sptr [k], 16) ;
+
+               total += count ;
+               len -= readcount ;
+               if (count != readcount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_read_i */
+
+static sf_count_t
+nms_adpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
+{      BUF_UNION       ubuf ;
+       NMS_ADPCM_PRIVATE *pnms ;
+       short           *sptr ;
+       int                     k, bufferlen, readcount = 0, count ;
+       sf_count_t      total = 0 ;
+       float           normfact ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
+
+       sptr = ubuf.sbuf ;
+       bufferlen = SF_BUFFER_LEN / sizeof (short) ;
+       while (len > 0)
+       {       readcount = (len >= bufferlen) ? bufferlen : len ;
+               count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
+               for (k = 0 ; k < readcount ; k++)
+                       ptr [total + k] = normfact * sptr [k] ;
+
+               total += count ;
+               len -= readcount ;
+               if (count != readcount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_read_f */
+
+static sf_count_t
+nms_adpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
+{      BUF_UNION       ubuf ;
+       NMS_ADPCM_PRIVATE *pnms ;
+       short           *sptr ;
+       int                     k, bufferlen, readcount = 0, count ;
+       sf_count_t      total = 0 ;
+       double          normfact ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
+
+       sptr = ubuf.sbuf ;
+       bufferlen = SF_BUFFER_LEN / sizeof (short) ;
+       while (len > 0)
+       {       readcount = (len >= bufferlen) ? bufferlen : len ;
+               count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
+               for (k = 0 ; k < readcount ; k++)
+                       ptr [total + k] = normfact * (double) (sptr [k]) ;
+
+               total += count ;
+               len -= readcount ;
+               if (count != readcount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_read_d */
+
+static int
+psf_nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms)
+{      int k ;
+
+       /* Encode the samples. */
+       nms_adpcm_encode_block (psf, pnms, pnms->samples, pnms->block) ;
+
+       if (CPU_IS_BIG_ENDIAN)
+               endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ;
+
+       /* Write the block to disk. */
+       if ((k = psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock)
+               psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pnms->shortsperblock) ;
+
+       pnms->sample_curr = 0 ;
+       pnms->block_curr ++ ;
+
+       return 1 ;
+} /* psf_nms_adpcm_encode_block */
+
+static int
+nms_adpcm_write_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms, const short *ptr, int len)
+{      int     count, total = 0, indx = 0 ;
+
+       while (indx < len)
+       {       count = NMS_SAMPLES_PER_BLOCK - pnms->sample_curr ;
+
+               if (count > len - indx)
+                       count = len - indx ;
+
+               memcpy (&(pnms->samples [pnms->sample_curr]), &(ptr [indx]), count * sizeof (short)) ;
+               indx += count ;
+               pnms->sample_curr += count ;
+               total = indx ;
+
+               if (pnms->sample_curr >= NMS_SAMPLES_PER_BLOCK)
+                       psf_nms_adpcm_encode_block (psf, pnms) ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_write_block */
+
+static sf_count_t
+nms_adpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
+{      NMS_ADPCM_PRIVATE       *pnms ;
+       int                     writecount, count ;
+       sf_count_t      total = 0 ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       while (len > 0)
+       {       writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
+
+               count = nms_adpcm_write_block (psf, pnms, ptr, writecount) ;
+
+               total += count ;
+               len -= count ;
+               if (count != writecount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_write_s */
+
+static sf_count_t
+nms_adpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
+{      BUF_UNION       ubuf ;
+       NMS_ADPCM_PRIVATE *pnms ;
+       short           *sptr ;
+       int                     k, bufferlen, writecount = 0, count ;
+       sf_count_t      total = 0 ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       sptr = ubuf.sbuf ;
+       bufferlen = SF_BUFFER_LEN / sizeof (short) ;
+       while (len > 0)
+       {       writecount = (len >= bufferlen) ? bufferlen : len ;
+               for (k = 0 ; k < writecount ; k++)
+                       sptr [k] = ptr [total + k] >> 16 ;
+               count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;
+
+               total += count ;
+               len -= writecount ;
+               if (count != writecount)
+                       break ;
+               } ;
+       return total ;
+} /* nms_adpcm_write_i */
+
+static sf_count_t
+nms_adpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
+{      BUF_UNION       ubuf ;
+       NMS_ADPCM_PRIVATE *pnms ;
+       short           *sptr ;
+       int                     k, bufferlen, writecount = 0, count ;
+       sf_count_t      total = 0 ;
+       float           normfact ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
+
+       sptr = ubuf.sbuf ;
+       bufferlen = SF_BUFFER_LEN / sizeof (short) ;
+       while (len > 0)
+       {       writecount = (len >= bufferlen) ? bufferlen : len ;
+               for (k = 0 ; k < writecount ; k++)
+                       sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
+               count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;
+
+               total += count ;
+               len -= writecount ;
+               if (count != writecount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_write_f */
+
+static sf_count_t
+nms_adpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
+{      BUF_UNION       ubuf ;
+       NMS_ADPCM_PRIVATE *pnms ;
+       short           *sptr ;
+       int                     k, bufferlen, writecount = 0, count ;
+       sf_count_t      total = 0 ;
+       double          normfact ;
+
+       if (psf->codec_data == NULL)
+               return 0 ;
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
+
+       sptr = ubuf.sbuf ;
+       bufferlen = SF_BUFFER_LEN / sizeof (short) ;
+       while (len > 0)
+       {       writecount = (len >= bufferlen) ? bufferlen : len ;
+               for (k = 0 ; k < writecount ; k++)
+                       sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
+               count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;
+
+               total += count ;
+               len -= writecount ;
+               if (count != writecount)
+                       break ;
+               } ;
+
+       return total ;
+} /* nms_adpcm_write_d */
+
+int
+nms_adpcm_init (SF_PRIVATE *psf)
+{      NMS_ADPCM_PRIVATE       *pnms ;
+
+       if (psf->codec_data != NULL)
+       {       psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
+               return SFE_INTERNAL ;
+               } ;
+
+       psf->sf.seekable = SF_FALSE ;
+
+       if (psf->sf.channels != 1)
+               return SFE_NMS_ADPCM_NOT_MONO ;
+
+       if ((pnms = calloc (1, sizeof (NMS_ADPCM_PRIVATE))) == NULL)
+               return SFE_MALLOC_FAILED ;
+
+       psf->codec_data = (void*) pnms ;
+
+       pnms->block_curr = 0 ;
+       pnms->sample_curr = 0 ;
+
+       switch (SF_CODEC (psf->sf.format))
+       {       case SF_FORMAT_NMS_ADPCM_16 :
+                                       pnms->type = NMS16 ;
+                                       pnms->shortsperblock = NMS_BLOCK_SHORTS_16 ;
+                                       break ;
+               case SF_FORMAT_NMS_ADPCM_24 :
+                                       pnms->type = NMS24 ;
+                                       pnms->shortsperblock = NMS_BLOCK_SHORTS_24 ;
+                                       break ;
+               case SF_FORMAT_NMS_ADPCM_32 :
+                                       pnms->type = NMS32 ;
+                                       pnms->shortsperblock = NMS_BLOCK_SHORTS_32 ;
+                                       break ;
+
+               default : return SFE_UNIMPLEMENTED ;
+       } ;
+       nms_adpcm_codec_init (&pnms->state, pnms->type) ;
+
+       psf->filelength = psf_get_filelen (psf) ;
+       if (psf->filelength < psf->dataoffset)
+               psf->filelength = psf->dataoffset ;
+
+       psf->datalength = psf->filelength - psf->dataoffset ;
+       if (psf->dataend > 0)
+               psf->datalength -= psf->filelength - psf->dataend ;
+
+       if (psf->file.mode == SFM_READ)
+       {       psf->read_short         = nms_adpcm_read_s ;
+               psf->read_int           = nms_adpcm_read_i ;
+               psf->read_float         = nms_adpcm_read_f ;
+               psf->read_double        = nms_adpcm_read_d ;
+               }
+       else if (psf->file.mode == SFM_WRITE)
+       {       psf->write_short        = nms_adpcm_write_s ;
+               psf->write_int          = nms_adpcm_write_i ;
+               psf->write_float        = nms_adpcm_write_f ;
+               psf->write_double       = nms_adpcm_write_d ;
+               } ;
+
+       if (psf->datalength % (pnms->shortsperblock * sizeof (short)))
+       {       psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n",
+                                               psf->datalength, pnms->shortsperblock * sizeof (short)) ;
+               pnms->blocks_total = (psf->datalength / (pnms->shortsperblock * sizeof (short))) + 1 ;
+               }
+       else
+               pnms->blocks_total = psf->datalength / (pnms->shortsperblock * sizeof (short)) ;
+
+       psf->sf.frames          = pnms->blocks_total * NMS_SAMPLES_PER_BLOCK ;
+       psf->codec_close        = nms_adpcm_close ;
+       psf->seek                       = nms_adpcm_seek ;
+
+       return 0 ;
+} /* nms_adpcm_init */
+
+static int
+nms_adpcm_close (SF_PRIVATE *psf)
+{      NMS_ADPCM_PRIVATE *pnms ;
+
+       pnms = (NMS_ADPCM_PRIVATE*) psf->codec_data ;
+
+       /*
+       ** If a block has been partially assembled, write it out as the final
+       ** block.
+       */
+       if (psf->file.mode == SFM_WRITE)
+       {       if (pnms->sample_curr && pnms->sample_curr < NMS_SAMPLES_PER_BLOCK)
+               {       memset (pnms->samples + pnms->sample_curr, 0, (NMS_SAMPLES_PER_BLOCK - pnms->sample_curr) * sizeof (short)) ;
+                       psf_nms_adpcm_encode_block (psf, pnms) ;
+                       }
+
+               if (psf->write_header)
+                       psf->write_header (psf, SF_FALSE) ;
+               }
+
+       return 0 ;
+} /* nms_adpcm_close */
+
+static sf_count_t
+nms_adpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
+{      NMS_ADPCM_PRIVATE *pnms ;
+
+       pnms = (NMS_ADPCM_PRIVATE *) psf->codec_data ;
+
+       /*
+       ** NMS ADPCM is symmetric, so transitioning from reading and writing is
+       ** possible, but unimplemented, as it would require syncing partial blocks.
+       */
+       if (mode != psf->file.mode)
+       {       psf->error = SFE_BAD_SEEK ;
+               return PSF_SEEK_ERROR ;
+               } ;
+
+       /*
+       ** NMS ADPCM cannot be seek'ed, as codec state depends on previous samples,
+       ** so only a seek to 0 is supported.
+       */
+       if (offset != 0)
+       {       psf->error = SFE_BAD_SEEK ;
+               return PSF_SEEK_ERROR ;
+               } ;
+
+       if (psf_fseek (psf, psf->dataoffset, SEEK_SET) == PSF_SEEK_ERROR)
+                       return PSF_SEEK_ERROR ;
+
+       nms_adpcm_codec_init (&pnms->state, pnms->type) ;
+       pnms->block_curr = 0 ;
+       pnms->sample_curr = 0 ;
+       return 0 ;
+} /* nms_adpcm_seek */
+
index 0856f77..7a4a167 100644 (file)
--- a/src/ogg.c
+++ b/src/ogg.c
@@ -1,6 +1,7 @@
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2007 John ffitch
+** Copyright (C) 2018 Arthur Taylor <art@ified.ca>
 **
 ** This program is free software ; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+/*
+** This file contains code based on OpusFile and Opus-Tools, both by
+** Xiph.Org. COPYING from each is identical and is as follows:
+**
+** Copyright (c) 1994-2013 Xiph.Org Foundation and contributors
+**
+** 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 name of the Xiph.Org Foundation nor the names of its
+** 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 FOUNDATION
+** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
 #include "sfconfig.h"
 
 #include <stdio.h>
@@ -28,6 +63,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "sndfile.h"
 
 #include "ogg.h"
 
-static int     ogg_close (SF_PRIVATE *psf) ;
-static int     ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE * odata) ;
-static int     ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ;
+#define OGG_SYNC_READ_SIZE (2048)
+#define OGG_PAGE_SIZE_MAX (65307)
+#define OGG_CHUNK_SIZE (65536)
+#define OGG_CHUNK_SIZE_MAX (1024*1024)
+
+/*
+ * The Ogg container may seem overly complicated, particularly when used for a
+ * on-disk audio file format. This is probably because Ogg is designed with
+ * streaming rather than storage as a priority, and can handle multiple codec
+ * payloads multiplexed together, then possibly chained on top of that.
+ * Ogg achieves its goals well, but it does lend to a bit of a learning curve,
+ * with many internal structures to push data around in compared to most sound
+ * file formats which only have a header and raw data.
+ *
+ * See
+ *  - [https://xiph.org/ogg/doc/oggstream.html]
+ *  - [https://xiph.org/ogg/doc/framing.html]
+ *
+ * libogg Memory Management
+ * ===========================================================================
+ *
+ * libOgg's memory management is documented in code, not in headers or external
+ * documentation. What follows is not an attempt to completely document it, but
+ * an explanation of the basics.
+ *
+ * libOgg has two data structures which allocate and manage data buffers: The
+ * ogg_sync_state structure and the ogg_stream_state structure. The remaining
+ * structures of ogg_page and ogg_packet are views into the buffers managed by
+ * the previous structures.
+ *
+ * ogg_sync_state is used for reading purposes. It takes a physical bitstream
+ * and searches for, validates, and returns complete Ogg Pages. The
+ * ogg_sync_state buffers the returned page data, holding at most one
+ * complete page at a time. A returned Ogg page remains valid until any
+ * operation other than ogg_sync_check() is called.
+ *
+ * ogg_stream_state is used for both reading and writing. For reading, the
+ * contents of an ogg_page is copied into the stream state. This data is
+ * buffered to be split or joined as necessary into complete ogg_packets. If,
+ * after copying an ogg_page into an ogg_stream_state, packets are available to
+ * be read, then all of those packets remain in memory and valid until either
+ * the ogg_stream_state is reset, destroyed, or a new ogg_page is read into it.
+ * As the maximum number of packets an Ogg Page may contain is 255, at most 255
+ * packets may be available from an ogg_stream_state at one time.
+ *
+ * For writing, the life cycle of a buffer pointed to by a ogg_packet is the
+ * responsibility of the caller. Packets written into an ogg_stream_state are
+ * buffered until a complete page is ready for writing. Pages for writing out
+ * remain in the ogg_stream_state's buffer and valid until either the
+ * ogg_stream_state is reset, cleared, destroyed. Writing another packet into
+ * the ogg_stream_state might also invalidate such pages, but writing in
+ * packets when a page is ready to be written out is a caller bug anyways.
+ */
+
+/*-----------------------------------------------------------------------------------------------
+** Private function prototypes.
+*/
+
+static int             ogg_close (SF_PRIVATE *psf) ;
+static int             ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE * odata) ;
+static int             ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ;
+static uint64_t        ogg_page_search_do_rescale (uint64_t x, uint64_t from, uint64_t to) ;
+static void            ogg_page_search_continued_data (OGG_PRIVATE *odata, ogg_page *page) ;
+
+/*-----------------------------------------------------------------------------------------------
+** Exported functions.
+*/
+
+int
+ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
+{      int ret ;
+       char *buffer ;
+
+       /*
+       ** The ogg standard requires that the first pages of a physical ogg
+       ** bitstream be only the first pages of each logical bitstream. These
+       ** pages MUST have the Beginning-Of-Stream bit set, and must contain
+       ** only the stream's relevant header. Currently we only load the first
+       ** page and check that it contains a codec we support as supporting
+       ** multiplexed streams (video+audio(en)+audio(fs)+subtitles, etc) is
+       ** beyond the scope of this library.
+       */
+
+       ret = ogg_sync_fseek (psf, psf->header.indx, SEEK_SET) ;
+       if (ret < 0)
+               return SFE_NOT_SEEKABLE ;
+
+       buffer = ogg_sync_buffer (&odata->osync, psf->header.indx) ;
+       memcpy (buffer, psf->header.ptr, psf->header.indx) ;
+       ogg_sync_wrote (&odata->osync, psf->header.indx) ;
+
+       ret = ogg_sync_next_page (psf, &odata->opage, SF_MAX ((sf_count_t) 0, 4096 - psf->header.indx), NULL) ;
+
+       /* Have we simply run out of data?  If so, we're done. */
+       if (ret == 0)
+               return 0 ;
+       if (ret < 0)
+               return psf->error ;
+
+       if (!ogg_page_bos (&odata->opage))
+       {       /*
+               ** Error case. Either must not be an Ogg bitstream, or is in the
+               ** middle of a bitstream (live capture), or in the middle of a
+               ** bitstream and no complete page was in the buffer.
+               */
+               psf_log_printf (psf, "Input does not appear to be the start of an Ogg bitstream.\n") ;
+               return SFE_MALFORMED_FILE ;
+               } ;
+
+       /*
+       **      Get the serial number and set up the rest of decode.
+       **      Serialno first ; use it to set up a logical stream.
+       */
+       ogg_stream_reset_serialno (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
+
+       if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
+       {       /* Error ; stream version mismatch perhaps. */
+               psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
+               return SFE_MALFORMED_FILE ;
+               } ;
+
+       if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
+       {       /* No page? */
+               psf_log_printf (psf, "Error reading initial header page packet.\n") ;
+               return SFE_MALFORMED_FILE ;
+               } ;
+
+       return 0 ;
+} /* ogg_read_first_page */
+
+int
+ogg_write_page (SF_PRIVATE *psf, ogg_page *page)
+{      int bytes ;
+
+       bytes = psf_fwrite (page->header, 1, page->header_len, psf) ;
+       bytes += psf_fwrite (page->body, 1, page->body_len, psf) ;
+
+       return bytes == page->header_len + page->body_len ;
+} /* ogg_write_page */
+
+sf_count_t
+ogg_sync_ftell (SF_PRIVATE *psf)
+{      OGG_PRIVATE* odata = (OGG_PRIVATE *) psf->container_data ;
+       sf_count_t position ;
+
+       position = psf_ftell (psf) ;
+       if (position >= 0)
+       {       /* success */
+               if (position < odata->osync.fill)
+               {       /* Really, this should be an assert. */
+                       psf->error = SFE_INTERNAL ;
+                       return -1 ;
+                       }
+               position += (sf_count_t) (odata->osync.returned - odata->osync.fill) ;
+               }
+
+       return position ;
+} /* ogg_sync_ftell */
+
+sf_count_t
+ogg_sync_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
+{      OGG_PRIVATE* odata = (OGG_PRIVATE *) psf->container_data ;
+       sf_count_t ret ;
+
+       ret = psf_fseek (psf, offset, whence) ;
+       if (ret >= 0)
+       {       /* success */
+               odata->eos = 0 ;
+               ogg_sync_reset (&odata->osync) ;
+               }
+
+       return ret ;
+} /* ogg_sync_fseek */
+
+int
+ogg_sync_next_page (SF_PRIVATE * psf, ogg_page *og, sf_count_t readmax, sf_count_t *offset)
+{      OGG_PRIVATE* odata = (OGG_PRIVATE *) psf->container_data ;
+       sf_count_t position, nb_read, read_ret ;
+       unsigned char *buffer ;
+       int synced ;
+       int report_hole = 0 ;
+
+       for (position = 0 ; readmax <= 0 || readmax > position ; )
+       {       synced = ogg_sync_pageseek (&odata->osync, og) ;
+               if (synced < 0)
+               {       /*
+                       ** Skipped -synced bytes before finding the start of a page.
+                       ** If seeking, we have just landed in the middle of a page.
+                       ** Otherwise, warn about junk in the bitstream.
+                       ** Page might not yet be ready, hence the continue.
+                       */
+                       if (!offset)
+                               report_hole = 1 ;
+                       position -= synced ;
+                       continue ;
+                       } ;
+
+               if (report_hole)
+               {       psf_log_printf (psf, "Ogg : Skipped %d bytes looking for the next page. Corrupted bitstream?!\n", position) ;
+                       report_hole = 0 ;
+                       } ;
+
+               if (synced > 0)
+               {       /* Have a page */
+                       if (offset)
+                               *offset += position ;
+                       return og->header_len + og->body_len ;
+                       } ;
+
+               /*
+               ** Else readmax == 0, Out of data. Try to read more in without
+               ** invalidating our boundary (readmax) constraint.
+               */
+               if (readmax == 0)
+                       return 0 ;
+               if (readmax > 0)
+                       nb_read = SF_MIN ((sf_count_t) OGG_SYNC_READ_SIZE, readmax - position) ;
+               else
+                       nb_read = OGG_SYNC_READ_SIZE ;
+               buffer = (unsigned char *) ogg_sync_buffer (&odata->osync, nb_read) ;
+               read_ret = psf_fread (buffer, 1, nb_read, psf) ;
+               if (read_ret == 0)
+                       return psf->error ? -1 : 0 ;
+               ogg_sync_wrote (&odata->osync, read_ret) ;
+               } ;
+       return 0 ;
+} /* ogg_sync_next_page */
+
+int
+ogg_stream_next_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
+{      int nn ;
+
+       if (odata->eos)
+               return 0 ;
+
+       for ( ; ; )
+       {       nn = ogg_sync_next_page (psf, &odata->opage, -1, NULL) ;
+               if (nn == 0)
+               {       psf_log_printf (psf, "Ogg : File ended unexpectedly without an End-Of-Stream flag set.\n") ;
+                       odata->eos = 1 ;
+                       }
+               if (nn <= 0)
+                       return nn ;
+
+               if (ogg_page_serialno (&odata->opage) == odata->ostream.serialno)
+                       break ;
+               } ;
+
+       if (ogg_page_eos (&odata->opage))
+               odata->eos = 1 ;
+
+       if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
+       {       psf->error = SFE_INTERNAL ;
+               return -1 ;
+               }
+
+       return 1 ;
+} /* ogg_stream_next_page */
+
+int
+ogg_stream_unpack_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
+{      int nn ;
+       int i ;
+       int found_hole = 0 ;
+       ogg_packet *ppkt = odata->pkt ;
+
+       odata->pkt_indx = 0 ;
+       nn = ogg_stream_packetout (&odata->ostream, ppkt) ;
+       if (nn == 0)
+       {       /*
+               ** Steam is out of packets. Read in more pages until there is one, or
+               ** the stream ends, or an error occurs.
+               */
+               for ( ; nn == 0 ; nn = ogg_stream_packetout (&odata->ostream, ppkt))
+               {       nn = ogg_stream_next_page (psf, odata) ;
+                       if (nn <= 0)
+                       {       odata->pkt_len = 0 ;
+                               return nn ;
+                               }
+                       }
+               /*
+               ** In the case of the for loop exiting because
+               ** ogg_stream_packetout() == -1, fall-through.
+               */
+               }
+
+       if (nn == -1)
+       {       /*
+               ** libOgg found a hole. That is, the next packet found was out of
+               ** sequence. As such, "flush" the hole marker by removing the invalid
+               ** packet, as the valid packets are queued behind it.
+               */
+               psf_log_printf (psf, "Ogg : Warning, libogg reports a hole at %d bytes.\n", ogg_sync_ftell (psf)) ;
+               nn = ogg_stream_packetout (&odata->ostream, ppkt) ;
+               found_hole = 1 ;
+               }
+
+       /*
+       ** Unpack all the packets on the page. It is undocumented (like much of
+       ** libOgg behavior) but all packets from a page read into the stream are
+       ** guarenteed to remain valid in memory until a new page is read into the
+       ** stream.
+       */
+       for (i = 1 ; ; i++)
+       {       /* Not an off-by-one, there are 255 not 256 packets max. */
+               if (i == 255)
+               {       if (ogg_stream_packetpeek (&odata->ostream, NULL) == 1)
+                       {       psf->error = SFE_INTERNAL ;
+                               return -1 ;
+                               }
+                       break ;
+                       }
+               if (ogg_stream_packetout (&odata->ostream, ++ ppkt) != 1)
+                       break ;
+               }
+       odata->pkt_len = i ;
+
+       /* 1 = ok, 2 = ok, and found a hole. */
+       return 1 + found_hole ;
+} /* ogg_stream_unpack_page */
+
+sf_count_t
+ogg_sync_last_page_before (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t *gp_out, sf_count_t offset, int32_t serialno)
+{      sf_count_t begin, end, original_end, chunk_size, ret ;
+       sf_count_t position = 0 ;
+       uint64_t gp = -1 ;
+       int left_link ;
+
+       /* Based on code from Xiph.org's Opusfile */
+
+       original_end = end = begin = offset ;
+       offset = -1 ;
+       chunk_size = OGG_CHUNK_SIZE ;
+       do
+       {       begin = SF_MAX (begin - chunk_size, (sf_count_t) 0) ;
+               position = ogg_sync_fseek (psf, begin, SEEK_SET) ;
+               if (position < 0)
+                       return position ;
+               left_link = 0 ;
+               while (position < end)
+               {       ret = ogg_sync_next_page (psf, &odata->opage, end - position, &position) ;
+                       if (ret <= 0)
+                               return -1 ;
+                       if (ogg_page_serialno (&odata->opage) == serialno)
+                       {       uint64_t page_gp = ogg_page_granulepos (&odata->opage) ;
+                               if (page_gp != (uint64_t) -1)
+                               {       offset = position ;
+                                       gp = page_gp ;
+                                       }
+                               }
+                       else
+                               left_link = 1 ;
+                       position += ret ;
+                       }
+
+               if ((left_link || !begin) && offset < 0)
+               {       psf->error = SFE_MALFORMED_FILE ;
+                       return -1 ;
+                       }
+
+               chunk_size = SF_MIN (2 * chunk_size, (sf_count_t) OGG_CHUNK_SIZE_MAX) ;
+               end = SF_MIN (begin + OGG_PAGE_SIZE_MAX - 1, original_end) ;
+               }
+       while (offset < 0) ;
+
+       *gp_out = gp ;
+       return offset ;
+} /* ogg_sync_last_page_before */
+
+int
+ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t target_gp, uint64_t pcm_start, uint64_t pcm_end, uint64_t *best_gp, sf_count_t begin, sf_count_t end)
+{      ogg_page page ;
+       uint64_t gp ;
+       sf_count_t d0, d1, d2 ;
+       sf_count_t best ;
+       sf_count_t best_start ;
+       sf_count_t boundary ;
+       sf_count_t next_boundary ;
+       sf_count_t page_offset = -1 ;
+       sf_count_t seek_pos = -1 ;
+       sf_count_t bisect ;
+       sf_count_t chunk_size ;
+       int buffering = SF_FALSE ;
+       int force_bisect = SF_FALSE ;
+       int ret ;
+       int has_packets ;
+
+       *best_gp = pcm_start ;
+       best = best_start = begin ;
+       boundary = end ;
+
+       ogg_stream_reset_serialno (&odata->ostream, odata->ostream.serialno) ;
+
+       /*
+       ** This code is based on op_pcm_seek_page() from Opusfile, which is in turn
+       ** based on "new search algorithm by Nicholas Vinen" from libvorbisfile.
+       */
+
+       d2 = d1 = d0 = end - begin ;
+       while (begin < end)
+       {       /*
+               ** Figure out if and where to try and seek in the file.
+               */
+               if (end - begin < OGG_CHUNK_SIZE)
+                       bisect = begin ;
+               else
+               {       /* Update the interval size history */
+                       d0 = d1 >> 1 ;
+                       d1 = d2 >> 1 ;
+                       d2 = (end - begin) >> 1 ;
+                       if (force_bisect == SF_TRUE)
+                               bisect = begin + ((end - begin) >> 1) ;
+                       else
+                       {       /* Take a decent guess. */
+                               bisect = begin + ogg_page_search_do_rescale (target_gp - pcm_start, pcm_end - pcm_start, end - begin) ;
+                               }
+                       if (bisect - OGG_CHUNK_SIZE < begin)
+                               bisect = begin ;
+                       else
+                               bisect -= OGG_CHUNK_SIZE ;
+                       force_bisect = SF_FALSE ;
+                       }
+
+               /*
+               ** Avoid an actual fseek if we can (common for final iterations.)
+               */
+               if (seek_pos != bisect)
+               {       if (buffering == SF_TRUE)
+                               ogg_stream_reset (&odata->ostream) ;
+                       buffering = SF_FALSE ;
+                       page_offset = -1 ;
+                       seek_pos = ogg_sync_fseek (psf, bisect, SEEK_SET) ;
+                       if (seek_pos < 0)
+                               return seek_pos ;
+                       }
+
+               chunk_size = OGG_CHUNK_SIZE ;
+               next_boundary = boundary ;
+
+               /*
+               ** Scan forward, figure out where we landed.
+               ** The ideal case is we see a page that ends before our target followed
+               ** by a page that ends after our target.
+               ** If we are too far before or after, breaking out will bisect what we
+               ** have found so far.
+               */
+               while (begin < end)
+               {       ret = ogg_sync_next_page (psf, &page, boundary - seek_pos, &seek_pos) ;
+                       if (ret <= 0)
+                               return ret ;
+                       page_offset = seek_pos ;
+                       if (ret == 0)
+                       {       /*
+                               ** There are no more pages in this interval from our stream
+                               ** with a granulepos less than our target.
+                               */
+                               if (bisect <= begin + 1)
+                               {       /* Scanned the whole interval, so we are done. */
+                                       end = begin ;
+                                       }
+                               else
+                               {       /*
+                                       ** Otherwise, back up one chunk. First discard any data
+                                       ** from a continued packet.
+                                       */
+                                       if (buffering)
+                                               ogg_stream_reset (&odata->ostream) ;
+                                       buffering = SF_FALSE ;
+                                       bisect = SF_MAX (bisect - chunk_size, begin) ;
+                                       seek_pos = ogg_sync_fseek (psf, bisect, SEEK_SET) ;
+                                       if (seek_pos < 0)
+                                               return seek_pos ;
+                                       /* Bump up the chunk size. */
+                                       chunk_size = SF_MIN (2 * chunk_size, (sf_count_t) OGG_CHUNK_SIZE_MAX) ;
+                                       /*
+                                       ** If we did find a page from another stream or without a
+                                       ** timestamp, don't read past it.
+                                       */
+                                       boundary = next_boundary ;
+                                       }
+                               continue ;
+                               }
+
+                       /* Found a page. Advance seek_pos past it */
+                       seek_pos += page.header_len + page.body_len ;
+                       /*
+                       ** Save the offset of the first page we found after the seek,
+                       ** regardless of the stream it came from or whether or not it has a
+                       ** timestamp.
+                       */
+                       next_boundary = SF_MIN (page_offset, next_boundary) ;
+
+                       /* If not from our stream, continue. */
+                       if (odata->ostream.serialno != ogg_page_serialno (&page))
+                               continue ;
+
+                       /*
+                       ** The Ogg spec says that a page with a granule pos of -1 must not
+                       ** contain and packets which complete, but the lack of biconditional
+                       ** wording means that /technically/ a packet which does not complete
+                       ** any packets can have a granule pos other than -1. To make matters
+                       ** worse, older versions of libogg did just that.
+                       */
+                       has_packets = ogg_page_packets (&page) > 0 ;
+                       gp = has_packets ? ogg_page_granulepos (&page) : -1 ;
+                       if (gp == (uint64_t) -1)
+                       {       if (buffering == SF_TRUE)
+                               {       if (!has_packets)
+                                               ogg_stream_pagein (&odata->ostream, &page) ;
+                                       else
+                                       {       /*
+                                               ** If packets did end on this page, but we still didn't
+                                               ** have a valid granule position (in violation of the
+                                               ** spec!), stop buffering continued packet data.
+                                               ** Otherwise we might continue past the packet we
+                                               ** actually wanted.
+                                               */
+                                               ogg_stream_reset (&odata->ostream) ;
+                                               buffering = SF_FALSE ;
+                                               }
+                                       }
+                               continue ;
+                               }
+
+                       if (gp < target_gp)
+                       {       /*
+                               ** We found a page that ends before our target. Advance to
+                               ** the raw offset of the next page.
+                               */
+                               begin = seek_pos ;
+                               if (pcm_start > gp || pcm_end < gp)
+                                       break ;
+                               /* Save the byte offset of after this page. */
+                               best = best_start = begin ;
+                               if (buffering)
+                                       ogg_stream_reset (&odata->ostream) ;
+                               /* Check to see if the last packet continues. */
+                               if (page.header [27 + page.header [26] - 1] == 255)
+                               {       ogg_page_search_continued_data (odata, &page) ;
+                                       /*
+                                       ** If we have a continued packet, remember the offset of
+                                       ** this page's start, so that if we do wind up having to
+                                       ** seek back here later, we can prime the stream with the
+                                       ** continued packet data. With no continued packet, we
+                                       ** remember the end of the page.
+                                       */
+                                       best_start = page_offset ;
+                                       } ;
+                               /*
+                               ** Then force buffering on, so that if a packet starts (but
+                               ** does not end) on the next page, we still avoid the extra
+                               ** seek back.
+                               */
+                               buffering = SF_TRUE ;
+                               *best_gp = pcm_start = gp ;
+                               if (target_gp - gp > 48000)
+                               {       /* Out by over a second. Try another bisection. */
+                                       break ;
+                                       }
+                               /* Otherwise, keep scanning forward (do NOT use begin+1). */
+                               bisect = begin ;
+                               }
+                       else
+                       {       /*
+                               ** Found a page that ends after our target. If we had just
+                               ** scanned the whole interval before we found it, we're good.
+                               */
+                               if (bisect <= begin + 1)
+                                       end = begin ;
+                               else
+                               {       end = bisect ;
+                                       /*
+                                       ** In later iterations, don't read past the first page we
+                                       ** found.
+                                       */
+                                       boundary = next_boundary ;
+                                       /*
+                                       ** If we're not making much progress shrinking the interval
+                                       ** size, start forcing straight bisection to limit the
+                                       ** worst case.
+                                       */
+                                       force_bisect = end - begin > d0 * 2 ? SF_TRUE : SF_FALSE ;
+                                       /*
+                                       ** Don't let pcm_end get out of range! That could happen
+                                       ** with an invalid timestamp.
+                                       */
+                                       if (pcm_end > gp && pcm_start <= gp)
+                                               pcm_end = gp ;
+                                       }
+                               break ;
+                               }
+                       }
+               }
+
+       /*
+       ** If we are buffering, the page we want is currently buffered in the
+       ** Ogg stream structure, or in the Ogg page which has not been submitted.
+       ** If not, we need to seek back and load it again.
+       */
+       if (buffering == SF_FALSE)
+       {       if (best_start != page_offset)
+               {       page_offset = -1 ;
+                       seek_pos = ogg_sync_fseek (psf, best_start, SEEK_SET) ;
+                       if (seek_pos < 0)
+                               return seek_pos ;
+                       }
+               if (best_start < best)
+               {       if (page_offset < 0)
+                       {       ret = ogg_sync_next_page (psf, &page, -1, &seek_pos) ;
+                               if (seek_pos != best_start)
+                                       return -1 ;
+                               }
+                       ogg_page_search_continued_data (odata, &page) ;
+                       page_offset = -1 ;
+                       }
+               } ;
+
+       if (page_offset >= 0)
+               ogg_stream_pagein (&odata->ostream, &page) ;
+
+       return 0 ;
+} /* ogg_stream_seek_page_search */
 
 int
 ogg_open (SF_PRIVATE *psf)
@@ -60,11 +716,6 @@ ogg_open (SF_PRIVATE *psf)
                if ((error = ogg_stream_classify (psf, odata)) != 0)
                        return error ;
 
-       /* Reset everything to an initial state. */
-       ogg_sync_clear (&odata->osync) ;
-       ogg_stream_clear (&odata->ostream) ;
-       psf_fseek (psf, pos, SEEK_SET) ;
-
        if (SF_ENDIAN (psf->sf.format) != 0)
                return SFE_BAD_ENDIAN ;
 
@@ -73,11 +724,18 @@ ogg_open (SF_PRIVATE *psf)
                        return ogg_vorbis_open (psf) ;
 
                case SF_FORMAT_OGGFLAC :
+                       /* Reset everything to an initial state. */
+                       ogg_sync_clear (&odata->osync) ;
+                       ogg_stream_clear (&odata->ostream) ;
+                       psf_fseek (psf, pos, SEEK_SET) ;
                        free (psf->container_data) ;
                        psf->container_data = NULL ;
                        psf->container_close = NULL ;
                        return flac_open (psf) ;
 
+               case SF_FORMAT_OGG | SF_FORMAT_OPUS :
+                       return ogg_opus_open (psf) ;
+
 #if ENABLE_EXPERIMENTAL_CODE
                case SF_FORMAT_OGG | SF_FORMAT_SPEEX :
                        return ogg_speex_open (psf) ;
@@ -95,6 +753,9 @@ ogg_open (SF_PRIVATE *psf)
        return SFE_INTERNAL ;
 } /* ogg_open */
 
+/*==============================================================================
+** Private functions.
+*/
 
 static int
 ogg_close (SF_PRIVATE *psf)
@@ -108,66 +769,15 @@ ogg_close (SF_PRIVATE *psf)
 
 static int
 ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
-{      char *buffer ;
-       int     bytes, nn ;
+{      int error ;
 
        /* Call this here so it only gets called once, so no memory is leaked. */
        ogg_sync_init (&odata->osync) ;
+       ogg_stream_init (&odata->ostream, 0) ;
 
-       odata->eos = 0 ;
-
-       /* Weird stuff happens if these aren't called. */
-       ogg_stream_reset (&odata->ostream) ;
-       ogg_sync_reset (&odata->osync) ;
-
-       /*
-       **      Grab some data at the head of the stream.  We want the first page
-       **      (which is guaranteed to be small and only contain the Vorbis
-       **      stream initial header) We need the first page to get the stream
-       **      serialno.
-       */
-
-       /* Expose the buffer */
-       buffer = ogg_sync_buffer (&odata->osync, 4096L) ;
-
-       /* Grab the part of the header that has already been read. */
-       memcpy (buffer, psf->header.ptr, psf->header.indx) ;
-       bytes = psf->header.indx ;
-
-       /* Submit a 4k block to libvorbis' Ogg layer */
-       bytes += psf_fread (buffer + psf->header.indx, 1, 4096 - psf->header.indx, psf) ;
-       ogg_sync_wrote (&odata->osync, bytes) ;
-
-       /* Get the first page. */
-       if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
-       {
-               /* Have we simply run out of data?  If so, we're done. */
-               if (bytes < 4096)
-                       return 0 ;
-
-               /* Error case.  Must not be Vorbis data */
-               psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
-               return SFE_MALFORMED_FILE ;
-               } ;
-
-       /*
-       **      Get the serial number and set up the rest of decode.
-       **      Serialno first ; use it to set up a logical stream.
-       */
-       ogg_stream_clear (&odata->ostream) ;
-       ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
-
-       if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
-       {       /* Error ; stream version mismatch perhaps. */
-               psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
-               return SFE_MALFORMED_FILE ;
-               } ;
-
-       if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
-       {       /* No page? must not be vorbis. */
-               psf_log_printf (psf, "Error reading initial header packet.\n") ;
-               return SFE_MALFORMED_FILE ;
-               } ;
+       /* Load the first page in the physical bitstream. */
+       if ((error = ogg_read_first_page (psf, odata)) != 0)
+               return error ;
 
        odata->codec = ogg_page_classify (psf, &odata->opage) ;
 
@@ -185,6 +795,10 @@ ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
                        psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
                        return 0 ;
 
+               case OGG_OPUS :
+                       psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
+                       return 0 ;
+
                case OGG_PCM :
                        psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ;
                        return SFE_UNIMPLEMENTED ;
@@ -211,6 +825,7 @@ static struct
        {       "PCM     ",             "PCM",          8, OGG_PCM },
        {       "Speex",                "Speex",        5, OGG_SPEEX },
        {       "\001vorbis",   "Vorbis",       7, OGG_VORBIS },
+       {       "OpusHead",             "Opus",         8, OGG_OPUS },
 } ;
 
 static int
@@ -241,6 +856,47 @@ ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og)
        return 0 ;
 } /* ogg_page_classify */
 
+/*
+** Scale x from the range [0, from] to the range [0, to]
+*/
+static uint64_t
+ogg_page_search_do_rescale (uint64_t x, uint64_t from, uint64_t to)
+{      uint64_t frac ;
+       uint64_t ret ;
+       int i ;
+
+       /* I should have paid more attention in CSc 349A: Numerical Analysis */
+       if (x >= from)
+               return to ;
+       if (x == 0)
+               return 0 ;
+       frac = 0 ;
+       for (i = 0 ; i < 63 ; i++)
+       {       frac <<= 1 ;
+               if (x >= from >> 1)
+               {       x -= from - x ;
+                       frac |= 1 ;
+                       }
+               else
+                       x <<= 1 ;
+               }
+       ret = 0 ;
+       for (i = 0 ; i < 63 ; i++)
+       {       if (frac & 1)
+                       ret = (ret & to & 1) + (ret >> 1) + (to >> 1) ;
+               else
+                       ret >>= 1 ;
+               frac >>= 1 ;
+               }
+       return ret ;
+} /* ogg_page_search_do_rescale */
+
+static void
+ogg_page_search_continued_data (OGG_PRIVATE *odata, ogg_page *page)
+{      ogg_stream_pagein (&odata->ostream, page) ;
+       while (ogg_stream_packetout (&odata->ostream, &odata->opacket)) ;
+} /* ogg_page_search_continued_data */
+
 #else /* HAVE_EXTERNAL_XIPH_LIBS */
 
 int
index 88544bb..5c837a8 100644 (file)
--- a/src/ogg.h
+++ b/src/ogg.h
@@ -1,5 +1,6 @@
 /*
 ** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2018 Arthur Taylor <art@ified.ca>
 **
 ** This program is free software ; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -17,6 +18,7 @@
 */
 
 #ifndef SF_SRC_OGG_H
+#define SF_SRC_OGG_H
 
 enum
 {      OGG_ANNODEX = 300,
@@ -26,6 +28,7 @@ enum
        OGG_PCM,
        OGG_SPEEX,
        OGG_VORBIS,
+       OGG_OPUS,
 } ;
 
 typedef struct
@@ -33,10 +36,18 @@ typedef struct
        ogg_sync_state osync ;
        /* Take physical pages, weld into a logical stream of packets */
        ogg_stream_state ostream ;
-       /* One Ogg bitstream page.  Vorbis packets are inside */
+       /* One Ogg bitstream page. Codec packets are inside */
        ogg_page opage ;
        /* One raw packet of data for decode */
        ogg_packet opacket ;
+
+       /* Unpacked packets. 255 is max there can ever be in one page. */
+       ogg_packet pkt [255] ;
+       /* How many packets */
+       int pkt_len ;
+       /* Current packet */
+       int pkt_indx ;
+
        int eos ;
        int codec ;
 } OGG_PRIVATE ;
@@ -47,6 +58,77 @@ typedef struct
                                                                ((buf [base + 1] << 8) & 0xff00) | \
                                                                (buf [base] & 0xff))
 
+int    ogg_read_first_page     (SF_PRIVATE *, OGG_PRIVATE *) ;
 
+/*
+** Write the whole Ogg page out. Convenience function as the ogg_page struct
+** splits header and body data into separate buffers.
+*/
+int    ogg_write_page  (SF_PRIVATE *, ogg_page *) ;
+
+/*
+** Wrapper around psf_ftell() that returns the current offset in the file after
+** the most recent page that has been returned by ogg_sync_pageout().
+*/
+sf_count_t ogg_sync_ftell (SF_PRIVATE *) ;
+
+/*
+** Wrapper around psf_fseek() that on success resets the ogg_sync_state struct
+** so that it doesn't get corrupted.
+*/
+sf_count_t ogg_sync_fseek (SF_PRIVATE *, sf_count_t offset, int whence) ;
+
+/*
+** Get the next page from the physical bitstream, reading in data as necessary.
+** Pays no attention to Ogg BOS/EOS markers or stream serial numbers.
+** The page is buffered in the ogg_sync_state struct, (replacing any other
+** buffered there) and also returned in *og. readmax sets a boundary for how
+** many bytes more may be read from the file, use already buffered only, or
+** unlimited reading in the case of a positive, zero or negative argument
+** respectively. If a pointer to a sf_count_t is passed in offset, then it will
+** be incremented by how many bytes were skipped to find the next page header.
+** (Useful for seeking, normally zero.) Returns the page size in bytes on
+** success, 0 on out-of-data (be it end of file or readmax reached) and -1 on
+** error with psf->error set appropriately.
+*/
+int    ogg_sync_next_page (SF_PRIVATE * psf, ogg_page *og, sf_count_t readmax, sf_count_t *offset) ;
+
+/*
+** Load the last page of a stream before the provided file offset. Searches the
+** physical bitstream, and selects a page of the passed serialno. The page
+** found is loaded in the sync buffer and exposed in odata->opage, and not
+** loaded into the ogg_stream_state. If found, the granulepos is returned in
+** *gp_out. Returns the file offset *before* the last page on success, or -1 on
+** error, setting psf->error as appropriate.
+*/
+sf_count_t ogg_sync_last_page_before (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t *gp_out, sf_count_t offset, int32_t serialno) ;
+
+/*
+** Load the next page from the virtual bitstream, reading data as necessary.
+** Reads in pages from the physical bitstream, skipping pages until one of the
+** virtual bitstream of interest is found, and then feeds it into the
+** ogg_stream_state of odata->ostream, where it is buffered. Heeds EOS markers.
+** Returns 1 on success, 0 on end of stream, and -1 on fatal error.
+*/
+int ogg_stream_next_page (SF_PRIVATE * psf, OGG_PRIVATE *odata) ;
+
+/*
+** Loads the next page using ogg_stream_next_page() and unpacks all packets
+** into the array odata->pkt, updating odata->pkt_len and setting
+** odata->pkt_indx to 0. Returns 1 if okay, 2 if okay but a hole was found
+** in the bitstream, 0 if on end of stream, and -1 on fatal error.
+*/
+int ogg_stream_unpack_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) ;
+
+/*
+** Seek within the Ogg virtual bitstream for a page containing target_gp.
+** Preforms a bisection search. If not found exactly, the best result is
+** returned in *best_gp. Found page is loaded into the virtual bitstream,
+** ready for unpacking. Arguments pcm_start and pcm_end are the highest and
+** lowest granule positions of the file. begin and end are the file offsets.
+*/
+int ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata,
+                                                               uint64_t target_gp, uint64_t pcm_start, uint64_t pcm_end,
+                                                               uint64_t *best_gp, sf_count_t begin, sf_count_t end) ;
 
 #endif /* SF_SRC_OGG_H */
index f5769e2..9be6e91 100644 (file)
@@ -1,5 +1,6 @@
 /*
-** Copyright (C) 2013-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2013-2020 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2018 Arthur Taylor <art@ified.ca>
 **
 ** This program is free software ; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+/*
+** This file contains code based on OpusFile and Opus-Tools, both by
+** Xiph.Org. COPYING from each is identical and is as follows:
+**
+** Copyright (c) 1994-2013 Xiph.Org Foundation and contributors
+**
+** 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 name of the Xiph.Org Foundation nor the names of its
+** 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 FOUNDATION
+** 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.
+*/
+
+/*
+** TODO:
+**  - Channel mapping modification / reporting
+**      - connect psf->channel_map and Opus channel mapping somehow?
+**  - Gain parameters and their mappings
+*/
+
+/*
+** Opus Sample, Frame, and Samples/Channel Terminology
+**
+** libsndfile refers to one PCM value as a 'sample,' and a group of samples of
+** the same sample time, one for each channel, as a 'frame.' This differs from
+** Opus, which has no corresponding name for sample, and refers to a group of
+** PCM values, one per channel (aka libsndfile frames) as 'samples.'
+** Further, Opus has an object called a 'frame' that is made up of multiple
+** Opus-samples.
+** All this means that one has to be careful with what is meant by each term.
+** In an attempt to avoid ambiguity, this file adopts the following terms:
+**  - Samples shall refer to discrete PCM values, regardless of any channel
+**     considerations. This is the same as what libsndfile calls samples.
+**  - Samples/channel shall refer to groups of samples, one for each channel.
+**     This is what Opus calles samples, and what libsndfile calles frames. It
+**     has the advantage that its name is also the formula to calculate it.
+**
+**
+** Opus vs OggOpus
+**
+** In this file a distinction is made between Opus and OggOpus. Opus refers to
+** the codec alone, support for which is by libopus. OggOpus refers to an Opus
+** payload encapsulated in an Ogg stream. This is also know as an "Opus file."
+** The OggOpus spec includes information on header and granule position
+** interpretation, which is outside of the scope of the Opus spec. As such, an
+** attempt here is made to refer to either Opus or OggOpus depending on which
+** spec is being referenced. See https://wiki.xiph.org/OggOpus
+**
+**
+** Opus Sample Rates
+**
+** Opus only supports a fixed number of sample rates: 48kHz, 24kHz, 16kHz,
+** 12kHz, 8kHz. Audio may be decoded or encoded at any of these rates,
+** independent of the rate it was encoded at or to be decoded at respectively.
+** Other sample rates must be converted to one of these rates.
+**
+** As 44.1kHz (CD sample rate) and 22.5kHz are popular sample rates, and to
+** support any other sample rate there may be, the Opus header includes a field
+** to save the input (original) sample rate before converting it to a supported
+** one. Implementations are recommended by the Opus spec to do a sample rate
+** conversion at encode, but decode at 48kHz if outputting to hardware, or do
+** the reverse sample rate conversion if outputting to file.
+**
+** Heretofore libsndfile does not contain a sample rate converter, so doing the
+** sample rate conversion is not supported. Instead audio must be provided by
+** the user at a supported rate. However, the input sample rate field can be
+** set and retrieved by the user using sf_command(). At decode we choose to
+** decode at the lowest valid rate that is greater than or equal to the input
+** sample rate.
+**
+**
+** OggOpus Granule Positions
+**
+** Ogg streams include a strictly increasing granule position value. The
+** interpretation of this value is dependent on the payload type. For Opus
+** streams the granule position is the count of samples in the stream when
+** encoding/decoding at 48kHz. Note that the actual position of the output
+** sample relative to the granule position is offset by the preskip amount.
+** That is, if a packet ends with a granule position of x, the last sample
+** output when decoding is actually sample (x - preskip).
+**
+** Further, to allow for clipping off of the front of a stream without
+** rewriting all following granule positions, an Opus stream granule position
+** may be offset by a constant amount. This amount is evident by comparing the
+** granule position of the first page of an Opus stream on which an audio
+** packet completes is greater than the sum of the samples of all audio
+** packets completed on the page. Only the first such page is allows to have an
+** 'excessive' granule position, and only if it is not also the last page of
+** the stream (e_o_s bit is not set.)
+**
+** The granule position is an unsigned 64-bit integer, with the special value
+** of UINT64_MAX/-1 being treated as invalid. However, as not all platforms
+** support unsigned 64-bit integers, libOgg uses signed 64-bit integers for the
+** granule position.
+**
+** Remembering that signed integer overflow/underflow is explicitly undefined
+** in C, and as we already assume support for unsigned 64-bit integers, the
+** easiest way to deal with this problem is to modify granule positions as
+** unsigned integers.
+*/
+
 
 #include "sfconfig.h"
 
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "sndfile.h"
 #include "sfendian.h"
 #include "common.h"
 
-#if (ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_XIPH_LIBS)
+#if HAVE_EXTERNAL_XIPH_LIBS
 
 #include <ogg/ogg.h>
+#include <opus/opus.h>
+#include <opus/opus_multistream.h>
 
 #include "ogg.h"
+#include "ogg_vcomment.h"
+
+#define OGG_OPUS_COMMENT_PAD (512) /* Same as oggenc default */
+
+/*
+** Opus packets can be any multiple of 2.5ms (at 48kHz). We use the recommended
+** default for non-realtime of 20ms. While longer packets reduce the overhead
+** data somewhat, it also decreases the quality.
+*/
+#define OGG_OPUS_ENCODE_PACKET_LEN(samplerate) ((20 * (samplerate)) / 1000)
+
+/*
+** How long does it take for a decoder to converge (avoiding flush on seek.
+*/
+#define OGG_OPUS_PREROLL (80 * 48) /* 80 milliseconds */
 
 typedef struct
-{      int32_t serialno ;
+{      uint8_t version ;
+
+       /* Number of channels, 1...255 */
+       uint8_t channels ;
+
+       /* Encoder latency, the amount to skip before valid data comes out. */
+       uint16_t preskip ;
+
+       /* The sample rate of a the encoded source, as it may have been converted. */
+       int32_t input_samplerate ;
+
+       /* 'baked-in' gain to apply, dB S7.8 format. Should be zero when possible. */
+       int16_t gain ;
+
+       /* Channel mapping type. See OggOpus spec */
+       uint8_t channel_mapping ;
+
+       /* The rest is only used if channel_mapping != 0 */
+       /* How many streams are there? */
+       uint8_t nb_streams ;
 
+       /* How man of those streams are coupled? (aka stereo) */
+       uint8_t nb_coupled ;
 
-       void * state ;
+       /* Mapping of opus streams to output channels */
+       uint8_t stream_map [255] ;
+} OpusHeader ;
+
+typedef struct
+{      uint32_t serialno ;
+       OpusHeader header ;
+
+       /* Granule position before the current packet */
+       uint64_t pkt_pos ;
+
+       /* Granule position at the end of the current page (encode: last completed) */
+       uint64_t pg_pos ;
+
+       /* integer coefficient of (current sample rate) / 48000Hz */
+       int sr_factor ;
+
+       /* Current position in buffer expressed as samples/channel */
+       int loc ;
+
+       /* Current data fill (decode) or target (encode) of buffer expressed in samples/channel */
+       int len ;
+
+       /* Size of the buffer storage, in sizeof (float) * channels */
+       int buffersize ;
+
+       /* Samples, either decoded from a packet, or assembling for encode. */
+       float *buffer ;
+
+       union {
+               /* decode only members */
+               struct {
+                       OpusMSDecoder *state ;
+                       uint64_t gp_start ;
+                       uint64_t gp_end ;
+                       sf_count_t last_offset ;
+               } decode ;
+
+               /* encode only members */
+               struct {
+                       OpusMSEncoder *state ;
+
+                       /* How many Ogg page segments are in Ogg page currently being assembled. */
+                       int last_segments ;
+
+                       int bitrate ;
+                       unsigned long latency ;
+
+                       /* Least significant bit of the source (aka bitwidth) */
+                       int lsb ;
+                       int lsb_last ;
+               } encode ;
+       } u ;
 } OPUS_PRIVATE ;
 
-static int     ogg_opus_read_header (SF_PRIVATE * psf) ;
-static int     ogg_opus_close (SF_PRIVATE *psf) ;
+/*-----------------------------------------------------------------------------------------------
+** Private function prototypes.
+*/
+
+static int                     ogg_opus_close (SF_PRIVATE *psf) ;
+static void                    opus_print_header (SF_PRIVATE *psf, OpusHeader *h) ;
+static int                     opus_read_header_packet (SF_PRIVATE *psf, OpusHeader *h, ogg_packet *opacket) ;
+static int                     ogg_opus_read_header (SF_PRIVATE * psf) ;
+static int                     ogg_opus_setup_decoder (SF_PRIVATE *psf, int input_samplerate) ;
+
+static int                     ogg_opus_setup_encoder (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus) ;
+static int                     ogg_opus_write_header (SF_PRIVATE * psf, int calc_length) ;
+static void                    ogg_opus_flush (SF_PRIVATE *psf) ;
+static int                     ogg_opus_unpack_next_page (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus) ;
+static int                     ogg_opus_calculate_page_duration (OGG_PRIVATE *odata) ;
+static int                     ogg_opus_read_refill (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus) ;
+static int                     ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus) ;
+
+static sf_count_t      ogg_opus_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
+static sf_count_t      ogg_opus_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
+static sf_count_t      ogg_opus_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
+static sf_count_t      ogg_opus_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
+
+static sf_count_t      ogg_opus_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
+static sf_count_t      ogg_opus_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
+static sf_count_t      ogg_opus_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
+static sf_count_t      ogg_opus_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
+
+static sf_count_t      ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
+static sf_count_t      ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset) ;
+static sf_count_t      ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp) ;
+static int                     ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp) ;
+
+static int                     ogg_opus_analyze_file (SF_PRIVATE *psf) ;
+static int                     ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
+static int                     ogg_opus_byterate (SF_PRIVATE *psf) ;
+
+/*-----------------------------------------------------------------------------------------------
+*/
+
+static vorbiscomment_ident opustags_ident =    { "OpusTags", 8 } ;
+
+/*-----------------------------------------------------------------------------------------------
+** Exported functions.
+*/
 
 int
 ogg_opus_open (SF_PRIVATE *psf)
@@ -58,6 +316,7 @@ ogg_opus_open (SF_PRIVATE *psf)
 
        if (odata == NULL)
        {       psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
+               free (oopus) ;
                return SFE_INTERNAL ;
                } ;
 
@@ -68,76 +327,1446 @@ ogg_opus_open (SF_PRIVATE *psf)
        if (psf->file.mode == SFM_RDWR)
                return SFE_BAD_MODE_RW ;
 
-       if (psf->file.mode == SFM_READ)
-       {       /* Call this here so it only gets called once, so no memory is leaked. */
-               ogg_sync_init (&odata->osync) ;
+       psf_log_printf (psf, "Opus library version: %s\n", opus_get_version_string ()) ;
 
-               if ((error = ogg_opus_read_header (psf)))
+       psf->codec_close = ogg_opus_close ;
+       if (psf->file.mode == SFM_READ)
+       {       if ((error = ogg_opus_read_header (psf)))
+                       return error ;
+               if ((error = ogg_opus_analyze_file (psf)))
                        return error ;
 
-#if 0
                psf->read_short         = ogg_opus_read_s ;
                psf->read_int           = ogg_opus_read_i ;
                psf->read_float         = ogg_opus_read_f ;
                psf->read_double        = ogg_opus_read_d ;
-               psf->sf.frames          = ogg_opus_length (psf) ;
-#endif
                } ;
 
-       psf->codec_close = ogg_opus_close ;
-
        if (psf->file.mode == SFM_WRITE)
-       {
-#if 0
-               /* Set the default oopus quality here. */
-               vdata->quality = 0.4 ;
+       {       if ((error = ogg_opus_setup_encoder (psf, odata, oopus)))
+                       return error ;
 
                psf->write_header       = ogg_opus_write_header ;
                psf->write_short        = ogg_opus_write_s ;
                psf->write_int          = ogg_opus_write_i ;
                psf->write_float        = ogg_opus_write_f ;
                psf->write_double       = ogg_opus_write_d ;
-#endif
 
                psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
                psf->strings.flags = SF_STR_ALLOW_START ;
+               psf->datalength = 0 ;
+               psf->dataoffset = 0 ; /* will be updated */
                } ;
 
-       psf->bytewidth = 1 ;
-       psf->blockwidth = psf->bytewidth * psf->sf.channels ;
-
-#if 0
        psf->seek = ogg_opus_seek ;
        psf->command = ogg_opus_command ;
-#endif
-
-       /* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
-       psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
-       psf->sf.sections = 1 ;
-
-       psf->datalength = 1 ;
-       psf->dataoffset = 0 ;
-       /* End FIXME. */
+       psf->byterate = ogg_opus_byterate ;
+       psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ;
 
        return error ;
 } /* ogg_opus_open */
 
+/*==============================================================================
+** Private functions.
+*/
+
 static int
-ogg_opus_read_header (SF_PRIVATE * UNUSED (psf))
-{
+ogg_opus_close (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+
+       if (!oopus)
+               return 0 ;
+
+       if (psf->file.mode == SFM_WRITE)
+       {       if (psf->have_written)
+                       ogg_opus_flush (psf) ;
+               else {
+                       /* Write a header... it is expected. */
+                       ogg_opus_write_header (psf, 0) ;
+                       } ;
+               ogg_packet_clear (&odata->opacket) ;
+               if (oopus->u.encode.state)
+               {       opus_multistream_encoder_destroy (oopus->u.encode.state) ;
+                       oopus->u.encode.state = NULL ;
+                       } ;
+               }
+       else if (psf->file.mode == SFM_READ)
+       {       if (oopus->u.decode.state)
+               {       opus_multistream_decoder_destroy (oopus->u.decode.state) ;
+                       oopus->u.decode.state = NULL ;
+                       } ;
+               } ;
+
+       psf->codec_data = NULL ;
+       if (oopus->buffer)
+               free (oopus->buffer) ;
+       free (oopus) ;
+
+       return 0 ;
+} /* ogg_opus_close */
+
+static void
+opus_print_header (SF_PRIVATE *psf, OpusHeader *h)
+{      psf_log_printf (psf, "Opus Header Metadata\n") ;
+       psf_log_printf (psf, "  OggOpus version  : %d\n", h->version) ;
+       psf_log_printf (psf, "  Channels                 : %d\n", h->channels) ;
+       psf_log_printf (psf, "  Preskip           : %d samples @48kHz\n", h->preskip) ;
+       psf_log_printf (psf, "  Input Samplerate : %d Hz\n", h->input_samplerate) ;
+       psf_log_printf (psf, "  Gain                     : %d.%d\n", arith_shift_right (h->gain & 0xF0, 8), h->gain & 0x0F) ;
+       psf_log_printf (psf, "  Channel Mapping  : ") ;
+       switch (h->channel_mapping)
+       {       case 0 :        psf_log_printf (psf, "0 (mono or stereo)\n") ; break ;
+               case 1 :        psf_log_printf (psf, "1 (surround, AC3 channel order)\n") ; break ;
+               case 255 :      psf_log_printf (psf, "255 (no channel order)\n") ; break ;
+               default :       psf_log_printf (psf, "%d (unknown or unsupported)\n", h->channel_mapping) ; break ;
+               } ;
+
+       if (h->channel_mapping > 0)
+       {       int i ;
+               psf_log_printf (psf, "   streams total   : %d\n", h->nb_streams) ;
+               psf_log_printf (psf, "   streams coupled : %d\n", h->nb_coupled) ;
+               psf_log_printf (psf, "  stream mapping : [") ;
+               for (i = 0 ; i < h->channels - 1 ; i++)
+                       psf_log_printf (psf, "%d,", h->stream_map [i]) ;
+               psf_log_printf (psf, "%d]\n", h->stream_map [i]) ;
+               } ;
+} /* opus_print_header */
+
+static int
+opus_read_header_packet (SF_PRIVATE *psf, OpusHeader *h, ogg_packet *opacket)
+{      int count, i ;
+
+       /*
+       ** Opus headers are 19 bytes, in the case of type 0 channel mapping,
+       ** or 19 + 2 + (1 * channel count) bytes for other channel mappings, to a
+       ** maximum of 276 (255 channels).
+       */
+
+       if (opacket->bytes < 19 || opacket->bytes > 276)
+               return SFE_MALFORMED_FILE ;
+
+       if (memcmp (opacket->packet, "OpusHead", 8) != 0)
+               return SFE_MALFORMED_FILE ;
+
+       /*
+       ** Copy the header page into the binheader so we can use binheader
+       ** functions to safely unpack it.
+       */
+       count = psf_binheader_writef (psf, "ob", BHWo (0), BHWv (opacket->packet), BHWz (opacket->bytes)) ;
+       psf->header.end = count ;
+
+       count = psf_binheader_readf (psf, "ep1", 8, &h->version) ;
+       if (! (h->version == 1 || h->version == 0))
+       {       psf_log_printf (psf, "Opus : Unknown / unsupported embedding scheme version: %d.\n", h->version) ;
+               return SFE_UNIMPLEMENTED ;
+               } ;
+
+       count += psf_binheader_readf (psf, "e12421", &h->channels, &h->preskip,
+               &h->input_samplerate, &h->gain, &h->channel_mapping) ;
+
+       if (h->channel_mapping == 0)
+       {       if (h->channels > 2)
+                       return SFE_MALFORMED_FILE ;
+
+               /*
+               ** Setup the stream mapping, so we can use the multistream decoder,
+               ** rather than have to deal with two decoder pointer types
+               */
+               h->nb_streams = 1 ;
+               h->nb_coupled = h->channels - 1 ;
+               h->stream_map [0] = 0 ;
+               h->stream_map [1] = 1 ;
+               }
+       else
+       {       if (opacket->bytes < 19 + 2 + h->channels)
+                       return SFE_MALFORMED_FILE ;
+
+               if (h->channel_mapping == 1 && h->channels > 8)
+                       return SFE_MALFORMED_FILE ;
+
+               count += psf_binheader_readf (psf, "11", &h->nb_streams, &h->nb_coupled) ;
+
+               if (h->nb_streams < 1 ||
+                       h->nb_coupled > h->nb_streams ||
+                       h->nb_coupled + h->nb_streams > 255)
+                       return SFE_MALFORMED_FILE ;
+
+               for (i = 0 ; i < h->channels ; i++)
+               {       count += psf_binheader_readf (psf, "1", &(h->stream_map [i])) ;
+                       if (h->stream_map [i] > h->nb_streams + h->nb_coupled && h->stream_map [i] != 255)
+                               return SFE_MALFORMED_FILE ;
+                       } ;
+               } ;
+
+       if (count != opacket->bytes)
+       {       /* OggOpus spec mandates that this is a hard error. */
+               psf_log_printf (psf, "Opus : Error, extra data in Ogg Opus header.\n") ;
+               return SFE_MALFORMED_FILE ;
+               } ;
+
+       opus_print_header (psf, h) ;
+
        return 0 ;
+} /* ogg_opus_read_header_packet */
+
+static int
+ogg_opus_read_header (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       int error ;
+
+       /*
+       ** First page is already loaded by the ogg container code when it
+       ** classified the stream, no need to re-load it now.
+       */
+
+       if (ogg_page_packets (&odata->opage) != 1 || !ogg_page_bos (&odata->opage))
+               return SFE_MALFORMED_FILE ;
+
+       oopus->serialno = ogg_page_serialno (&odata->opage) ;
+       if ((error = opus_read_header_packet (psf, &oopus->header, &odata->opacket)))
+               return error ;
+
+       /*
+       ** The comment header MUST be next. It is one packet, that packet MUST begin
+       ** on the second page of the stream, but it MAY span multiple pages.
+       */
+
+       while (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
+       {       if (ogg_stream_next_page (psf, odata) != 1)
+               {       /* out of data... technically that's malformed. */
+                       return psf->error ? psf->error : SFE_MALFORMED_FILE ;
+                       } ;
+               } ;
+
+       if ((error = vorbiscomment_read_tags (psf, &odata->opacket, &opustags_ident)))
+               return error ;
+
+       return ogg_opus_setup_decoder (psf, oopus->header.input_samplerate) ;
 } /* ogg_opus_read_header */
 
 static int
-ogg_opus_close (SF_PRIVATE * UNUSED (psf))
-{
+ogg_opus_setup_decoder (SF_PRIVATE *psf, int input_samplerate)
+{      OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       OpusMSDecoder *decoder ;
+       int sr_factor ;
+       int error ;
+
+       /*
+       ** Decide what sample rate to decode at. We choose the lowest valid rate
+       ** that is greater or equal to the original rate.
+       **
+       ** Opus documentation recommends always decoding at 48000Hz if the file is
+       ** being decoded for playback, since most hardware will resample it back to
+       ** 48000Hz anyways. We don't know if that's true, maybe the user is
+       ** decoding for editing or transcoding purposes.
+       */
+       if (input_samplerate > 24000)
+               sr_factor = 1 ;
+       else if (input_samplerate > 16000)
+               sr_factor = 2 ;
+       else if (input_samplerate > 12000)
+               sr_factor = 3 ;
+       else if (input_samplerate > 8000)
+               sr_factor = 4 ;
+       else
+               sr_factor = 6 ;
+
+       decoder = opus_multistream_decoder_create (
+               48000 / sr_factor,
+               oopus->header.channels,
+               oopus->header.nb_streams,
+               oopus->header.nb_coupled,
+               oopus->header.stream_map,
+               &error) ;
+
+       if (error != OPUS_OK)
+       {       psf_log_printf (psf, "Opus : Failed to create multistream decoder: %s\n",
+                       opus_strerror (error)) ;
+               return SFE_INTERNAL ;
+               }
 
+       /*
+       ** Replace the decoder, if one was already initialized (see
+       ** SFC_GET_ORIGINAL_SAMPLERATE)
+       */
+       if (oopus->u.decode.state)
+               opus_multistream_decoder_destroy (oopus->u.decode.state) ;
+       oopus->u.decode.state = decoder ;
+
+       oopus->sr_factor = sr_factor ;
+       psf->sf.samplerate = 48000 / sr_factor ;
+       psf->sf.channels = oopus->header.channels ;
+       oopus->loc = oopus->len = 0 ;
+
+       /*
+       ** The Opus decoder can do our gain for us. The OggOpus header contains a
+       ** gain field. This field, unlike various gain-related tags, is intended to
+       ** be a perminent baked-in gain applied before any user-configurable gain
+       ** (eg replay-gain.) This is so the gain of track can be set without having
+       ** to re-encode.
+       **
+       ** Both the header.gain field and the parameter are in the Q7.8 format.
+       **
+       ** TODO: Make this configurable? Include other gain sources too?
+       */
+       opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_SET_GAIN (oopus->header.gain)) ;
+
+       /*
+       ** Opus packets can vary in length, with the legal values being 2.5, 5, 10,
+       ** 20, 40 or 60ms. The recommended default for non-realtime is 20ms. As
+       ** such, allocate a buffer of that size now, we'll realloc later if a
+       ** larger one is needed.
+       **
+       ** buffersize is expressed in samples/channel, as that is what opus_decode
+       ** expects.
+       */
+       if (oopus->buffer)
+       {       free (oopus->buffer) ;
+               oopus->buffer = NULL ;
+               } ;
+       oopus->buffersize = 20 * psf->sf.samplerate / 1000 ;
+       oopus->buffer = malloc (sizeof (float) * psf->sf.channels * oopus->buffersize) ;
+       if (oopus->buffer == NULL)
+               return SFE_MALLOC_FAILED ;
 
        return 0 ;
-} /* ogg_opus_close */
+} /* ogg_opus_setup_decoder */
+
+static int
+ogg_opus_setup_encoder (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
+{      int error ;
+       int lookahead ;
+       int nb_streams ;
+       int nb_coupled ;
+
+       /* default page latency value (1000ms) */
+       oopus->u.encode.latency = 1000 * 48 ;
+
+       switch (psf->sf.samplerate)
+       {       case 8000 :
+               case 12000 :
+               case 16000 :
+               case 24000 :
+               case 48000 :
+                       oopus->sr_factor = 48000 / psf->sf.samplerate ;
+                       break ;
+               default :
+                       return SFE_OPUS_BAD_SAMPLERATE ;
+               } ;
+
+       if (psf->sf.channels <= 2)
+       {       oopus->header.channel_mapping = 0 ;
+               nb_streams = 1 ;
+               nb_coupled = psf->sf.channels - 1 ;
+               oopus->header.stream_map [0] = 0 ;
+               oopus->header.stream_map [1] = 1 ;
+
+               oopus->u.encode.state = opus_multistream_encoder_create (
+                       psf->sf.samplerate,
+                       psf->sf.channels,
+                       nb_streams,
+                       nb_coupled,
+                       oopus->header.stream_map,
+                       OPUS_APPLICATION_AUDIO,
+                       &error) ;
+               }
+       else
+       {       if (psf->sf.channels <= 8)
+               {       /* Use Vorbis/AC3 channel mappings for surround. */
+                       oopus->header.channel_mapping = 1 ;
+                       }
+               else
+               {       /* There is no channel mapping, just audio, in parallel, good luck */
+                       oopus->header.channel_mapping = 255 ;
+                       }
+
+               oopus->u.encode.state = opus_multistream_surround_encoder_create (
+                       psf->sf.samplerate,
+                       psf->sf.channels,
+                       oopus->header.channel_mapping,
+                       &nb_streams,
+                       &nb_coupled,
+                       oopus->header.stream_map,
+                       OPUS_APPLICATION_AUDIO,
+                       &error) ;
+
+               }
+
+       if (error != OPUS_OK)
+       {       psf_log_printf (psf, "Opus : Error, opus_multistream_encoder_create returned %s\n", opus_strerror (error)) ;
+               return SFE_BAD_OPEN_FORMAT ;
+               } ;
+       oopus->header.nb_streams = nb_streams ;
+       oopus->header.nb_coupled = nb_coupled ;
+
+       opus_multistream_encoder_ctl (oopus->u.encode.state, OPUS_GET_BITRATE (&oopus->u.encode.bitrate)) ;
+       psf_log_printf (psf, "Encoding at target bitrate of %dbps\n", oopus->u.encode.bitrate) ;
+
+       /* TODO: Make configurable? */
+       error = opus_multistream_encoder_ctl (oopus->u.encode.state, OPUS_SET_COMPLEXITY (10)) ;
+       if (error != OPUS_OK)
+       {       /* Non-fatal */
+               psf_log_printf (psf, "Opus : OPUS_SET_COMPLEXITY returned: %s\n", opus_strerror (error)) ;
+               }
+
+       /*
+       ** Get the encoder delay. This can vary depending on implementation and
+       ** encoder configuration.
+       ** GOTCHA: This returns the preskip at the encoder samplerate, not the
+       ** granulepos rate of 48000Hz needed for header.preskip.
+       */
+       error = opus_multistream_encoder_ctl (oopus->u.encode.state, OPUS_GET_LOOKAHEAD (&lookahead)) ;
+       if (error != OPUS_OK)
+       {       psf_log_printf (psf, "Opus : OPUS_GET_LOOKAHEAD returned: %s\n", opus_strerror (error)) ;
+               return SFE_BAD_OPEN_FORMAT ;
+               } ;
+       oopus->header.preskip = lookahead * oopus->sr_factor ;
+
+       oopus->len = OGG_OPUS_ENCODE_PACKET_LEN (psf->sf.samplerate) ;
+       oopus->buffer = malloc (sizeof (float) * psf->sf.channels * oopus->len) ;
+       if (oopus->buffer == NULL)
+               return SFE_MALLOC_FAILED ;
+
+       /*
+       ** Set up the resident ogg packet structure, ready for writing into.
+       ** 1275 * 3 + 7 bytes of packet per stream is from opusenc from opus-tools
+       */
+       ogg_packet_clear (&odata->opacket) ;
+       oopus->buffersize = (1275 * 3 + 7) * oopus->header.nb_streams ;
+       odata->opacket.packet = malloc (oopus->buffersize) ;
+       odata->opacket.packetno = 2 ;
+       if (odata->opacket.packet == NULL)
+               return SFE_MALLOC_FAILED ;
+
+       oopus->serialno = psf_rand_int32 () ;
+       ogg_stream_init (&odata->ostream, oopus->serialno) ;
+
+       return 0 ;
+} /* ogg_opus_setup_encoder */
+
+static int
+ogg_opus_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       int nn ;
+       ogg_packet op ;
+
+       oopus->header.version = 1 ;
+       oopus->header.channels = psf->sf.channels ;
+
+       /* FIXME: Allow the user to set this ?! */
+       oopus->header.gain = 0 ;
+
+       if (psf->dataoffset > 0)
+       {       if (psf->have_written)
+               {       /*
+                       ** Might be possible to deal with this, but it's difficult as we
+                       ** have to take Ogg Page header sizes in to account, not just
+                       ** packet sizes.
+                       */
+                       return SFE_UNIMPLEMENTED ;
+                       }
+               if (psf_is_pipe (psf))
+                       return SFE_NOT_SEEKABLE ;
+               if (psf_fseek (psf, 0, SEEK_SET) < 0)
+                       return SFE_SEEK_FAILED ;
+               ogg_stream_reset_serialno (&odata->ostream, oopus->serialno) ;
+               psf->dataoffset = 0 ;
+               }
+       else
+               opus_print_header (psf, &oopus->header) ;
+
+       psf->header.ptr [0] = 0 ;
+       psf->header.indx = 0 ;
+
+       /* Opus Header Marker */
+       psf_binheader_writef (psf, "eb", BHWv ("OpusHead"), BHWz (8)) ;
+
+       /* Ogg Embedding scheme version, Channel Count, Preskip Samples */
+       psf_binheader_writef (psf, "e112", BHW1 (oopus->header.version), BHW1 (psf->sf.channels), BHW2 (oopus->header.preskip)) ;
+
+       /*
+       ** If an original samplerate has not been set by the user command
+       ** SFC_SET_ORIGINAL_SAMPLERATE, write the current samplerate.
+       */
+       if (oopus->header.input_samplerate)
+               psf_binheader_writef (psf, "e4", BHW4 (oopus->header.input_samplerate)) ;
+       else
+               psf_binheader_writef (psf, "e4", BHW4 (psf->sf.samplerate)) ;
+
+       /* Input Sample Rate, Gain (S7.8 format), Channel Mapping Type */
+       psf_binheader_writef (psf, "e21", BHW2 (oopus->header.gain), BHW1 (oopus->header.channel_mapping)) ;
+
+       /* Channel mappings, required if not using type 0 (mono/stereo) */
+       if (oopus->header.channel_mapping > 0)
+       {       psf_binheader_writef (psf, "11", BHW1 (oopus->header.nb_streams), BHW1 (oopus->header.nb_coupled)) ;
+               for (nn = 0 ; nn < oopus->header.channels ; nn++)
+                       psf_binheader_writef (psf, "1", BHW1 (oopus->header.stream_map [nn])) ;
+               } ;
+
+       op.packet = psf->header.ptr ;
+       op.bytes = psf->header.indx ;
+       op.b_o_s = 1 ;
+       op.e_o_s = 0 ;
+       op.granulepos = 0 ;
+       op.packetno = 1 ;
+
+       /* The first page MUST only contain the header, so flush it out now */
+       ogg_stream_packetin (&odata->ostream, &op) ;
+       for ( ; (nn = ogg_stream_flush (&odata->ostream, &odata->opage)) ; )
+       {       if (! (nn = ogg_write_page (psf, &odata->opage)))
+               {       psf_log_printf (psf, "Opus : Failed to write header!\n") ;
+                       if (psf->error)
+                               return psf->error ;
+                       return SFE_INTERNAL ;
+                       } ;
+               psf->dataoffset += nn ;
+               }
+
+       /*
+       ** Metadata Tags (manditory)
+       **
+       ** All tags must be in one packet, which may span pages, and these pages
+       ** must not contain any other packets, so flush. The vendor string should
+       ** be the libopus library version, as it is doing the actual encoding. We
+       ** put the libsndfile identifier in the ENCODER tag.
+       **
+       ** See: https://wiki.xiph.org/VorbisComment#ENCODER
+       */
+       vorbiscomment_write_tags (psf, &op, &opustags_ident, opus_get_version_string (), - (OGG_OPUS_COMMENT_PAD)) ;
+       op.packetno = 2 ;
+       ogg_stream_packetin (&odata->ostream, &op) ;
+       for ( ; (nn = ogg_stream_flush (&odata->ostream, &odata->opage)) ; )
+       {       if (! (nn = ogg_write_page (psf, &odata->opage)))
+               {       psf_log_printf (psf, "Opus : Failed to write comments!\n") ;
+                       if (psf->error)
+                               return psf->error ;
+                       return SFE_INTERNAL ;
+                       } ;
+               psf->dataoffset += nn ;
+               }
+
+       return 0 ;
+} /* ogg_opus_write_header */
+
+static void
+ogg_opus_flush (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       uint64_t last_granulepos ;
+       int nbytes ;
+       int len ;
+       int last_packet ;
+
+       /*
+       ** Need to flush both samples waiting for a complete packet and samples
+       ** currently 'inside' the encoder because of its latency. In the case of
+       ** the latter, we need to encode an equivalent amount of silence to push
+       ** them out.
+       **
+       ** Note that the last packet's granule position might be less than the
+       ** total number of samples completed in it. This is how Ogg embedded Opus
+       ** encodes the amount of appended padding to truncate for gapless playback.
+       */
+
+       last_granulepos = oopus->pkt_pos + (oopus->sr_factor * oopus->loc) + oopus->header.preskip ;
+       last_packet = SF_FALSE ;
+       memset (&(oopus->buffer [oopus->loc * psf->sf.channels]), 0, sizeof (float) * psf->sf.channels * (oopus->len - oopus->loc)) ;
+
+       for (last_packet = SF_FALSE ; last_packet == SF_FALSE ; )
+       {       oopus->pkt_pos += oopus->len * oopus->sr_factor ;
+               if (oopus->pkt_pos >= last_granulepos)
+               {       last_packet = SF_TRUE ;
+                       /*
+                       ** Try to shorten the last packet to the smallest valid packet size
+                       ** to minimize padding samples.
+                       */
+                       len = (oopus->len * oopus->sr_factor) - (oopus->pkt_pos - last_granulepos) ;
+                       if (len <= 120) /* 2.5 ms */
+                               len = 120 / oopus->sr_factor ;
+                       else if (len <= 240) /* 5 ms */
+                               len = 240 / oopus->sr_factor ;
+                       else if (len <= 480) /* 10 ms */
+                               len = 480 / oopus->sr_factor ;
+                       else
+                               len = oopus->len ;
+                       }
+               else
+                       len = oopus->len ;
+
+               nbytes = opus_multistream_encode_float (oopus->u.encode.state, oopus->buffer,
+                                       len, odata->opacket.packet, oopus->buffersize) ;
+
+               if (nbytes < 0)
+               {       psf_log_printf (psf, "Opus : opus_multistream_encode_float returned: %s\n", opus_strerror (nbytes)) ;
+                       break ;
+                       }
+
+               odata->opacket.bytes = nbytes ;
+               odata->opacket.packetno++ ;
+               if (last_packet)
+               {       odata->opacket.granulepos = (ogg_int64_t) last_granulepos ;
+                       odata->opacket.e_o_s = 1 ;
+                       }
+               else
+                       odata->opacket.granulepos = (ogg_int64_t) oopus->pkt_pos ;
+
+               ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
+               while (ogg_stream_pageout (&odata->ostream, &odata->opage))
+                       ogg_write_page (psf, &odata->opage) ;
+               } ;
+
+       while (ogg_stream_flush (&odata->ostream, &odata->opage))
+               ogg_write_page (psf, &odata->opage) ;
+} /* ogg_opus_flush */
+
+static int
+ogg_opus_calculate_page_duration (OGG_PRIVATE *odata)
+{      int i, samples, duration ;
+       ogg_packet *ppkt ;
+
+       duration = 0 ;
+       for (i = 0 , ppkt = odata->pkt ; i < odata->pkt_len ; i++, ppkt++)
+       {       /* Use 48kHz to get the sample count for use with granule positions. */
+               samples = opus_packet_get_nb_samples (ppkt->packet, ppkt->bytes, 48000) ;
+               if (samples > 0)
+                       duration += samples ;
+               } ;
+       return duration ;
+} /* ogg_opus_calculate_page_duration */
+
+static int
+ogg_opus_unpack_next_page (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
+{      int nn ;
+
+       nn = ogg_stream_unpack_page (psf, odata) ;
+
+       if (nn == 1)
+       {       oopus->pkt_pos = oopus->pg_pos ;
+               oopus->pg_pos = odata->pkt [odata->pkt_len - 1].granulepos ;
+               }
+       else if (nn == 2)
+       {       uint64_t gp, last_page ;
+
+               /* Found a hole. Need to recalculated pkt_pos from pg_pos */
+               last_page = oopus->pg_pos ;
+               oopus->pg_pos = odata->pkt [odata->pkt_len - 1].granulepos ;
+               gp = ogg_opus_calculate_page_duration (odata) ;
+               oopus->pkt_pos = oopus->pg_pos - gp ;
+               psf_log_printf (psf, "Opus : Hole found appears to be of length %d samples.\n",
+                               (oopus->pkt_pos - last_page) / oopus->sr_factor) ;
+               /*
+               ** Could save the hole size here, and have ogg_opus_read_refill()
+               ** do packet loss concealment until the hole is gone, but libopus does
+               ** PLC by generating white-noise for the duration of the hole. That is
+               ** the correct thing for use in telephony, but it isn't generally
+               ** appropriate here. It actually sounds better with no PLC, as the
+               ** lapped nature of full-width Opus means the two edges of the hole
+               ** will be blended together.
+               */
+               return 1 ;
+               }
+
+       return nn ;
+} /* ogg_opus_unpack_next_page */
+
+static int
+ogg_opus_read_refill (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
+{      uint64_t pkt_granulepos ;
+       int nn, nsamp ;
+       ogg_packet *ppkt ;
+
+       if (odata->pkt_indx == odata->pkt_len)
+       {       nn = ogg_opus_unpack_next_page (psf, odata, oopus) ;
+               if (nn <= 0)
+                       return nn ;
+               }
+
+       if (odata->pkt_indx == odata->pkt_len)
+               return 0 ;
+
+       ppkt = odata->pkt + odata->pkt_indx ;
+       nsamp = opus_multistream_decode_float (oopus->u.decode.state,
+                               ppkt->packet, ppkt->bytes, oopus->buffer, oopus->buffersize, 0) ;
+
+       if (nsamp == OPUS_BUFFER_TOO_SMALL)
+       {       nsamp = opus_packet_get_nb_samples (ppkt->packet, ppkt->bytes, psf->sf.samplerate) ;
+               psf_log_printf (psf, "Growing decode buffer to hold %d samples from %d\n",
+                       nsamp, oopus->buffersize) ;
+               if (nsamp > 5760)
+               {       psf_log_printf (psf, "Packet is larger than maximum allowable of 120ms!? Skipping.\n") ;
+                       return 0 ;
+                       } ;
+               oopus->buffersize = nsamp ;
+
+               free (oopus->buffer) ;
+               oopus->buffer = NULL ;
+               oopus->buffer = malloc (sizeof (float) * oopus->buffersize * psf->sf.channels) ;
+               if (oopus->buffer == NULL)
+               {       psf->error = SFE_MALLOC_FAILED ;
+                       oopus->buffersize = 0 ;
+                       return -1 ;
+                       } ;
+
+               nsamp = opus_multistream_decode_float (oopus->u.decode.state,
+                               ppkt->packet, ppkt->bytes, oopus->buffer, oopus->buffersize, 0) ;
+               } ;
+       odata->pkt_indx ++ ;
+
+       if (nsamp < 0)
+       {       psf_log_printf (psf, "Opus : opus_multistream_decode returned: %s\n",
+                       opus_strerror (nsamp)) ;
+               psf->error = SFE_INTERNAL ;
+               return nsamp ;
+               } ;
+
+       /*
+       ** Check for if this decoded packet is the last of the stream, in
+       ** which case a page granule position which is shorter than the
+       ** sample count of all packets in the page indicates that the last
+       ** samples are padding and should be dropped.
+       */
+       pkt_granulepos = oopus->pkt_pos + (nsamp * oopus->sr_factor) ;
+       if (pkt_granulepos <= oopus->pg_pos)
+       {       oopus->len = nsamp ;
+               }
+       else
+       {       if (ogg_page_eos (&odata->opage))
+               {       /*
+                       ** Possible for pg_pos < pkt_pos if there is a trailing
+                       ** packet. It's not supposed to happen, but could.
+                       */
+                       oopus->len = SF_MAX ((int) (oopus->pg_pos - oopus->pkt_pos) / oopus->sr_factor, 0) ;
+                       }
+               else
+               {       /*
+                       ** From https://wiki.xiph.org/OggOpus#Granule_Position
+                       **      A decoder MUST reject as invalid any stream where the granule
+                       **      position is smaller than the number of samples contained in
+                       **      packets that complete on the first page with a completed
+                       **      packet, unless that page has the 'end of stream' flag set. It
+                       **      MAY defer this action until it decodes the last packet
+                       **      completed on that page.
+                       */
+                       psf_log_printf (psf, "Opus : Mid-strem page's granule position %d is less than total samples of %d\n", oopus->pg_pos, pkt_granulepos) ;
+                       psf->error = SFE_MALFORMED_FILE ;
+                       return -1 ;
+                       } ;
+               } ;
+
+       if (oopus->len > oopus->buffersize)
+       {       free (oopus->buffer) ;
+               oopus->buffersize = oopus->len ;
+               oopus->buffer = malloc (sizeof (float) * oopus->buffersize * psf->sf.channels) ;
+               if (oopus->buffer == NULL)
+               {       psf->error = SFE_MALLOC_FAILED ;
+                       oopus->buffersize = 0 ;
+                       return -1 ;
+                       } ;
+               } ;
+
+       /*
+       ** Check for if this decoded packet contains samples from before the pre-
+       ** skip point, indicating that these samples are padding to get the decoder
+       ** to converge and should be dropped.
+       */
+       if (oopus->pkt_pos < (unsigned) oopus->header.preskip)
+               oopus->loc = SF_MIN ((oopus->header.preskip - (int) oopus->pkt_pos) / oopus->sr_factor, oopus->len) ;
+       else
+               oopus->loc = 0 ;
+
+       oopus->pkt_pos = pkt_granulepos ;
+
+       return nsamp ;
+} /* ogg_opus_read_refill */
+
+static int
+ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
+{      int nbytes ;
+
+       if (oopus->u.encode.lsb != oopus->u.encode.lsb_last)
+               opus_multistream_encoder_ctl (oopus->u.encode.state, OPUS_SET_LSB_DEPTH (oopus->u.encode.lsb)) ;
+
+       nbytes = opus_multistream_encode_float (oopus->u.encode.state,
+               oopus->buffer, oopus->len,
+               odata->opacket.packet, oopus->buffersize) ;
+
+       if (nbytes < 0)
+       {       psf_log_printf (psf, "Opus : Error, opus_multistream_encode_float returned: %s\n", opus_strerror (nbytes)) ;
+               psf->error = SFE_INTERNAL ;
+               return nbytes ;
+               } ;
+
+       oopus->u.encode.last_segments += (nbytes + 255) / 255 ;
+       oopus->pkt_pos += oopus->len * oopus->sr_factor ;
+       odata->opacket.bytes = nbytes ;
+       odata->opacket.granulepos = oopus->pkt_pos ;
+       odata->opacket.packetno++ ;
+
+       /*
+       ** Decide whether to flush the Ogg page *before* adding the new packet to
+       ** it. Check both for if there is more than 1 second of audio (our default
+       ** Ogg page latency, this latency can be modified using sf_command())
+       ** or if adding the packet would cause a continued page,
+       ** in which case we might as well make a new page anyways.
+       */
+       for ( ; ; )
+       {       if (oopus->pkt_pos - oopus->pg_pos >= oopus->u.encode.latency || oopus->u.encode.last_segments >= 255)
+                       nbytes = ogg_stream_flush_fill (&odata->ostream, &odata->opage, 255 * 255) ;
+               else
+                       nbytes = ogg_stream_pageout_fill (&odata->ostream, &odata->opage, 255 * 255) ;
+               if (nbytes > 0)
+               {       /*
+                       ** LibOgg documentation is noted as being bad by it's author. Ogg
+                       ** page header byte 26 is the segment count.
+                       */
+                       oopus->u.encode.last_segments -= odata->opage.header [26] ;
+                       oopus->pg_pos = oopus->pkt_pos ;
+                       ogg_write_page (psf, &odata->opage) ;
+                       }
+               else
+                       break ;
+               } ;
+
+       ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
+       oopus->loc = 0 ;
+       oopus->u.encode.lsb_last = oopus->u.encode.lsb ;
+       oopus->u.encode.lsb = 0 ;
+
+       return 1 ;
+} /* ogg_opus_write_out */
+
+static sf_count_t
+ogg_opus_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total = 0 ;
+       sf_count_t readlen, i ;
+       float *iptr ;
+
+       while (total < len)
+       {       if (oopus->loc == oopus->len)
+               {       if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               readlen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (readlen > 0)
+               {       iptr = oopus->buffer + oopus->loc * psf->sf.channels ;
+                       i = total ;
+                       total += readlen ;
+
+                       if (psf->float_int_mult)
+                       {       float inverse = 1.0 / psf->float_max ;
+                               for ( ; i < total ; i++)
+                               {       ptr [i] = psf_lrintf (((*(iptr++)) * inverse) * 32767.0f) ;
+                                       } ;
+                               }
+                       else
+                       {       for ( ; i < total ; i++)
+                               {       ptr [i] = psf_lrintf ((*(iptr++)) * 32767.0f) ;
+                                       } ;
+                               } ;
+                       oopus->loc += (readlen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_read_s */
+
+static sf_count_t
+ogg_opus_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total = 0 ;
+       sf_count_t readlen, i ;
+       float *iptr ;
+
+       while (total < len)
+       {       if (oopus->loc == oopus->len)
+               {       if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               readlen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (readlen > 0)
+               {       iptr = oopus->buffer + oopus->loc * psf->sf.channels ;
+                       i = total ;
+                       total += readlen ;
+
+                       if (psf->float_int_mult)
+                       {       float inverse = 1.0 / psf->float_max ;
+                               for ( ; i < total ; i++)
+                               {       ptr [i] = psf_lrintf (((*(iptr++)) * inverse) * 2147483647.0f) ;
+                                       }
+                               }
+                       else
+                       {       for ( ; i < total ; i++)
+                               {       ptr [i] = psf_lrintf ((*(iptr++)) * 2147483647.0f) ;
+                                       }
+                               } ;
+                       oopus->loc += (readlen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_read_i */
+
+static sf_count_t
+ogg_opus_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total = 0 ;
+       sf_count_t readlen ;
+
+       while (total < len)
+       {       if (oopus->loc == oopus->len)
+               {       if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               readlen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (readlen > 0)
+               {       memcpy (&(ptr [total]), &(oopus->buffer [oopus->loc * psf->sf.channels]), sizeof (float) * readlen) ;
+                       total += readlen ;
+                       oopus->loc += (readlen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_read_f */
+
+static sf_count_t
+ogg_opus_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total = 0 ;
+       sf_count_t readlen, i ;
+       float *fptr ;
+
+       while (total < len)
+       {       if (oopus->loc >= oopus->len)
+               {       if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               readlen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+
+               if (readlen > 0)
+               {       fptr = oopus->buffer + oopus->loc * psf->sf.channels ;
+                       i = total ;
+                       total += readlen ;
+                       for ( ; i < total ; i++)
+                       {       ptr [i] = *fptr++ ;
+                               } ;
+                       oopus->loc += readlen / psf->sf.channels ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_read_d */
+
+static sf_count_t
+ogg_opus_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total, i ;
+       int writelen ;
+       float *optr ;
+
+       if (oopus->u.encode.lsb < 16)
+               oopus->u.encode.lsb = 16 ;
+
+       for (total = 0 ; total < len ; )
+       {       if (oopus->loc >= oopus->len)
+               {       /* Need to encode the buffer */
+                       if (ogg_opus_write_out (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               writelen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (writelen)
+               {       optr = oopus->buffer + oopus->loc * psf->sf.channels ;
+                       i = total ;
+                       total += writelen ;
+                       for ( ; i < total ; i++)
+                       {       *optr++ = (float) (ptr [i]) / 32767.0f ;
+                               }
+                       oopus->loc += (writelen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_write_s */
+
+static sf_count_t
+ogg_opus_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total, i ;
+       int writelen ;
+       float *optr ;
+
+       if (oopus->u.encode.lsb < 24)
+               oopus->u.encode.lsb = 24 ;
+
+       for (total = 0 ; total < len ; )
+       {       if (oopus->loc >= oopus->len)
+               {       /* Need to encode the buffer */
+                       if (ogg_opus_write_out (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               writelen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (writelen)
+               {       optr = oopus->buffer + oopus->loc * psf->sf.channels ;
+                       i = total ;
+                       total += writelen ;
+                       for ( ; i < total ; i++)
+                       {       *optr++ = (float) (ptr [i]) / 2147483647.0f ;
+                               } ;
+                       oopus->loc += (writelen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_write_i */
+
+static sf_count_t
+ogg_opus_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total ;
+       int writelen ;
+
+       if (oopus->u.encode.lsb < 24)
+               oopus->u.encode.lsb = 24 ;
+
+       for (total = 0 ; total < len ; )
+       {       if (oopus->loc >= oopus->len)
+               {       /* Need to encode the buffer */
+                       if (ogg_opus_write_out (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               writelen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (writelen)
+               {       memcpy (&(oopus->buffer [oopus->loc * psf->sf.channels]), &(ptr [total]), sizeof (float) * writelen) ;
+                       total += writelen ;
+                       oopus->loc += (writelen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_write_f */
+
+static sf_count_t
+ogg_opus_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total, i ;
+       int writelen ;
+       float *optr ;
+
+       if (oopus->u.encode.lsb < 24)
+               oopus->u.encode.lsb = 24 ;
+
+       for (total = 0 ; total < len ; )
+       {       if (oopus->loc >= oopus->len)
+               {       /* Need to encode the buffer */
+                       if (ogg_opus_write_out (psf, odata, oopus) <= 0)
+                               return total ;
+                       } ;
+
+               writelen = SF_MIN (len - total, (sf_count_t) (oopus->len - oopus->loc) * psf->sf.channels) ;
+               if (writelen)
+               {       optr = oopus->buffer + oopus->loc * psf->sf.channels ;
+                       i = total ;
+                       total += writelen ;
+                       for ( ; i < total ; i++)
+                       {       *optr++ = (float) (ptr [i]) ;
+                               } ;
+                       oopus->loc += (writelen / psf->sf.channels) ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_write_d */
+
+static int
+ogg_opus_analyze_file (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       uint64_t gp ;
+       sf_count_t saved_offset, last_page ;
+       int error ;
+
+       psf->sf.sections = 1 ;
+       psf->sf.frames  = SF_COUNT_MAX ;
+       oopus->u.decode.gp_end = (uint64_t) -1 ;
+       oopus->u.decode.last_offset = SF_COUNT_MAX ;
+
+       psf->dataoffset = ogg_sync_ftell (psf) ;
+       if (psf->filelength != SF_COUNT_MAX)
+               psf->datalength = psf->filelength - psf->dataoffset ;
+       else
+               psf->datalength = SF_COUNT_MAX ;
+
+       /*
+       ** Calculate the start granule position offset
+       **
+       ** OggOpus streams are allowed to start with a granule position other than
+       ** zero. This allows for cutting the beginning off of streams without
+       ** having to modify all following granule positions, or for recording/
+       ** joining a live stream in the middle. To figure out the offset, we need
+       ** to sum up how many samples are in all the packets that complete in the
+       ** page and subtract it from the page granule position.
+       **
+       ** If this is the last page of the steam (EOS set), this is not possible,
+       ** as the granule position may be /less/ than the number of samples, to
+       ** indicate how many samples are end-padding. In this case the granule
+       ** position offset of the file must be 0, as otherwise it is considered
+       ** malformed.
+       */
+       error = ogg_opus_unpack_next_page (psf, odata, oopus) ;
+       if (error < 0 && psf->error)
+               return psf->error ;
+
+       gp = ogg_opus_calculate_page_duration (odata) ;
+       if (gp <= 0)
+       {       psf_log_printf (psf, "Opus : Page duration of zero!\n") ;
+               return SFE_MALFORMED_FILE ;
+               } ;
+
+       if (!ogg_page_eos (&odata->opage))
+       {       if (gp > oopus->pg_pos)
+               {       psf_log_printf (psf, "Opus : First data page's granule position is less than total number of samples on the page!\n") ;
+                       return SFE_MALFORMED_FILE ;
+                       }
+               oopus->pkt_pos = oopus->pg_pos - gp ;
+               }
+       else if (gp < oopus->pg_pos)
+       {       psf_log_printf (psf, "Opus : First data page is also the last, and granule position has an (ambigious) offset.\n") ;
+               return SFE_MALFORMED_FILE ;
+               } ;
+       oopus->u.decode.gp_start = oopus->pkt_pos ;
+
+       if (!psf->sf.seekable)
+               return 0 ;
+
+       /*
+       ** Find the last page and fetch the last granule position.
+       ** First, save were we are now.
+       */
+       saved_offset = ogg_sync_ftell (psf) ;
+
+       /* This uses the sync page buffer, the stream page buffer is untouched. */
+       last_page = ogg_sync_last_page_before (psf, odata, &oopus->u.decode.gp_end, psf->filelength, oopus->serialno) ;
+       if (last_page > 0)
+       {       if (!ogg_page_eos (&odata->opage))
+                       psf_log_printf (psf, "Ogg : Last page lacks an end-of-stream bit.\n") ;
+               if (last_page + odata->opage.header_len + odata->opage.body_len < psf->filelength)
+                       psf_log_printf (psf, "Ogg : Junk after the last page.\n") ;
+               oopus->u.decode.last_offset = last_page ;
+
+               if (oopus->u.decode.gp_end != (uint64_t) -1)
+               {       psf->sf.frames = (oopus->u.decode.gp_end - oopus->u.decode.gp_start
+                               - oopus->header.preskip) / oopus->sr_factor ;
+                       } ;
+       }
+
+       /* Go back to where we left off. */
+       ogg_sync_fseek (psf, saved_offset, SEEK_SET) ;
+       return 0 ;
+} /* ogg_opus_analyze_file */
+
+/*
+** ogg_opus_seek_null_read
+**
+** Decode samples, doing nothing with them, until the desired granule position
+** is reached.
+*/
+static sf_count_t
+ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t total ;
+       sf_count_t readlen ;
+
+       total = oopus->pkt_pos / oopus->sr_factor ;
+       total += oopus->loc ;
+
+       for ( ; total < offset ; )
+       {       if (oopus->loc == oopus->len)
+               {       if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
+                               return total ;
+                       /*
+                       ** Ignore pre-skip skipping. The preskip was accounted for in the
+                       ** arugment to offset, so we need to count it.
+                       */
+                       oopus->loc = 0 ;
+                       } ;
+
+               readlen = SF_MIN ((int) (offset - total), (oopus->len - oopus->loc)) ;
+               if (readlen > 0)
+               {       total += readlen ;
+                       oopus->loc += readlen ;
+                       } ;
+               } ;
+       return total ;
+} /* ogg_opus_seek_null_read */
+
+/*
+** Search within the file for the page with the highest granule position at or
+** before our target.
+*/
+static int
+ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       uint64_t pcm_start ;
+       uint64_t pcm_end ;
+       uint64_t best_gp ;
+       sf_count_t begin ;
+       sf_count_t end ;
+       int ret ;
+
+       best_gp = pcm_start = oopus->u.decode.gp_start ;
+       pcm_end = oopus->u.decode.gp_end ;
+       begin = psf->dataoffset ;
+
+       /* Adjust the target to give time to converge. */
+       if (target_gp >= OGG_OPUS_PREROLL)
+               target_gp -= OGG_OPUS_PREROLL ;
+       if (target_gp < pcm_start)
+               target_gp = pcm_start ;
+
+       /* Seek to beginning special case */
+       if (target_gp < pcm_start + (uint64_t) oopus->header.preskip)
+               end = begin ;
+       else
+               end = oopus->u.decode.last_offset ;
+
+       ogg_stream_seek_page_search (psf, odata, target_gp, pcm_start, pcm_end, &best_gp, begin, end) ;
+
+       oopus->loc = 0 ;
+       oopus->len = 0 ;
+       if ((ret = ogg_opus_unpack_next_page (psf, odata, oopus)) != 1)
+               return ret ;
+       oopus->pkt_pos = best_gp ;
+       opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_RESET_STATE) ;
+       /* Gain decoder settings survive resets. */
+
+       return 0 ;
+} /* ogg_opus_seek_page_search */
+
+static sf_count_t
+ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       sf_count_t pos ;
+       int nn ;
+
+       if (target_gp > OGG_OPUS_PREROLL)
+               target_gp -= OGG_OPUS_PREROLL ;
+       if (target_gp < oopus->pg_pos)
+               target_gp = oopus->pg_pos ;
+
+       if (oopus->pg_pos > target_gp)
+       {       ogg_stream_reset (&odata->ostream) ;
+               pos = ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ;
+               if (pos < 0)
+                       return pos ;
+               oopus->pg_pos = oopus->u.decode.gp_start ;
+               opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_RESET_STATE) ;
+               } ;
+
+       while (oopus->pg_pos < target_gp)
+       {       nn = ogg_opus_unpack_next_page (psf, odata, oopus) ;
+               if (nn <= 0)
+                       return nn ;
+               } ;
+
+       return 1 ;
+} /* ogg_opus_seek_manual */
+
+static sf_count_t
+ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
+{      OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       uint64_t target_gp ;
+       uint64_t current ;
+       int ret ;
+
+       /* Only support seeking in read mode. */
+       if (mode != SFM_READ || psf->file.mode != SFM_READ)
+       {       psf->error = SFE_BAD_SEEK ;
+               return PSF_SEEK_ERROR ;
+               } ;
+
+       current = oopus->pkt_pos + oopus->loc * oopus->sr_factor ;
+       /*
+       ** Remember, there are preskip granulepos worth of samples at the front of
+       ** the stream which are bunk. Also, granule positions can be offset.
+       */
+       target_gp = offset * oopus->sr_factor + oopus->u.decode.gp_start + oopus->header.preskip ;
+
+       if (oopus->u.decode.gp_end == (uint64_t) -1)
+       {       /*
+               ** Don't know the end of the file. Could be a chained file we don't yet
+               ** support. Oh well, just do it manually.
+               */
+               ogg_opus_seek_manual (psf, target_gp) ;
+               }
+       else
+       {       /*
+               ** Avoid seeking in the file if where we want is just ahead or exactly
+               ** were we are. To avoid needing to flush the decoder we choose pre-
+               ** roll plus 10ms.
+               */
+               if (target_gp < current || target_gp - current > OGG_OPUS_PREROLL + 10 * 48)
+               {       ret = ogg_opus_seek_page_search (psf, target_gp) ;
+                       if (ret < 0)
+                       {       /*
+                               ** Page seek failed, what to do? Could be bad data. We can
+                               ** either fall-back to manual seeking or bail. Manaul seeking
+                               ** from the beginning has the advantage of finding where the
+                               ** file goes bad.
+                               */
+                               ret = ogg_opus_seek_manual (psf, target_gp) ;
+                               if (ret < 0)
+                               {       /*
+                                       ** If were here, and there is no error, we can be pretty
+                                       ** sure that it's the file that is to blame.
+                                       */
+                                       if (!psf->error)
+                                               psf->error = SFE_MALFORMED_FILE ;
+                                       return ret ;
+                                       } ;
+                               } ;
+                       } ;
+               } ;
+
+       /*
+       ** We've seeked or skipped through pages until just before our target,
+       ** now decode until we hit it.
+       */
+       offset = ogg_opus_seek_null_read (psf, target_gp / oopus->sr_factor) ;
+       return offset - ((oopus->header.preskip + oopus->u.decode.gp_start) / oopus->sr_factor) ;
+
+} /* ogg_opus_seek */
+
+static int
+ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       double quality ;
+       double latency ;
+       int error ;
+
+       switch (command)
+       {       case SFC_SET_CHANNEL_MAP_INFO :
+                       /* TODO: figure this out */
+                       break ;
+
+               case SFC_SET_OGG_PAGE_LATENCY :
+                       /*
+                       ** Argument: double, range 50 to 1600.
+                       ** Average length of OGG page in ms.
+                       ** This length drive the flush of pages.
+                       */
+                       if (data == NULL || datasize != SIGNED_SIZEOF (double))
+                               return SFE_BAD_COMMAND_PARAM ;
+
+                       latency = *((double *) data) ;
+                       if (latency < 50)
+                               latency = 50 ;
+
+                       if (latency > 1600)
+                               latency = 1600 ;
+
+                       oopus->u.encode.latency = ((unsigned long) latency) * 48 ;
+                       break ;
+
+               case SFC_SET_COMPRESSION_LEVEL :
+                       /*
+                       ** Argument: double, range 0.0 (lest compressed, best quality) to
+                       ** 1.0 (most compressed, worst quality)
+                       */
+                       if (data == NULL || datasize != SIGNED_SIZEOF (double))
+                               return SFE_BAD_COMMAND_PARAM ;
+
+                       /* Usable bitrate range is  [6, 256] kbps per channel. */
+                       quality = *((double *) data) ;
+                       oopus->u.encode.bitrate = (int) (((1.0 - quality) * (250000.0)) + 6000.0) * psf->sf.channels ;
+                       if (opus_multistream_encoder_ctl (oopus->u.encode.state, OPUS_SET_BITRATE (oopus->u.encode.bitrate)) == OPUS_OK)
+                       {       psf_log_printf (psf, "User changed encoding target bitrate to %dbps\n", oopus->u.encode.bitrate) ;
+                               return SF_TRUE ;
+                               }
+                       psf_log_printf (psf, "Failed to set user encoding target bitrate of %dbps\n", oopus->u.encode.bitrate) ;
+                       return SF_FALSE ;
+                       break ;
+
+               case SFC_SET_ORIGINAL_SAMPLERATE :
+                       if (data == NULL || datasize != SIGNED_SIZEOF (int))
+                               return SFE_BAD_COMMAND_PARAM ;
+                       /*
+                       ** Only allow changing the input samplerate if at the beginning
+                       ** of the stream, because while it might be possible to change
+                       ** samplerate mid-decode, or to re-write the header for encode,
+                       ** ain't nobody got time to implement and test that.
+                       */
+                       if (psf->file.mode == SFM_WRITE)
+                       {       if (psf->have_written)
+                                       return SF_FALSE ;
+                               oopus->header.input_samplerate = *((int *) data) ;
+                               }
+                       else {
+                               if (oopus->pkt_pos > oopus->u.decode.gp_start || oopus->loc > 0)
+                                       return SF_FALSE ;
+                               if ((error = ogg_opus_setup_decoder (psf, *((int *) data))))
+                                       return error ;
+                               odata->pkt_indx = 0 ;
+                               /* Adjust file frames count. */
+                               if (oopus->u.decode.gp_end != (uint64_t) -1)
+                                       psf->sf.frames = (oopus->u.decode.gp_end - oopus->u.decode.gp_start
+                                               - oopus->header.preskip) / oopus->sr_factor ;
+                               } ;
+                       return SF_TRUE ;
+
+               case SFC_GET_ORIGINAL_SAMPLERATE :
+                       if (data == NULL || datasize != SIGNED_SIZEOF (int))
+                               return SFE_BAD_COMMAND_PARAM ;
+                       *((int *) data) = oopus->header.input_samplerate ;
+                       return SF_TRUE ;
+
+               default :
+                       break ;
+       }
+
+       return SF_FALSE ;
+} /* ogg_opus_command */
+
+static int
+ogg_opus_byterate (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+
+       if (psf->file.mode == SFM_READ)
+       {       if (odata->pkt_indx == odata->pkt_len)
+               {       if (ogg_opus_unpack_next_page (psf, odata, oopus) < 0)
+                               return -1 ;
+                       } ;
+
+               if (odata->pkt_indx < odata->pkt_len)
+               {       ogg_packet *ppkt = &odata->pkt [odata->pkt_indx] ;
+                       return (ppkt->bytes * 8000) / opus_packet_get_nb_samples (ppkt->packet, ppkt->bytes, 8000) ;
+                       } ;
+
+               if (psf->datalength != SF_COUNT_MAX)
+                       return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
+               } ;
+
+       if (psf->file.mode == SFM_WRITE && oopus->u.encode.state != NULL)
+               return (oopus->u.encode.bitrate + 7) / 8 ;
 
+       return -1 ;
+} /* ogg_opus_byterate */
 
-#else /* ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_XIPH_LIBS */
+#else /* HAVE_EXTERNAL_XIPH_LIBS */
 
 int
 ogg_opus_open (SF_PRIVATE *psf)
index f3cd94c..f105214 100644 (file)
@@ -28,6 +28,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "sndfile.h"
@@ -58,6 +60,7 @@ ogg_pcm_open (SF_PRIVATE *psf)
 
        if (odata == NULL)
        {       psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
+               free (opcm) ;
                return SFE_INTERNAL ;
                } ;
 
index b95d4db..546cf35 100644 (file)
@@ -28,6 +28,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "sndfile.h"
@@ -74,6 +76,7 @@ ogg_speex_open (SF_PRIVATE *psf)
 
        if (odata == NULL)
        {       psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
+               free (spx) ;
                return SFE_INTERNAL ;
                } ;
 
diff --git a/src/ogg_vcomment.c b/src/ogg_vcomment.c
new file mode 100644 (file)
index 0000000..252ed61
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+** Copyright (C) 2008-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2018 Arthur Taylor <art@ified.ca>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation ; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+** GNU Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "sndfile.h"
+#include "sfendian.h"
+#include "common.h"
+
+#if HAVE_EXTERNAL_XIPH_LIBS
+
+#include <ogg/ogg.h>
+
+#include "ogg_vcomment.h"
+
+typedef struct
+{      int id ;
+       const char *name ;
+} STR_PAIR ;
+
+/* See https://xiph.org/vorbis/doc/v-comment.html */
+static STR_PAIR vorbiscomment_mapping [] =
+{      {       SF_STR_TITLE,           "TITLE"                 },
+       {       SF_STR_COPYRIGHT,       "COPYRIGHT",    },
+       {       SF_STR_SOFTWARE,        "ENCODER",              },
+       {       SF_STR_ARTIST,          "ARTIST"                },
+       {       SF_STR_COMMENT,         "COMMENT"               },
+       {       SF_STR_DATE,            "DATE",                 },
+       {       SF_STR_ALBUM,           "ALBUM"                 },
+       {       SF_STR_LICENSE,         "LICENSE",              },
+       {       SF_STR_TRACKNUMBER,     "TRACKNUMBER",  },
+       {       SF_STR_GENRE,           "GENRE",                },
+       {       0,                                      NULL,                   },
+} ;
+
+/*-----------------------------------------------------------------------------------------------
+** Private function prototypes.
+*/
+
+static int     vorbiscomment_lookup_id (const char *name) ;
+static const char *    vorbiscomment_lookup_name (int id) ;
+
+static inline size_t read_32bit_size_t (const unsigned char * ptr)
+{      /* Read a 32 bit positive value from the provided pointer. */
+       return LE2H_32_PTR (ptr) & 0x7fffffff ;
+} /* read_32bit_size_t */
+
+/*-----------------------------------------------------------------------------------------------
+** Exported functions.
+*/
+
+int
+vorbiscomment_read_tags (SF_PRIVATE *psf, ogg_packet *packet, vorbiscomment_ident *ident)
+{      unsigned char *p, *ep ;
+       char *tag, *c ;
+       size_t tag_size, tag_len = 0 ;
+       unsigned int ntags, i = 0 ;
+       int id, ret = 0 ;
+
+       /*
+       ** The smallest possible header is the ident string length plus two 4-byte
+       ** integers, (vender string length, tags count.)
+       */
+       if (packet->bytes < (ident ? ident->length : 0) + 4 + 4)
+               return SFE_MALFORMED_FILE ;
+
+       /* Our working pointer. */
+       p = packet->packet ;
+       /* Our end pointer for bound checking. */
+       ep = p + packet->bytes ;
+
+       if (ident)
+       {       if (memcmp (p, ident->ident, ident->length) != 0)
+               {       psf_log_printf (psf, "Expected comment packet identifier missing.\n") ;
+                       return SFE_MALFORMED_FILE ;
+                       } ;
+               p += ident->length ;
+               } ;
+
+       tag_size = 1024 ;
+       tag = malloc (tag_size) ;
+       /* Unlikely */
+       if (!tag)
+               return SFE_MALLOC_FAILED ;
+
+       psf_log_printf (psf, "VorbisComment Metadata\n") ;
+
+       /*
+       ** Vendor tag, manditory, no field name.
+       */
+       tag_len = read_32bit_size_t (p) ;
+       p += 4 ;
+       if (tag_len > 0)
+       {       /* Bound checking. 4 bytes for remaining manditory fields. */
+               if (p + tag_len + 4 > ep)
+               {       ret = SFE_MALFORMED_FILE ;
+                       goto free_tag_out ;
+                       } ;
+               if (tag_len > tag_size - 1)
+               {       free (tag) ;
+                       tag_size = tag_len + 1 ;
+                       tag = malloc (tag_size) ;
+                       /* Unlikely */
+                       if (!tag)
+                               return SFE_MALLOC_FAILED ;
+                       } ;
+               memcpy (tag, p, tag_len) ; p += tag_len ;
+               tag [tag_len] = '\0' ;
+               psf_log_printf (psf, "  Vendor: %s\n", tag) ;
+               } ;
+
+       /*
+       ** List of tags of the form NAME=value
+       ** Allowable characters for NAME are the same as shell variable names.
+       */
+       ntags = read_32bit_size_t (p) ;
+       p += 4 ;
+       for (i = 0 ; i < ntags ; i++)
+       {       if (p + 4 > ep)
+               {       ret = SFE_MALFORMED_FILE ;
+                       goto free_tag_out ;
+                       } ;
+               tag_len = read_32bit_size_t (p) ;
+               p += 4 ;
+               if (p + tag_len > ep)
+               {       ret = SFE_MALFORMED_FILE ;
+                       goto free_tag_out ;
+                       } ;
+               if (tag_len > tag_size - 1)
+               {       free (tag) ;
+                       tag_size = tag_len + 1 ;
+                       tag = malloc (tag_size) ;
+                       /* Unlikely */
+                       if (!tag)
+                               return SFE_MALLOC_FAILED ;
+                       } ;
+               memcpy (tag, p, tag_len) ; p += tag_len ;
+               tag [tag_len] = '\0' ;
+               psf_log_printf (psf, "  %s\n", tag) ;
+               for (c = tag ; *c ; c++)
+               {       if (*c == '=')
+                               break ;
+                       *c = toupper (*c) ;
+                       } ;
+               if (!c)
+               {       psf_log_printf (psf, "Malformed Vorbis comment, no '=' found.\n") ;
+                       continue ;
+                       } ;
+               *c = '\0' ;
+               if ((id = vorbiscomment_lookup_id (tag)) != 0)
+                       psf_store_string (psf, id, c + 1) ;
+               } ;
+
+free_tag_out:
+       if (tag != NULL)
+               free (tag) ;
+       return ret ;
+} /* vorbiscomment_read_tags */
+
+int
+vorbiscomment_write_tags (SF_PRIVATE *psf, ogg_packet *packet, vorbiscomment_ident *ident, const char *vendor, int targetsize)
+{      int i, ntags ;
+       int tags_start ;
+       const char *tag_name ;
+       int tag_name_len, tag_body_len ;
+
+       psf->header.ptr [0] = 0 ;
+       psf->header.indx = 0 ;
+
+       /* Packet identifier */
+       if (ident)
+               psf_binheader_writef (psf, "eb", BHWv (ident->ident), BHWz (ident->length)) ;
+
+       /* Manditory Vendor Tag */
+       tag_name_len = vendor ? strlen (vendor) : 0 ;
+       psf_binheader_writef (psf, "e4b", BHW4 (tag_name_len), BHWv (vendor), BHWz (tag_name_len)) ;
+
+       /* Tags Count. Skip for now, write after. */
+       tags_start = psf->header.indx ;
+       psf_binheader_writef (psf, "j", BHWj (4)) ;
+
+       ntags = 0 ;
+       /* Write each tag */
+       for (i = 0 ; i < SF_MAX_STRINGS ; i++)
+       {       if (psf->strings.data [i].type == 0)
+                       continue ;
+
+               tag_name = vorbiscomment_lookup_name (psf->strings.data [i].type) ;
+               if (tag_name == NULL)
+                       continue ;
+
+               tag_name_len = strlen (tag_name) ;
+               tag_body_len = strlen (psf->strings.storage + psf->strings.data [i].offset) ;
+               if (targetsize > 0 && tag_name_len + tag_body_len + psf->header.indx > targetsize)
+               {       /* If we are out of space, stop now. */
+                       return SFE_STR_MAX_DATA ;
+                       }
+               psf_binheader_writef (psf, "e4b1b",
+                       BHW4 (tag_name_len + 1 + tag_body_len),
+                       BHWv (tag_name), BHWz (tag_name_len),
+                       BHW1 ('='),
+                       BHWv (psf->strings.storage + psf->strings.data [i].offset), BHWz (tag_body_len)) ;
+               ntags++ ;
+               } ;
+
+       if (targetsize < 0)
+       {       /*
+               ** Padding.
+               **
+               ** Pad to a minimum of -targetsize, but make sure length % 255
+               ** = 254 so that we get the most out of the ogg segment lacing.
+               */
+               psf_binheader_writef (psf, "z", BHWz ((psf->header.indx + -targetsize + 255) / 255 * 255 - 1)) ;
+               }
+       else if (targetsize > 0)
+               psf_binheader_writef (psf, "z", BHWz (targetsize - psf->header.indx)) ;
+
+       packet->packet = psf->header.ptr ;
+       packet->bytes = psf->header.indx ;
+       packet->b_o_s = 0 ;
+       packet->e_o_s = 0 ;
+
+       /* Seek back and write the tag count. */
+       psf_binheader_writef (psf, "eo4", BHWo (tags_start), BHW4 (ntags)) ;
+
+       return 0 ;
+} /* vorbiscomment_write_tags */
+
+/*==============================================================================
+** Private functions.
+*/
+
+static int
+vorbiscomment_lookup_id (const char * name)
+{      STR_PAIR *p ;
+
+       for (p = vorbiscomment_mapping ; p->id ; p++)
+       {       if (!strcmp (name, p->name))
+                       return p->id ;
+               } ;
+
+       return 0 ;
+} /* vorbiscomment_lookup_id */
+
+static const char *
+vorbiscomment_lookup_name (int id)
+{      STR_PAIR *p ;
+
+       for (p = vorbiscomment_mapping ; p->id ; p++)
+       {       if (p->id == id)
+                       return p->name ;
+               } ;
+
+       return NULL ;
+} /* vorbiscomment_lookup_name */
+
+#endif /* HAVE_EXTERNAL_XIPH_LIBS */
diff --git a/src/ogg_vcomment.h b/src/ogg_vcomment.h
new file mode 100644 (file)
index 0000000..c25d900
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+** Copyright (C) 2008-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2018 Arthur Taylor <art@ified.ca>
+**
+** This program is free software ; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation ; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY ; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+** GNU Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program ; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SF_SRC_OGG_VCOMMENT_H
+#define SF_SRC_OGG_VCOMMENT_H
+
+/*
+** Voriscomment identifier. Some Ogg stream embedding schemes require it.
+*/
+typedef struct
+{      const char *ident ;
+       int length ;
+} vorbiscomment_ident ;
+
+/*
+** Read all vorbiscomment tags from *packet. Tags which match ones used
+** by libsndfile strings are loaded into *psf. Ogg streams which require an
+** identifier for the tags packet should pass it in *ident.
+*/
+int vorbiscomment_read_tags (SF_PRIVATE *psf, ogg_packet *packet, vorbiscomment_ident *ident) ;
+
+/*
+** Write metadata strings stored in *psf to *packet. The packet is optionally
+** prefixed with *ident. The always-present vendor field should be the library
+** used for encoding the audio data.
+*/
+int vorbiscomment_write_tags (SF_PRIVATE *psf, ogg_packet *packet, vorbiscomment_ident *ident, const char *vendor, int targetsize) ;
+
+#endif /* SF_SRC_OGG_VCOMMENT_H */
index 78acd38..5f53651 100644 (file)
@@ -62,6 +62,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "sndfile.h"
 
 typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ;
 
-static int     vorbis_read_header (SF_PRIVATE *psf, int log_data) ;
+static int     vorbis_read_header (SF_PRIVATE *psf) ;
 static int     vorbis_write_header (SF_PRIVATE *psf, int calc_length) ;
 static int     vorbis_close (SF_PRIVATE *psf) ;
 static int     vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
 static int     vorbis_byterate (SF_PRIVATE *psf) ;
+static sf_count_t      vorbis_calculate_page_duration (SF_PRIVATE *psf) ;
 static sf_count_t      vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
 static sf_count_t      vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
 static sf_count_t      vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
@@ -93,13 +96,15 @@ static sf_count_t   vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t le
 static sf_count_t      vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
 static sf_count_t      vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
 static sf_count_t      vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn) ;
-static sf_count_t      vorbis_length (SF_PRIVATE *psf) ;
+static int     vorbis_rnull (SF_PRIVATE *psf, int samples, void *vptr, int off , int channels, float **pcm) ;
 
 typedef struct
 {      int id ;
        const char *name ;
 } STR_PAIRS ;
 
+
+/* See https://xiph.org/vorbis/doc/v-comment.html */
 static STR_PAIRS vorbis_metatypes [] =
 {      {       SF_STR_TITLE,           "Title" },
        {       SF_STR_COPYRIGHT,       "Copyright" },
@@ -127,93 +132,45 @@ typedef struct
 
        /* Encoding quality in range [0.0, 1.0]. */
        double quality ;
+
+       /* Current granule position. */
+       uint64_t pcm_current ;
+       /* Offset of the first samples' granule position. */
+       uint64_t pcm_start ;
+       /* Last valid samples' granule position. */
+       uint64_t pcm_end ;
+       /* File offset of the start of the last page. */
+       sf_count_t last_page ;
 } VORBIS_PRIVATE ;
 
 static int
-vorbis_read_header (SF_PRIVATE *psf, int log_data)
-{
-       OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+vorbis_read_header (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
        VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
-       char *buffer ;
-       int     bytes ;
-       int i, nn ;
-
-       odata->eos = 0 ;
-
-       /* Weird stuff happens if these aren't called. */
-       ogg_stream_reset (&odata->ostream) ;
-       ogg_sync_reset (&odata->osync) ;
+       sf_count_t duration ;
+       int printed_metadata_msg = 0 ;
+       int i, k, nn ;
 
        /*
-       **      Grab some data at the head of the stream.  We want the first page
-       **      (which is guaranteed to be small and only contain the Vorbis
-       **      stream initial header) We need the first page to get the stream
-       **      serialno.
+       **  The first page of the Ogg stream we are told to try and open as Vorbis
+       **  has already been loaded into odata->ostream by ogg_open().
+       **
+       **      Extract the initial header from the first page and verify that the
+       **      Ogg bitstream is in fact Vorbis data.
        */
 
-       /* Expose the buffer */
-       buffer = ogg_sync_buffer (&odata->osync, 4096L) ;
-
-       /* Grab the part of the header that has already been read. */
-       memcpy (buffer, psf->header.ptr, psf->header.indx) ;
-       bytes = psf->header.indx ;
-
-       /* Submit a 4k block to libvorbis' Ogg layer */
-       bytes += psf_fread (buffer + psf->header.indx, 1, 4096 - psf->header.indx, psf) ;
-       ogg_sync_wrote (&odata->osync, bytes) ;
-
-       /* Get the first page. */
-       if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
-       {
-               /* Have we simply run out of data?  If so, we're done. */
-               if (bytes < 4096)
-                       return 0 ;
-
-               /* Error case.  Must not be Vorbis data */
-               psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
-               return SFE_MALFORMED_FILE ;
-               } ;
-
-       /*
-       **      Get the serial number and set up the rest of decode.
-       **      Serialno first ; use it to set up a logical stream.
-       */
-       ogg_stream_clear (&odata->ostream) ;
-       ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
+       vorbis_info_init (&vdata->vinfo) ;
+       vorbis_comment_init (&vdata->vcomment) ;
 
-       if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
-       {       /* Error ; stream version mismatch perhaps. */
-               psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
+       if (!odata->opacket.b_o_s)
+       {       psf_log_printf (psf, "Vorbis: First packet does not have a beginning-of-stream bit.\n") ;
                return SFE_MALFORMED_FILE ;
-               } ;
+               }
 
-       if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
-       {       /* No page? must not be vorbis. */
-               psf_log_printf (psf, "Error reading initial header packet.\n") ;
+       if (ogg_stream_packetpeek (&odata->ostream, NULL))
+       {       psf_log_printf (psf, "Vorbis: First page contains extraneous packets!\n") ;
                return SFE_MALFORMED_FILE ;
-               } ;
-
-       /*
-       **      This function (vorbis_read_header) gets called multiple times, so the OGG
-       **      and vorbis structs have to be cleared every time we pass through to
-       **      prevent memory leaks.
-       */
-       vorbis_block_clear (&vdata->vblock) ;
-       vorbis_dsp_clear (&vdata->vdsp) ;
-       vorbis_comment_clear (&vdata->vcomment) ;
-       vorbis_info_clear (&vdata->vinfo) ;
-
-       /*
-       **      Extract the initial header from the first page and verify that the
-       **      Ogg bitstream is in fact Vorbis data.
-       **
-       **      I handle the initial header first instead of just having the code
-       **      read all three Vorbis headers at once because reading the initial
-       **      header is an easy way to identify a Vorbis bitstream and it's
-       **      useful to see that functionality seperated out.
-       */
-       vorbis_info_init (&vdata->vinfo) ;
-       vorbis_comment_init (&vdata->vcomment) ;
+               }
 
        if (vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) < 0)
        {       /* Error case ; not a vorbis header. */
@@ -222,25 +179,6 @@ vorbis_read_header (SF_PRIVATE *psf, int log_data)
                } ;
 
        /*
-       **      Common Ogg metadata fields?
-       **      TITLE, VERSION, ALBUM, TRACKNUMBER, ARTIST, PERFORMER, COPYRIGHT, LICENSE,
-       **      ORGANIZATION, DESCRIPTION, GENRE, DATE, LOCATION, CONTACT, ISRC,
-       */
-
-       if (log_data)
-       {       int k ;
-
-               for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
-               {       char *dd ;
-
-                       dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
-                       if (dd == NULL)
-                               continue ;
-                       psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
-                       } ;
-               } ;
-
-       /*
        **      At this point, we're sure we're Vorbis. We've set up the logical (Ogg)
        **      bitstream decoder. Get the comment and codebook headers and set up the
        **      Vorbis decoder.
@@ -254,74 +192,112 @@ vorbis_read_header (SF_PRIVATE *psf, int log_data)
 
        i = 0 ;                 /* Count of number of packets read */
        while (i < 2)
-       {       int result = ogg_sync_pageout (&odata->osync, &odata->opage) ;
-               if (result == 0)
-               {       /* Need more data */
-                       buffer = ogg_sync_buffer (&odata->osync, 4096) ;
-                       bytes = psf_fread (buffer, 1, 4096, psf) ;
+       {       nn = ogg_stream_packetout (&odata->ostream, &odata->opacket) ;
 
-                       if (bytes == 0 && i < 2)
+               if (nn == 0)
+               {       nn = ogg_stream_next_page (psf, odata) ;
+                       if (nn == 0)
                        {       psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ;
                                return SFE_MALFORMED_FILE ;
                                } ;
-                       nn = ogg_sync_wrote (&odata->osync, bytes) ;
+                       if (nn == -1)
+                       {       psf_log_printf (psf, "Error reading file while finding Vorbis headers!\n") ;
+                               return psf->error ;
+                               } ;
+                       continue ;
                        }
-               else if (result == 1)
-               {       /*
-                       **      Don't complain about missing or corrupt data yet. We'll
-                       **      catch it at the packet output phase.
-                       **
-                       **      We can ignore any errors here as they'll also become apparent
-                       **      at packetout.
-                       */
-                       nn = ogg_stream_pagein (&odata->ostream, &odata->opage) ;
-                       while (i < 2)
-                       {       result = ogg_stream_packetout (&odata->ostream, &odata->opacket) ;
-                               if (result == 0)
-                                       break ;
-                               if (result < 0)
-                               {       /*      Uh oh ; data at some point was corrupted or missing!
-                                       **      We can't tolerate that in a header. Die. */
-                                       psf_log_printf (psf, "Corrupt secondary header. Exiting.\n") ;
-                                       return SFE_MALFORMED_FILE ;
-                                       } ;
 
-                               vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) ;
-                               i++ ;
-                               } ;
+               if (nn < 0)
+               {       /* A hole while reading headers. This could be bad. */
+                       psf_log_printf (psf, "Corrupt secondary header. Exiting.\n") ;
+                       return SFE_MALFORMED_FILE ;
                        } ;
+
+               vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) ;
+               i++ ;
                } ;
 
-       if (log_data)
-       {       int printed_metadata_msg = 0 ;
-               int k ;
+       /* Check for extraneous packets in the last headers page. */
+       while (ogg_stream_packetout (&odata->ostream, &odata->opacket) == 1)
+       {       i++ ;
+               }
+       if (i > 2)
+               psf_log_printf (psf, "Vorbis: stream has extraneous header packets.\n") ;
 
-               psf_log_printf (psf, "Bitstream is %d channel, %D Hz\n", vdata->vinfo.channels, vdata->vinfo.rate) ;
-               psf_log_printf (psf, "Encoded by : %s\n", vdata->vcomment.vendor) ;
+       psf_log_printf (psf, "Bitstream is %d channel, %D Hz\n", vdata->vinfo.channels, vdata->vinfo.rate) ;
+       psf_log_printf (psf, "Encoded by : %s\n", vdata->vcomment.vendor) ;
 
-               /* Throw the comments plus a few lines about the bitstream we're decoding. */
-               for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
-               {       char *dd ;
+       /* Save the offset of the first payload page */
+       psf->dataoffset = ogg_sync_ftell (psf) ;
 
-                       dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
-                       if (dd == NULL)
-                               continue ;
+       /*
+       **      Caculate the granule position offset. The first page with a payload
+       **      packet shouldn't end in a continued packet. The difference between the
+       **      page's granule position and the sum of frames on the page tells us the
+       **      granule position offset.
+       **      See https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-132000A.2
+       */
+       ogg_stream_unpack_page (psf, odata) ;
+       vdata->pcm_start = odata->pkt [odata->pkt_len - 1].granulepos ;
+       duration = vorbis_calculate_page_duration (psf) ;
 
-                       if (printed_metadata_msg == 0)
-                       {       psf_log_printf (psf, "Metadata :\n") ;
-                               printed_metadata_msg = 1 ;
-                               } ;
+       if (duration < (sf_count_t) vdata->pcm_start)
+               vdata->pcm_start -= duration ;
+       else
+               vdata->pcm_start = 0 ;
 
-                       psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
-                       psf_log_printf (psf, "  %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
+       /*
+       **      Find the end of the stream, save it. Only works if the file is seekable.
+       */
+       vdata->loc = vdata->pcm_start ;
+       vdata->pcm_end = (uint64_t) -1 ;
+       psf->datalength = psf->filelength ;
+       if (!psf->is_pipe)
+       {       sf_count_t last_page ;
+               sf_count_t saved_offset ;
+
+               saved_offset = ogg_sync_ftell (psf) ;
+               last_page = ogg_sync_last_page_before (psf, odata, &vdata->pcm_end, psf->filelength, odata->ostream.serialno) ;
+               if (last_page > 0)
+               {       if (!ogg_page_eos (&odata->opage))
+                               psf_log_printf (psf, "Ogg: Last page lacks an end-of-stream bit.\n") ;
+                       psf->datalength = last_page + odata->opage.header_len + odata->opage.body_len - psf->dataoffset ;
+                       if (psf->datalength + psf->dataoffset < psf->filelength)
+                               psf_log_printf (psf, "Ogg: Junk after the last page.\n") ;
+                       vdata->last_page = last_page ;
                        } ;
 
-               psf_log_printf (psf, "End\n") ;
+               ogg_sync_fseek (psf, saved_offset, SEEK_SET) ;
+               }
+
+       psf_log_printf (psf, "PCM offset  : %d\n", vdata->pcm_start) ;
+       if (vdata->pcm_end != (uint64_t) -1)
+               psf_log_printf (psf, "PCM end     : %d\n", vdata->pcm_end) ;
+       else
+               psf_log_printf (psf, "PCM end     : unknown\n") ;
+
+       /* Throw the comments plus a few lines about the bitstream we're decoding. */
+       for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
+       {       char *dd ;
+
+               dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
+               if (dd == NULL)
+                       continue ;
+
+               if (printed_metadata_msg == 0)
+               {       psf_log_printf (psf, "Metadata :\n") ;
+                       printed_metadata_msg = 1 ;
+                       } ;
+
+               psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
+               psf_log_printf (psf, "  %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
                } ;
+       psf_log_printf (psf, "End\n") ;
 
        psf->sf.samplerate      = vdata->vinfo.rate ;
        psf->sf.channels        = vdata->vinfo.channels ;
        psf->sf.format          = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+       psf->sf.frames          = (vdata->pcm_end != (uint64_t) -1) ? vdata->pcm_end - vdata->pcm_start : SF_COUNT_MAX ;
 
        /*      OK, got and parsed all three headers. Initialize the Vorbis
        **      packet->PCM decoder.
@@ -333,8 +309,6 @@ vorbis_read_header (SF_PRIVATE *psf, int log_data)
        **      for vd here. */
        vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;
 
-       vdata->loc = 0 ;
-
        return 0 ;
 } /* vorbis_read_header */
 
@@ -423,8 +397,7 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
                 * audio data will start on a new page, as per spec
                 */
                while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
-               {       psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
-                       psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
+               {       ogg_write_page (psf, &odata->opage) ;
                        } ;
        }
 
@@ -463,8 +436,7 @@ vorbis_close (SF_PRIVATE *psf)
                                while (!odata->eos)
                                {       int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
                                        if (result == 0) break ;
-                                       psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
-                                       psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
+                                       ogg_write_page (psf, &odata->opage) ;
 
                /* this could be set above, but for illustrative purposes, I do
                   it here (to show that vorbis does know where the stream ends) */
@@ -506,17 +478,13 @@ ogg_vorbis_open (SF_PRIVATE *psf)
        psf_log_printf (psf, "Vorbis library version : %s\n", vorbis_version_string ()) ;
 
        if (psf->file.mode == SFM_READ)
-       {       /* Call this here so it only gets called once, so no memory is leaked. */
-               ogg_sync_init (&odata->osync) ;
-
-               if ((error = vorbis_read_header (psf, 1)))
+       {       if ((error = vorbis_read_header (psf)))
                        return error ;
 
                psf->read_short         = vorbis_read_s ;
                psf->read_int           = vorbis_read_i ;
                psf->read_float         = vorbis_read_f ;
                psf->read_double        = vorbis_read_d ;
-               psf->sf.frames          = vorbis_length (psf) ;
                } ;
 
        psf->codec_close = vorbis_close ;
@@ -531,22 +499,19 @@ ogg_vorbis_open (SF_PRIVATE *psf)
                psf->write_float        = vorbis_write_f ;
                psf->write_double       = vorbis_write_d ;
 
-               psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
+               psf->sf.frames = 0 ;
+               psf->datalength = 0 ;
+               psf->filelength = 0 ;
+               psf->dataoffset = 0 ;
                psf->strings.flags = SF_STR_ALLOW_START ;
                } ;
 
        psf->seek = vorbis_seek ;
        psf->command = vorbis_command ;
        psf->byterate = vorbis_byterate ;
-
-       /* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
        psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
        psf->sf.sections = 1 ;
 
-       psf->datalength = 1 ;
-       psf->dataoffset = 0 ;
-       /* End FIXME. */
-
        return error ;
 } /* ogg_vorbis_open */
 
@@ -593,13 +558,13 @@ vorbis_rshort (SF_PRIVATE *psf, int samples, void *vptr, int off, int channels,
                float inverse = 1.0 / psf->float_max ;
                for (j = 0 ; j < samples ; j++)
                        for (n = 0 ; n < channels ; n++)
-                               ptr [i++] = lrintf ((pcm [n][j] * inverse) * 32767.0f) ;
+                               ptr [i++] = psf_lrintf ((pcm [n][j] * inverse) * 32767.0f) ;
        }
        else
        {
                for (j = 0 ; j < samples ; j++)
                        for (n = 0 ; n < channels ; n++)
-                               ptr [i++] = lrintf (pcm [n][j] * 32767.0f) ;
+                               ptr [i++] = psf_lrintf (pcm [n][j] * 32767.0f) ;
        }
        return i ;
 } /* vorbis_rshort */
@@ -615,13 +580,13 @@ vorbis_rint (SF_PRIVATE *psf, int samples, void *vptr, int off, int channels, fl
                float inverse = 1.0 / psf->float_max ;
                for (j = 0 ; j < samples ; j++)
                        for (n = 0 ; n < channels ; n++)
-                               ptr [i++] = lrintf ((pcm [n][j] * inverse) * 2147483647.0f) ;
+                               ptr [i++] = psf_lrintf ((pcm [n][j] * inverse) * 2147483647.0f) ;
        }
        else
        {
                for (j = 0 ; j < samples ; j++)
                        for (n = 0 ; n < channels ; n++)
-                               ptr [i++] = lrintf (pcm [n][j] * 2147483647.0f) ;
+                               ptr [i++] = psf_lrintf (pcm [n][j] * 2147483647.0f) ;
        }
        return i ;
 } /* vorbis_rint */
@@ -651,81 +616,50 @@ vorbis_rdouble (SF_PRIVATE *UNUSED (psf), int samples, void *vptr, int off, int
 
 static sf_count_t
 vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn)
-{
-       VORBIS_PRIVATE *vdata = psf->codec_data ;
+{      VORBIS_PRIVATE *vdata = psf->codec_data ;
        OGG_PRIVATE *odata = psf->container_data ;
-       int len, samples, i = 0 ;
+       int len, samples, i = 0 , nn ;
        float **pcm ;
 
        len = lens / psf->sf.channels ;
 
-       while ((samples = vorbis_synthesis_pcmout (&vdata->vdsp, &pcm)) > 0)
-       {       if (samples > len) samples = len ;
-               i += transfn (psf, samples, ptr, i, psf->sf.channels, pcm) ;
-               len -= samples ;
-               /* tell libvorbis how many samples we actually consumed */
-               vorbis_synthesis_read (&vdata->vdsp, samples) ;
-               vdata->loc += samples ;
-               if (len == 0)
-                       return i ; /* Is this necessary */
-       }
-       goto start0 ;           /* Jump into the nasty nest */
-       while (len > 0 && !odata->eos)
-       {
-               while (len > 0 && !odata->eos)
-               {       int result = ogg_sync_pageout (&odata->osync, &odata->opage) ;
-                       if (result == 0) break ; /* need more data */
-                       if (result < 0)
-                       {       /* missing or corrupt data at this page position */
-                               psf_log_printf (psf, "Corrupt or missing data in bitstream ; continuing...\n") ;
-                               }
-                       else
-                       {       /* can safely ignore errors at this point */
-                               ogg_stream_pagein (&odata->ostream, &odata->opage) ;
-                       start0:
-                               while (1)
-                               {       result = ogg_stream_packetout (&odata->ostream, &odata->opacket) ;
-                                       if (result == 0)
-                                               break ; /* need more data */
-                                       if (result < 0)
-                                       {       /* missing or corrupt data at this page position */
-                                               /* no reason to complain ; already complained above */
-                                               }
-                                       else
-                                       {       /* we have a packet.    Decode it */
-                                               if (vorbis_synthesis (&vdata->vblock, &odata->opacket) == 0) /* test for success! */
-                                                       vorbis_synthesis_blockin (&vdata->vdsp, &vdata->vblock) ;
-                                               /*
-                                               ** pcm is a multichannel float vector.   In stereo, for
-                                               ** example, pcm [0] is left, and pcm [1] is right.       samples is
-                                               ** the size of each channel.     Convert the float values
-                                               ** (-1.<=range<=1.) to whatever PCM format and write it out.
-                                               */
-
-                                               while ((samples = vorbis_synthesis_pcmout (&vdata->vdsp, &pcm)) > 0)
-                                               {       if (samples > len) samples = len ;
-                                                       i += transfn (psf, samples, ptr, i, psf->sf.channels, pcm) ;
-                                                       len -= samples ;
-                                                       /* tell libvorbis how many samples we actually consumed */
-                                                       vorbis_synthesis_read (&vdata->vdsp, samples) ;
-                                                       vdata->loc += samples ;
-                                                       if (len == 0)
-                                                               return i ; /* Is this necessary */
-                                                       } ;
-                                       }
+       while (len > 0)
+       {       /*
+               ** pcm is a multichannel float vector.   In stereo, for
+               ** example, pcm [0] is left, and pcm [1] is right.       samples is
+               ** the size of each channel.     Convert the float values
+               ** (-1.<=range<=1.) to whatever PCM format and write it out.
+               */
+               while ((samples = vorbis_synthesis_pcmout (&vdata->vdsp, &pcm)) > 0)
+               {       if (samples > len) samples = len ;
+                       i += transfn (psf, samples, ptr, i, psf->sf.channels, pcm) ;
+                       len -= samples ;
+                       /* tell libvorbis how many samples we actually consumed */
+                       vorbis_synthesis_read (&vdata->vdsp, samples) ;
+                       vdata->loc += samples ;
+                       if (len == 0)
+                               return i ; /* Is this necessary */
+                       } ;
+
+               /* Out of samples, load the next packet. */
+               if (odata->pkt_indx == odata->pkt_len)
+               {       /* Page out of packets, load and unpack the next page. */
+                       nn = ogg_stream_unpack_page (psf, odata) ;
+                       if (nn <= 0)
+                               return i ;
+                       if (nn == 2)
+                       {       /* Ran over a hole. loc is now out of date, need to recalculate. */
+                               vdata->loc = odata->pkt [odata->pkt_len - 1].granulepos ;
+                               vdata->loc -= vorbis_calculate_page_duration (psf) ;
                                }
-                               if (ogg_page_eos (&odata->opage)) odata->eos = 1 ;
-                       }
-               }
-               if (!odata->eos)
-               {       char *buffer ;
-                       int bytes ;
-                       buffer = ogg_sync_buffer (&odata->osync, 4096) ;
-                       bytes = psf_fread (buffer, 1, 4096, psf) ;
-                       ogg_sync_wrote (&odata->osync, bytes) ;
-                       if (bytes == 0) odata->eos = 1 ;
-               }
-       }
+                       } ;
+
+               /* Decode the packet */
+               if (vorbis_synthesis (&vdata->vblock, &(odata->pkt [odata->pkt_indx])) == 0) /* test for success! */
+                       vorbis_synthesis_blockin (&vdata->vdsp, &vdata->vblock) ;
+               odata->pkt_indx++ ;
+               } ;
+
        return i ;
 } /* vorbis_read_sample */
 
@@ -778,8 +712,7 @@ vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata
                        {       int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
                                if (result == 0)
                                        break ;
-                               psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
-                               psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
+                               ogg_write_page (psf, &odata->opage) ;
 
                                /*      This could be set above, but for illustrative purposes, I do
                                **      it here (to show that vorbis does know where the stream ends) */
@@ -860,9 +793,10 @@ vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens)
 
 static sf_count_t
 vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
-{
-       OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
        VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+       sf_count_t target ;
+       int ret ;
 
        if (odata == NULL || vdata == NULL)
                return 0 ;
@@ -873,12 +807,40 @@ vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
                } ;
 
        if (psf->file.mode == SFM_READ)
-       {       sf_count_t target = offset - vdata->loc ;
+       {       target = offset + vdata->pcm_start ;
+
+               /*
+               ** If the end of the file is know, and the seek isn't for the near
+               ** future, do a search of the file for a good place to start.
+               */
+               ret = 0 ;
+               if ((vdata->pcm_end != (uint64_t) -1) &&
+                       (target < vdata->loc || target - vdata->loc > (2 * psf->sf.samplerate)))
+               {       uint64_t best_gp ;
+
+                       best_gp = vdata->pcm_start ;
+
+                       ret = ogg_stream_seek_page_search (psf, odata, target, vdata->pcm_start,
+                               vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page) ;
+                       if (ret >= 0)
+                       {       ret = ogg_stream_unpack_page (psf, odata) ;
+                               if (ret == 1)
+                               {       vdata->loc = best_gp ;
+                                       vorbis_synthesis_restart (&vdata->vdsp) ;
+                                       } ;
+                               } ;
+                       } ;
 
-               if (target < 0)
-               {       /* 12 to allow for OggS bit */
-                       psf_fseek (psf, 12, SEEK_SET) ;
-                       vorbis_read_header (psf, 0) ; /* Reset state */
+               if (ret >= 0 && offset + (sf_count_t) vdata->pcm_start >= vdata->loc)
+                       target = offset + vdata->pcm_start - vdata->loc ;
+               else
+               {       /* Search failed (bad data?), reset to the beginning of the stream. */
+                       ogg_stream_reset_serialno (&odata->ostream, odata->ostream.serialno) ;
+                       odata->pkt_len = 0 ;
+                       odata->pkt_indx = 0 ;
+                       ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ;
+                       vdata->loc = 0 ;
+                       vorbis_synthesis_restart (&vdata->vdsp) ;
                        target = offset ;
                        } ;
 
@@ -895,7 +857,7 @@ vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
                        target -= m ;
                        } ;
 
-               return vdata->loc ;
+               return vdata->loc - vdata->pcm_start ;
                } ;
 
        return 0 ;
@@ -911,260 +873,27 @@ vorbis_byterate (SF_PRIVATE *psf)
        return -1 ;
 } /* vorbis_byterate */
 
-/*==============================================================================
-**     Most of the following code was snipped from Mike Smith's ogginfo utility
-**     which is part of vorbis-tools.
-**     Vorbis tools is released under the GPL but Mike has kindly allowed the
-**     following to be relicensed as LGPL for libsndfile.
-*/
-
-typedef struct
-{
-       int isillegal ;
-       int shownillegal ;
-       int isnew ;
-       int end ;
-
-       uint32_t serial ; /* must be 32 bit unsigned */
-       ogg_stream_state ostream ;
-
-       vorbis_info vinfo ;
-       vorbis_comment vcomment ;
-       sf_count_t lastgranulepos ;
-       int doneheaders ;
-} stream_processor ;
-
-typedef struct
-{
-       stream_processor *streams ;
-       int allocated ;
-       int used ;
-       int in_headers ;
-} stream_set ;
-
-static stream_set *
-create_stream_set (void)
-{      stream_set *set = calloc (1, sizeof (stream_set)) ;
-
-       set->streams = calloc (5, sizeof (stream_processor)) ;
-       set->allocated = 5 ;
-       set->used = 0 ;
-
-       return set ;
-} /* create_stream_set */
-
-static void
-vorbis_end (stream_processor *stream, sf_count_t * len)
-{      *len += stream->lastgranulepos ;
-       vorbis_comment_clear (&stream->vcomment) ;
-       vorbis_info_clear (&stream->vinfo) ;
-} /* vorbis_end */
-
-static void
-free_stream_set (stream_set *set, sf_count_t * len)
-{      int i ;
-
-       for (i = 0 ; i < set->used ; i++)
-       {       if (!set->streams [i].end)
-                       vorbis_end (&set->streams [i], len) ;
-               ogg_stream_clear (&set->streams [i].ostream) ;
-               } ;
-
-       free (set->streams) ;
-       free (set) ;
-} /* free_stream_set */
-
-static int
-streams_open (stream_set *set)
-{      int i, res = 0 ;
-
-       for (i = 0 ; i < set->used ; i++)
-               if (!set->streams [i].end)
-                       res ++ ;
-       return res ;
-} /* streams_open */
-
-static stream_processor *
-find_stream_processor (stream_set *set, ogg_page *page)
-{      uint32_t serial = ogg_page_serialno (page) ;
-       int i, invalid = 0 ;
-
-       stream_processor *stream ;
-
-       for (i = 0 ; i < set->used ; i++)
-       {
-               if (serial == set->streams [i].serial)
-               {       /* We have a match! */
-                       stream = & (set->streams [i]) ;
-
-                       set->in_headers = 0 ;
-                       /* if we have detected EOS, then this can't occur here. */
-                       if (stream->end)
-                       {       stream->isillegal = 1 ;
-                               return stream ;
-                               }
-
-                       stream->isnew = 0 ;
-                       stream->end = ogg_page_eos (page) ;
-                       stream->serial = serial ;
-                       return stream ;
-                       } ;
-               } ;
-
-       /* If there are streams open, and we've reached the end of the
-       ** headers, then we can't be starting a new stream.
-       ** XXX: might this sometimes catch ok streams if EOS flag is missing,
-       ** but the stream is otherwise ok?
-       */
-       if (streams_open (set) && !set->in_headers)
-               invalid = 1 ;
-
-       set->in_headers = 1 ;
-
-       if (set->allocated < set->used)
-               stream = &set->streams [set->used] ;
-       else
-       {       set->allocated += 5 ;
-               set->streams = realloc (set->streams, sizeof (stream_processor) * set->allocated) ;
-               stream = &set->streams [set->used] ;
-               } ;
-
-       set->used++ ;
-
-       stream->isnew = 1 ;
-       stream->isillegal = invalid ;
-
-       {
-               int res ;
-               ogg_packet packet ;
-
-               /* We end up processing the header page twice, but that's ok. */
-               ogg_stream_init (&stream->ostream, serial) ;
-               ogg_stream_pagein (&stream->ostream, page) ;
-               res = ogg_stream_packetout (&stream->ostream, &packet) ;
-               if (res <= 0)
-                       return NULL ;
-               else if (packet.bytes >= 7 && memcmp (packet.packet, "\x01vorbis", 7) == 0)
-               {
-                       stream->lastgranulepos = 0 ;
-                       vorbis_comment_init (&stream->vcomment) ;
-                       vorbis_info_init (&stream->vinfo) ;
-                       } ;
-
-               res = ogg_stream_packetout (&stream->ostream, &packet) ;
-
-               /* re-init, ready for processing */
-               ogg_stream_clear (&stream->ostream) ;
-               ogg_stream_init (&stream->ostream, serial) ;
-       }
-
-       stream->end = ogg_page_eos (page) ;
-       stream->serial = serial ;
-
-       return stream ;
-} /* find_stream_processor */
-
-static int
-vorbis_length_get_next_page (SF_PRIVATE *psf, ogg_sync_state * osync, ogg_page *page)
-{      static const int CHUNK_SIZE = 4500 ;
-
-       while (ogg_sync_pageout (osync, page) <= 0)
-       {       char * buffer = ogg_sync_buffer (osync, CHUNK_SIZE) ;
-               int bytes = psf_fread (buffer, 1, 4096, psf) ;
-
-               if (bytes <= 0)
-               {       ogg_sync_wrote (osync, 0) ;
-                       return 0 ;
-                       } ;
-
-               ogg_sync_wrote (osync, bytes) ;
-               } ;
-
-       return 1 ;
-} /* vorbis_length_get_next_page */
-
 static sf_count_t
-vorbis_length_aux (SF_PRIVATE * psf)
-{
-       ogg_sync_state osync ;
-       ogg_page page ;
-       sf_count_t len = 0 ;
-       stream_set *processors ;
-
-       processors = create_stream_set () ;
-       if (processors == NULL)
-               return 0 ;      // out of memory?
-
-       ogg_sync_init (&osync) ;
-
-       while (vorbis_length_get_next_page (psf, &osync, &page))
-       {
-               stream_processor *p = find_stream_processor (processors, &page) ;
-
-               if (!p)
-               {       len = 0 ;
-                       break ;
-                       } ;
-
-               if (p->isillegal && !p->shownillegal)
-               {
-                       p->shownillegal = 1 ;
-                       /* If it's a new stream, we want to continue processing this page
-                       ** anyway to suppress additional spurious errors
-                       */
-                       if (!p->isnew) continue ;
-                       } ;
-
-               if (!p->isillegal)
-               {       ogg_packet packet ;
-                       int header = 0 ;
-
-                       ogg_stream_pagein (&p->ostream, &page) ;
-                       if (p->doneheaders < 3)
-                               header = 1 ;
-
-                       while (ogg_stream_packetout (&p->ostream, &packet) > 0)
-                       {
-                               if (p->doneheaders < 3)
-                               {       if (vorbis_synthesis_headerin (&p->vinfo, &p->vcomment, &packet) < 0)
-                                               continue ;
-                                       p->doneheaders ++ ;
-                                       } ;
-                               } ;
-                       if (!header)
-                       {       sf_count_t gp = ogg_page_granulepos (&page) ;
-                               if (gp > 0) p->lastgranulepos = gp ;
-                               } ;
-                       if (p->end)
-                       {       vorbis_end (p, &len) ;
-                               p->isillegal = 1 ;
-                               } ;
+vorbis_calculate_page_duration (SF_PRIVATE *psf)
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+       long thisblock, lastblock ;
+       sf_count_t duration ;
+       int i ;
+
+       lastblock = -1 ;
+       duration = 0 ;
+       for (i = 0 ; i < odata->pkt_len ; i++)
+       {       thisblock = vorbis_packet_blocksize (&vdata->vinfo, &(odata->pkt [i])) ;
+               if (thisblock >= 0)
+               {       if (lastblock != -1)
+                               duration += (lastblock + thisblock) >> 2 ;
+                       lastblock = thisblock ;
                        } ;
                } ;
 
-       ogg_sync_clear (&osync) ;
-       free_stream_set (processors, &len) ;
-
-       return len ;
-} /* vorbis_length_aux */
-
-static sf_count_t
-vorbis_length (SF_PRIVATE *psf)
-{      sf_count_t length ;
-       int error ;
-
-       if (psf->sf.seekable == 0)
-               return SF_COUNT_MAX ;
-
-       psf_fseek (psf, 0, SEEK_SET) ;
-       length = vorbis_length_aux (psf) ;
-
-       psf_fseek (psf, 12, SEEK_SET) ;
-       if ((error = vorbis_read_header (psf, 0)) != 0)
-               psf->error = error ;
-
-       return length ;
-} /* vorbis_length */
+       return duration ;
+}
 
 #else /* HAVE_EXTERNAL_XIPH_LIBS */
 
index e9e0ed4..459bc46 100644 (file)
--- a/src/paf.c
+++ b/src/paf.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -303,19 +303,19 @@ paf_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
 
        if (psf->endian == SF_ENDIAN_BIG)
        {       /* Marker, version, endianness, samplerate */
-               psf_binheader_writef (psf, "Em444", PAF_MARKER, 0, 0, psf->sf.samplerate) ;
+               psf_binheader_writef (psf, "Em444", BHWm (PAF_MARKER), BHW4 (0), BHW4 (0), BHW4 (psf->sf.samplerate)) ;
                /* format, channels, source */
-               psf_binheader_writef (psf, "E444", paf_format, psf->sf.channels, 0) ;
+               psf_binheader_writef (psf, "E444", BHW4 (paf_format), BHW4 (psf->sf.channels), BHW4 (0)) ;
                }
        else if (psf->endian == SF_ENDIAN_LITTLE)
        {       /* Marker, version, endianness, samplerate */
-               psf_binheader_writef (psf, "em444", FAP_MARKER, 0, 1, psf->sf.samplerate) ;
+               psf_binheader_writef (psf, "em444", BHWm (FAP_MARKER), BHW4 (0), BHW4 (1), BHW4 (psf->sf.samplerate)) ;
                /* format, channels, source */
-               psf_binheader_writef (psf, "e444", paf_format, psf->sf.channels, 0) ;
+               psf_binheader_writef (psf, "e444", BHW4 (paf_format), BHW4 (psf->sf.channels), BHW4 (0)) ;
                } ;
 
        /* Zero fill to dataoffset. */
-       psf_binheader_writef (psf, "z", (size_t) (psf->dataoffset - psf->header.indx)) ;
+       psf_binheader_writef (psf, "z", BHWz ((size_t) (psf->dataoffset - psf->header.indx))) ;
 
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
 
@@ -774,7 +774,7 @@ paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       iptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       iptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = paf24_write (psf, ppaf24, iptr, writecount) ;
                total += count ;
                len -= writecount ;
@@ -805,7 +805,7 @@ paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : len ;
                for (k = 0 ; k < writecount ; k++)
-                       iptr [k] = lrint (normfact * ptr [total+k]) ;
+                       iptr [k] = psf_lrint (normfact * ptr [total+k]) ;
                count = paf24_write (psf, ppaf24, iptr, writecount) ;
                total += count ;
                len -= writecount ;
index d10336a..3ea0d09 100644 (file)
--- a/src/pcm.c
+++ b/src/pcm.c
@@ -28,7 +28,9 @@
 ** type and use SIZEOF_TRIBYTE instead of (tribyte).
 */
 
-typedef        void    tribyte ;
+typedef        struct tribyte
+{      uint8_t bytes [3] ;
+       } tribyte ;
 
 #define        SIZEOF_TRIBYTE  3
 
@@ -280,43 +282,33 @@ pcm_init (SF_PRIVATE *psf)
 */
 
 static inline void
-sc2s_array     (signed char *src, int count, short *dest)
+sc2s_array     (const signed char *src, int count, short *dest)
 {      while (--count >= 0)
        {       dest [count] = ((uint16_t) src [count]) << 8 ;
                } ;
 } /* sc2s_array */
 
 static inline void
-uc2s_array     (unsigned char *src, int count, short *dest)
+uc2s_array     (const unsigned char *src, int count, short *dest)
 {      while (--count >= 0)
        {       dest [count] = (((uint32_t) src [count]) - 0x80) << 8 ;
                } ;
 } /* uc2s_array */
 
 static inline void
-let2s_array (tribyte *src, int count, short *dest)
-{      unsigned char   *ucptr ;
-
-       ucptr = ((unsigned char*) src) + 3 * count ;
-       while (--count >= 0)
-       {       ucptr -= 3 ;
-               dest [count] = LET2H_16_PTR (ucptr) ;
-               } ;
+let2s_array (const tribyte *src, int count, short *dest)
+{      while (--count >= 0)
+               dest [count] = LET2H_16_PTR (src [count].bytes) ;
 } /* let2s_array */
 
 static inline void
-bet2s_array (tribyte *src, int count, short *dest)
-{      unsigned char   *ucptr ;
-
-       ucptr = ((unsigned char*) src) + 3 * count ;
-       while (--count >= 0)
-       {       ucptr -= 3 ;
-               dest [count] = BET2H_16_PTR (ucptr) ;
-               } ;
+bet2s_array (const tribyte *src, int count, short *dest)
+{      while (--count >= 0)
+               dest [count] = BET2H_16_PTR (src [count].bytes) ;
 } /* bet2s_array */
 
 static inline void
-lei2s_array (int *src, int count, short *dest)
+lei2s_array (const int *src, int count, short *dest)
 {      int value ;
 
        while (--count >= 0)
@@ -326,7 +318,7 @@ lei2s_array (int *src, int count, short *dest)
 } /* lei2s_array */
 
 static inline void
-bei2s_array (int *src, int count, short *dest)
+bei2s_array (const int *src, int count, short *dest)
 {      int value ;
 
        while (--count >= 0)
@@ -339,21 +331,21 @@ bei2s_array (int *src, int count, short *dest)
 */
 
 static inline void
-sc2i_array     (signed char *src, int count, int *dest)
+sc2i_array     (const signed char *src, int count, int *dest)
 {      while (--count >= 0)
        {       dest [count] = arith_shift_left ((int) src [count], 24) ;
                } ;
 } /* sc2i_array */
 
 static inline void
-uc2i_array     (unsigned char *src, int count, int *dest)
+uc2i_array     (const unsigned char *src, int count, int *dest)
 {      while (--count >= 0)
        {       dest [count] = arith_shift_left (((int) src [count]) - 128, 24) ;
                } ;
 } /* uc2i_array */
 
 static inline void
-bes2i_array (short *src, int count, int *dest)
+bes2i_array (const short *src, int count, int *dest)
 {      short value ;
 
        while (--count >= 0)
@@ -363,7 +355,7 @@ bes2i_array (short *src, int count, int *dest)
 } /* bes2i_array */
 
 static inline void
-les2i_array (short *src, int count, int *dest)
+les2i_array (const short *src, int count, int *dest)
 {      short value ;
 
        while (--count >= 0)
@@ -373,44 +365,34 @@ les2i_array (short *src, int count, int *dest)
 } /* les2i_array */
 
 static inline void
-bet2i_array (tribyte *src, int count, int *dest)
-{      unsigned char   *ucptr ;
-
-       ucptr = ((unsigned char*) src) + 3 * count ;
-       while (--count >= 0)
-       {       ucptr -= 3 ;
-               dest [count] = psf_get_be24 (ucptr, 0) ;
-               } ;
+bet2i_array (const tribyte *src, int count, int *dest)
+{      while (--count >= 0)
+               dest [count] = psf_get_be24 (src [count].bytes, 0) ;
 } /* bet2i_array */
 
 static inline void
-let2i_array (tribyte *src, int count, int *dest)
-{      unsigned char   *ucptr ;
-
-       ucptr = ((unsigned char*) src) + 3 * count ;
-       while (--count >= 0)
-       {       ucptr -= 3 ;
-               dest [count] = psf_get_le24 (ucptr, 0) ;
-               } ;
+let2i_array (const tribyte *src, int count, int *dest)
+{      while (--count >= 0)
+               dest [count] = psf_get_le24 (src [count].bytes, 0) ;
 } /* let2i_array */
 
 /*--------------------------------------------------------------------------
 */
 
 static inline void
-sc2f_array     (signed char *src, int count, float *dest, float normfact)
+sc2f_array     (const signed char *src, int count, float *dest, float normfact)
 {      while (--count >= 0)
                dest [count] = ((float) src [count]) * normfact ;
 } /* sc2f_array */
 
 static inline void
-uc2f_array     (unsigned char *src, int count, float *dest, float normfact)
+uc2f_array     (const unsigned char *src, int count, float *dest, float normfact)
 {      while (--count >= 0)
                dest [count] = (((int) src [count]) - 128) * normfact ;
 } /* uc2f_array */
 
 static inline void
-les2f_array (short *src, int count, float *dest, float normfact)
+les2f_array (const short *src, int count, float *dest, float normfact)
 {      short   value ;
 
        while (--count >= 0)
@@ -421,7 +403,7 @@ les2f_array (short *src, int count, float *dest, float normfact)
 } /* les2f_array */
 
 static inline void
-bes2f_array (short *src, int count, float *dest, float normfact)
+bes2f_array (const short *src, int count, float *dest, float normfact)
 {      short                   value ;
 
        while (--count >= 0)
@@ -432,33 +414,27 @@ bes2f_array (short *src, int count, float *dest, float normfact)
 } /* bes2f_array */
 
 static inline void
-let2f_array (tribyte *src, int count, float *dest, float normfact)
-{      unsigned char   *ucptr ;
-       int                     value ;
+let2f_array (const tribyte *src, int count, float *dest, float normfact)
+{      int value ;
 
-       ucptr = ((unsigned char*) src) + 3 * count ;
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = psf_get_le24 (ucptr, 0) ;
+       {       value = psf_get_le24 (src [count].bytes, 0) ;
                dest [count] = ((float) value) * normfact ;
                } ;
 } /* let2f_array */
 
 static inline void
-bet2f_array (tribyte *src, int count, float *dest, float normfact)
-{      unsigned char   *ucptr ;
-       int                             value ;
+bet2f_array (const tribyte *src, int count, float *dest, float normfact)
+{      int value ;
 
-       ucptr = ((unsigned char*) src) + 3 * count ;
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = psf_get_be24 (ucptr, 0) ;
+       {       value = psf_get_be24 (src [count].bytes, 0) ;
                dest [count] = ((float) value) * normfact ;
                } ;
 } /* bet2f_array */
 
 static inline void
-lei2f_array (int *src, int count, float *dest, float normfact)
+lei2f_array (const int *src, int count, float *dest, float normfact)
 {      int                     value ;
 
        while (--count >= 0)
@@ -469,7 +445,7 @@ lei2f_array (int *src, int count, float *dest, float normfact)
 } /* lei2f_array */
 
 static inline void
-bei2f_array (int *src, int count, float *dest, float normfact)
+bei2f_array (const int *src, int count, float *dest, float normfact)
 {      int                     value ;
 
        while (--count >= 0)
@@ -483,19 +459,19 @@ bei2f_array (int *src, int count, float *dest, float normfact)
 */
 
 static inline void
-sc2d_array     (signed char *src, int count, double *dest, double normfact)
+sc2d_array     (const signed char *src, int count, double *dest, double normfact)
 {      while (--count >= 0)
                dest [count] = ((double) src [count]) * normfact ;
 } /* sc2d_array */
 
 static inline void
-uc2d_array     (unsigned char *src, int count, double *dest, double normfact)
+uc2d_array     (const unsigned char *src, int count, double *dest, double normfact)
 {      while (--count >= 0)
                dest [count] = (((int) src [count]) - 128) * normfact ;
 } /* uc2d_array */
 
 static inline void
-les2d_array (short *src, int count, double *dest, double normfact)
+les2d_array (const short *src, int count, double *dest, double normfact)
 {      short   value ;
 
        while (--count >= 0)
@@ -506,7 +482,7 @@ les2d_array (short *src, int count, double *dest, double normfact)
 } /* les2d_array */
 
 static inline void
-bes2d_array (short *src, int count, double *dest, double normfact)
+bes2d_array (const short *src, int count, double *dest, double normfact)
 {      short   value ;
 
        while (--count >= 0)
@@ -517,33 +493,27 @@ bes2d_array (short *src, int count, double *dest, double normfact)
 } /* bes2d_array */
 
 static inline void
-let2d_array (tribyte *src, int count, double *dest, double normfact)
-{      unsigned char   *ucptr ;
-       int                             value ;
+let2d_array (const tribyte *src, int count, double *dest, double normfact)
+{      int value ;
 
-       ucptr = ((unsigned char*) src) + 3 * count ;
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = psf_get_le24 (ucptr, 0) ;
+       {       value = psf_get_le24 (src [count].bytes, 0) ;
                dest [count] = ((double) value) * normfact ;
                } ;
 } /* let2d_array */
 
 static inline void
-bet2d_array (tribyte *src, int count, double *dest, double normfact)
-{      unsigned char   *ucptr ;
-       int                             value ;
+bet2d_array (const tribyte *src, int count, double *dest, double normfact)
+{      int value ;
 
-       ucptr = ((unsigned char*) src) + 3 * count ;
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = psf_get_be24 (ucptr, 0) ;
+       {       value = psf_get_be24 (src [count].bytes, 0) ;
                dest [count] = ((double) value) * normfact ;
                } ;
 } /* bet2d_array */
 
 static inline void
-lei2d_array (int *src, int count, double *dest, double normfact)
+lei2d_array (const int *src, int count, double *dest, double normfact)
 {      int     value ;
 
        while (--count >= 0)
@@ -554,7 +524,7 @@ lei2d_array (int *src, int count, double *dest, double normfact)
 } /* lei2d_array */
 
 static inline void
-bei2d_array (int *src, int count, double *dest, double normfact)
+bei2d_array (const int *src, int count, double *dest, double normfact)
 {      int     value ;
 
        while (--count >= 0)
@@ -581,27 +551,19 @@ s2uc_array        (const short *src, unsigned char *dest, int count)
 
 static inline void
 s2let_array (const short *src, tribyte *dest, int count)
-{      unsigned char   *ucptr ;
-
-       ucptr = ((unsigned char*) dest) + 3 * count ;
-       while (--count >= 0)
-       {       ucptr -= 3 ;
-               ucptr [0] = 0 ;
-               ucptr [1] = src [count] ;
-               ucptr [2] = src [count] >> 8 ;
+{      while (--count >= 0)
+       {       dest [count].bytes [0] = 0 ;
+               dest [count].bytes [1] = src [count] ;
+               dest [count].bytes [2] = src [count] >> 8 ;
                } ;
 } /* s2let_array */
 
 static inline void
 s2bet_array (const short *src, tribyte *dest, int count)
-{      unsigned char   *ucptr ;
-
-       ucptr = ((unsigned char*) dest) + 3 * count ;
-       while (--count >= 0)
-       {       ucptr -= 3 ;
-               ucptr [2] = 0 ;
-               ucptr [1] = src [count] ;
-               ucptr [0] = src [count] >> 8 ;
+{      while (--count >= 0)
+       {       dest [count].bytes [2] = 0 ;
+               dest [count].bytes [1] = src [count] ;
+               dest [count].bytes [0] = src [count] >> 8 ;
                } ;
 } /* s2bet_array */
 
@@ -674,31 +636,25 @@ i2les_array (const int *src, short *dest, int count)
 
 static inline void
 i2let_array (const int *src, tribyte *dest, int count)
-{      unsigned char   *ucptr ;
-       int                             value ;
+{      int value ;
 
-       ucptr = ((unsigned char*) dest) + 3 * count ;
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = src [count] >> 8 ;
-               ucptr [0] = value ;
-               ucptr [1] = value >> 8 ;
-               ucptr [2] = value >> 16 ;
+       {       value = src [count] >> 8 ;
+               dest [count].bytes [0] = value ;
+               dest [count].bytes [1] = value >> 8 ;
+               dest [count].bytes [2] = value >> 16 ;
                } ;
 } /* i2let_array */
 
 static inline void
 i2bet_array (const int *src, tribyte *dest, int count)
-{      unsigned char   *ucptr ;
-       int                             value ;
+{      int value ;
 
-       ucptr = ((unsigned char*) dest) + 3 * count ;
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = src [count] >> 8 ;
-               ucptr [2] = value ;
-               ucptr [1] = value >> 8 ;
-               ucptr [0] = value >> 16 ;
+       {       value = src [count] >> 8 ;
+               dest [count].bytes [2] = value ;
+               dest [count].bytes [1] = value >> 8 ;
+               dest [count].bytes [0] = value >> 16 ;
                } ;
 } /* i2bet_array */
 
@@ -1810,7 +1766,7 @@ f2sc_array (const float *src, signed char *dest, int count, int normalize)
        normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
 
        while (--count >= 0)
-       {       dest [count] = lrintf (src [count] * normfact) ;
+       {       dest [count] = psf_lrintf (src [count] * normfact) ;
                } ;
 } /* f2sc_array */
 
@@ -1831,7 +1787,7 @@ f2sc_clip_array (const float *src, signed char *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               dest [count] = lrintf (scaled_value) >> 24 ;
+               dest [count] = psf_lrintf (scaled_value) >> 24 ;
                } ;
 } /* f2sc_clip_array */
 
@@ -1869,7 +1825,7 @@ f2uc_array        (const float *src, unsigned char *dest, int count, int normalize)
        normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
 
        while (--count >= 0)
-       {       dest [count] = lrintf (src [count] * normfact) + 128 ;
+       {       dest [count] = psf_lrintf (src [count] * normfact) + 128 ;
                } ;
 } /* f2uc_array */
 
@@ -1890,7 +1846,7 @@ f2uc_clip_array   (const float *src, unsigned char *dest, int count, int normalize
                        continue ;
                        } ;
 
-               dest [count] = (lrintf (scaled_value) >> 24) + 128 ;
+               dest [count] = (psf_lrintf (scaled_value) >> 24) + 128 ;
                } ;
 } /* f2uc_clip_array */
 
@@ -1932,7 +1888,7 @@ f2bes_array (const float *src, short *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 2 ;
-               value = lrintf (src [count] * normfact) ;
+               value = psf_lrintf (src [count] * normfact) ;
                ucptr [1] = value ;
                ucptr [0] = value >> 8 ;
                        } ;
@@ -1961,7 +1917,7 @@ f2bes_clip_array (const float *src, short *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrintf (scaled_value) ;
+               value = psf_lrintf (scaled_value) ;
                ucptr [1] = value >> 16 ;
                ucptr [0] = value >> 24 ;
                } ;
@@ -2005,7 +1961,7 @@ f2les_array (const float *src, short *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 2 ;
-               value = lrintf (src [count] * normfact) ;
+               value = psf_lrintf (src [count] * normfact) ;
                ucptr [0] = value ;
                ucptr [1] = value >> 8 ;
                } ;
@@ -2034,7 +1990,7 @@ f2les_clip_array (const float *src, short *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrintf (scaled_value) ;
+               value = psf_lrintf (scaled_value) ;
                ucptr [0] = value >> 16 ;
                ucptr [1] = value >> 24 ;
                } ;
@@ -2069,51 +2025,45 @@ pcm_write_f2les (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
 
 static void
 f2let_array (const float *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       float                   normfact ;
-       int                             value ;
+{      float   normfact ;
+       int             value ;
 
        normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = lrintf (src [count] * normfact) ;
-               ucptr [0] = value ;
-               ucptr [1] = value >> 8 ;
-               ucptr [2] = value >> 16 ;
+       {       value = psf_lrintf (src [count] * normfact) ;
+               dest [count].bytes [0] = value ;
+               dest [count].bytes [1] = value >> 8 ;
+               dest [count].bytes [2] = value >> 16 ;
                } ;
 } /* f2let_array */
 
 static void
 f2let_clip_array (const float *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       float                   normfact, scaled_value ;
-       int                             value ;
+{      float   normfact, scaled_value ;
+       int             value ;
 
        normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               scaled_value = src [count] * normfact ;
+       {       scaled_value = src [count] * normfact ;
                if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
-               {       ucptr [0] = 0xFF ;
-                       ucptr [1] = 0xFF ;
-                       ucptr [2] = 0x7F ;
+               {       dest [count].bytes [0] = 0xFF ;
+                       dest [count].bytes [1] = 0xFF ;
+                       dest [count].bytes [2] = 0x7F ;
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
-               {       ucptr [0] = 0x00 ;
-                       ucptr [1] = 0x00 ;
-                       ucptr [2] = 0x80 ;
+               {       dest [count].bytes [0] = 0x00 ;
+                       dest [count].bytes [1] = 0x00 ;
+                       dest [count].bytes [2] = 0x80 ;
                        continue ;
                } ;
 
-               value = lrintf (scaled_value) ;
-               ucptr [0] = value >> 8 ;
-               ucptr [1] = value >> 16 ;
-               ucptr [2] = value >> 24 ;
+               value = psf_lrintf (scaled_value) ;
+               dest [count].bytes [0] = value >> 8 ;
+               dest [count].bytes [1] = value >> 16 ;
+               dest [count].bytes [2] = value >> 24 ;
                } ;
 } /* f2let_clip_array */
 
@@ -2146,51 +2096,45 @@ pcm_write_f2let (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
 
 static void
 f2bet_array (const float *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       float                   normfact ;
-       int                             value ;
+{      float   normfact ;
+       int             value ;
 
        normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = lrintf (src [count] * normfact) ;
-               ucptr [0] = value >> 16 ;
-               ucptr [1] = value >> 8 ;
-               ucptr [2] = value ;
+       {       value = psf_lrintf (src [count] * normfact) ;
+               dest [count].bytes [0] = value >> 16 ;
+               dest [count].bytes [1] = value >> 8 ;
+               dest [count].bytes [2] = value ;
                } ;
 } /* f2bet_array */
 
 static void
 f2bet_clip_array (const float *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       float                   normfact, scaled_value ;
-       int                             value ;
+{      float   normfact, scaled_value ;
+       int             value ;
 
        normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               scaled_value = src [count] * normfact ;
+       {       scaled_value = src [count] * normfact ;
                if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
-               {       ucptr [0] = 0x7F ;
-                       ucptr [1] = 0xFF ;
-                       ucptr [2] = 0xFF ;
+               {       dest [count].bytes [0] = 0x7F ;
+                       dest [count].bytes [1] = 0xFF ;
+                       dest [count].bytes [2] = 0xFF ;
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
-               {       ucptr [0] = 0x80 ;
-                       ucptr [1] = 0x00 ;
-                       ucptr [2] = 0x00 ;
+               {       dest [count].bytes [0] = 0x80 ;
+                       dest [count].bytes [1] = 0x00 ;
+                       dest [count].bytes [2] = 0x00 ;
                        continue ;
                } ;
 
-               value = lrint (scaled_value) ;
-               ucptr [0] = value >> 24 ;
-               ucptr [1] = value >> 16 ;
-               ucptr [2] = value >> 8 ;
+               value = psf_lrint (scaled_value) ;
+               dest [count].bytes [0] = value >> 24 ;
+               dest [count].bytes [1] = value >> 16 ;
+               dest [count].bytes [2] = value >> 8 ;
                } ;
 } /* f2bet_clip_array */
 
@@ -2231,7 +2175,7 @@ f2bei_array (const float *src, int *dest, int count, int normalize)
        ucptr = ((unsigned char*) dest) + 4 * count ;
        while (--count >= 0)
        {       ucptr -= 4 ;
-               value = lrintf (src [count] * normfact) ;
+               value = psf_lrintf (src [count] * normfact) ;
                ucptr [0] = value >> 24 ;
                ucptr [1] = value >> 16 ;
                ucptr [2] = value >> 8 ;
@@ -2266,7 +2210,7 @@ f2bei_clip_array (const float *src, int *dest, int count, int normalize)
                        continue ;
                } ;
 
-               value = lrintf (scaled_value) ;
+               value = psf_lrintf (scaled_value) ;
                ucptr [0] = value >> 24 ;
                ucptr [1] = value >> 16 ;
                ucptr [2] = value >> 8 ;
@@ -2312,7 +2256,7 @@ f2lei_array (const float *src, int *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 4 ;
-               value = lrintf (src [count] * normfact) ;
+               value = psf_lrintf (src [count] * normfact) ;
                ucptr [0] = value ;
                ucptr [1] = value >> 8 ;
                ucptr [2] = value >> 16 ;
@@ -2347,7 +2291,7 @@ f2lei_clip_array (const float *src, int *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrintf (scaled_value) ;
+               value = psf_lrintf (scaled_value) ;
                ucptr [0] = value ;
                ucptr [1] = value >> 8 ;
                ucptr [2] = value >> 16 ;
@@ -2389,7 +2333,7 @@ d2sc_array        (const double *src, signed char *dest, int count, int normalize)
        normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
 
        while (--count >= 0)
-       {       dest [count] = lrint (src [count] * normfact) ;
+       {       dest [count] = psf_lrint (src [count] * normfact) ;
                } ;
 } /* d2sc_array */
 
@@ -2410,7 +2354,7 @@ d2sc_clip_array   (const double *src, signed char *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               dest [count] = lrintf (scaled_value) >> 24 ;
+               dest [count] = psf_lrintf (scaled_value) >> 24 ;
                } ;
 } /* d2sc_clip_array */
 
@@ -2448,7 +2392,7 @@ d2uc_array        (const double *src, unsigned char *dest, int count, int normalize)
        normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
 
        while (--count >= 0)
-       {       dest [count] = lrint (src [count] * normfact) + 128 ;
+       {       dest [count] = psf_lrint (src [count] * normfact) + 128 ;
                } ;
 } /* d2uc_array */
 
@@ -2469,7 +2413,7 @@ d2uc_clip_array   (const double *src, unsigned char *dest, int count, int normaliz
                        continue ;
                        } ;
 
-               dest [count] = (lrint (src [count] * normfact) >> 24) + 128 ;
+               dest [count] = (psf_lrint (src [count] * normfact) >> 24) + 128 ;
                } ;
 } /* d2uc_clip_array */
 
@@ -2511,7 +2455,7 @@ d2bes_array (const double *src, short *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 2 ;
-               value = lrint (src [count] * normfact) ;
+               value = psf_lrint (src [count] * normfact) ;
                ucptr [1] = value ;
                ucptr [0] = value >> 8 ;
                } ;
@@ -2540,7 +2484,7 @@ d2bes_clip_array (const double *src, short *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrint (scaled_value) ;
+               value = psf_lrint (scaled_value) ;
                ucptr [1] = value >> 16 ;
                ucptr [0] = value >> 24 ;
                } ;
@@ -2584,7 +2528,7 @@ d2les_array (const double *src, short *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 2 ;
-               value = lrint (src [count] * normfact) ;
+               value = psf_lrint (src [count] * normfact) ;
                ucptr [0] = value ;
                ucptr [1] = value >> 8 ;
                } ;
@@ -2613,7 +2557,7 @@ d2les_clip_array (const double *src, short *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrint (scaled_value) ;
+               value = psf_lrint (scaled_value) ;
                ucptr [0] = value >> 16 ;
                ucptr [1] = value >> 24 ;
                } ;
@@ -2648,51 +2592,45 @@ pcm_write_d2les (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
 
 static void
 d2let_array (const double *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       int                             value ;
-       double                  normfact ;
+{      int             value ;
+       double  normfact ;
 
        normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = lrint (src [count] * normfact) ;
-               ucptr [0] = value ;
-               ucptr [1] = value >> 8 ;
-               ucptr [2] = value >> 16 ;
+       {       value = psf_lrint (src [count] * normfact) ;
+               dest [count].bytes [0] = value ;
+               dest [count].bytes [1] = value >> 8 ;
+               dest [count].bytes [2] = value >> 16 ;
                } ;
 } /* d2let_array */
 
 static void
 d2let_clip_array (const double *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       int                             value ;
-       double                  normfact, scaled_value ;
+{      int             value ;
+       double  normfact, scaled_value ;
 
        normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               scaled_value = src [count] * normfact ;
+       {       scaled_value = src [count] * normfact ;
                if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
-               {       ucptr [0] = 0xFF ;
-                       ucptr [1] = 0xFF ;
-                       ucptr [2] = 0x7F ;
+               {       dest [count].bytes [0] = 0xFF ;
+                       dest [count].bytes [1] = 0xFF ;
+                       dest [count].bytes [2] = 0x7F ;
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
-               {       ucptr [0] = 0x00 ;
-                       ucptr [1] = 0x00 ;
-                       ucptr [2] = 0x80 ;
+               {       dest [count].bytes [0] = 0x00 ;
+                       dest [count].bytes [1] = 0x00 ;
+                       dest [count].bytes [2] = 0x80 ;
                        continue ;
                        } ;
 
-               value = lrint (scaled_value) ;
-               ucptr [0] = value >> 8 ;
-               ucptr [1] = value >> 16 ;
-               ucptr [2] = value >> 24 ;
+               value = psf_lrint (scaled_value) ;
+               dest [count].bytes [0] = value >> 8 ;
+               dest [count].bytes [1] = value >> 16 ;
+               dest [count].bytes [2] = value >> 24 ;
                } ;
 } /* d2let_clip_array */
 
@@ -2725,51 +2663,45 @@ pcm_write_d2let (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
 
 static void
 d2bet_array (const double *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       int                             value ;
-       double                  normfact ;
+{      int             value ;
+       double  normfact ;
 
        normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               value = lrint (src [count] * normfact) ;
-               ucptr [2] = value ;
-               ucptr [1] = value >> 8 ;
-               ucptr [0] = value >> 16 ;
+       {       value = psf_lrint (src [count] * normfact) ;
+               dest [count].bytes [2] = value ;
+               dest [count].bytes [1] = value >> 8 ;
+               dest [count].bytes [0] = value >> 16 ;
                } ;
 } /* d2bet_array */
 
 static void
 d2bet_clip_array (const double *src, tribyte *dest, int count, int normalize)
-{      unsigned char   *ucptr ;
-       int                             value ;
-       double                  normfact, scaled_value ;
+{      int             value ;
+       double  normfact, scaled_value ;
 
        normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ;
-       ucptr = ((unsigned char*) dest) + 3 * count ;
 
        while (--count >= 0)
-       {       ucptr -= 3 ;
-               scaled_value = src [count] * normfact ;
+       {       scaled_value = src [count] * normfact ;
                if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
-               {       ucptr [2] = 0xFF ;
-                       ucptr [1] = 0xFF ;
-                       ucptr [0] = 0x7F ;
+               {       dest [count].bytes [2] = 0xFF ;
+                       dest [count].bytes [1] = 0xFF ;
+                       dest [count].bytes [0] = 0x7F ;
                        continue ;
                        } ;
                if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
-               {       ucptr [2] = 0x00 ;
-                       ucptr [1] = 0x00 ;
-                       ucptr [0] = 0x80 ;
+               {       dest [count].bytes [2] = 0x00 ;
+                       dest [count].bytes [1] = 0x00 ;
+                       dest [count].bytes [0] = 0x80 ;
                        continue ;
                        } ;
 
-               value = lrint (scaled_value) ;
-               ucptr [2] = value >> 8 ;
-               ucptr [1] = value >> 16 ;
-               ucptr [0] = value >> 24 ;
+               value = psf_lrint (scaled_value) ;
+               dest [count].bytes [2] = value >> 8 ;
+               dest [count].bytes [1] = value >> 16 ;
+               dest [count].bytes [0] = value >> 24 ;
                } ;
 } /* d2bet_clip_array */
 
@@ -2811,7 +2743,7 @@ d2bei_array (const double *src, int *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 4 ;
-               value = lrint (src [count] * normfact) ;
+               value = psf_lrint (src [count] * normfact) ;
                ucptr [0] = value >> 24 ;
                ucptr [1] = value >> 16 ;
                ucptr [2] = value >> 8 ;
@@ -2846,7 +2778,7 @@ d2bei_clip_array (const double *src, int *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrint (scaled_value) ;
+               value = psf_lrint (scaled_value) ;
                ucptr [0] = value >> 24 ;
                ucptr [1] = value >> 16 ;
                ucptr [2] = value >> 8 ;
@@ -2892,7 +2824,7 @@ d2lei_array (const double *src, int *dest, int count, int normalize)
 
        while (--count >= 0)
        {       ucptr -= 4 ;
-               value = lrint (src [count] * normfact) ;
+               value = psf_lrint (src [count] * normfact) ;
                ucptr [0] = value ;
                ucptr [1] = value >> 8 ;
                ucptr [2] = value >> 16 ;
@@ -2927,7 +2859,7 @@ d2lei_clip_array (const double *src, int *dest, int count, int normalize)
                        continue ;
                        } ;
 
-               value = lrint (scaled_value) ;
+               value = psf_lrint (scaled_value) ;
                ucptr [0] = value ;
                ucptr [1] = value >> 8 ;
                ucptr [2] = value >> 16 ;
index e5dc49e..c8fcbfd 100644 (file)
--- a/src/raw.c
+++ b/src/raw.c
@@ -72,6 +72,13 @@ raw_open     (SF_PRIVATE *psf)
                                break ;
 
                /* Lite remove start */
+
+               case SF_FORMAT_NMS_ADPCM_16 :
+               case SF_FORMAT_NMS_ADPCM_24 :
+               case SF_FORMAT_NMS_ADPCM_32 :
+                               error = nms_adpcm_init (psf) ;
+                               break ;
+
                case SF_FORMAT_FLOAT :
                                error = float32_init (psf) ;
                                break ;
index c373bb0..876cd45 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2008-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2008-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2009      Uli Franke <cls@nebadje.org>
 **
 ** This program is free software; you can redistribute it and/or modify
@@ -339,6 +339,12 @@ rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
                                        } ;
                                break ;
 
+                       case JUNK_MARKER :
+                       case PAD_MARKER :
+                               psf_log_printf (psf, "%M : %d\n", marker, chunk_size) ;
+                               psf_binheader_readf (psf, "j", chunk_size) ;
+                               break ;
+
                        default :
                                        if (chunk_size >= 0xffff0000)
                                        {       psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %u. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ;
@@ -382,7 +388,7 @@ rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
        if (psf->sf.channels < 1)
                return SFE_CHANNEL_COUNT_ZERO ;
 
-       if (psf->sf.channels >= SF_MAX_CHANNELS)
+       if (psf->sf.channels > SF_MAX_CHANNELS)
                return SFE_CHANNEL_COUNT ;
 
        /* WAVs can be little or big endian */
@@ -537,25 +543,25 @@ rf64_write_fmt_chunk (SF_PRIVATE *psf)
                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ;
 
                        /* fmt : format, channels, samplerate */
-                       psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ;
+                       psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_EXTENSIBLE), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                        /*  fmt : bytespersec */
-                       psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                       psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                        /*  fmt : blockalign, bitwidth */
-                       psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
+                       psf_binheader_writef (psf, "22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ;
 
                        /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */
-                       psf_binheader_writef (psf, "2", 22) ;
+                       psf_binheader_writef (psf, "2", BHW2 (22)) ;
 
                        /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */
-                       psf_binheader_writef (psf, "2", psf->bytewidth * 8) ;
+                       psf_binheader_writef (psf, "2", BHW2 (psf->bytewidth * 8)) ;
 
                        /* For an Ambisonic file set the channel mask to zero.
                        ** Otherwise use a default based on the channel count.
                        */
                        if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE)
-                               psf_binheader_writef (psf, "4", 0) ;
+                               psf_binheader_writef (psf, "4", BHW4 (0)) ;
                        else if (wpriv->wavex_channelmask != 0)
-                               psf_binheader_writef (psf, "4", wpriv->wavex_channelmask) ;
+                               psf_binheader_writef (psf, "4", BHW4 (wpriv->wavex_channelmask)) ;
                        else
                        {       /*
                                ** Ok some liberty is taken here to use the most commonly used channel masks
@@ -564,27 +570,27 @@ rf64_write_fmt_chunk (SF_PRIVATE *psf)
                                */
                                switch (psf->sf.channels)
                                {       case 1 :        /* center channel mono */
-                                               psf_binheader_writef (psf, "4", 0x4) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x4)) ;
                                                break ;
 
                                        case 2 :        /* front left and right */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2)) ;
                                                break ;
 
                                        case 4 :        /* Quad */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x10 | 0x20) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x10 | 0x20)) ;
                                                break ;
 
                                        case 6 :        /* 5.1 */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20)) ;
                                                break ;
 
                                        case 8 :        /* 7.1 */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80)) ;
                                                break ;
 
                                        default :       /* 0 when in doubt , use direct out, ie NO mapping*/
-                                               psf_binheader_writef (psf, "4", 0x0) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x0)) ;
                                                break ;
                                        } ;
                                } ;
@@ -658,18 +664,18 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
        psf_fseek (psf, 0, SEEK_SET) ;
 
        if (wpriv->rf64_downgrade && psf->filelength < RIFF_DOWNGRADE_BYTES)
-       {       psf_binheader_writef (psf, "etm8m", RIFF_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8, WAVE_MARKER) ;
-               psf_binheader_writef (psf, "m4884", JUNK_MARKER, 20, 0, 0, 0, 0) ;
+       {       psf_binheader_writef (psf, "etm8m", BHWm (RIFF_MARKER), BHW8 ((psf->filelength < 8) ? 8 : psf->filelength - 8), BHWm (WAVE_MARKER)) ;
+               psf_binheader_writef (psf, "m4z", BHWm (JUNK_MARKER), BHW4 (24), BHWz (24)) ;
                add_fact_chunk = 1 ;
                }
        else
-       {       psf_binheader_writef (psf, "em4m", RF64_MARKER, 0xffffffff, WAVE_MARKER) ;
+       {       psf_binheader_writef (psf, "em4m", BHWm (RF64_MARKER), BHW4 (0xffffffff), BHWm (WAVE_MARKER)) ;
                /* Currently no table. */
-               psf_binheader_writef (psf, "m48884", ds64_MARKER, 28, psf->filelength - 8, psf->datalength, psf->sf.frames, 0) ;
+               psf_binheader_writef (psf, "m48884", BHWm (ds64_MARKER), BHW4 (28), BHW8 (psf->filelength - 8), BHW8 (psf->datalength), BHW8 (psf->sf.frames), BHW4 (0)) ;
                } ;
 
        /* WAVE and 'fmt ' markers. */
-       psf_binheader_writef (psf, "m", fmt_MARKER) ;
+       psf_binheader_writef (psf, "m", BHWm (fmt_MARKER)) ;
 
        /* Write the 'fmt ' chunk. */
        switch (psf->sf.format & SF_FORMAT_TYPEMASK)
@@ -683,7 +689,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
                                if ((error = rf64_write_fmt_chunk (psf)) != 0)
                                        return error ;
                                if (add_fact_chunk)
-                                       psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ;
+                                       psf_binheader_writef (psf, "tm48", BHWm (fact_MARKER), BHW4 (4), BHW8 (psf->sf.frames)) ;
                                break ;
 
                default :
@@ -712,14 +718,14 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
        {       int             tmp ;
                double  dtune = (double) (0x40000000) / 25.0 ;
 
-               psf_binheader_writef (psf, "m4", smpl_MARKER, 9 * 4 + psf->instrument->loop_count * 6 * 4) ;
-               psf_binheader_writef (psf, "44", 0, 0) ; /* Manufacturer zero is everyone */
+               psf_binheader_writef (psf, "m4", BHWm (smpl_MARKER), BHW4 (9 * 4 + psf->instrument->loop_count * 6 * 4)) ;
+               psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (0)) ; /* Manufacturer zero is everyone */
                tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */
-               psf_binheader_writef (psf, "44", tmp, psf->instrument->basenote) ;
+               psf_binheader_writef (psf, "44", BHW4 (tmp), BHW4 (psf->instrument->basenote)) ;
                tmp = (unsigned int) (psf->instrument->detune * dtune + 0.5) ;
-               psf_binheader_writef (psf, "4", tmp) ;
-               psf_binheader_writef (psf, "44", 0, 0) ; /* SMTPE format */
-               psf_binheader_writef (psf, "44", psf->instrument->loop_count, 0) ;
+               psf_binheader_writef (psf, "4", BHW4 (tmp)) ;
+               psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (0)) ; /* SMTPE format */
+               psf_binheader_writef (psf, "44", BHW4 (psf->instrument->loop_count), BHW4 (0)) ;
 
                for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++)
                {       int type ;
@@ -727,22 +733,23 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
                        type = psf->instrument->loops [tmp].mode ;
                        type = (type == SF_LOOP_FORWARD ? 0 : type == SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
 
-                       psf_binheader_writef (psf, "44", tmp, type) ;
-                       psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end) ;
-                       psf_binheader_writef (psf, "44", 0, psf->instrument->loops [tmp].count) ;
+                       psf_binheader_writef (psf, "44", BHW4 (tmp), BHW4 (type)) ;
+                       psf_binheader_writef (psf, "44", BHW4 (psf->instrument->loops [tmp].start), BHW4 (psf->instrument->loops [tmp].end)) ;
+                       psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (psf->instrument->loops [tmp].count)) ;
                        } ;
                } ;
 
 #endif
 
+       /* Padding may be needed if string data sizes change. */
        pad_size = psf->dataoffset - 16 - psf->header.indx ;
        if (pad_size >= 0)
-               psf_binheader_writef (psf, "m4z", PAD_MARKER, pad_size, make_size_t (pad_size)) ;
+               psf_binheader_writef (psf, "m4z", BHWm (PAD_MARKER), BHW4 ((unsigned int) pad_size), BHWz (pad_size)) ;
 
        if (wpriv->rf64_downgrade && (psf->filelength < RIFF_DOWNGRADE_BYTES))
-               psf_binheader_writef (psf, "tm8", data_MARKER, psf->datalength) ;
+               psf_binheader_writef (psf, "tm8", BHWm (data_MARKER), BHW8 (psf->datalength)) ;
        else
-               psf_binheader_writef (psf, "m4", data_MARKER, 0xffffffff) ;
+               psf_binheader_writef (psf, "m4", BHWm (data_MARKER), BHW4 (0xffffffff)) ;
 
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
        if (psf->error)
@@ -781,7 +788,7 @@ rf64_write_tailer (SF_PRIVATE *psf)
                psf->dataend = psf_fseek (psf, 0, SEEK_END) ;
 
        if (psf->dataend & 1)
-               psf_binheader_writef (psf, "z", 1) ;
+               psf_binheader_writef (psf, "z", BHWz (1)) ;
 
        if (psf->strings.flags & SF_STR_LOCATE_END)
                wavlike_write_strings (psf, SF_STR_LOCATE_END) ;
index 44b5c1b..dd3dbef 100644 (file)
--- a/src/sd2.c
+++ b/src/sd2.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2020 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2004 Paavo Jumppanen
 **
 ** This program is free software; you can redistribute it and/or modify
@@ -238,61 +238,61 @@ sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
        rsrc.map_offset = rsrc.data_offset + rsrc.data_length ;
 
        /* Very start of resource fork. */
-       psf_binheader_writef (psf, "E444", rsrc.data_offset, rsrc.map_offset, rsrc.data_length) ;
+       psf_binheader_writef (psf, "E444", BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ;
 
-       psf_binheader_writef (psf, "Eop", make_size_t (0x30), psf->file.name.c) ;
-       psf_binheader_writef (psf, "Eo2mm", make_size_t (0x50), 0, Sd2f_MARKER, lsf1_MARKER) ;
+       psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name.c)) ;
+       psf_binheader_writef (psf, "Eo2mm", BHWo (0x50), BHW2 (0), BHWm (Sd2f_MARKER), BHWm (lsf1_MARKER)) ;
 
        /* Very start of resource map. */
-       psf_binheader_writef (psf, "E444", make_size_t (rsrc.map_offset), rsrc.data_offset, rsrc.map_offset, rsrc.data_length) ;
+       psf_binheader_writef (psf, "E4444", BHW4 (rsrc.map_offset), BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ;
 
        /* These I don't currently understand. */
        if (1)
-       {       psf_binheader_writef (psf, "Eo1422", make_size_t (rsrc.map_offset + 16), 1, 0x12345678, 0xabcd, 0) ;
+       {       psf_binheader_writef (psf, "Eo1422", BHWo (rsrc.map_offset + 16), BHW1 (1), BHW4 (0x12345678), BHW2 (0xabcd), BHW2 (0)) ;
                } ;
 
        /* Resource type offset. */
        rsrc.type_offset = rsrc.map_offset + 30 ;
-       psf_binheader_writef (psf, "Eo2", make_size_t (rsrc.map_offset + 24), rsrc.type_offset - rsrc.map_offset - 2) ;
+       psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 24), BHW2 (rsrc.type_offset - rsrc.map_offset - 2)) ;
 
        /* Type index max. */
        rsrc.type_count = 2 ;
-       psf_binheader_writef (psf, "Eo2", make_size_t (rsrc.map_offset + 28), rsrc.type_count - 1) ;
+       psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 28), BHW2 (rsrc.type_count - 1)) ;
 
        rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
 
        rsrc.str_count = ARRAY_LEN (str_rsrc) ;
        rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ;
-       psf_binheader_writef (psf, "Eo2", make_size_t (rsrc.map_offset + 26), rsrc.string_offset) ;
+       psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 26), BHW2 (rsrc.string_offset)) ;
 
        /* Write 'STR ' resource type. */
        rsrc.str_count = 3 ;
-       psf_binheader_writef (psf, "Eom22", make_size_t (rsrc.type_offset), STR_MARKER, rsrc.str_count - 1, 0x12) ;
+       psf_binheader_writef (psf, "Eom22", BHWo (rsrc.type_offset), BHWm (STR_MARKER), BHW2 (rsrc.str_count - 1), BHW2 (0x12)) ;
 
        /* Write 'sdML' resource type. */
-       psf_binheader_writef (psf, "Em22", sdML_MARKER, 0, 0x36) ;
+       psf_binheader_writef (psf, "Em22", BHWm (sdML_MARKER), BHW2 (0), BHW2 (0x36)) ;
 
        str_offset = rsrc.map_offset + rsrc.string_offset ;
        next_str = 0 ;
        data_offset = rsrc.data_offset ;
        for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
-       {       psf_binheader_writef (psf, "Eop", make_size_t (str_offset), str_rsrc [k].name) ;
-               psf_binheader_writef (psf, "Eo22", make_size_t (rsrc.item_offset + k * 12), str_rsrc [k].id, next_str) ;
+       {       psf_binheader_writef (psf, "Eop", BHWo (str_offset), BHWp (str_rsrc [k].name)) ;
+               psf_binheader_writef (psf, "Eo22", BHWo (rsrc.item_offset + k * 12), BHW2 (str_rsrc [k].id), BHW2 (next_str)) ;
 
                str_offset += strlen (str_rsrc [k].name) ;
                next_str += strlen (str_rsrc [k].name) ;
 
-               psf_binheader_writef (psf, "Eo4", make_size_t (rsrc.item_offset + k * 12 + 4), data_offset - rsrc.data_offset) ;
-               psf_binheader_writef (psf, "Eo4", make_size_t (data_offset), str_rsrc [k].value_len) ;
+               psf_binheader_writef (psf, "Eo4", BHWo (rsrc.item_offset + k * 12 + 4), BHW4 (data_offset - rsrc.data_offset)) ;
+               psf_binheader_writef (psf, "Eo4", BHWo (data_offset), BHW4 (str_rsrc [k].value_len)) ;
 
-               psf_binheader_writef (psf, "Eob", make_size_t (data_offset + 4), str_rsrc [k].value, make_size_t (str_rsrc [k].value_len)) ;
+               psf_binheader_writef (psf, "Eob", BHWo (data_offset + 4), BHWv (str_rsrc [k].value), BHWz (str_rsrc [k].value_len)) ;
                data_offset += 4 + str_rsrc [k].value_len ;
                } ;
 
        /* Finally, calculate and set map length. */
        rsrc.map_length = str_offset - rsrc.map_offset ;
-       psf_binheader_writef (psf, "Eo4o4", make_size_t (12), rsrc.map_length,
-                                                       make_size_t (rsrc.map_offset + 12), rsrc.map_length) ;
+       psf_binheader_writef (psf, "Eo4o4", BHWo (12), BHW4 (rsrc.map_length),
+                                                       BHWo (rsrc.map_offset + 12), BHW4 (rsrc.map_length)) ;
 
        psf->header.indx = rsrc.map_offset + rsrc.map_length ;
 
@@ -516,6 +516,7 @@ parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
        str_offset = rsrc->string_offset ;
        psf_log_printf (psf, "  Offset    RsrcId    dlen    slen    Value\n") ;
 
+
        for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++)
        {       int slen ;
 
@@ -523,7 +524,13 @@ parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
                read_rsrc_str (rsrc, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
                str_offset += slen + 1 ;
 
-               rsrc_id = read_rsrc_short (rsrc, rsrc->item_offset + k * 12) ;
+               // work-around for GitHub issue #340
+               int id_offset = rsrc->item_offset + k * 12 ;
+               if (id_offset < 0 || id_offset + 1 >= rsrc->rsrc_len)
+               {       psf_log_printf (psf, "Exiting parser on id_offset of %d.\n", id_offset) ;
+                       break ;
+                       }
+               rsrc_id = read_rsrc_short (rsrc, id_offset) ;
 
                data_offset = rsrc->data_offset + read_rsrc_int (rsrc, rsrc->item_offset + k * 12 + 4) ;
                if (data_offset < 0 || data_offset > rsrc->rsrc_len)
@@ -542,6 +549,11 @@ parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
 
                psf_log_printf (psf, "  0x%04x     %4d     %4d     %3d    '%s'\n", data_offset, rsrc_id, data_len, slen, value) ;
 
+               if (strstr (value, "Photoshop"))
+               {       psf_log_printf (psf, "Exiting parser on Photoshop data.\n", data_offset) ;
+                       break ;
+                       } ;
+
                if (rsrc_id == 1000 && rsrc->sample_size == 0)
                        rsrc->sample_size = strtol (value, NULL, 10) ;
                else if (rsrc_id == 1001 && rsrc->sample_rate == 0)
index 77c2313..85c8c11 100644 (file)
--- a/src/sds.c
+++ b/src/sds.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -372,7 +372,7 @@ sds_write_header (SF_PRIVATE *psf, int calc_length)
        if (psf->is_pipe == SF_FALSE)
                psf_fseek (psf, 0, SEEK_SET) ;
 
-       psf_binheader_writef (psf, "E211", 0xF07E, 0, 1) ;
+       psf_binheader_writef (psf, "E211", BHW2 (0xF07E), BHW1 (0), BHW1 (1)) ;
 
        switch (SF_CODEC (psf->sf.format))
        {       case SF_FORMAT_PCM_S8 :
@@ -390,13 +390,13 @@ sds_write_header (SF_PRIVATE *psf, int calc_length)
 
        samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ;
 
-       psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ;
+       psf_binheader_writef (psf, "e213", BHW2 (0), BHW1 (psds->bitwidth), BHW3 (samp_period)) ;
 
        data_length                     = SDS_INT_TO_3BYTE_ENCODE (psds->total_written) ;
        sustain_loop_start      = SDS_INT_TO_3BYTE_ENCODE (0) ;
        sustain_loop_end        = SDS_INT_TO_3BYTE_ENCODE (0) ;
 
-       psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ;
+       psf_binheader_writef (psf, "e33311", BHW3 (data_length), BHW3 (sustain_loop_start), BHW3 (sustain_loop_end), BHW1 (loop_type), BHW1 (0xF7)) ;
 
        /* Header construction complete so write it out. */
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
index 9fca68e..698eff2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+/* Microsoft declares some 'unistd.h' functions in 'io.h'. */
+
+#include <sys/stat.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
 /* Some defines that microsoft 'forgot' to implement. */
 
+#ifndef R_OK
+#define R_OK   4               /* Test for read permission.  */
+#endif
+
+#ifndef W_OK
+#define W_OK   2               /* Test for write permission.  */
+#endif
+
+#ifndef X_OK
+#ifdef _WIN32
+#define        X_OK    0
+#else
+#define        X_OK    1               /* execute permission - unsupported in windows*/
+#endif
+#endif
+
+#ifndef F_OK
+#define        F_OK    0               /* Test for existence.  */
+#endif
+
 #ifndef S_IRWXU
 #define        S_IRWXU         0000700 /* rwx, owner */
 #endif
 #define                S_IXUSR 0000100 /* execute/search permission, owner */
 #endif
 
-/* Windows doesn't have group permissions so set all these to zero. */
-#define        S_IRWXG         0       /* rwx, group */
-#define                S_IRGRP 0       /* read permission, group */
-#define                S_IWGRP 0       /* write permission, grougroup */
-#define                S_IXGRP 0       /* execute/search permission, group */
+/* Windows (except MinGW) doesn't have group permissions so set all these to zero. */
+#ifndef S_IRWXG
+#define S_IRWXG                0       /* rwx, group */
+#endif
+
+#ifndef S_IRGRP
+#define S_IRGRP                0       /* read permission, group */
+#endif
+
+#ifndef S_IWGRP
+#define S_IWGRP                0       /* write permission, grougroup */
+#endif
 
-/* Windows doesn't have others permissions so set all these to zero. */
-#define        S_IRWXO         0       /* rwx, other */
-#define                S_IROTH 0       /* read permission, other */
-#define                S_IWOTH 0       /* write permission, other */
-#define                S_IXOTH 0       /* execute/search permission, other */
+#ifndef S_IXGRP
+#define S_IXGRP                0       /* execute/search permission, group */
+#endif
+
+/* Windows (except MinGW) doesn't have others permissions so set all these to zero. */
+#ifndef S_IRWXO
+#define S_IRWXO                0       /* rwx, other */
+#endif
+
+#ifndef S_IROTH
+#define S_IROTH                0       /* read permission, other */
+#endif
+
+#ifndef S_IWOTH
+#define S_IWOTH                0       /* write permission, other */
+#endif
+
+#ifndef S_IXOTH
+#define S_IXOTH                0       /* execute/search permission, other */
+#endif
 
 #ifndef S_ISFIFO
 #define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
index 0f30855..d70f405 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2005-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2005-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 #define HAVE_X86INTRIN_H 0
 #endif
 
-#define CPU_IS_X86             (defined __i486__ || defined __i586__ || defined __i686__ || defined __x86_64__)
-#define CPU_IS_X86_64  (defined __x86_64__)
+#if (defined __x86_64__) || (defined _M_X64)
+#define CPU_IS_X86_64  1       /* Define both for x86_64 */
+#define CPU_IS_X86             1
+#elif defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (_M_IX86)
+#define CPU_IS_X86             1
+#define CPU_IS_X86_64  0
+#else
+#define CPU_IS_X86             0
+#define CPU_IS_X86_64  0
+#endif
+
+#if (defined (__SSE2__) || defined (_M_AMD64) || (defined (_M_IX86_FP) && (_M_IX86_FP >= 2)) && HAVE_IMMINTRIN_H)
+#define USE_SSE2
+#endif
+
+#ifndef HAVE_SSIZE_T
+#define HAVE_SSIZE_T 0
+#endif
+
+#if (HAVE_SSIZE_T == 0)
+#define ssize_t intptr_t
+#endif
 
 #endif
index b2f553a..9367a96 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 #include <stdint.h>
 #include <inttypes.h>
 
+#if HAVE_BYTESWAP_H                    /* Linux, any CPU */
+#include <byteswap.h>
+
+#define        ENDSWAP_16(x)           (bswap_16 (x))
+#define        ENDSWAP_32(x)           (bswap_32 (x))
+#define        ENDSWAP_64(x)           (bswap_64 (x))
+
+#elif defined __has_builtin
+
+#if __has_builtin (__builtin_bswap16)
+#define ENDSWAP_16(x) ((int16_t) __builtin_bswap16 ((uint16_t) x))
+#endif
+
+#if __has_builtin (__builtin_bswap32)
+#define ENDSWAP_32(x) ((int32_t) __builtin_bswap32 ((uint32_t) x))
+#endif
+
+#if __has_builtin (__builtin_bswap64)
+#define ENDSWAP_64(x) ((int64_t) __builtin_bswap64 ((uint64_t) x))
+#endif
+
+#elif COMPILER_IS_GCC
 
-#if COMPILER_IS_GCC && CPU_IS_X86
+#if CPU_IS_X86
 
 static inline int16_t
-ENDSWAP_16 (int16_t x)
+ENDSWAP_16X (int16_t x)
 {      int16_t y ;
        __asm__ ("rorw $8, %w0" : "=r" (y) : "0" (x) : "cc") ;
        return y ;
 } /* ENDSWAP_16 */
 
 static inline int32_t
-ENDSWAP_32 (int32_t x)
+ENDSWAP_32X (int32_t x)
 {      int32_t y ;
        __asm__ ("bswap %0" : "=r" (y) : "0" (x)) ;
        return y ;
 } /* ENDSWAP_32 */
 
+#define ENDSWAP_16 ENDSWAP_16X
+#define ENDSWAP_32 ENDSWAP_32X
+
+#endif
+
 #if CPU_IS_X86_64
 
 static inline int64_t
@@ -54,18 +81,21 @@ ENDSWAP_64X (int64_t x)
 
 #endif
 
-#elif HAVE_BYTESWAP_H                  /* Linux, any CPU */
-#include <byteswap.h>
+#elif defined _MSC_VER
+#include <stdlib.h>
 
-#define        ENDSWAP_16(x)           (bswap_16 (x))
-#define        ENDSWAP_32(x)           (bswap_32 (x))
-#define        ENDSWAP_64(x)           (bswap_64 (x))
+#define        ENDSWAP_16(x)           (_byteswap_ushort (x))
+#define        ENDSWAP_32(x)           (_byteswap_ulong (x))
+#define        ENDSWAP_64(x)           (_byteswap_uint64 (x))
 
-#else
+#endif
 
+#ifndef ENDSWAP_16
 #define        ENDSWAP_16(x)           ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
-#define        ENDSWAP_32(x)           ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
+#endif
 
+#ifndef ENDSWAP_32
+#define        ENDSWAP_32(x)           ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
 #endif
 
 #ifndef ENDSWAP_64
@@ -139,6 +169,8 @@ ENDSWAP_64 (uint64_t x)
        #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
 #endif
 
+#define LE2H_32_PTR(x)                 (((x) [0]) + ((x) [1] << 8) + ((x) [2] << 16) + ((x) [3] << 24))
+
 #define LET2H_16_PTR(x)                        ((x) [1] + ((x) [2] << 8))
 #define LET2H_32_PTR(x)                        (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
 
@@ -148,34 +180,34 @@ ENDSWAP_64 (uint64_t x)
 static inline void
 psf_put_be64 (uint8_t *ptr, int offset, int64_t value)
 {
-       ptr [offset] = value >> 56 ;
-       ptr [offset + 1] = value >> 48 ;
-       ptr [offset + 2] = value >> 40 ;
-       ptr [offset + 3] = value >> 32 ;
-       ptr [offset + 4] = value >> 24 ;
-       ptr [offset + 5] = value >> 16 ;
-       ptr [offset + 6] = value >> 8 ;
-       ptr [offset + 7] = value ;
+       ptr [offset] = (uint8_t) (value >> 56) ;
+       ptr [offset + 1] = (uint8_t) (value >> 48) ;
+       ptr [offset + 2] = (uint8_t) (value >> 40) ;
+       ptr [offset + 3] = (uint8_t) (value >> 32) ;
+       ptr [offset + 4] = (uint8_t) (value >> 24) ;
+       ptr [offset + 5] = (uint8_t) (value >> 16) ;
+       ptr [offset + 6] = (uint8_t) (value >> 8) ;
+       ptr [offset + 7] = (uint8_t) value ;
 } /* psf_put_be64 */
 
 static inline void
 psf_put_be32 (uint8_t *ptr, int offset, int32_t value)
 {
-       ptr [offset] = value >> 24 ;
-       ptr [offset + 1] = value >> 16 ;
-       ptr [offset + 2] = value >> 8 ;
-       ptr [offset + 3] = value ;
+       ptr [offset] = (uint8_t) (value >> 24) ;
+       ptr [offset + 1] = (uint8_t) (value >> 16) ;
+       ptr [offset + 2] = (uint8_t) (value >> 8) ;
+       ptr [offset + 3] = (uint8_t) value ;
 } /* psf_put_be32 */
 
 static inline void
 psf_put_be16 (uint8_t *ptr, int offset, int16_t value)
 {
-       ptr [offset] = value >> 8 ;
-       ptr [offset + 1] = value ;
+       ptr [offset] = (uint8_t) (value >> 8) ;
+       ptr [offset + 1] = (uint8_t) value ;
 } /* psf_put_be16 */
 
 static inline int64_t
-psf_get_be64 (uint8_t *ptr, int offset)
+psf_get_be64 (const uint8_t *ptr, int offset)
 {      int64_t value ;
 
        value = ((uint32_t) ptr [offset]) << 24 ;
@@ -183,7 +215,7 @@ psf_get_be64 (uint8_t *ptr, int offset)
        value += ptr [offset + 2] << 8 ;
        value += ptr [offset + 3] ;
 
-       value = ((uint64_t) value) << 32 ;
+       value = (int64_t) (((uint64_t) value) << 32) ;
 
        value += ((uint32_t) ptr [offset + 4]) << 24 ;
        value += ptr [offset + 5] << 16 ;
@@ -193,7 +225,7 @@ psf_get_be64 (uint8_t *ptr, int offset)
 } /* psf_get_be64 */
 
 static inline int64_t
-psf_get_le64 (uint8_t *ptr, int offset)
+psf_get_le64 (const uint8_t *ptr, int offset)
 {      int64_t value ;
 
        value = ((uint32_t) ptr [offset + 7]) << 24 ;
@@ -201,7 +233,7 @@ psf_get_le64 (uint8_t *ptr, int offset)
        value += ptr [offset + 5] << 8 ;
        value += ptr [offset + 4] ;
 
-       value = ((uint64_t) value) << 32 ;
+       value = (int64_t) (((uint64_t) value) << 32) ;
 
        value += ((uint32_t) ptr [offset + 3]) << 24 ;
        value += ptr [offset + 2] << 16 ;
@@ -211,7 +243,7 @@ psf_get_le64 (uint8_t *ptr, int offset)
 } /* psf_get_le64 */
 
 static inline int32_t
-psf_get_be32 (uint8_t *ptr, int offset)
+psf_get_be32 (const uint8_t *ptr, int offset)
 {      int32_t value ;
 
        value = ((uint32_t) ptr [offset]) << 24 ;
@@ -222,7 +254,7 @@ psf_get_be32 (uint8_t *ptr, int offset)
 } /* psf_get_be32 */
 
 static inline int32_t
-psf_get_le32 (uint8_t *ptr, int offset)
+psf_get_le32 (const uint8_t *ptr, int offset)
 {      int32_t value ;
 
        value = ((uint32_t) ptr [offset + 3]) << 24 ;
@@ -233,7 +265,7 @@ psf_get_le32 (uint8_t *ptr, int offset)
 } /* psf_get_le32 */
 
 static inline int32_t
-psf_get_be24 (uint8_t *ptr, int offset)
+psf_get_be24 (const uint8_t *ptr, int offset)
 {      int32_t value ;
 
        value = ((uint32_t) ptr [offset]) << 24 ;
@@ -243,7 +275,7 @@ psf_get_be24 (uint8_t *ptr, int offset)
 } /* psf_get_be24 */
 
 static inline int32_t
-psf_get_le24 (uint8_t *ptr, int offset)
+psf_get_le24 (const uint8_t *ptr, int offset)
 {      int32_t value ;
 
        value = ((uint32_t) ptr [offset + 2]) << 24 ;
@@ -253,8 +285,8 @@ psf_get_le24 (uint8_t *ptr, int offset)
 } /* psf_get_le24 */
 
 static inline int16_t
-psf_get_be16 (uint8_t *ptr, int offset)
-{      return (ptr [offset] << 8) + ptr [offset + 1] ;
+psf_get_be16 (const uint8_t *ptr, int offset)
+{      return (int16_t) (ptr [offset] << 8) + ptr [offset + 1] ;
 } /* psf_get_be16 */
 
 /*-----------------------------------------------------------------------------------------------
index b76bfe9..63beda8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 #include       "sfendian.h"
 #include       "common.h"
 
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined _WIN32
+#include <io.h>
+#endif
+
 #define                SNDFILE_MAGICK  0x1234C0DE
 
 #ifdef __APPLE__
        */
        #ifdef __BIG_ENDIAN__
                #if (CPU_IS_LITTLE_ENDIAN == 1)
-                       #error "Universal binary compile detected. See http://www.mega-nerd.com/libsndfile/FAQ.html#Q018"
+                       #error "Universal binary compile detected. See http://libsndfile.github.io/libsndfile/FAQ.html#Q018"
                #endif
        #endif
 
        #ifdef __LITTLE_ENDIAN__
                #if (CPU_IS_BIG_ENDIAN == 1)
-                       #error "Universal binary compile detected. See http://www.mega-nerd.com/libsndfile/FAQ.html#Q018"
+                       #error "Universal binary compile detected. See http://libsndfile.github.io/libsndfile/FAQ.html#Q018"
                #endif
        #endif
 #endif
@@ -81,7 +87,6 @@ ErrorStruct SndfileErrors [] =
        {       SFE_UNIMPLEMENTED               , "File contains data in an unimplemented format." },
        {       SFE_BAD_READ_ALIGN              , "Attempt to read a non-integer number of channels." },
        {       SFE_BAD_WRITE_ALIGN     , "Attempt to write a non-integer number of channels." },
-       {       SFE_UNKNOWN_FORMAT              , "File contains data in an unknown format." },
        {       SFE_NOT_READMODE                , "Read attempted on file currently open for write." },
        {       SFE_NOT_WRITEMODE               , "Write attempted on file currently open for read." },
        {       SFE_BAD_MODE_RW                 , "Error : This file format does not support read/write mode." },
@@ -96,7 +101,7 @@ ErrorStruct SndfileErrors [] =
        {       SFE_BAD_BROADCAST_INFO_TOO_BIG
                                                                , "Error : SF_BROADCAST_INFO struct too large." },
        {       SFE_BAD_CART_INFO_SIZE                          , "Error: SF_CART_INFO struct too large." },
-       {       SFE_BAD_CART_INFO_TOO_BIG                       , "Error: bag tag_text_size in SF_CART_INFO struct." },
+       {       SFE_BAD_CART_INFO_TOO_BIG                       , "Error: bad tag_text_size in SF_CART_INFO struct." },
        {       SFE_INTERLEAVE_MODE             , "Attempt to write to file with non-interleaved data." },
        {       SFE_INTERLEAVE_SEEK             , "Bad karma in seek during interleave read operation." },
        {       SFE_INTERLEAVE_READ             , "Bad karma in read during interleave read operation." },
@@ -150,6 +155,7 @@ ErrorStruct SndfileErrors [] =
        {       SFE_WAV_ADPCM_CHANNELS  , "Error in ADPCM WAV file. Invalid number of channels." },
        {       SFE_WAV_ADPCM_SAMPLES   , "Error in ADPCM WAV file. Invalid number of samples per block." },
        {       SFE_WAV_GSM610_FORMAT   , "Error in GSM610 WAV file. Invalid format chunk." },
+       {       SFE_WAV_NMS_FORMAT              , "Error in NMS ADPCM WAV file. Invalid format chunk." },
 
        {       SFE_AIFF_NO_FORM                , "Error in AIFF file, bad 'FORM' marker." },
        {       SFE_AIFF_AIFF_NO_FORM   , "Error in AIFF file, 'AIFF' marker without 'FORM'." },
@@ -245,6 +251,7 @@ ErrorStruct SndfileErrors [] =
        {       SFE_FLAC_INIT_DECODER   , "Error : problem with initialization of the flac decoder." },
        {       SFE_FLAC_LOST_SYNC              , "Error : flac decoder lost sync." },
        {       SFE_FLAC_BAD_SAMPLE_RATE, "Error : flac does not support this sample rate." },
+       {       SFE_FLAC_CHANNEL_COUNT_CHANGED, "Error : flac channel changed mid stream." },
        {       SFE_FLAC_UNKOWN_ERROR   , "Error : unknown error in flac decoder." },
 
        {       SFE_WVE_NOT_WVE                 , "Error : not a WVE file." },
@@ -252,6 +259,7 @@ ErrorStruct SndfileErrors [] =
 
        {       SFE_DWVW_BAD_BITWIDTH   , "Error : Bad bit width for DWVW encoding. Must be 12, 16 or 24." },
        {       SFE_G72X_NOT_MONO               , "Error : G72x encoding does not support more than 1 channel." },
+       {       SFE_NMS_ADPCM_NOT_MONO  , "Error : NMS ADPCM encoding does not support more than 1 channel." },
 
        {       SFE_VORBIS_ENCODER_BUG  , "Error : Sample rate chosen is known to trigger a Vorbis encoder bug on this CPU." },
 
@@ -269,6 +277,8 @@ ErrorStruct SndfileErrors [] =
        {       SFE_FILENAME_TOO_LONG   , "Error : Supplied filename too long." },
        {       SFE_NEGATIVE_RW_LEN             , "Error : Length parameter passed to read/write is negative." },
 
+       {       SFE_OPUS_BAD_SAMPLERATE , "Error : Opus only supports sample rates of 8000, 12000, 16000, 24000 and 48000." },
+
        {       SFE_MAX_ERROR                   , "Maximum error number." },
        {       SFE_MAX_ERROR + 1               , NULL }
 } ;
@@ -319,7 +329,6 @@ static char sf_syserr [SF_SYSERR_LEN] = { 0 } ;
 **     Public functions.
 */
 
-SNDFILE_API
 SNDFILE*
 sf_open        (const char *path, int mode, SF_INFO *sfinfo)
 {      SF_PRIVATE      *psf ;
@@ -350,18 +359,24 @@ sf_open   (const char *path, int mode, SF_INFO *sfinfo)
        return psf_open_file (psf, sfinfo) ;
 } /* sf_open */
 
-SNDFILE_API
 SNDFILE*
 sf_open_fd     (int fd, int mode, SF_INFO *sfinfo, int close_desc)
 {      SF_PRIVATE      *psf ;
+       SNDFILE         *result ;
 
        if ((SF_CONTAINER (sfinfo->format)) == SF_FORMAT_SD2)
        {       sf_errno = SFE_SD2_FD_DISALLOWED ;
+               if (close_desc)
+                       close (fd) ;
+
                return  NULL ;
                } ;
 
        if ((psf = psf_allocate ()) == NULL)
        {       sf_errno = SFE_MALLOC_FAILED ;
+               if (close_desc)
+                       close (fd) ;
+
                return  NULL ;
                } ;
 
@@ -373,21 +388,27 @@ sf_open_fd        (int fd, int mode, SF_INFO *sfinfo, int close_desc)
        psf->is_pipe = psf_is_pipe (psf) ;
        psf->fileoffset = psf_ftell (psf) ;
 
-       if (! close_desc)
-               psf->file.do_not_close_descriptor = SF_TRUE ;
+       result = psf_open_file (psf, sfinfo) ;
+       if (result != NULL && ! close_desc)
+                       psf->file.do_not_close_descriptor = SF_TRUE ;
 
-       return psf_open_file (psf, sfinfo) ;
+       return result ;
 } /* sf_open_fd */
 
-SNDFILE_API
 SNDFILE*
 sf_open_virtual        (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data)
 {      SF_PRIVATE      *psf ;
 
        /* Make sure we have a valid set ot virtual pointers. */
-       if (sfvirtual->get_filelen == NULL || sfvirtual->seek == NULL || sfvirtual->tell == NULL)
+       if (sfvirtual->get_filelen == NULL)
        {       sf_errno = SFE_BAD_VIRTUAL_IO ;
-               snprintf (sf_parselog, sizeof (sf_parselog), "Bad vio_get_filelen / vio_seek / vio_tell in SF_VIRTUAL_IO struct.\n") ;
+               snprintf (sf_parselog, sizeof (sf_parselog), "Bad vio_get_filelen in SF_VIRTUAL_IO struct.\n") ;
+               return NULL ;
+               } ;
+
+       if ((sfvirtual->seek == NULL || sfvirtual->tell == NULL) && sfinfo->seekable)
+       {       sf_errno = SFE_BAD_VIRTUAL_IO ;
+               snprintf (sf_parselog, sizeof (sf_parselog), "Bad vio_seek / vio_tell in SF_VIRTUAL_IO struct.\n") ;
                return NULL ;
                } ;
 
@@ -419,7 +440,6 @@ sf_open_virtual     (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user
        return psf_open_file (psf, sfinfo) ;
 } /* sf_open_virtual */
 
-SNDFILE_API
 int
 sf_close       (SNDFILE *sndfile)
 {      SF_PRIVATE      *psf ;
@@ -429,7 +449,6 @@ sf_close    (SNDFILE *sndfile)
        return psf_close (psf) ;
 } /* sf_close */
 
-SNDFILE_API
 void
 sf_write_sync  (SNDFILE *sndfile)
 {      SF_PRIVATE      *psf ;
@@ -445,7 +464,6 @@ sf_write_sync       (SNDFILE *sndfile)
 /*==============================================================================
 */
 
-SNDFILE_API
 const char*
 sf_error_number        (int errnum)
 {      static const char *bad_errnum =
@@ -468,7 +486,6 @@ sf_error_number     (int errnum)
        return bad_errnum ;
 } /* sf_error_number */
 
-SNDFILE_API
 const char*
 sf_strerror (SNDFILE *sndfile)
 {      SF_PRIVATE      *psf = NULL ;
@@ -497,7 +514,6 @@ sf_strerror (SNDFILE *sndfile)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 int
 sf_error (SNDFILE *sndfile)
 {      SF_PRIVATE      *psf ;
@@ -516,7 +532,6 @@ sf_error (SNDFILE *sndfile)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 int
 sf_perror (SNDFILE *sndfile)
 {      SF_PRIVATE      *psf ;
@@ -538,7 +553,6 @@ sf_perror (SNDFILE *sndfile)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 int
 sf_error_str (SNDFILE *sndfile, char *str, size_t maxlen)
 {      SF_PRIVATE      *psf ;
@@ -562,7 +576,6 @@ sf_error_str (SNDFILE *sndfile, char *str, size_t maxlen)
 /*==============================================================================
 */
 
-SNDFILE_API
 int
 sf_format_check        (const SF_INFO *info)
 {      int     subformat, endian ;
@@ -570,7 +583,7 @@ sf_format_check     (const SF_INFO *info)
        subformat = SF_CODEC (info->format) ;
        endian = SF_ENDIAN (info->format) ;
 
-       /* This is the place where each file format can check if the suppiled
+       /* This is the place where each file format can check if the supplied
        ** SF_INFO struct is valid.
        ** Return 0 on failure, 1 ons success.
        */
@@ -598,6 +611,9 @@ sf_format_check     (const SF_INFO *info)
                                        return 1 ;
                                if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)
                                        return 1 ;
+                               if ((subformat == SF_FORMAT_NMS_ADPCM_16 || subformat == SF_FORMAT_NMS_ADPCM_24 ||
+                                                       subformat == SF_FORMAT_NMS_ADPCM_32) && info->channels == 1)
+                                       return 1 ;
                                break ;
 
                case SF_FORMAT_WAVEX :
@@ -683,6 +699,9 @@ sf_format_check     (const SF_INFO *info)
                                        return 1 ;
                                if (subformat == SF_FORMAT_VOX_ADPCM && info->channels == 1)
                                        return 1 ;
+                               if ((subformat == SF_FORMAT_NMS_ADPCM_16 || subformat == SF_FORMAT_NMS_ADPCM_24 ||
+                                                       subformat == SF_FORMAT_NMS_ADPCM_32) && info->channels == 1)
+                                       return 1 ;
                                break ;
 
                case SF_FORMAT_PAF :
@@ -839,6 +858,8 @@ sf_format_check     (const SF_INFO *info)
                                        return 0 ;
                                if (subformat == SF_FORMAT_VORBIS)
                                        return 1 ;
+                               if (subformat == SF_FORMAT_OPUS)
+                                       return 1 ;
                                break ;
 
                case SF_FORMAT_MPC2K :
@@ -872,7 +893,6 @@ sf_format_check     (const SF_INFO *info)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 const char *
 sf_version_string (void)
 {
@@ -887,11 +907,11 @@ sf_version_string (void)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 int
 sf_command     (SNDFILE *sndfile, int command, void *data, int datasize)
 {      SF_PRIVATE *psf = (SF_PRIVATE *) sndfile ;
        double quality ;
+       double latency ;
        int old_value ;
 
        /* This set of commands do not need the sndfile parameter. */
@@ -900,7 +920,7 @@ sf_command  (SNDFILE *sndfile, int command, void *data, int datasize)
                        if (data == NULL)
                        {       if (psf)
                                        psf->error = SFE_BAD_COMMAND_PARAM ;
-                               return SFE_BAD_COMMAND_PARAM ;
+                               return 0 ;
                                } ;
                        snprintf (data, datasize, "%s", sf_version_string ()) ;
                        return strlen (data) ;
@@ -1043,7 +1063,7 @@ sf_command        (SNDFILE *sndfile, int command, void *data, int datasize)
                        if (data == NULL)
                                return SFE_BAD_COMMAND_PARAM ;
                        snprintf (data, datasize, "%s", psf->parselog.buf) ;
-                       break ;
+                       return strlen (data) ;
 
                case SFC_CALC_SIGNAL_MAX :
                        if (data == NULL || datasize != sizeof (double))
@@ -1260,7 +1280,7 @@ sf_command        (SNDFILE *sndfile, int command, void *data, int datasize)
                        return SF_FALSE ;
 
                case SFC_GET_CUE :
-                       if (datasize != sizeof (SF_CUES) || data == NULL)
+                       if (datasize < (int) sizeof (uint32_t) || data == NULL)
                        {       psf->error = SFE_BAD_COMMAND_PARAM ;
                                return SF_FALSE ;
                                } ;
@@ -1274,12 +1294,11 @@ sf_command      (SNDFILE *sndfile, int command, void *data, int datasize)
                        {       psf->error = SFE_CMD_HAS_DATA ;
                                return SF_FALSE ;
                                } ;
-                       if (datasize != sizeof (SF_CUES) || data == NULL)
+                       if (datasize < (int) sizeof (uint32_t) || data == NULL)
                        {       psf->error = SFE_BAD_COMMAND_PARAM ;
                                return SF_FALSE ;
                                } ;
-
-                       if (psf->cues == NULL && (psf->cues = psf_cues_dup (data)) == NULL)
+                       if (psf->cues == NULL && (psf->cues = psf_cues_dup (data, datasize)) == NULL)
                        {       psf->error = SFE_MALLOC_FAILED ;
                                return SF_FALSE ;
                                } ;
@@ -1372,6 +1391,12 @@ sf_command       (SNDFILE *sndfile, int command, void *data, int datasize)
                        quality = 1.0 - SF_MAX (0.0, SF_MIN (1.0, quality)) ;
                        return sf_command (sndfile, SFC_SET_COMPRESSION_LEVEL, &quality, sizeof (quality)) ;
 
+               case SFC_SET_OGG_PAGE_LATENCY_MS :
+                       if (data == NULL || datasize != sizeof (double))
+                               return SF_FALSE ;
+
+                       latency = *((double *) data) ;
+                       return sf_command (sndfile, SFC_SET_OGG_PAGE_LATENCY, &latency, sizeof (latency)) ;
 
                default :
                        /* Must be a file specific command. Pass it on. */
@@ -1388,7 +1413,6 @@ sf_command        (SNDFILE *sndfile, int command, void *data, int datasize)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_seek        (SNDFILE *sndfile, sf_count_t offset, int whence)
 {      SF_PRIVATE      *psf ;
@@ -1507,7 +1531,6 @@ sf_seek   (SNDFILE *sndfile, sf_count_t offset, int whence)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 const char*
 sf_get_string (SNDFILE *sndfile, int str_type)
 {      SF_PRIVATE      *psf ;
@@ -1520,7 +1543,6 @@ sf_get_string (SNDFILE *sndfile, int str_type)
        return psf_get_string (psf, str_type) ;
 } /* sf_get_string */
 
-SNDFILE_API
 int
 sf_set_string (SNDFILE *sndfile, int str_type, const char* str)
 {      SF_PRIVATE      *psf ;
@@ -1533,7 +1555,6 @@ sf_set_string (SNDFILE *sndfile, int str_type, const char* str)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 int
 sf_current_byterate (SNDFILE *sndfile)
 {      SF_PRIVATE      *psf ;
@@ -1559,6 +1580,15 @@ sf_current_byterate (SNDFILE *sndfile)
                case SF_FORMAT_GSM610 :
                        return (psf->sf.samplerate * psf->sf.channels * 13000) / 8000 ;
 
+               case SF_FORMAT_NMS_ADPCM_16:
+                       return psf->sf.samplerate / 4 + 10 ;
+
+               case SF_FORMAT_NMS_ADPCM_24:
+                       return psf->sf.samplerate * 3 / 8 + 10 ;
+
+               case SF_FORMAT_NMS_ADPCM_32:
+                       return psf->sf.samplerate / 2 + 10 ;
+
                case SF_FORMAT_G721_32 :        /* 32kbs G721 ADPCM encoding. */
                        return (psf->sf.samplerate * psf->sf.channels) / 2 ;
 
@@ -1578,7 +1608,6 @@ sf_current_byterate (SNDFILE *sndfile)
 /*==============================================================================
 */
 
-SNDFILE_API
 sf_count_t
 sf_read_raw            (SNDFILE *sndfile, void *ptr, sf_count_t bytes)
 {      SF_PRIVATE      *psf ;
@@ -1631,7 +1660,6 @@ sf_read_raw               (SNDFILE *sndfile, void *ptr, sf_count_t bytes)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_read_short  (SNDFILE *sndfile, short *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -1687,7 +1715,6 @@ sf_read_short     (SNDFILE *sndfile, short *ptr, sf_count_t len)
        return count ;
 } /* sf_read_short */
 
-SNDFILE_API
 sf_count_t
 sf_readf_short         (SNDFILE *sndfile, short *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -1741,7 +1768,6 @@ sf_readf_short            (SNDFILE *sndfile, short *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_read_int            (SNDFILE *sndfile, int *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -1797,7 +1823,6 @@ sf_read_int               (SNDFILE *sndfile, int *ptr, sf_count_t len)
        return count ;
 } /* sf_read_int */
 
-SNDFILE_API
 sf_count_t
 sf_readf_int   (SNDFILE *sndfile, int *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -1851,7 +1876,6 @@ sf_readf_int      (SNDFILE *sndfile, int *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_read_float  (SNDFILE *sndfile, float *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -1907,7 +1931,6 @@ sf_read_float     (SNDFILE *sndfile, float *ptr, sf_count_t len)
        return count ;
 } /* sf_read_float */
 
-SNDFILE_API
 sf_count_t
 sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -1961,7 +1984,6 @@ sf_readf_float    (SNDFILE *sndfile, float *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -2017,7 +2039,6 @@ sf_read_double    (SNDFILE *sndfile, double *ptr, sf_count_t len)
        return count ;
 } /* sf_read_double */
 
-SNDFILE_API
 sf_count_t
 sf_readf_double        (SNDFILE *sndfile, double *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -2071,7 +2092,6 @@ sf_readf_double   (SNDFILE *sndfile, double *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_write_raw   (SNDFILE *sndfile, const void *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -2131,7 +2151,6 @@ sf_write_raw      (SNDFILE *sndfile, const void *ptr, sf_count_t len)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -2189,7 +2208,6 @@ sf_write_short    (SNDFILE *sndfile, const short *ptr, sf_count_t len)
        return count ;
 } /* sf_write_short */
 
-SNDFILE_API
 sf_count_t
 sf_writef_short        (SNDFILE *sndfile, const short *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -2245,7 +2263,6 @@ sf_writef_short   (SNDFILE *sndfile, const short *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_write_int   (SNDFILE *sndfile, const int *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -2303,7 +2320,6 @@ sf_write_int      (SNDFILE *sndfile, const int *ptr, sf_count_t len)
        return count ;
 } /* sf_write_int */
 
-SNDFILE_API
 sf_count_t
 sf_writef_int  (SNDFILE *sndfile, const int *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -2359,7 +2375,6 @@ sf_writef_int     (SNDFILE *sndfile, const int *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -2417,7 +2432,6 @@ sf_write_float    (SNDFILE *sndfile, const float *ptr, sf_count_t len)
        return count ;
 } /* sf_write_float */
 
-SNDFILE_API
 sf_count_t
 sf_writef_float        (SNDFILE *sndfile, const float *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -2473,7 +2487,6 @@ sf_writef_float   (SNDFILE *sndfile, const float *ptr, sf_count_t frames)
 /*------------------------------------------------------------------------------
 */
 
-SNDFILE_API
 sf_count_t
 sf_write_double        (SNDFILE *sndfile, const double *ptr, sf_count_t len)
 {      SF_PRIVATE      *psf ;
@@ -2531,7 +2544,6 @@ sf_write_double   (SNDFILE *sndfile, const double *ptr, sf_count_t len)
        return count ;
 } /* sf_write_double */
 
-SNDFILE_API
 sf_count_t
 sf_writef_double       (SNDFILE *sndfile, const double *ptr, sf_count_t frames)
 {      SF_PRIVATE      *psf ;
@@ -2764,7 +2776,8 @@ guess_file_type (SF_PRIVATE *psf)
        if (buffer [0] == MAKE_MARKER ('R', 'F', '6', '4') && buffer [2] == MAKE_MARKER ('W', 'A', 'V', 'E'))
                return SF_FORMAT_RF64 ;
 
-       if (buffer [0] == MAKE_MARKER ('I', 'D', '3', 3))
+       if (buffer [0] == MAKE_MARKER ('I', 'D', '3', 2) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 3)
+                       || buffer [0] == MAKE_MARKER ('I', 'D', '3', 4))
        {       psf_log_printf (psf, "Found 'ID3' marker.\n") ;
                if (id3_skip (psf))
                        return guess_file_type (psf) ;
@@ -2902,7 +2915,6 @@ psf_close (SF_PRIVATE *psf)
        free (psf->iterator) ;
        free (psf->cart_16k) ;
 
-       memset (psf, 0, sizeof (SF_PRIVATE)) ;
        free (psf) ;
 
        return error ;
@@ -3176,7 +3188,7 @@ psf_open_file (SF_PRIVATE *psf, SF_INFO *sfinfo)
                /* Lite remove end */
 
                default :
-                               error = SFE_UNKNOWN_FORMAT ;
+                               error = SF_ERR_UNRECOGNISED_FORMAT ;
                } ;
 
        if (error)
@@ -3275,7 +3287,6 @@ error_exit :
 ** It doesn't work for W64 because W64 uses weird GUID style chunk markers.
 */
 
-SNDFILE_API
 int
 sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info)
 {      SF_PRIVATE      *psf ;
@@ -3291,7 +3302,6 @@ sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info)
        return SFE_BAD_CHUNK_FORMAT ;
 } /* sf_set_chunk */
 
-SNDFILE_API
 SF_CHUNK_ITERATOR *
 sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info)
 {      SF_PRIVATE      *psf ;
@@ -3304,7 +3314,6 @@ sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info)
        return psf_get_chunk_iterator (psf, NULL) ;
 } /* sf_get_chunk_iterator */
 
-SNDFILE_API
 SF_CHUNK_ITERATOR *
 sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator)
 {      SF_PRIVATE      *psf ;
@@ -3318,7 +3327,6 @@ sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator)
        return NULL ;
 } /* sf_get_chunk_iterator_next */
 
-SNDFILE_API
 int
 sf_get_chunk_size (const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
 {      SF_PRIVATE      *psf ;
@@ -3333,10 +3341,8 @@ sf_get_chunk_size (const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_inf
                return psf->get_chunk_size (psf, iterator, chunk_info) ;
 
        return SFE_BAD_CHUNK_FORMAT ;
-       return 0 ;
 } /* sf_get_chunk_size */
 
-SNDFILE_API
 int
 sf_get_chunk_data (const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
 {      SF_PRIVATE      *psf ;
index 2dc322c..72d803f 100644 (file)
--- a/src/svx.c
+++ b/src/svx.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -362,29 +362,29 @@ svx_write_header (SF_PRIVATE *psf, int calc_length)
        psf_fseek (psf, 0, SEEK_SET) ;
 
        /* FORM marker and FORM size. */
-       psf_binheader_writef (psf, "Etm8", FORM_MARKER, (psf->filelength < 8) ?
-                       psf->filelength * 0 : psf->filelength - 8) ;
+       psf_binheader_writef (psf, "Etm8", BHWm (FORM_MARKER), BHW8 ((psf->filelength < 8) ?
+                       psf->filelength * 0 : psf->filelength - 8)) ;
 
-       psf_binheader_writef (psf, "m", (psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER) ;
+       psf_binheader_writef (psf, "m", BHWm ((psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER)) ;
 
        /* VHDR chunk. */
-       psf_binheader_writef (psf, "Em4", VHDR_MARKER, sizeof (VHDR_CHUNK)) ;
+       psf_binheader_writef (psf, "Em4", BHWm (VHDR_MARKER), BHW4 (sizeof (VHDR_CHUNK))) ;
        /* VHDR : oneShotHiSamples, repeatHiSamples, samplesPerHiCycle */
-       psf_binheader_writef (psf, "E444", psf->sf.frames, 0, 0) ;
+       psf_binheader_writef (psf, "E444", BHW4 (psf->sf.frames), BHW4 (0), BHW4 (0)) ;
        /* VHDR : samplesPerSec, octave, compression */
-       psf_binheader_writef (psf, "E211", psf->sf.samplerate, 1, 0) ;
+       psf_binheader_writef (psf, "E211", BHW2 (psf->sf.samplerate), BHW1 (1), BHW1 (0)) ;
        /* VHDR : volume */
-       psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ;
+       psf_binheader_writef (psf, "E4", BHW4 ((psf->bytewidth == 1) ? 0xFF : 0xFFFF)) ;
 
        if (psf->sf.channels == 2)
-               psf_binheader_writef (psf, "Em44", CHAN_MARKER, 4, 6) ;
+               psf_binheader_writef (psf, "Em44", BHWm (CHAN_MARKER), BHW4 (4), BHW4 (6)) ;
 
        /* Filename and annotation strings. */
-       psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->file.name.c, ANNO_MARKER, annotation) ;
+       psf_binheader_writef (psf, "Emsms", BHWm (NAME_MARKER), BHWs (psf->file.name.c), BHWm (ANNO_MARKER), BHWs (annotation)) ;
 
        /* BODY marker and size. */
-       psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ?
-                       psf->datalength * 0 : psf->datalength) ;
+       psf_binheader_writef (psf, "Etm8", BHWm (BODY_MARKER), BHW8 ((psf->datalength < 0) ?
+                       psf->datalength * 0 : psf->datalength)) ;
 
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
 
index 9706249..20926df 100644 (file)
@@ -23,6 +23,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <string.h>
index b76c825..8b1f9c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -43,7 +43,7 @@ test_binheader_writef (void)
        {       psf_strlcpy (buffer, sizeof (buffer), "abcdefghijklmnop") ;
                buffer [k] = 0 ;
 
-               psf_binheader_writef (psf, "Ep", buffer) ;
+               psf_binheader_writef (psf, "Ep", BHWp (buffer)) ;
 
                if ((psf->header.indx & 1) != 0)
                        errors = 1 ;
index 9f5a1cc..348a6be 100644 (file)
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "common.h"
@@ -144,7 +146,7 @@ test_endswap (void)
 
 [+ FOR int_size
 +]     test_psf_put_be[+ (get "name") +] () ;
-[+ ENDFOR int_endsize
+[+ ENDFOR int_size
 +]
 
 } /* test_endswap */
index 08fcceb..36a85b0 100644 (file)
@@ -23,6 +23,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <string.h>
@@ -46,6 +48,7 @@ static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf
 static void test_read_or_die   (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
 static void test_equal_or_die  (int *array1, int *array2, int len, int linenum) ;
 static void test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) ;
+static void test_tell_or_die   (SF_PRIVATE *psf, sf_count_t expected_position, int linenum) ;
 
 
 
@@ -324,6 +327,42 @@ file_truncate_test (const char *filename)
        puts ("ok") ;
 } /* file_truncate_test */
 
+static void
+file_seek_with_offset_test (const char *filename)
+{      SF_PRIVATE sf_data, *psf ;
+       sf_count_t real_end ;
+       const size_t fileoffset = 64 ;
+
+       print_test_name ("Testing seek with offset") ;
+
+       /* Open the file created by the previous test for reading. */
+       memset (&sf_data, 0, sizeof (sf_data)) ;
+       psf = &sf_data ;
+       psf->file.mode = SFM_READ ;
+       snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
+       test_open_or_die (psf, __LINE__) ;
+
+       /* Gather basic info before setting offset. */
+       real_end = psf_fseek (psf, 0, SEEK_END) ;
+       test_tell_or_die (psf, real_end, __LINE__) ;
+
+       /* Set the fileoffset (usually in a real system this is due to an id3 tag). */
+       psf->fileoffset = fileoffset ;
+
+       /* Check tell respects offset. */
+       test_tell_or_die (psf, real_end - fileoffset, __LINE__) ;
+
+       /* Check seeking works as expected. */
+       test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
+       test_seek_or_die (psf, 0, SEEK_CUR, 0, __LINE__) ;
+       test_seek_or_die (psf, 0, SEEK_CUR, 0, __LINE__) ;
+       test_seek_or_die (psf, 0, SEEK_END, real_end - fileoffset, __LINE__) ;
+
+       test_close_or_die (psf, __LINE__) ;
+
+       puts ("ok") ;
+} /* file_seek_with_offset_test */
+
 /*==============================================================================
 ** Testing helper functions.
 */
@@ -403,6 +442,20 @@ test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new
 } /* test_seek_or_die */
 
 static void
+test_tell_or_die       (SF_PRIVATE *psf, sf_count_t expected_position, int linenum)
+{
+       sf_count_t retval ;
+
+       retval = psf_ftell (psf) ;
+
+       if (retval != expected_position)
+       {       printf ("\n\nLine %d: psf_ftell() failed. Position reported as %" PRId64 " (should be %" PRId64 ").\n\n",
+                       linenum, retval, expected_position) ;
+               exit (1) ;
+               } ;
+}
+
+static void
 test_equal_or_die      (int *array1, int *array2, int len, int linenum)
 {      int k ;
 
@@ -431,6 +484,7 @@ test_file_io (void)
 
        file_open_test  (filename) ;
        file_read_write_test    (filename) ;
+       file_seek_with_offset_test (filename) ;
        file_truncate_test (filename) ;
 
        unlink (filename) ;
index 1f2437d..f5a501d 100644 (file)
@@ -20,6 +20,9 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#if defined (HAVE_SYS_TYPES_H) && (HAVE_SYS_TYPES_H == 1)
+#include <sys/types.h>
+#endif
 #include <string.h>
 #include <stdarg.h>
 #include <errno.h>
@@ -60,6 +63,8 @@ main (void)
        test_broadcast_var () ;
        test_cart_var () ;
 
+       test_nms_adpcm () ;
+
        return 0 ;
 } /* main */
 
index 156d374..d08fb2e 100644 (file)
@@ -40,3 +40,5 @@ void test_psf_strlcpy_crlf (void) ;
 void test_broadcast_var (void) ;
 
 void test_cart_var (void) ;
+
+void test_nms_adpcm (void) ;
diff --git a/src/test_nms_adpcm.c b/src/test_nms_adpcm.c
new file mode 100644 (file)
index 0000000..8558a04
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+** Copyright (C) 2007-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2017-2018 Arthur Taylor <art@ified.ca>
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or (at
+** your option) any later version.
+**
+** This library is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+** General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this library.  If not, write to the Free Software Foundation,
+** Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
+*/
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+
+#include "test_main.h"
+
+#include "nms_adpcm.c"
+
+static const short pcm_data_src [] =
+{      505, 743, 805, 409, 101, -552, -709, -679,
+       -624, -1174, -1050, 32, -401, -769, -679, 47,
+       -3273, -4425, -2158, -176, 824, 1057, 1245, 805,
+       2414, 3282, 1739, -624, -1197, -1663, -913, 603,
+       549, -614, 707, 3314, 2864, 1127, -294, -919,
+       -1251, -147, 30, -750, -131, 1394, 2197, 1829,
+       1387, 417, 391, 533, 581, 179, -210, -210,
+       -884, -937, -1373, -1338, -1811, -2727, -2536, -1552,
+       -651, -3556, -7713, -9083, -6182, 1070, 4983, 5341,
+       4596, 4682, 6488, 5197, 2401, -2702, -5261, -4036,
+       -1995, 463, 1056, 2436, 3238, 4395, 4478, 1130,
+       -2383, -4349, -4547, -3631, -1396, 1029, 2589, 3948,
+       4966, 4312, 2362, 492, -1289, -2259, -1659, -597,
+       239, 1433, 2353, 2512, 1763, 610, -291, -640,
+       7, 132, 432, 438, -1070, -1202, -1071, -1841,
+       -462, 225, -4465, -11313, -10492, -4522, -2096, -7013,
+       -11770, -2546, 7687, 12765, 12014, 5324, 1645, 1191,
+       3800, -187, -6689, -7778, -4631, 2487, 7352, 7928,
+       4317, 2424, 3784, 2301, -1713, -6668, -8345, -6453,
+       -2303, 2269, 3232, 4114, 5054, 5054, 3768, 1060,
+       -1793, -3302, -2059, -86, 1153, 1690, 2869, 3841,
+       3551, 1919, -197, -1391, -847, 128, 746, 1111,
+       431, 559, 1086, 138, -1539, -2758, -1886, 1351,
+       2407, -1883, -8356, -10999, -9917, -7329, -4295, -3209,
+       -11616, -15352, 1032, 12603, 13233, 9059, 4019, 1858,
+       3368, 7454, -56, -8600, -7278, -818, 5478, 7039,
+       5630, 1186, 1634, 5422, 2518, -3182, -8271, -7889,
+       -4399, -129, 3205, 2933, 3661, 5886, 6543, 3798,
+       374, -2722, -3378, -1804, -24, 385, 1663, 3595,
+       4749, 3865, 1402, -851, -1932, -1394, -725, -219,
+       290, 658, 1074, 1638, 536, 204, -340, 408,
+       1835, 1261, -2872, -4840, -5978, -8177, -7644, -6554,
+       -8093, -6174, -7796, -17019, -12355, 1280, 12576, 11868,
+       10710, 8578, 5605, 9675, 7123, -977, -8770, -6740,
+       -1327, 2905, 6386, 5026, 3809, 5137, 6392, 2463,
+       -4924, -8830, -9572, -6122, -1608, 1677, 3379, 5660,
+       8236, 7225, 4470, 295, -2628, -3572, -2107, -666,
+       951, 3101, 5049, 4759, 2367, -140, -2078, -2471,
+       -2332, -1547, -798, 410, 1825, 3329, 3092, 352,
+       -3310, -3307, -1229, -415, 532, 2091, 465, -1430
+} ;
+
+/* pcm_data encoded as 16kbs from a known reference */
+static const unsigned short test_codes_16 [] =
+{      0x5777, 0xfff0, 0xdcd0, 0x672d, 0x1826, 0xc11c, 0x0822, 0xffee,
+       0x3ddc, 0x6372, 0x0116, 0xc8d8, 0x6780, 0x8624, 0x3323, 0x33ef,
+       0xd865, 0x4cd8, 0x3372, 0x1096, 0x0049, 0xa911, 0x1288, 0xa74d,
+       0x3fee, 0xcc45, 0x52de, 0x6a72, 0x9118, 0xe291, 0x60a2, 0x3164,
+       0x73fe, 0xeddf, 0x57b5, 0x185a, 0xe889, 0x460e, 0x2646, 0x8d87,
+       0xe5ba, 0x004c
+} ;
+
+/* pcm_data encoded as 24kbs from a known reference */
+static const unsigned short test_codes_24 [] =
+{      0x7776, 0x2fec, 0xceb0, 0xffd0, 0x3241, 0x650a, 0x0a26, 0x61ba,
+       0xa10b, 0x3912, 0x39a8, 0xebfa, 0x1fff, 0x8552, 0x2342, 0x0204,
+       0x454b, 0xccbb, 0x4318, 0xaa00, 0x1642, 0x3031, 0xfc8f, 0x38ff,
+       0xf604, 0x4924, 0x2ddb, 0x0469, 0xbcaa, 0x83b6, 0x0049, 0x8828,
+       0x2266, 0x3801, 0x873d, 0xcb86, 0x0eff, 0xef64, 0xd402, 0x44fa,
+       0x2867, 0xd1d0, 0xa109, 0x2a11, 0x8a64, 0x4018, 0x1357, 0xd5a5,
+       0x4bfc, 0xcbfe, 0x070a, 0x6307, 0x1858, 0x624b, 0xf9a9, 0x783b,
+       0x0880, 0x1652, 0xc893, 0x641c, 0xf30d, 0x004c
+} ;
+
+/* pcm_data encoded as 32kbs from a known reference */
+static const unsigned short test_codes_32 [] =
+{      0x7772, 0x0cdc, 0xbec2, 0xacb2, 0xff90, 0x1220, 0x551c, 0xcc84,
+       0x2c47, 0x30aa, 0xa10b, 0x0663, 0x2812, 0x28a9, 0xf9ba, 0xceb9,
+       0x1fec, 0x9553, 0x2361, 0x9ed8, 0x8314, 0x564b, 0xddba, 0x1346,
+       0x6308, 0xab00, 0x0721, 0x2908, 0x3820, 0xf89c, 0x38ff, 0xa2bf,
+       0xc535, 0x2933, 0x5de9, 0x8633, 0x8569, 0xbeca, 0x1186, 0x5528,
+       0xd000, 0xaa21, 0x0473, 0x2800, 0x1112, 0xa64d, 0xdc17, 0x8eeb,
+       0xccac, 0xfe74, 0xc501, 0x63f9, 0x2040, 0x3a73, 0xc9b9, 0x9188,
+       0x7318, 0x0a81, 0x9a65, 0x5188, 0x00ba, 0x2256, 0xd5b6, 0x4bfa,
+       0xbeac, 0xe8fe, 0x343b, 0x7117, 0x9ca4, 0x915a, 0x563d, 0xcad0,
+       0xa837, 0x302a, 0x1a2a, 0x3561, 0x98a9, 0xb9b5, 0x578a, 0xc48b,
+       0x25f0, 0x1000
+} ;
+
+
+/* test_codes_16 decoded by a known reference */
+const short pcm_data_out16 [] =
+{      12, 16, 24, 36, 52, -68, -104, -156,
+       -224, -309, -433, 12, -449, -618, -851, 32,
+       -871, -1176, -1586, 60, 1172, 634, 1566, 983,
+       1995, 2586, 1718, -1152, -815, -2313, -1610, 1261,
+       1056, -253, 522, 1799, 2506, 1518, 72, -329,
+       -1510, -76, 337, -1144, 68, 1369, 2200, 1337,
+       1016, 60, 405, 461, 433, 389, -36, -164,
+       -550, -871, -1212, -1626, -2136, -2791, -2064, -1642,
+       -485, -1566, -2538, -3445, -4481, 650, 4381, 3799,
+       5807, 4742, 6674, 5590, 2072, -2228, -5650, -4983,
+       -1698, 441, 1333, 3064, 2855, 3815, 5108, 2156,
+       -2228, -3321, -5028, -4405, -1550, 771, 3232, 3273,
+       4008, 5008, 2024, 859, -654, -2746, -1694, -136,
+       68, 1409, 1759, 2453, 2016, 522, -514, -445,
+       0, 305, 493, 518, -232, -1076, -1116, -1321,
+       -506, 365, -140, -1132, -2076, -2895, -2357, -2477,
+       -3325, -2859, 666, 4449, 7164, 6244, 1847, 1365,
+       3827, -779, -7682, -8951, -3811, 1718, 6566, 7120,
+       4674, 1959, 1819, 2032, -1104, -5220, -8518, -7626,
+       -2385, 2714, 3510, 3871, 4831, 4024, 4156, 1590,
+       -1694, -3437, -2393, 96, 959, 1847, 2775, 3638,
+       3072, 1734, -204, -1730, -718, -92, 453, 807,
+       220, 514, 1349, -40, -1285, -2477, -1566, 1273,
+       2586, 546, -2887, -5534, -6883, -7461, -5281, -2224,
+       -2361, -5104, -48, 9228, 12140, 9048, 3614, 1927,
+       4618, 6004, -148, -9871, -5582, -489, 6835, 6746,
+       6839, 2851, 3028, 4566, 1461, -2028, -6883, -7642,
+       -5321, -610, 3385, 3461, 3088, 3389, 4570, 4321,
+       -389, -2630, -3369, -1706, -136, 220, 1594, 3024,
+       4622, 4232, 1265, -943, -2273, -1638, -726, -232,
+       365, 538, 995, 1530, 289, 453, -68, 12,
+       1184, 1562, 92, -2558, -4859, -6277, -7096, -5461,
+       -4811, -6020, -8851, -12594, -11501, -943, 12927, 10449,
+       8935, 10389, 5662, 5755, 9108, 1827, -10224, -7807,
+       -148, 3429, 7722, 5212, 4734, 3847, 5570, 3433,
+       -3931, -8244, -8461, -5397, -1710, 1919, 3787, 4558,
+       5040, 5722, 4811, -441, -3140, -4180, -2397, -493,
+       1309, 3064, 4116, 5040, 2759, -730, -2445, -2847,
+       -2080, -1682, -1124, 706, 2032, 3325, 3248, 425,
+       -3586, -2987, -1397, -188, 144, 1506, 4, -2028
+} ;
+
+/* test_codes_24 decoded by a known reference */
+static const short pcm_data_out24 [] =
+{      16, 32, 68, 140, 116, -232, -510, -650,
+       -771, -1329, -1052, -152, -317, -907, -710, -104,
+       -1144, -2132, -2598, -301, 662, 827, 1469, 702,
+       2401, 2987, 1574, -244, -1481, -1365, -903, 738,
+       369, -469, 473, 1630, 3124, 1542, -582, -1172,
+       -1381, -317, 4, -610, -40, 1236, 1843, 1493,
+       1349, 417, 389, 630, 686, 188, -228, -168,
+       -742, -795, -1530, -1473, -1903, -3008, -2907, -1317,
+       -445, -2309, -4919, -8939, -5867, 1204, 5293, 5337,
+       4871, 4562, 5602, 5104, 2485, -2337, -5594, -4240,
+       -1694, 867, 1281, 2622, 3638, 4228, 4654, 1405,
+       -1947, -4112, -4184, -3582, -1570, 1325, 2538, 4036,
+       5144, 4630, 2718, 518, -1373, -2397, -1642, -453,
+       349, 1566, 2558, 2493, 1927, 662, -365, -610,
+       -136, 188, 453, 437, -385, -1281, -1196, -1534,
+       -369, 265, -899, -3445, -7176, -4538, -2726, -5650,
+       -13152, -1694, 7040, 11489, 12224, 5971, 1971, 1779,
+       3457, -373, -6040, -7714, -5008, 2594, 7658, 8156,
+       4461, 2333, 4369, 2867, -1919, -7180, -8465, -6409,
+       -2618, 2152, 3120, 4208, 5570, 5558, 4120, 690,
+       -2088, -3345, -1975, -208, 1180, 1738, 2144, 3289,
+       3686, 1819, -417, -1534, -875, 88, 678, 967,
+       437, 558, 951, 20, -1638, -2558, -1967, 558,
+       2289, 465, -4449, -11080, -8931, -6248, -4208, -3337,
+       -6493, -14550, -5068, 12305, 13261, 9742, 4261, 1851,
+       3016, 6971, 441, -9554, -7096, -975, 5188, 6658,
+       5409, 1341, 855, 6164, 1726, -2381, -7991, -7212,
+       -4799, -433, 3236, 3273, 3253, 4445, 6706, 3329,
+       582, -2602, -3028, -1614, -152, 196, 1598, 3638,
+       5144, 4016, 1586, -1004, -2016, -1401, -682, -128,
+       273, 614, 963, 1614, 425, 269, -449, 277,
+       1746, 1240, -1510, -4598, -6397, -8008, -7602, -7152,
+       -7393, -6738, -8606, -15385, -13385, 1192, 12212, 11152,
+       9967, 8622, 5240, 6939, 7369, -2216, -9602, -7425,
+       -999, 3228, 6329, 4702, 4305, 4550, 6216, 3072,
+       -4983, -9313, -9437, -5586, -1987, 2088, 3184, 4662,
+       8244, 6598, 4606, -277, -2718, -3188, -2321, -437,
+       835, 2855, 4638, 4943, 2116, -393, -2269, -2502,
+       -2445, -1630, -646, 469, 1927, 3188, 2943, 502,
+       -3148, -3100, -1144, -642, 658, 1843, 449, -1445
+} ;
+
+/* test_codes_32 decoded by a known reference */
+static const short pcm_data_out32 [] =
+{      20, 96, 417, 433, 140, -506, -742, -714,
+       -598, -1092, -1044, 56, -445, -702, -622, 76,
+       -1116, -4293, -2429, -433, 606, 1196, 1357, 650,
+       2465, 3040, 1730, -682, -1381, -1759, -867, 518,
+       614, -698, 751, 2172, 3216, 1369, -562, -1076,
+       -1293, -116, -12, -803, -176, 1297, 2228, 1759,
+       1257, 425, 453, 614, 622, 188, -212, -220,
+       -975, -951, -1441, -1309, -1698, -2578, -2405, -1650,
+       -590, -2293, -7052, -8506, -5907, 1100, 5192, 5305,
+       4244, 4425, 6779, 5313, 2152, -2654, -5598, -3803,
+       -2176, 301, 1080, 2281, 3361, 4485, 4690, 1269,
+       -2253, -4477, -4562, -3598, -1345, 1108, 2638, 3783,
+       4819, 4401, 2357, 409, -1180, -2204, -1730, -662,
+       168, 1566, 2550, 2333, 1879, 485, -293, -690,
+       -28, 176, 445, 413, -767, -1088, -1204, -1847,
+       -481, 261, -1321, -8714, -10646, -4265, -1979, -7100,
+       -11678, -1911, 7449, 13333, 11991, 5244, 1935, 1072,
+       3638, -4, -6377, -7650, -4819, 2674, 7148, 8036,
+       4325, 2433, 3855, 2204, -1638, -6361, -8192, -6634,
+       -2184, 2144, 3357, 4164, 4783, 5168, 3835, 1100,
+       -1670, -3224, -2140, -144, 1120, 1755, 2530, 3626,
+       3678, 1771, -281, -1289, -875, 48, 755, 1112,
+       449, 546, 1140, 232, -1530, -2783, -1871, 1128,
+       2216, -1899, -8606, -11333, -10140, -7546, -4357, -2979,
+       -6044, -14851, -3726, 13136, 13477, 9534, 3871, 1489,
+       3526, 7012, 80, -8188, -7140, -1120, 5783, 7060,
+       5823, 1337, 1108, 5566, 2345, -3373, -8140, -7919,
+       -4566, 76, 3060, 2795, 3385, 5907, 6558, 3638,
+       257, -2630, -3401, -1807, -116, 349, 1610, 3417,
+       4750, 3967, 1489, -907, -1923, -1385, -666, -265,
+       253, 682, 1084, 1586, 538, 184, -381, 433,
+       1875, 1289, -1574, -4538, -6168, -8196, -7887, -6750,
+       -7526, -6060, -8148, -16036, -12546, 895, 12991, 12060,
+       10827, 8931, 5321, 8646, 7654, -473, -8582, -6614,
+       -1321, 2803, 6542, 5184, 3847, 4943, 6397, 2148,
+       -4999, -8799, -9614, -5931, -1574, 1546, 3493, 5397,
+       7879, 6919, 4610, 160, -2538, -3582, -2052, -578,
+       1060, 2987, 4843, 4791, 2421, -116, -1987, -2518,
+       -2333, -1534, -855, 365, 1779, 3389, 3080, 477,
+       -3281, -3120, -1188, -265, 638, 2224, 333, -1377
+} ;
+
+
+static void
+test_nms_adpcm_32 (void)
+{
+       struct nms_adpcm_state nms ;
+       int16_t *buffer ;
+       unsigned char code ;
+       int i, j, sl ;
+
+       buffer = (int16_t *) malloc (sizeof (int16_t) * NMS_SAMPLES_PER_BLOCK) ;
+
+       print_test_name ("Testing nms adpcm 32kbs encoder") ;
+
+       nms_adpcm_codec_init (&nms, NMS32) ;
+       for (i = 0 ; i * NMS_BLOCK_SHORTS_32 < ARRAY_LEN (test_codes_32) ; i ++)
+       {       /* Unpack the reference */
+               nms_adpcm_block_unpack_32 (&(test_codes_32 [i * NMS_BLOCK_SHORTS_32]), buffer, NULL) ;
+               for (j = 0 ; j < NMS_SAMPLES_PER_BLOCK ; j++)
+               {       sl = pcm_data_src [i * NMS_SAMPLES_PER_BLOCK + j] ;
+                       code = nms_adpcm_encode_sample (&nms, sl) ;
+                       if (code != buffer [j])
+                       {       printf ("\n\nFail at sample %d (block %d, sample %d). Expected 0x%x got 0x%x\n\n",
+                                       i * NMS_SAMPLES_PER_BLOCK + j, i, j, buffer [j], code) ;
+                               exit (1) ;
+                               }
+                       }
+               }
+
+       puts ("ok") ;
+
+       print_test_name ("Testing nms adpcm 32kbs decoder") ;
+
+       nms_adpcm_codec_init (&nms, NMS32) ;
+       for (i = 0 ; i * NMS_BLOCK_SHORTS_32 < ARRAY_LEN (test_codes_32) ; i ++)
+       {       /* Unpack the code */
+               nms_adpcm_block_unpack_32 (&(test_codes_32 [i * NMS_BLOCK_SHORTS_32]), buffer, NULL) ;
+               for (j = 0 ; j < NMS_SAMPLES_PER_BLOCK ; j++)
+               {       sl = nms_adpcm_decode_sample (&nms, buffer [j]) ;
+                       if (sl != pcm_data_out32 [i * NMS_SAMPLES_PER_BLOCK + j])
+                       {       printf ("\n\nFail at sample %d (block %d, sample %d). Expected %d got %d\n\n",
+                                       i * NMS_SAMPLES_PER_BLOCK + j, i, j, pcm_data_out32 [i * NMS_SAMPLES_PER_BLOCK + j], sl) ;
+                               exit (1) ;
+                               }
+                       }
+               }
+
+       puts ("ok") ;
+
+       free (buffer) ;
+}
+
+
+static void
+test_nms_adpcm_24 (void)
+{
+       struct nms_adpcm_state nms ;
+       int16_t *buffer ;
+       unsigned char code ;
+       int i, j, sl ;
+
+       buffer = (int16_t *) malloc (sizeof (int16_t) * NMS_SAMPLES_PER_BLOCK) ;
+
+
+       print_test_name ("Testing nms adpcm 24kbs encoder") ;
+
+       nms_adpcm_codec_init (&nms, NMS24) ;
+       for (i = 0 ; i * NMS_BLOCK_SHORTS_24 < ARRAY_LEN (test_codes_24) ; i ++)
+       {       /* Unpack the reference */
+               nms_adpcm_block_unpack_24 (&test_codes_24 [i * NMS_BLOCK_SHORTS_24], buffer, NULL) ;
+               for (j = 0 ; j < NMS_SAMPLES_PER_BLOCK ; j++)
+               {       sl = pcm_data_src [i * NMS_SAMPLES_PER_BLOCK + j] ;
+                       code = nms_adpcm_encode_sample (&nms, sl) ;
+                       if (code != buffer [j])
+                       {       printf ("\n\nFail at sample %d (block %d, sample %d). Expected 0x%x got 0x%x\n\n",
+                                       i * NMS_SAMPLES_PER_BLOCK + j, i, j, buffer [j], code) ;
+                               exit (1) ;
+                               }
+                       }
+               }
+
+       puts ("ok") ;
+
+
+       print_test_name ("Testing nms adpcm 24kbs decoder") ;
+
+       nms_adpcm_codec_init (&nms, NMS24) ;
+       for (i = 0 ; i * NMS_BLOCK_SHORTS_24 < ARRAY_LEN (test_codes_24) ; i ++)
+       {       /* Unpack the code */
+               nms_adpcm_block_unpack_24 (&test_codes_24 [i * NMS_BLOCK_SHORTS_24], buffer, NULL) ;
+               for (j = 0 ; j < NMS_SAMPLES_PER_BLOCK ; j++)
+               {       sl = nms_adpcm_decode_sample (&nms, buffer [j]) ;
+                       if (sl != pcm_data_out24 [i * NMS_SAMPLES_PER_BLOCK + j])
+                       {       printf ("\n\nFail at sample %d (block %d, sample %d). Expected %d got %d\n\n",
+                                       i * NMS_SAMPLES_PER_BLOCK + j, i, j, pcm_data_out24 [i * NMS_SAMPLES_PER_BLOCK + j], sl) ;
+                               exit (1) ;
+                               }
+                       }
+               }
+
+       puts ("ok") ;
+
+       free (buffer) ;
+} /* test_nms_adpcm_24 */
+
+static void
+test_nms_adpcm_16 (void)
+{      struct nms_adpcm_state nms ;
+       int16_t *buffer ;
+       unsigned char code ;
+       int i, j, sl ;
+
+       buffer = (int16_t *) malloc (sizeof (int16_t) * NMS_SAMPLES_PER_BLOCK) ;
+
+       print_test_name ("Testing nms adpcm 16kbs encoder") ;
+
+       nms_adpcm_codec_init (&nms, NMS16) ;
+       for (i = 0 ; i * NMS_BLOCK_SHORTS_16 < ARRAY_LEN (test_codes_16) ; i ++)
+       {       /* Unpack the reference */
+               nms_adpcm_block_unpack_16 (&test_codes_16 [i * NMS_BLOCK_SHORTS_16], buffer, NULL) ;
+               for (j = 0 ; j < NMS_SAMPLES_PER_BLOCK ; j++)
+               {       sl = pcm_data_src [i * NMS_SAMPLES_PER_BLOCK + j] ;
+                       code = nms_adpcm_encode_sample (&nms, sl) ;
+                       if (code != buffer [j])
+                       {       printf ("\n\nFail at sample %d (block %d, sample %d). Expected 0x%x got 0x%x\n\n",
+                                       i * NMS_SAMPLES_PER_BLOCK + j, i, j, buffer [j], code) ;
+                               exit (1) ;
+                               }
+                       }
+               }
+
+       puts ("ok") ;
+
+       print_test_name ("Testing nms adpcm 16kbs decoder") ;
+
+       nms_adpcm_codec_init (&nms, NMS16) ;
+       for (i = 0 ; i * NMS_BLOCK_SHORTS_16 < ARRAY_LEN (test_codes_16) ; i ++)
+       {       /* Unpack the code */
+               nms_adpcm_block_unpack_16 (&test_codes_16 [i * NMS_BLOCK_SHORTS_16], buffer, NULL) ;
+               for (j = 0 ; j < NMS_SAMPLES_PER_BLOCK ; j++)
+               {       sl = nms_adpcm_decode_sample (&nms, buffer [j]) ;
+                       if (sl != pcm_data_out16 [i * NMS_SAMPLES_PER_BLOCK + j])
+                       {       printf ("\n\nFail at sample %d (block %d, sample %d). Expected %d got %d\n\n",
+                                       i * NMS_SAMPLES_PER_BLOCK + j, i, j, pcm_data_out16 [i * NMS_SAMPLES_PER_BLOCK + j], sl) ;
+                               exit (1) ;
+                               }
+                       }
+               }
+
+       puts ("ok") ;
+
+       free (buffer) ;
+} /* test_nms_adpcm_16 */
+
+void
+test_nms_adpcm (void)
+{      test_nms_adpcm_32 () ;
+       test_nms_adpcm_24 () ;
+       test_nms_adpcm_16 () ;
+} /* main */
+
index e50b4cb..744e354 100644 (file)
@@ -19,6 +19,7 @@
 #include       "sfconfig.h"
 
 #include       <math.h>
+#include       <limits.h>
 
 #include       "sndfile.h"
 #include       "common.h"
@@ -827,7 +828,9 @@ s2ulaw_array (const short *ptr, int count, unsigned char *buffer)
 static inline void
 i2ulaw_array (const int *ptr, int count, unsigned char *buffer)
 {      while (--count >= 0)
-       {       if (ptr [count] >= 0)
+       {       if (ptr [count] == INT_MIN)
+                       buffer [count] = ulaw_encode [INT_MAX >> (16 + 2)] ;
+               else if (ptr [count] >= 0)
                        buffer [count] = ulaw_encode [ptr [count] >> (16 + 2)] ;
                else
                        buffer [count] = 0x7F & ulaw_encode [-ptr [count] >> (16 + 2)] ;
@@ -838,19 +841,21 @@ static inline void
 f2ulaw_array (const float *ptr, int count, unsigned char *buffer, float normfact)
 {      while (--count >= 0)
        {       if (ptr [count] >= 0)
-                       buffer [count] = ulaw_encode [lrintf (normfact * ptr [count])] ;
+                       buffer [count] = ulaw_encode [psf_lrintf (normfact * ptr [count])] ;
                else
-                       buffer [count] = 0x7F & ulaw_encode [- lrintf (normfact * ptr [count])] ;
+                       buffer [count] = 0x7F & ulaw_encode [- psf_lrintf (normfact * ptr [count])] ;
                } ;
 } /* f2ulaw_array */
 
 static inline void
 d2ulaw_array (const double *ptr, int count, unsigned char *buffer, double normfact)
 {      while (--count >= 0)
-       {       if (ptr [count] >= 0)
-                       buffer [count] = ulaw_encode [lrint (normfact * ptr [count])] ;
+       {       if (!isfinite (ptr [count]))
+                       buffer [count] = 0 ;
+               else if (ptr [count] >= 0)
+                       buffer [count] = ulaw_encode [psf_lrint (normfact * ptr [count])] ;
                else
-                       buffer [count] = 0x7F & ulaw_encode [- lrint (normfact * ptr [count])] ;
+                       buffer [count] = 0x7F & ulaw_encode [- psf_lrint (normfact * ptr [count])] ;
                } ;
 } /* d2ulaw_array */
 
index ed79b22..a672e4b 100644 (file)
@@ -19,7 +19,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
                        VALUE "Full Version", "@PACKAGE_VERSION@"
                        VALUE "InternalName", "libsndfile"
                        VALUE "LegalCopyright", "Copyright (C) 1999-2012, Licensed LGPL"
-                       VALUE "OriginalFilename", "libsndfile-1.dll"
                        VALUE "ProductName", "libsndfile-1 DLL"
                        VALUE "ProductVersion", "@CLEAN_VERSION@.0\0"
                        VALUE "Language", "Language Neutral"
index e783b68..380d3a3 100644 (file)
--- a/src/voc.c
+++ b/src/voc.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -405,7 +405,7 @@ voc_read_header     (SF_PRIVATE *psf)
                                        break ;
 
                        default : /* Unknown */
-                                       return SFE_UNKNOWN_FORMAT ;
+                                       return SFE_VOC_BAD_FORMAT ;
                                        break ;
                        } ;
 
@@ -441,10 +441,10 @@ voc_write_header (SF_PRIVATE *psf, int calc_length)
        psf_fseek (psf, 0, SEEK_SET) ;
 
        /* VOC marker and 0x1A byte. */
-       psf_binheader_writef (psf, "eb1", "Creative Voice File", make_size_t (19), 0x1A) ;
+       psf_binheader_writef (psf, "eb1", BHWv ("Creative Voice File"), BHWz (19), BHW1 (0x1A)) ;
 
        /* Data offset, version and other. */
-       psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ;
+       psf_binheader_writef (psf, "e222", BHW2 (26), BHW2 (0x0114), BHW2 (0x111F)) ;
 
        /*      Use same logic as SOX.
        **      If the file is mono 8 bit data, use VOC_SOUND_DATA.
@@ -457,7 +457,7 @@ voc_write_header (SF_PRIVATE *psf, int calc_length)
                rate_const = 256 - 1000000 / psf->sf.samplerate ;
 
                /* First type marker, length, rate_const and compression */
-               psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ;
+               psf_binheader_writef (psf, "e1311", BHW1 (VOC_SOUND_DATA), BHW3 ((int) (psf->datalength + 1)), BHW1 (rate_const), BHW1 (0)) ;
                }
        else if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 2)
        {       /* sample_rate = 128000000 / (65536 - rate_short) ; */
@@ -466,7 +466,7 @@ voc_write_header (SF_PRIVATE *psf, int calc_length)
                /* First write the VOC_EXTENDED section
                **              marker, length, rate_const and compression
                */
-               psf_binheader_writef (psf, "e13211", VOC_EXTENDED, 4, rate_const, 0, 1) ;
+               psf_binheader_writef (psf, "e13211", BHW1 (VOC_EXTENDED), BHW3 (4), BHW2 (rate_const), BHW1 (0), BHW1 (1)) ;
 
                /* samplerate = 1000000 / (256 - rate_const) ; */
                rate_const = 256 - 1000000 / psf->sf.samplerate ;
@@ -474,7 +474,7 @@ voc_write_header (SF_PRIVATE *psf, int calc_length)
                /*      Now write the VOC_SOUND_DATA section
                **              marker, length, rate_const and compression
                */
-               psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ;
+               psf_binheader_writef (psf, "e1311", BHW1 (VOC_SOUND_DATA), BHW3 ((int) (psf->datalength + 1)), BHW1 (rate_const), BHW1 (0)) ;
                }
        else
        {       int length ;
@@ -487,26 +487,26 @@ voc_write_header (SF_PRIVATE *psf, int calc_length)
                                        psf->bytewidth = 1 ;
                                        length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
                                        /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */
-                                       psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ;
+                                       psf_binheader_writef (psf, "e1341124", BHW1 (VOC_EXTENDED_II), BHW3 (length), BHW4 (psf->sf.samplerate), BHW1 (16), BHW1 (psf->sf.channels), BHW2 (4), BHW4 (0)) ;
                                        break ;
 
                        case SF_FORMAT_PCM_16 :
                                        psf->bytewidth = 2 ;
                                        length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
                                        /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */
-                                       psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ;
+                                       psf_binheader_writef (psf, "e1341124", BHW1 (VOC_EXTENDED_II), BHW3 (length), BHW4 (psf->sf.samplerate), BHW1 (16), BHW1 (psf->sf.channels), BHW2 (4), BHW4 (0)) ;
                                        break ;
 
                        case SF_FORMAT_ALAW :
                                        psf->bytewidth = 1 ;
                                        length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
-                                       psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 6, 0) ;
+                                       psf_binheader_writef (psf, "e1341124", BHW1 (VOC_EXTENDED_II), BHW3 (length), BHW4 (psf->sf.samplerate), BHW1 (8), BHW1 (psf->sf.channels), BHW2 (6), BHW4 (0)) ;
                                        break ;
 
                        case SF_FORMAT_ULAW :
                                        psf->bytewidth = 1 ;
                                        length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
-                                       psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 7, 0) ;
+                                       psf_binheader_writef (psf, "e1341124", BHW1 (VOC_EXTENDED_II), BHW3 (length), BHW4 (psf->sf.samplerate), BHW1 (8), BHW1 (psf->sf.channels), BHW2 (7), BHW4 (0)) ;
                                        break ;
 
                        default : return SFE_UNIMPLEMENTED ;
index 6db6618..50c3d05 100644 (file)
@@ -356,7 +356,7 @@ vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrintf (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
                count = vox_write_block (psf, pvox, sptr, writecount) ;
                total += count ;
                len -= writecount ;
@@ -387,7 +387,7 @@ vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
        while (len > 0)
        {       writecount = (len >= bufferlen) ? bufferlen : (int) len ;
                for (k = 0 ; k < writecount ; k++)
-                       sptr [k] = lrint (normfact * ptr [total + k]) ;
+                       sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
                count = vox_write_block (psf, pvox, sptr, writecount) ;
                total += count ;
                len -= writecount ;
index 1b84dd6..426480b 100644 (file)
--- a/src/w64.c
+++ b/src/w64.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -326,37 +326,30 @@ w64_read_header   (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
 
                        case levl_HASH16 :
                                        psf_log_printf (psf, "levl : %D\n", chunk_size) ;
-                                       chunk_size -= 24 ;
                                        break ;
 
                        case list_HASH16 :
                                        psf_log_printf (psf, "list : %D\n", chunk_size) ;
-                                       chunk_size -= 24 ;
                                        break ;
 
                        case junk_HASH16 :
                                        psf_log_printf (psf, "junk : %D\n", chunk_size) ;
-                                       chunk_size -= 24 ;
                                        break ;
 
                        case bext_HASH16 :
                                        psf_log_printf (psf, "bext : %D\n", chunk_size) ;
-                                       chunk_size -= 24 ;
                                        break ;
 
                        case MARKER_HASH16 :
                                        psf_log_printf (psf, "marker : %D\n", chunk_size) ;
-                                       chunk_size -= 24 ;
                                        break ;
 
                        case SUMLIST_HASH16 :
                                        psf_log_printf (psf, "summary list : %D\n", chunk_size) ;
-                                       chunk_size -= 24 ;
                                        break ;
 
                        default :
-                                       psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %D. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ;
-                                       done = SF_TRUE ;
+                                       psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %D. Skipping and continuing.\n", marker, psf_ftell (psf) - 8, chunk_size) ;
                                        break ;
                        } ;     /* switch (dword) */
 
@@ -383,7 +376,7 @@ w64_read_header     (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
        if (psf->sf.channels < 1)
                return SFE_CHANNEL_COUNT_ZERO ;
 
-       if (psf->sf.channels >= SF_MAX_CHANNELS)
+       if (psf->sf.channels > SF_MAX_CHANNELS)
                return SFE_CHANNEL_COUNT ;
 
        psf->endian = SF_ENDIAN_LITTLE ;                /* All W64 files are little endian. */
@@ -465,7 +458,7 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
        psf_fseek (psf, 0, SEEK_SET) ;
 
        /* riff marker, length, wave and 'fmt ' markers. */
-       psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength, wave_MARKER16, fmt_MARKER16) ;
+       psf_binheader_writef (psf, "eh8hh", BHWh (riff_MARKER16), BHW8 (psf->filelength), BHWh (wave_MARKER16), BHWh (fmt_MARKER16)) ;
 
        subformat = SF_CODEC (psf->sf.format) ;
 
@@ -479,11 +472,11 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                        fmt_size += fmt_pad ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "e8224", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_PCM), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "e4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth */
-                                       psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
+                                       psf_binheader_writef (psf, "e22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ;
                                        break ;
 
                case SF_FORMAT_FLOAT :
@@ -493,11 +486,11 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                        fmt_size += fmt_pad ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "e8224", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_IEEE_FLOAT), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "e4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth */
-                                       psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
+                                       psf_binheader_writef (psf, "e22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
@@ -508,11 +501,11 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                        fmt_size += fmt_pad ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "e8224", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_MULAW), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "e4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth */
-                                       psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ;
+                                       psf_binheader_writef (psf, "e22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (8)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
@@ -523,11 +516,11 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                        fmt_size += fmt_pad ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "e8224", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_ALAW), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "e4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth */
-                                       psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ;
+                                       psf_binheader_writef (psf, "e22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (8)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
@@ -546,13 +539,13 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                                fmt_size += fmt_pad ;
 
                                                /* fmt : size, WAV format type, channels. */
-                                               psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ;
+                                               psf_binheader_writef (psf, "e822", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_IMA_ADPCM), BHW2 (psf->sf.channels)) ;
 
                                                /* fmt : samplerate, bytespersec. */
-                                               psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
+                                               psf_binheader_writef (psf, "e44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ;
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
-                                               psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ;
+                                               psf_binheader_writef (psf, "e2222", BHW2 (blockalign), BHW2 (4), BHW2 (2), BHW2 (framesperblock)) ;
                                                } ;
 
                                        add_fact_chunk = SF_TRUE ;
@@ -572,13 +565,13 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                                fmt_size += fmt_pad ;
 
                                                /* fmt : size, W64 format type, channels. */
-                                               psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
+                                               psf_binheader_writef (psf, "e822", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_MS_ADPCM), BHW2 (psf->sf.channels)) ;
 
                                                /* fmt : samplerate, bytespersec. */
-                                               psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
+                                               psf_binheader_writef (psf, "e44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ;
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
-                                               psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ;
+                                               psf_binheader_writef (psf, "e22222", BHW2 (blockalign), BHW2 (4), BHW2 (extrabytes), BHW2 (framesperblock), BHW2 (7)) ;
 
                                                wavlike_msadpcm_write_adapt_coeffs (psf) ;
                                                } ;
@@ -598,13 +591,13 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
                                                fmt_size += fmt_pad ;
 
                                                /* fmt : size, WAV format type, channels. */
-                                               psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
+                                               psf_binheader_writef (psf, "e822", BHW8 (fmt_size), BHW2 (WAVE_FORMAT_GSM610), BHW2 (psf->sf.channels)) ;
 
                                                /* fmt : samplerate, bytespersec. */
-                                               psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
+                                               psf_binheader_writef (psf, "e44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ;
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
-                                               psf_binheader_writef (psf, "e2222", WAVLIKE_GSM610_BLOCKSIZE, 0, 2, WAVLIKE_GSM610_SAMPLES) ;
+                                               psf_binheader_writef (psf, "e2222", BHW2 (WAVLIKE_GSM610_BLOCKSIZE), BHW2 (0), BHW2 (2), BHW2 (WAVLIKE_GSM610_SAMPLES)) ;
                                                } ;
 
                                        add_fact_chunk = SF_TRUE ;
@@ -615,12 +608,12 @@ w64_write_header (SF_PRIVATE *psf, int calc_length)
 
        /* Pad to 8 bytes with zeros. */
        if (fmt_pad > 0)
-               psf_binheader_writef (psf, "z", fmt_pad) ;
+               psf_binheader_writef (psf, "z", BHWz (fmt_pad)) ;
 
        if (add_fact_chunk)
-               psf_binheader_writef (psf, "eh88", fact_MARKER16, (sf_count_t) (16 + 8 + 8), psf->sf.frames) ;
+               psf_binheader_writef (psf, "eh88", BHWh (fact_MARKER16), BHW8 ((sf_count_t) (16 + 8 + 8)), BHW8 (psf->sf.frames)) ;
 
-       psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ;
+       psf_binheader_writef (psf, "eh8", BHWh (data_MARKER16), BHW8 (psf->datalength + 24)) ;
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
 
        if (psf->error)
index 4b943dc..fd3e453 100644 (file)
--- a/src/wav.c
+++ b/src/wav.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2004-2005 David Viens <davidv@plogue.com>
 **
 ** This program is free software; you can redistribute it and/or modify
@@ -261,6 +261,13 @@ wav_open   (SF_PRIVATE *psf)
                case SF_FORMAT_G721_32 :
                                        error = g72x_init (psf) ;
                                        break ;
+
+               case SF_FORMAT_NMS_ADPCM_16 :
+               case SF_FORMAT_NMS_ADPCM_24 :
+               case SF_FORMAT_NMS_ADPCM_32 :
+                                       error = nms_adpcm_init (psf) ;
+                                       break ;
+
                /* Lite remove end */
 
                case SF_FORMAT_GSM610 :
@@ -466,14 +473,19 @@ wav_read_header   (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
                                                bytesread = psf_binheader_readf (psf, "4", &cue_count) ;
                                                psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
 
-                                               if (cue_count > 1000)
+                                               if (cue_count > 2500) /* 2500 is close to the largest number of cues possible because of block sizes */
                                                {       psf_log_printf (psf, "  Count : %u (skipping)\n", cue_count) ;
-                                                       psf_binheader_readf (psf, "j", (cue_count > 20 ? 20 : cue_count) * 24) ;
+                                                       psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
                                                        break ;
                                                        } ;
 
                                                psf_log_printf (psf, "  Count : %d\n", cue_count) ;
 
+                                               if (psf->cues)
+                                               {       free (psf->cues) ;
+                                                       psf->cues = NULL ;
+                                                       } ;
+
                                                if ((psf->cues = psf_cues_alloc (cue_count)) == NULL)
                                                        return SFE_MALLOC_FAILED ;
 
@@ -485,11 +497,15 @@ wav_read_header   (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
                                                                break ;
                                                        bytesread += thisread ;
 
-                                                       psf_log_printf (psf,    "   Cue ID : %2d"
-                                                                                                       "  Pos : %5u  Chunk : %M"
-                                                                                                       "  Chk Start : %d  Blk Start : %d"
-                                                                                                       "  Offset : %5d\n",
-                                                                       id, position, chunk_id, chunk_start, block_start, offset) ;
+                                                       if (cue_index < 10) /* avoid swamping log buffer with cues */
+                                                               psf_log_printf (psf,    "   Cue ID : %2d"
+                                                                                       "  Pos : %5u  Chunk : %M"
+                                                                                       "  Chk Start : %d  Blk Start : %d"
+                                                                                       "  Offset : %5d\n",
+                                                                               id, position, chunk_id, chunk_start, block_start, offset) ;
+                                                       else if (cue_index == 10)
+                                                               psf_log_printf (psf,    "   (Skipping)\n") ;
+
                                                        psf->cues->cue_points [cue_index].indx = id ;
                                                        psf->cues->cue_points [cue_index].position = position ;
                                                        psf->cues->cue_points [cue_index].fcc_chunk = chunk_id ;
@@ -627,7 +643,7 @@ wav_read_header     (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
        if (psf->sf.channels < 1)
                return SFE_CHANNEL_COUNT_ZERO ;
 
-       if (psf->sf.channels >= SF_MAX_CHANNELS)
+       if (psf->sf.channels > SF_MAX_CHANNELS)
                return SFE_CHANNEL_COUNT ;
 
        if (format != WAVE_FORMAT_PCM && (parsestage & HAVE_fact) == 0)
@@ -666,6 +682,25 @@ wav_read_header    (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
                                } ;
                        break ;
 
+               case WAVE_FORMAT_NMS_VBXADPCM :
+                       *blockalign = wav_fmt->min.blockalign ;
+                       *framesperblock = 160 ;
+                       switch (wav_fmt->min.bitwidth)
+                       {       case 2 :
+                                       psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16 ;
+                                       break ;
+                               case 3 :
+                                       psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24 ;
+                                       break ;
+                               case 4 :
+                                       psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32 ;
+                                       break ;
+
+                               default :
+                                       return SFE_UNIMPLEMENTED ;
+                               }
+                               break ;
+
                case WAVE_FORMAT_PCM :
                                        psf->sf.format = SF_FORMAT_WAV | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
                                        break ;
@@ -732,11 +767,11 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_PCM), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth */
-                                       psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
+                                       psf_binheader_writef (psf, "22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ;
                                        break ;
 
                case SF_FORMAT_FLOAT :
@@ -744,11 +779,11 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_IEEE_FLOAT), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth */
-                                       psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
+                                       psf_binheader_writef (psf, "22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
@@ -757,11 +792,11 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_MULAW), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth, extrabytes */
-                                       psf_binheader_writef (psf, "222", psf->bytewidth * psf->sf.channels, 8, 0) ;
+                                       psf_binheader_writef (psf, "222", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (8), BHW2 (0)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
@@ -770,11 +805,11 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
 
                                        /* fmt : format, channels, samplerate */
-                                       psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ;
+                                       psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_ALAW), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                                        /*  fmt : bytespersec */
-                                       psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                                       psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                                        /*  fmt : blockalign, bitwidth, extrabytes */
-                                       psf_binheader_writef (psf, "222", psf->bytewidth * psf->sf.channels, 8, 0) ;
+                                       psf_binheader_writef (psf, "222", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (8), BHW2 (0)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
@@ -791,11 +826,11 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                                fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
 
                                                /* fmt : size, WAV format type, channels, samplerate, bytespersec */
-                                               psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_IMA_ADPCM,
-                                                                       psf->sf.channels, psf->sf.samplerate, bytespersec) ;
+                                               psf_binheader_writef (psf, "42244", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_IMA_ADPCM),
+                                                                       BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ;
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
-                                               psf_binheader_writef (psf, "2222", blockalign, 4, 2, framesperblock) ;
+                                               psf_binheader_writef (psf, "2222", BHW2 (blockalign), BHW2 (4), BHW2 (2), BHW2 (framesperblock)) ;
                                                } ;
 
                                        add_fact_chunk = SF_TRUE ;
@@ -813,13 +848,13 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                                fmt_size        = 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ;
 
                                                /* fmt : size, WAV format type, channels. */
-                                               psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
+                                               psf_binheader_writef (psf, "422", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_MS_ADPCM), BHW2 (psf->sf.channels)) ;
 
                                                /* fmt : samplerate, bytespersec. */
-                                               psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ;
+                                               psf_binheader_writef (psf, "44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ;
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
-                                               psf_binheader_writef (psf, "22222", blockalign, 4, extrabytes, framesperblock, 7) ;
+                                               psf_binheader_writef (psf, "22222", BHW2 (blockalign), BHW2 (4), BHW2 (extrabytes), BHW2 (framesperblock), BHW2 (7)) ;
 
                                                wavlike_msadpcm_write_adapt_coeffs (psf) ;
                                                } ;
@@ -833,15 +868,37 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
 
                                        /* fmt : size, WAV format type, channels, samplerate, bytespersec */
-                                       psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_G721_ADPCM,
-                                                               psf->sf.channels, psf->sf.samplerate, psf->sf.samplerate * psf->sf.channels / 2) ;
+                                       psf_binheader_writef (psf, "42244", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_G721_ADPCM),
+                                                               BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate), BHW4 (psf->sf.samplerate * psf->sf.channels / 2)) ;
 
                                        /* fmt : blockalign, bitwidth, extrabytes, auxblocksize. */
-                                       psf_binheader_writef (psf, "2222", 64, 4, 2, 0) ;
+                                       psf_binheader_writef (psf, "2222", BHW2 (64), BHW2 (4), BHW2 (2), BHW2 (0)) ;
 
                                        add_fact_chunk = SF_TRUE ;
                                        break ;
 
+               case SF_FORMAT_NMS_ADPCM_16 :
+               case SF_FORMAT_NMS_ADPCM_24 :
+               case SF_FORMAT_NMS_ADPCM_32 :
+                                       {       int bytespersec, blockalign, bitwidth ;
+
+                                               bitwidth        = subformat == SF_FORMAT_NMS_ADPCM_16 ? 2 : subformat == SF_FORMAT_NMS_ADPCM_24 ? 3 : 4 ;
+                                               blockalign      = 20 * bitwidth + 2 ;
+                                               bytespersec     = psf->sf.samplerate * blockalign / 160 ;
+
+                                               /* fmt chunk. */
+                                               fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
+
+                                               /* fmt : format, channels, samplerate */
+                                               psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_NMS_VBXADPCM),
+                                                                       BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
+                                               /*  fmt : bytespersec, blockalign, bitwidth */
+                                               psf_binheader_writef (psf, "422", BHW4 (bytespersec), BHW2 (blockalign), BHW2 (bitwidth)) ;
+
+                                               add_fact_chunk = SF_TRUE ;
+                                               break ;
+                                               }
+
                /* Lite remove end */
 
                case SF_FORMAT_GSM610 :
@@ -855,13 +912,13 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                                                fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
 
                                                /* fmt : size, WAV format type, channels. */
-                                               psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
+                                               psf_binheader_writef (psf, "422", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_GSM610), BHW2 (psf->sf.channels)) ;
 
                                                /* fmt : samplerate, bytespersec. */
-                                               psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ;
+                                               psf_binheader_writef (psf, "44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ;
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
-                                               psf_binheader_writef (psf, "2222", blockalign, 0, 2, framesperblock) ;
+                                               psf_binheader_writef (psf, "2222", BHW2 (blockalign), BHW2 (0), BHW2 (2), BHW2 (framesperblock)) ;
                                                } ;
 
                                        add_fact_chunk = SF_TRUE ;
@@ -871,7 +928,7 @@ wav_write_fmt_chunk (SF_PRIVATE *psf)
                } ;
 
        if (add_fact_chunk)
-               psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ;
+               psf_binheader_writef (psf, "tm48", BHWm (fact_MARKER), BHW4 (4), BHW8 (psf->sf.frames)) ;
 
        return 0 ;
 } /* wav_write_fmt_chunk */
@@ -899,25 +956,25 @@ wavex_write_fmt_chunk (SF_PRIVATE *psf)
                        fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ;
 
                        /* fmt : format, channels, samplerate */
-                       psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ;
+                       psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_EXTENSIBLE), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ;
                        /*  fmt : bytespersec */
-                       psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
+                       psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ;
                        /*  fmt : blockalign, bitwidth */
-                       psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
+                       psf_binheader_writef (psf, "22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ;
 
                        /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */
-                       psf_binheader_writef (psf, "2", 22) ;
+                       psf_binheader_writef (psf, "2", BHW2 (22)) ;
 
                        /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */
-                       psf_binheader_writef (psf, "2", psf->bytewidth * 8) ;
+                       psf_binheader_writef (psf, "2", BHW2 (psf->bytewidth * 8)) ;
 
                        /* For an Ambisonic file set the channel mask to zero.
                        ** Otherwise use a default based on the channel count.
                        */
                        if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE)
-                               psf_binheader_writef (psf, "4", 0) ;
+                               psf_binheader_writef (psf, "4", BHW4 (0)) ;
                        else if (wpriv->wavex_channelmask != 0)
-                               psf_binheader_writef (psf, "4", wpriv->wavex_channelmask) ;
+                               psf_binheader_writef (psf, "4", BHW4 (wpriv->wavex_channelmask)) ;
                        else
                        {       /*
                                ** Ok some liberty is taken here to use the most commonly used channel masks
@@ -926,27 +983,27 @@ wavex_write_fmt_chunk (SF_PRIVATE *psf)
                                */
                                switch (psf->sf.channels)
                                {       case 1 :        /* center channel mono */
-                                               psf_binheader_writef (psf, "4", 0x4) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x4)) ;
                                                break ;
 
                                        case 2 :        /* front left and right */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2)) ;
                                                break ;
 
                                        case 4 :        /* Quad */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x10 | 0x20) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x10 | 0x20)) ;
                                                break ;
 
                                        case 6 :        /* 5.1 */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20)) ;
                                                break ;
 
                                        case 8 :        /* 7.1 */
-                                               psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80)) ;
                                                break ;
 
                                        default :       /* 0 when in doubt , use direct out, ie NO mapping*/
-                                               psf_binheader_writef (psf, "4", 0x0) ;
+                                               psf_binheader_writef (psf, "4", BHW4 (0x0)) ;
                                                break ;
                                        } ;
                                } ;
@@ -993,7 +1050,7 @@ wavex_write_fmt_chunk (SF_PRIVATE *psf)
                default : return SFE_UNIMPLEMENTED ;
                } ;
 
-       psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ;
+       psf_binheader_writef (psf, "tm48", BHWm (fact_MARKER), BHW4 (4), BHW8 (psf->sf.frames)) ;
 
        return 0 ;
 } /* wavex_write_fmt_chunk */
@@ -1034,12 +1091,12 @@ wav_write_header (SF_PRIVATE *psf, int calc_length)
        /* RIFF/RIFX marker, length, WAVE and 'fmt ' markers. */
 
        if (psf->endian == SF_ENDIAN_LITTLE)
-               psf_binheader_writef (psf, "etm8", RIFF_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8) ;
+               psf_binheader_writef (psf, "etm8", BHWm (RIFF_MARKER), BHW8 ((psf->filelength < 8) ? 8 : psf->filelength - 8)) ;
        else
-               psf_binheader_writef (psf, "Etm8", RIFX_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8) ;
+               psf_binheader_writef (psf, "Etm8", BHWm (RIFX_MARKER), BHW8 ((psf->filelength < 8) ? 8 : psf->filelength - 8)) ;
 
        /* WAVE and 'fmt ' markers. */
-       psf_binheader_writef (psf, "mm", WAVE_MARKER, fmt_MARKER) ;
+       psf_binheader_writef (psf, "mm", BHWm (WAVE_MARKER), BHWm (fmt_MARKER)) ;
 
        /* Write the 'fmt ' chunk. */
        switch (SF_CONTAINER (psf->sf.format))
@@ -1073,26 +1130,30 @@ wav_write_header (SF_PRIVATE *psf, int calc_length)
        if (psf->cues != NULL)
        {       uint32_t k ;
 
-               psf_binheader_writef (psf, "em44", cue_MARKER, 4 + psf->cues->cue_count * 6 * 4, psf->cues->cue_count) ;
+               psf_binheader_writef (psf, "em44", BHWm (cue_MARKER), BHW4 (4 + psf->cues->cue_count * 6 * 4), BHW4 (psf->cues->cue_count)) ;
 
                for (k = 0 ; k < psf->cues->cue_count ; k++)
-                       psf_binheader_writef (psf, "e44m444", psf->cues->cue_points [k].indx, psf->cues->cue_points [k].position,
-                                               psf->cues->cue_points [k].fcc_chunk, psf->cues->cue_points [k].chunk_start,
-                                               psf->cues->cue_points [k].block_start, psf->cues->cue_points [k].sample_offset) ;
+                       psf_binheader_writef (psf, "e44m444", BHW4 (psf->cues->cue_points [k].indx), BHW4 (psf->cues->cue_points [k].position),
+                                               BHWm (psf->cues->cue_points [k].fcc_chunk), BHW4 (psf->cues->cue_points [k].chunk_start),
+                                               BHW4 (psf->cues->cue_points [k].block_start), BHW4 (psf->cues->cue_points [k].sample_offset)) ;
                } ;
 
        if (psf->instrument != NULL)
        {       int             tmp ;
                double  dtune = (double) (0x40000000) / 25.0 ;
 
-               psf_binheader_writef (psf, "m4", smpl_MARKER, 9 * 4 + psf->instrument->loop_count * 6 * 4) ;
-               psf_binheader_writef (psf, "44", 0, 0) ; /* Manufacturer zero is everyone */
+               psf_binheader_writef (psf, "m4", BHWm (smpl_MARKER), BHW4 (9 * 4 + psf->instrument->loop_count * 6 * 4)) ;
+               psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (0)) ; /* Manufacturer zero is everyone */
                tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */
-               psf_binheader_writef (psf, "44", tmp, psf->instrument->basenote) ;
+               psf_binheader_writef (psf, "44", BHW4 (tmp), BHW4 (psf->instrument->basenote)) ;
                tmp = (uint32_t) (psf->instrument->detune * dtune + 0.5) ;
-               psf_binheader_writef (psf, "4", tmp) ;
-               psf_binheader_writef (psf, "44", 0, 0) ; /* SMTPE format */
-               psf_binheader_writef (psf, "44", psf->instrument->loop_count, 0) ;
+               psf_binheader_writef (psf, "4", BHW4 (tmp)) ;
+               psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (0)) ; /* SMTPE format */
+               psf_binheader_writef (psf, "44", BHW4 (psf->instrument->loop_count), BHW4 (0)) ;
+
+               /* Make sure we don't read past the loops array end. */
+               if (psf->instrument->loop_count > ARRAY_LEN (psf->instrument->loops))
+                       psf->instrument->loop_count = ARRAY_LEN (psf->instrument->loops) ;
 
                for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++)
                {       int type ;
@@ -1100,9 +1161,9 @@ wav_write_header (SF_PRIVATE *psf, int calc_length)
                        type = psf->instrument->loops [tmp].mode ;
                        type = (type == SF_LOOP_FORWARD ? 0 : type == SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
 
-                       psf_binheader_writef (psf, "44", tmp, type) ;
-                       psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end - 1) ;
-                       psf_binheader_writef (psf, "44", 0, psf->instrument->loops [tmp].count) ;
+                       psf_binheader_writef (psf, "44", BHW4 (tmp), BHW4 (type)) ;
+                       psf_binheader_writef (psf, "44", BHW4 (psf->instrument->loops [tmp].start), BHW4 (psf->instrument->loops [tmp].end - 1)) ;
+                       psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (psf->instrument->loops [tmp].count)) ;
                        } ;
                } ;
 
@@ -1113,10 +1174,10 @@ wav_write_header (SF_PRIVATE *psf, int calc_length)
        if (psf->header.indx + 16 < psf->dataoffset)
        {       /* Add PAD data if necessary. */
                size_t k = psf->dataoffset - (psf->header.indx + 16) ;
-               psf_binheader_writef (psf, "m4z", PAD_MARKER, k, k) ;
+               psf_binheader_writef (psf, "m4z", BHWm (PAD_MARKER), BHW4 (k), BHWz (k)) ;
                } ;
 
-       psf_binheader_writef (psf, "tm8", data_MARKER, psf->datalength) ;
+       psf_binheader_writef (psf, "tm8", BHWm (data_MARKER), BHW8 (psf->datalength)) ;
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
        if (psf->error)
                return psf->error ;
@@ -1155,7 +1216,7 @@ wav_write_tailer (SF_PRIVATE *psf)
                psf->dataend = psf_fseek (psf, 0, SEEK_END) ;
 
        if (psf->dataend & 1)
-               psf_binheader_writef (psf, "z", 1) ;
+               psf_binheader_writef (psf, "z", BHWz (1)) ;
 
        /* Add a PEAK chunk if requested. */
        if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_END)
@@ -1233,8 +1294,8 @@ wav_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize)
 static int
 wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
 {      char buffer [512] ;
-       uint32_t thisread, bytesread = 0, dword, sampler_data, loop_count ;
-       uint32_t note, start, end, type = -1, count ;
+       uint32_t thisread, bytesread = 0, dword, sampler_data, loop_count, actually_loop_count = 0 ;
+       uint32_t note, pitch, start, end, type = -1, count ;
        int j, k ;
 
        chunklen += (chunklen & 1) ;
@@ -1251,10 +1312,10 @@ wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
        bytesread += psf_binheader_readf (psf, "4", &note) ;
        psf_log_printf (psf, "  Midi Note    : %u\n", note) ;
 
-       bytesread += psf_binheader_readf (psf, "4", &dword) ;
-       if (dword != 0)
+       bytesread += psf_binheader_readf (psf, "4", &pitch) ;
+       if (pitch != 0)
        {       snprintf (buffer, sizeof (buffer), "%f",
-                                       (1.0 * 0x80000000) / ((uint32_t) dword)) ;
+                                       (1.0 * 0x80000000) / ((uint32_t) pitch)) ;
                psf_log_printf (psf, "  Pitch Fract. : %s\n", buffer) ;
                }
        else
@@ -1279,6 +1340,11 @@ wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
        */
        bytesread += psf_binheader_readf (psf, "4", &sampler_data) ;
 
+       if (psf->instrument)
+       {       psf_log_printf (psf, "  Found more than one SMPL chunk, using last one.\n") ;
+               free (psf->instrument) ;
+               psf->instrument = NULL ;
+               } ;
        if ((psf->instrument = psf_instrument_alloc ()) == NULL)
                return SFE_MALLOC_FAILED ;
 
@@ -1325,8 +1391,17 @@ wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
                                        break ;
                                } ;
                        } ;
+               actually_loop_count ++ ;
+               } ;
 
-               loop_count -- ;
+       if (actually_loop_count > ARRAY_LEN (psf->instrument->loops))
+       {
+               psf_log_printf (psf, "*** Warning, actual Loop Points count exceeds %u, changing Loop Count from %u to %u\n", ARRAY_LEN (psf->instrument->loops), loop_count, ARRAY_LEN (psf->instrument->loops)) ;
+               psf->instrument->loop_count = ARRAY_LEN (psf->instrument->loops) ;
+               }
+       else if (loop_count != actually_loop_count)
+       {       psf_log_printf (psf, "*** Warning, actual Loop Points count != Loop Count, changing Loop Count from %u to %u\n", loop_count, actually_loop_count) ;
+               psf->instrument->loop_count = actually_loop_count ;
                } ;
 
        if (chunklen - bytesread == 0)
@@ -1360,6 +1435,7 @@ wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
                } ;
 
        psf->instrument->basenote = note ;
+       psf->instrument->detune = (int8_t) (pitch / (0x40000000 / 25.0) + 0.5) ;
        psf->instrument->gain = 1 ;
        psf->instrument->velocity_lo = psf->instrument->key_lo = 0 ;
        psf->instrument->velocity_hi = psf->instrument->key_hi = 127 ;
@@ -1429,6 +1505,11 @@ wav_read_acid_chunk (SF_PRIVATE *psf, uint32_t chunklen)
 
        psf_binheader_readf (psf, "j", chunklen - bytesread) ;
 
+       if (psf->loop_info)
+       {       psf_log_printf (psf, "  Found existing loop info, using last one.\n") ;
+               free (psf->loop_info) ;
+               psf->loop_info = NULL ;
+               } ;
        if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL)
                return SFE_MALLOC_FAILED ;
 
index 86ebf01..b59c684 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2020 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2004-2005 David Viens <davidv@plogue.com>
 **
 ** This program is free software; you can redistribute it and/or modify
@@ -432,6 +432,21 @@ wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
                                        psf_log_printf (psf, "*** 'fmt ' chunk should be bigger than this!\n") ;
                                break ;
 
+               case WAVE_FORMAT_NMS_VBXADPCM :
+                               if (wav_fmt->min.channels != 1 || wav_fmt->min.bitwidth < 2 || wav_fmt->min.bitwidth * 20 + 2 != wav_fmt->min.blockalign)
+                                       return SFE_WAV_NMS_FORMAT ;
+
+                               bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / 160 ;
+                               if (wav_fmt->min.bytespersec == (unsigned) bytespersec)
+                                       psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->min.bytespersec) ;
+                               else
+                                       psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ;
+                               if (fmtsize >= 18)
+                               {       bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ;
+                                       psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->size20.extrabytes) ;
+                                       } ;
+                               break ;
+
                default :
                                psf_log_printf (psf, "*** No 'fmt ' chunk dumper for this format!\n") ;
                                return SFE_WAV_BAD_FMT ;
@@ -452,9 +467,9 @@ wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
 void
 wavlike_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat)
 {
-       psf_binheader_writef (psf, "422b", subformat->esf_field1,
-                                       subformat->esf_field2, subformat->esf_field3,
-                                       subformat->esf_field4, make_size_t (8)) ;
+       psf_binheader_writef (psf, "422b", BHW4 (subformat->esf_field1),
+                                       BHW2 (subformat->esf_field2), BHW2 (subformat->esf_field3),
+                                       BHWv (subformat->esf_field4), BHWz (8)) ;
 } /* wavlike_write_guid */
 
 
@@ -725,10 +740,17 @@ wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
 
        psf_log_printf (psf, "bext : %u\n", chunksize) ;
 
-       if ((psf->broadcast_16k = broadcast_var_alloc ()) == NULL)
-       {       psf->error = SFE_MALLOC_FAILED ;
-               return psf->error ;
-               } ;
+       if (!psf->broadcast_16k)
+       {       psf->broadcast_16k = broadcast_var_alloc () ;
+               if (!psf->broadcast_16k)
+               {       psf->error = SFE_MALLOC_FAILED ;
+                       return psf->error ;
+                       }
+               }
+       else
+       {       psf_log_printf (psf, "bext : found more than one bext chunk, using last one.\n") ;
+               memset (psf->broadcast_16k, 0, sizeof (SF_BROADCAST_INFO_16K)) ;
+               }
 
        b = psf->broadcast_16k ;
 
@@ -738,7 +760,10 @@ wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
        bytes += psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
        bytes += psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
        bytes += psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ;
-       bytes += psf_binheader_readf (psf, "bj", &b->umid, sizeof (b->umid), 190) ;
+       bytes += psf_binheader_readf (psf, "b", &b->umid, sizeof (b->umid)) ;
+       bytes += psf_binheader_readf (psf, "22", &b->loudness_value, &b->loudness_range) ;
+       bytes += psf_binheader_readf (psf, "222", &b->max_true_peak_level, &b->max_momentary_loudness, &b->max_shortterm_loudness) ;
+       bytes += psf_binheader_readf (psf, "j", 180) ;
 
        if (chunksize > WAV_BEXT_MIN_CHUNK_SIZE)
        {       /* File has coding history data. */
@@ -746,11 +771,11 @@ wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
                b->coding_history_size = chunksize - WAV_BEXT_MIN_CHUNK_SIZE ;
 
                /* We do not parse the coding history */
-               bytes += psf_binheader_readf (psf, "b", b->coding_history, b->coding_history_size) ;
+               bytes += psf_binheader_readf (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ;
                } ;
 
        if (bytes < chunksize)
-               psf_binheader_readf (psf, "j", chunksize - bytes) ;
+               psf_binheader_readf (psf, "j", BHWj (chunksize - bytes)) ;
 
        return 0 ;
 } /* wavlike_read_bext_chunk */
@@ -764,24 +789,26 @@ wavlike_write_bext_chunk (SF_PRIVATE *psf)
 
        b = psf->broadcast_16k ;
 
-       psf_binheader_writef (psf, "m4", bext_MARKER, WAV_BEXT_MIN_CHUNK_SIZE + b->coding_history_size) ;
+       psf_binheader_writef (psf, "m4", BHWm (bext_MARKER), BHW4 (WAV_BEXT_MIN_CHUNK_SIZE + b->coding_history_size)) ;
 
        /*
        **      Note that it is very important that the field widths of the SF_BROADCAST_INFO
        **      struct match those of the bext chunk fields.
        */
 
-       psf_binheader_writef (psf, "b", b->description, sizeof (b->description)) ;
-       psf_binheader_writef (psf, "b", b->originator, sizeof (b->originator)) ;
-       psf_binheader_writef (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ;
-       psf_binheader_writef (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
-       psf_binheader_writef (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
-       psf_binheader_writef (psf, "442", b->time_reference_low, b->time_reference_high, b->version) ;
-       psf_binheader_writef (psf, "b", b->umid, sizeof (b->umid)) ;
-       psf_binheader_writef (psf, "z", make_size_t (190)) ;
+       psf_binheader_writef (psf, "b", BHWv (b->description), BHWz (sizeof (b->description))) ;
+       psf_binheader_writef (psf, "b", BHWv (b->originator), BHWz (sizeof (b->originator))) ;
+       psf_binheader_writef (psf, "b", BHWv (b->originator_reference), BHWz (sizeof (b->originator_reference))) ;
+       psf_binheader_writef (psf, "b", BHWv (b->origination_date), BHWz (sizeof (b->origination_date))) ;
+       psf_binheader_writef (psf, "b", BHWv (b->origination_time), BHWz (sizeof (b->origination_time))) ;
+       psf_binheader_writef (psf, "442", BHW4 (b->time_reference_low), BHW4 (b->time_reference_high), BHW2 (b->version)) ;
+       psf_binheader_writef (psf, "b", BHWv (b->umid), BHWz (sizeof (b->umid))) ;
+       psf_binheader_writef (psf, "22", BHW2 (b->loudness_value), BHW2 (b->loudness_range)) ;
+       psf_binheader_writef (psf, "222", BHW2 (b->max_true_peak_level), BHW2 (b->max_momentary_loudness), BHW2 (b->max_shortterm_loudness)) ;
+       psf_binheader_writef (psf, "z", BHWz (180)) ;
 
        if (b->coding_history_size > 0)
-               psf_binheader_writef (psf, "b", b->coding_history, make_size_t (b->coding_history_size)) ;
+               psf_binheader_writef (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ;
 
        return 0 ;
 } /* wavlike_write_bext_chunk */
@@ -811,6 +838,12 @@ wavlike_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize)
 
        psf_log_printf (psf, "cart : %u\n", chunksize) ;
 
+       if (psf->cart_16k)
+       {       psf_log_printf (psf, "  Found more than one cart chunk, using last one.\n") ;
+               free (psf->cart_16k) ;
+               psf->cart_16k = NULL ;
+               } ;
+
        if ((psf->cart_16k = cart_var_alloc ()) == NULL)
        {       psf->error = SFE_MALLOC_FAILED ;
                return psf->error ;
@@ -858,36 +891,36 @@ wavlike_write_cart_chunk (SF_PRIVATE *psf)
                return -1 ;
 
        c = psf->cart_16k ;
-       psf_binheader_writef (psf, "m4", cart_MARKER, WAV_CART_MIN_CHUNK_SIZE + c->tag_text_size) ;
+       psf_binheader_writef (psf, "m4", BHWm (cart_MARKER), BHW4 (WAV_CART_MIN_CHUNK_SIZE + c->tag_text_size)) ;
        /*
        **      Note that it is very important that the field widths of the SF_CART_INFO
        **      struct match those of the cart chunk fields.
        */
-       psf_binheader_writef (psf, "b", c->version, sizeof (c->version)) ;
-       psf_binheader_writef (psf, "b", c->title, sizeof (c->title)) ;
-       psf_binheader_writef (psf, "b", c->artist, sizeof (c->artist)) ;
-       psf_binheader_writef (psf, "b", c->cut_id, sizeof (c->cut_id)) ;
-       psf_binheader_writef (psf, "b", c->client_id, sizeof (c->client_id)) ;
-       psf_binheader_writef (psf, "b", c->category, sizeof (c->category)) ;
-       psf_binheader_writef (psf, "b", c->classification, sizeof (c->classification)) ;
-       psf_binheader_writef (psf, "b", c->out_cue, sizeof (c->out_cue)) ;
-       psf_binheader_writef (psf, "b", c->start_date, sizeof (c->start_date)) ;
-       psf_binheader_writef (psf, "b", c->start_time, sizeof (c->start_time)) ;
-       psf_binheader_writef (psf, "b", c->end_date, sizeof (c->end_date)) ;
-       psf_binheader_writef (psf, "b", c->end_time, sizeof (c->end_time)) ;
-       psf_binheader_writef (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ;
-       psf_binheader_writef (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ;
-       psf_binheader_writef (psf, "b", c->user_def, sizeof (c->user_def)) ;
-       psf_binheader_writef (psf, "4", c->level_reference, sizeof (c->level_reference)) ;
+       psf_binheader_writef (psf, "b", BHWv (c->version), BHWz (sizeof (c->version))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->title), BHWz (sizeof (c->title))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->artist), BHWz (sizeof (c->artist))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->cut_id), BHWz (sizeof (c->cut_id))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->client_id), BHWz (sizeof (c->client_id))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->category), BHWz (sizeof (c->category))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->classification), BHWz (sizeof (c->classification))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->out_cue), BHWz (sizeof (c->out_cue))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->start_date), BHWz (sizeof (c->start_date))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->start_time), BHWz (sizeof (c->start_time))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->end_date), BHWz (sizeof (c->end_date))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->end_time), BHWz (sizeof (c->end_time))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->producer_app_id), BHWz (sizeof (c->producer_app_id))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->producer_app_version), BHWz (sizeof (c->producer_app_version))) ;
+       psf_binheader_writef (psf, "b", BHWv (c->user_def), BHWz (sizeof (c->user_def))) ;
+       psf_binheader_writef (psf, "e4", BHW4 (c->level_reference)) ;
 
        for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++)
-               psf_binheader_writef (psf, "b4", c->post_timers [k].usage, make_size_t (4), c->post_timers [k].value) ;
+               psf_binheader_writef (psf, "b4", BHWv (c->post_timers [k].usage), BHWz (4), BHW4 (c->post_timers [k].value)) ;
 
-       psf_binheader_writef (psf, "z", sizeof (c->reserved)) ; // just write zeros, we don't have any other use for it
-       psf_binheader_writef (psf, "b", c->url, sizeof (c->url)) ;
+       psf_binheader_writef (psf, "z", BHWz (sizeof (c->reserved))) ;  // just write zeros, we don't have any other use for it
+       psf_binheader_writef (psf, "b", BHWv (c->url), BHWz (sizeof (c->url))) ;
 
        if (c->tag_text_size > 0)
-               psf_binheader_writef (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
+               psf_binheader_writef (psf, "b", BHWv (c->tag_text), BHWz (c->tag_text_size)) ;
 
        return 0 ;
 } /* wavlike_write_cart_chunk */
@@ -948,7 +981,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                                        */
                                        psf_log_printf (psf, "    *** Found weird-ass zero marker. Jumping to end of chunk.\n") ;
                                        if (bytesread < chunk_length)
-                                               bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread + 4) ;
+                                               bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread) ;
                                        psf_log_printf (psf, "    *** Offset is now : 0x%X\n", psf_fseek (psf, 0, SEEK_CUR)) ;
                                        return 0 ;
 
@@ -996,11 +1029,25 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
 
                                                bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
                                                buffer [chunk_size] = 0 ;
-                                               psf_log_printf (psf, "    %M : %u : %s\n", chunk, mark_id, buffer) ;
+
+                                               if (mark_id < 10) /* avoid swamping log buffer with labels */
+                                                       psf_log_printf (psf, "    %M : %u : %s\n", chunk, mark_id, buffer) ;
+                                               else if (mark_id == 10)
+                                                       psf_log_printf (psf, "    (Skipping)\n") ;
+
+                                               if (psf->cues)
+                                               {       unsigned int i = 0 ;
+
+                                                       /* find id to store label */
+                                                       while (i < psf->cues->cue_count && psf->cues->cue_points [i].indx != mark_id)
+                                                               i++ ;
+
+                                                       if (i < psf->cues->cue_count)
+                                                               memcpy (psf->cues->cue_points [i].name, buffer, sizeof (psf->cues->cue_points [i].name)) ;
+                                                       } ;
                                                } ;
                                        break ;
 
-
                        case DISP_MARKER :
                        case ltxt_MARKER :
                        case note_MARKER :
@@ -1078,7 +1125,7 @@ wavlike_write_strings (SF_PRIVATE *psf, int location)
 
        prev_head_index = psf->header.indx + 4 ;
 
-       psf_binheader_writef (psf, "m4m", LIST_MARKER, 0xBADBAD, INFO_MARKER) ;
+       psf_binheader_writef (psf, "m4m", BHWm (LIST_MARKER), BHW4 (0xBADBAD), BHWm (INFO_MARKER)) ;
 
        for (k = 0 ; k < SF_MAX_STRINGS ; k++)
        {       if (psf->strings.data [k].type == 0)
@@ -1088,39 +1135,39 @@ wavlike_write_strings (SF_PRIVATE *psf, int location)
 
                switch (psf->strings.data [k].type)
                {       case SF_STR_SOFTWARE :
-                               psf_binheader_writef (psf, "ms", ISFT_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (ISFT_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_TITLE :
-                               psf_binheader_writef (psf, "ms", INAM_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (INAM_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_COPYRIGHT :
-                               psf_binheader_writef (psf, "ms", ICOP_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (ICOP_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_ARTIST :
-                               psf_binheader_writef (psf, "ms", IART_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (IART_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_COMMENT :
-                               psf_binheader_writef (psf, "ms", ICMT_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (ICMT_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_DATE :
-                               psf_binheader_writef (psf, "ms", ICRD_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (ICRD_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_GENRE :
-                               psf_binheader_writef (psf, "ms", IGNR_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (IGNR_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_ALBUM :
-                               psf_binheader_writef (psf, "ms", IPRD_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (IPRD_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        case SF_STR_TRACKNUMBER :
-                               psf_binheader_writef (psf, "ms", ITRK_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
+                               psf_binheader_writef (psf, "ms", BHWm (ITRK_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
                                break ;
 
                        default :
@@ -1130,7 +1177,7 @@ wavlike_write_strings (SF_PRIVATE *psf, int location)
 
        saved_head_index = psf->header.indx ;
        psf->header.indx = prev_head_index ;
-       psf_binheader_writef (psf, "4", saved_head_index - prev_head_index - 4) ;
+       psf_binheader_writef (psf, "4", BHW4 (saved_head_index - prev_head_index - 4)) ;
        psf->header.indx = saved_head_index ;
 
 } /* wavlike_write_strings */
@@ -1146,6 +1193,11 @@ wavlike_read_peak_chunk (SF_PRIVATE * psf, size_t chunk_size)
                return SFE_WAV_BAD_PEAK ;
                } ;
 
+       if (psf->peak_info)
+       {       psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ;
+               free (psf->peak_info) ;
+               psf->peak_info = NULL ;
+               } ;
        if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
                return SFE_MALLOC_FAILED ;
 
@@ -1184,10 +1236,10 @@ wavlike_write_peak_chunk (SF_PRIVATE * psf)
        if (psf->peak_info == NULL)
                return ;
 
-       psf_binheader_writef (psf, "m4", PEAK_MARKER, WAVLIKE_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
-       psf_binheader_writef (psf, "44", 1, time (NULL)) ;
+       psf_binheader_writef (psf, "m4", BHWm (PEAK_MARKER), BHW4 (WAVLIKE_PEAK_CHUNK_SIZE (psf->sf.channels))) ;
+       psf_binheader_writef (psf, "44", BHW4 (1), BHW4 (time (NULL))) ;
        for (k = 0 ; k < psf->sf.channels ; k++)
-               psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
+               psf_binheader_writef (psf, "ft8", BHWf (psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ;
 } /* wavlike_write_peak_chunk */
 
 /*==============================================================================
@@ -1217,7 +1269,7 @@ exif_fill_and_sink (SF_PRIVATE *psf, char* buf, size_t bufsz, size_t toread)
 */
 static int
 exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length)
-{      uint32_t marker, dword, vmajor = -1, vminor = -1, bytesread = 0 ;
+{      uint32_t marker, dword = 0, vmajor = -1, vminor = -1, bytesread = 0 ;
        char buf [4096] ;
        int thisread ;
 
@@ -1292,6 +1344,7 @@ wavlike_write_custom_chunks (SF_PRIVATE * psf)
 {      uint32_t k ;
 
        for (k = 0 ; k < psf->wchunks.used ; k++)
-               psf_binheader_writef (psf, "m4b", (int) psf->wchunks.chunks [k].mark32, psf->wchunks.chunks [k].len, psf->wchunks.chunks [k].data, make_size_t (psf->wchunks.chunks [k].len)) ;
+               psf_binheader_writef (psf, "m4b", BHWm (psf->wchunks.chunks [k].mark32), BHW4 (psf->wchunks.chunks [k].len),
+                                                       BHWv (psf->wchunks.chunks [k].data), BHWz (psf->wchunks.chunks [k].len)) ;
 
 } /* wavlike_write_custom_chunks */
index d3ec4ae..4cde1e9 100644 (file)
@@ -267,7 +267,7 @@ typedef struct
 {      unsigned int    esf_field1 ;
        unsigned short  esf_field2 ;
        unsigned short  esf_field3 ;
-       char                    esf_field4 [8] ;
+       unsigned char   esf_field4 [8] ;
 } EXT_SUBFORMAT ;
 
 typedef        struct
@@ -340,10 +340,10 @@ void      wavlike_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat) ;
 void   wavlike_analyze (SF_PRIVATE *psf) ;
 int            wavlike_gen_channel_mask (const int *chan_map, int channels) ;
 
-int            wavlike_read_bext_chunk (SF_PRIVATE *psf, unsigned int chunksize) ;
+int            wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize) ;
 int            wavlike_write_bext_chunk (SF_PRIVATE *psf) ;
 
-int            wavlike_read_cart_chunk (SF_PRIVATE *psf, unsigned int chunksize) ;
+int            wavlike_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize) ;
 int            wavlike_write_cart_chunk (SF_PRIVATE *psf) ;
 
 int            wavlike_subchunk_parse  (SF_PRIVATE *psf, int chunk, uint32_t length) ;
index 2845fef..2ef3002 100644 (file)
@@ -35,7 +35,6 @@ extern int sf_errno ;
 
 static void copy_filename (SF_PRIVATE * psf, LPCWSTR wpath) ;
 
-SNDFILE_API
 SNDFILE*
 sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo)
 {      SF_PRIVATE      *psf ;
index 845cafa..4b9fc8a 100644 (file)
--- a/src/wve.c
+++ b/src/wve.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 ** Copyright (C) 2007 Reuben Thomas
 **
 ** This program is free software; you can redistribute it and/or modify
@@ -174,8 +174,8 @@ wve_write_header (SF_PRIVATE *psf, int calc_length)
 
        /* Write header. */
        datalen = psf->datalength ;
-       psf_binheader_writef (psf, "Emmmm", ALAW_MARKER, SOUN_MARKER, DFIL_MARKER, ESSN_MARKER) ;
-       psf_binheader_writef (psf, "E2422222", PSION_VERSION, datalen, 0, 0, 0, 0, 0) ;
+       psf_binheader_writef (psf, "Emmmm", BHWm (ALAW_MARKER), BHWm (SOUN_MARKER), BHWm (DFIL_MARKER), BHWm (ESSN_MARKER)) ;
+       psf_binheader_writef (psf, "E2422222", BHW2 (PSION_VERSION), BHW4 (datalen), BHW2 (0), BHW2 (0), BHW2 (0), BHW2 (0), BHW2 (0)) ;
        psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
 
        if (psf->sf.channels != 1)
index 17d6277..c102060 100644 (file)
--- a/src/xi.c
+++ b/src/xi.c
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2003-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2003-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
@@ -285,32 +285,32 @@ xi_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
        psf_fseek (psf, 0, SEEK_SET) ;
 
        string = "Extended Instrument: " ;
-       psf_binheader_writef (psf, "b", string, strlen (string)) ;
-       psf_binheader_writef (psf, "b1", pxi->filename, sizeof (pxi->filename), 0x1A) ;
+       psf_binheader_writef (psf, "b", BHWv (string), BHWz (strlen (string))) ;
+       psf_binheader_writef (psf, "b1", BHWv (pxi->filename), BHWz (sizeof (pxi->filename)), BHW1 (0x1A)) ;
 
        /* Write software version and two byte XI version. */
-       psf_binheader_writef (psf, "eb2", pxi->software, sizeof (pxi->software), (1 << 8) + 2) ;
+       psf_binheader_writef (psf, "eb2", BHWv (pxi->software), BHWz (sizeof (pxi->software)), BHW2 ((1 << 8) + 2)) ;
 
        /*
        ** Jump note numbers (96), volume envelope (48), pan envelope (48),
        ** volume points (1), pan points (1)
        */
-       psf_binheader_writef (psf, "z", (size_t) (96 + 48 + 48 + 1 + 1)) ;
+       psf_binheader_writef (psf, "z", BHWz ((size_t) (96 + 48 + 48 + 1 + 1))) ;
 
        /* Jump volume loop (3 bytes), pan loop (3), envelope flags (3), vibrato (3)
        ** fade out (2), 22 unknown bytes, and then write sample_count (2 bytes).
        */
-       psf_binheader_writef (psf, "ez2z2", (size_t) (4 * 3), 0x1234, make_size_t (22), 1) ;
+       psf_binheader_writef (psf, "ez2z2", BHWz ((size_t) (4 * 3)), BHW2 (0x1234), BHWz (22), BHW2 (1)) ;
 
        pxi->loop_begin = 0 ;
        pxi->loop_end = 0 ;
 
-       psf_binheader_writef (psf, "et844", psf->sf.frames, pxi->loop_begin, pxi->loop_end) ;
+       psf_binheader_writef (psf, "et844", BHW8 (psf->sf.frames), BHW4 (pxi->loop_begin), BHW4 (pxi->loop_end)) ;
 
        /* volume, fine tune, flags, pan, note, namelen */
-       psf_binheader_writef (psf, "111111", 128, 0, pxi->sample_flags, 128, 0, strlen (pxi->sample_name)) ;
+       psf_binheader_writef (psf, "111111", BHW1 (128), BHW1 (0), BHW1 (pxi->sample_flags), BHW1 (128), BHW1 (0), BHW1 (strlen (pxi->sample_name))) ;
 
-       psf_binheader_writef (psf, "b", pxi->sample_name, sizeof (pxi->sample_name)) ;
+       psf_binheader_writef (psf, "b", BHWv (pxi->sample_name), BHWz (sizeof (pxi->sample_name))) ;
 
 
 
@@ -1072,7 +1072,7 @@ f2dsc_array (XI_PRIVATE *pxi, const float *src, signed char *dest, int count, fl
        last_val = pxi->last_16 >> 8 ;
 
        for (k = 0 ; k < count ; k++)
-       {       current = lrintf (src [k] * normfact) ;
+       {       current = psf_lrintf (src [k] * normfact) ;
                dest [k] = current - last_val ;
                last_val = current ;
                } ;
@@ -1088,7 +1088,7 @@ d2dsc_array (XI_PRIVATE *pxi, const double *src, signed char *dest, int count, d
        last_val = pxi->last_16 >> 8 ;
 
        for (k = 0 ; k < count ; k++)
-       {       current = lrint (src [k] * normfact) ;
+       {       current = psf_lrint (src [k] * normfact) ;
                dest [k] = current - last_val ;
                last_val = current ;
                } ;
@@ -1202,7 +1202,7 @@ f2dles_array (XI_PRIVATE *pxi, const float *src, short *dest, int count, float n
        last_val = pxi->last_16 ;
 
        for (k = 0 ; k < count ; k++)
-       {       current = lrintf (src [k] * normfact) ;
+       {       current = psf_lrintf (src [k] * normfact) ;
                diff = current - last_val ;
                dest [k] = LE2H_16 (diff) ;
                last_val = current ;
@@ -1219,7 +1219,7 @@ d2dles_array (XI_PRIVATE *pxi, const double *src, short *dest, int count, double
        last_val = pxi->last_16 ;
 
        for (k = 0 ; k < count ; k++)
-       {       current = lrint (src [k] * normfact) ;
+       {       current = psf_lrint (src [k] * normfact) ;
                diff = current - last_val ;
                dest [k] = LE2H_16 (diff) ;
                last_val = current ;
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644 (file)
index 6012388..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-if ENABLE_TEST_COVERAGE
-CPP_TEST =
-else
-CPP_TEST = cpp_test
-endif
-
-AM_CPPFLAGS = -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 chunk_test \
-       scale_clip_test win32_test fix_this aiff_rw_test virtual_io_test \
-       locale_test largefile_test win32_ordinal_test ogg_test compression_size_test \
-       checksum_test external_libs_test rdwr_test format_check_test $(CPP_TEST) \
-       channel_test long_read_write_test
-
-noinst_HEADERS = dft_cmp.h utils.h generate.h
-
-autogen_sources = \
-       write_read_test.c      write_read_test.tpl     write_read_test.def \
-       pcm_test.c             pcm_test.tpl            pcm_test.def \
-       header_test.c          header_test.tpl         header_test.def \
-       utils.c                utils.tpl               utils.def \
-       scale_clip_test.c      scale_clip_test.tpl     scale_clip_test.def \
-       pipe_test.c            pipe_test.tpl           pipe_test.def \
-       rdwr_test.c            rdwr_test.tpl           rdwr_test.def \
-       floating_point_test.c  floating_point_test.tpl floating_point_test.def \
-       benchmark.c            benchmark.tpl           benchmark.def
-
-EXTRA_DIST = $(autogen_sources)
-
-CLEANFILES = *~ *.exe
-
-#===============================================================================
-# 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
-
-chunk_test_SOURCES = chunk_test.c utils.c
-chunk_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
-
-compression_size_test_SOURCES = compression_size_test.c utils.c
-compression_size_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
-
-channel_test_SOURCES = channel_test.c utils.c
-channel_test_LDADD = $(top_builddir)/src/libsndfile.la
-
-long_read_write_test_SOURCES = long_read_write_test.c utils.c
-long_read_write_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
-
-#===============================================================================
-
-SUFFIXES = .def .tpl
-
-.def.c:
-       autogen --writable $<
-.def.h:
-       autogen --writable $<
index 43d34db..54eec4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2003-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2003-2017 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
 ** 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>
+#else
+#include "sf_unistd.h"
+#endif
 #include <math.h>
 #include <inttypes.h>
 
index 6d71ffe..b928083 100644 (file)
@@ -24,6 +24,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 6fdb35d..a69cd32 100644 (file)
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <math.h>
index 747f233..4b37b3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2008-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2008-2017 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
@@ -87,6 +87,7 @@ checksum_test (const CHECKSUM * cksum)
 
        print_test_name (__func__, cksum->enc_name) ;
 
+       memset (&info, 0, sizeof (info)) ;
        info.format = cksum->enc_fmt ;
        info.channels = 1 ;
        info.samplerate = SAMPLE_RATE ;
index f1bc074..ed34064 100644 (file)
@@ -25,6 +25,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include       <sndfile.h>
index 941e76b..625d8e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2019 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
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <math.h>
@@ -46,7 +48,8 @@ static        void    format_tests                    (void) ;
 static void    calc_peak_test                  (int filetype, const char *filename, int channels) ;
 static void    truncate_test                   (const char *filename, int filetype) ;
 static void    instrument_test                 (const char *filename, int filetype) ;
-static void    cue_test                        (const char *filename, int filetype) ;
+static void    cue_test                                (const char *filename, int filetype) ;
+static void    cue_test_var                    (const char *filename, int filetype, int count) ;
 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) ;
@@ -57,7 +60,7 @@ static        void    broadcast_coding_history_test   (const char *filename) ;
 static void    broadcast_coding_history_size   (const char *filename) ;
 
 /* Cart Chunk tests */
-static void    cart_test                       (const char *filename, int filetype) ;
+static void    cart_test                               (const char *filename, int filetype) ;
 static void    cart_rdwr_test                  (const char *filename, int filetype) ;
 
 /* Force the start of this buffer to be double aligned. Sparc-solaris will
@@ -138,14 +141,24 @@ main (int argc, char *argv [])
 
        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.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], "cue") == 0)
-       {       cue_test ("cue.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
+       {       /* 2500 is close to the largest number of cues possible because of block sizes (enforced in aiff.c, wav.c) */
+               int cuecounts [] = { 0, 1, 10, 100, 101, 1000, 1001, 2500 } ;
+               unsigned int i ;
+
+               cue_test ("cue.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
                cue_test ("cue.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_24) ;
+
+               for (i = 0 ; i < ARRAY_LEN (cuecounts) ; i++)
+               {       cue_test_var ("cue.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16, cuecounts [i]) ;
+                       cue_test_var ("cue.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_24, cuecounts [i]) ;
+                       } ;
+
                test_count ++ ;
                } ;
 
@@ -766,7 +779,6 @@ instrument_test (const char *filename, int filetype)
                **      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 ;
@@ -835,6 +847,50 @@ instrument_test (const char *filename, int filetype)
 } /* instrument_test */
 
 static void
+print_cue (SF_CUES *cue, int i)
+{
+       printf ("   indx[%d]       : %d\n"
+               "   position      : %u\n"
+               "   fcc_chunk     : %x\n"
+               "   chunk_start   : %d\n"
+               "   block_start   : %d\n"
+               "   sample_offset : %u\n"
+               "   name          : %s\n",
+               i,
+               cue->cue_points [i].indx,
+               cue->cue_points [i].position,
+               cue->cue_points [i].fcc_chunk,
+               cue->cue_points [i].chunk_start,
+               cue->cue_points [i].block_start,
+               cue->cue_points [i].sample_offset,
+               cue->cue_points [i].name) ;
+}
+
+static int
+cue_compare (SF_CUES *write_cue, SF_CUES *read_cue, size_t cue_size, int line)
+{
+       if (memcmp (write_cue, read_cue, cue_size) != 0)
+       {
+               printf ("\n\nLine %d : cue comparison failed.\n\n", line) ;
+               printf ("W  Cue count     : %d\n", write_cue->cue_count) ;
+               if (write_cue->cue_count > 0)
+                       print_cue (write_cue, 0) ;
+               if (write_cue->cue_count > 2)   /* print last if at least 2 */
+                       print_cue (write_cue, write_cue->cue_count - 1) ;
+
+               printf ("R  Cue count     : %d\n", read_cue->cue_count) ;
+               if (read_cue->cue_count > 0)
+                       print_cue (read_cue, 0) ;
+               if (read_cue->cue_count > 2)    /* print last if at least 2 */
+                       print_cue (read_cue, read_cue->cue_count - 1) ;
+
+               return SF_FALSE ;
+               } ;
+
+       return SF_TRUE ;
+} /* cue_compare */
+
+static void
 cue_rw_test (const char *filename)
 {      SNDFILE *sndfile ;
        SF_INFO sfinfo ;
@@ -923,71 +979,8 @@ cue_test (const char *filename, int filetype)
        check_log_buffer_or_die (file, __LINE__) ;
        sf_close (file) ;
 
-       if (memcmp (&write_cue, &read_cue, sizeof (write_cue)) != 0)
-       {       printf ("\n\nLine %d : cue comparison failed.\n\n", __LINE__) ;
-               printf ("W  Cue count      : %d\n"
-                       "   indx          : %d\n"
-                       "   position      : %u\n"
-                       "   fcc_chunk     : %x\n"
-                       "   chunk_start   : %d\n"
-                       "   block_start   : %d\n"
-                       "   sample_offset : %u\n"
-                       "   name          : %s\n"
-                       "   indx          : %d\n"
-                       "   position      : %u\n"
-                       "   fcc_chunk     : %x\n"
-                       "   chunk_start   : %d\n"
-                       "   block_start   : %d\n"
-                       "   sample_offset : %u\n"
-                       "   name           : %s\n",
-                       write_cue.cue_count,
-                       write_cue.cue_points [0].indx,
-                       write_cue.cue_points [0].position,
-                       write_cue.cue_points [0].fcc_chunk,
-                       write_cue.cue_points [0].chunk_start,
-                       write_cue.cue_points [0].block_start,
-                       write_cue.cue_points [0].sample_offset,
-                       write_cue.cue_points [0].name,
-                       write_cue.cue_points [1].indx,
-                       write_cue.cue_points [1].position,
-                       write_cue.cue_points [1].fcc_chunk,
-                       write_cue.cue_points [1].chunk_start,
-                       write_cue.cue_points [1].block_start,
-                       write_cue.cue_points [1].sample_offset,
-                       write_cue.cue_points [1].name) ;
-               printf ("R  Cue count      : %d\n"
-                       "   indx          : %d\n"
-                       "   position      : %u\n"
-                       "   fcc_chunk     : %x\n"
-                       "   chunk_start   : %d\n"
-                       "   block_start   : %d\n"
-                       "   sample_offset : %u\n"
-                       "   name          : %s\n"
-                       "   indx          : %d\n"
-                       "   position      : %u\n"
-                       "   fcc_chunk     : %x\n"
-                       "   chunk_start   : %d\n"
-                       "   block_start   : %d\n"
-                       "   sample_offset : %u\n"
-                       "   name          : %s\n",
-                       read_cue.cue_count,
-                       read_cue.cue_points [0].indx,
-                       read_cue.cue_points [0].position,
-                       read_cue.cue_points [0].fcc_chunk,
-                       read_cue.cue_points [0].chunk_start,
-                       read_cue.cue_points [0].block_start,
-                       read_cue.cue_points [0].sample_offset,
-                       read_cue.cue_points [0].name,
-                       read_cue.cue_points [1].indx,
-                       read_cue.cue_points [1].position,
-                       read_cue.cue_points [1].fcc_chunk,
-                       read_cue.cue_points [1].chunk_start,
-                       read_cue.cue_points [1].block_start,
-                       read_cue.cue_points [1].sample_offset,
-                       read_cue.cue_points [1].name) ;
-
+       if (cue_compare (&write_cue, &read_cue, sizeof (write_cue), __LINE__) == SF_FALSE)
                        exit (1) ;
-               } ;
 
        if (0) cue_rw_test (filename) ;
 
@@ -995,6 +988,68 @@ cue_test (const char *filename, int filetype)
        puts ("ok") ;
 } /* cue_test */
 
+/* calculate size of SF_CUES struct given number of cues */
+#define SF_CUES_SIZE(count)    (sizeof (uint32_t) + sizeof (SF_CUE_POINT) * (count))
+
+static void
+cue_test_var (const char *filename, int filetype, int count)
+{      size_t cues_size = SF_CUES_SIZE (count) ;
+       SF_CUES *write_cue = calloc (1, cues_size) ;
+       SF_CUES *read_cue = calloc (1, cues_size) ;
+       SNDFILE *file ;
+       SF_INFO sfinfo ;
+       char name [40] ;
+       int i ;
+
+       snprintf (name, sizeof (name), "cue_test_var %d", count) ;
+       print_test_name (name, filename) ;
+
+       if (write_cue == NULL || read_cue == NULL)
+       {       printf ("ok (can't alloc)\n") ;
+               return ;
+               } ;
+
+       write_cue->cue_count = count ;
+       for (i = 0 ; i < count ; i++)
+       {       write_cue->cue_points [i] = (SF_CUE_POINT) { i, 0, data_MARKER, 0, 0, i, "" } ;
+               if (filetype == (SF_FORMAT_AIFF | SF_FORMAT_PCM_24))
+                       snprintf (write_cue->cue_points [i].name, sizeof (write_cue->cue_points [i].name), "Cue%03d", i) ;
+               } ;
+
+       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_CUE, write_cue, cues_size) == SF_FALSE)
+       {       printf ("\n\nLine %d : sf_command (SFC_SET_CUE) failed with %d cues, datasize %zu --> error: %s\n\n", __LINE__, count, cues_size, sf_strerror (file)) ;
+               exit (1) ;
+               } ;
+       test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
+       sf_close (file) ;
+
+       memset (read_cue, 0, cues_size) ;
+
+       file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+       if (sf_command (file, SFC_GET_CUE, read_cue, cues_size) == SF_FALSE)
+       {       printf ("\n\nLine %d : sf_command (SFC_GET_CUE) failed with %d cues, datasize %zu --> error: %s\n\n", __LINE__, count, cues_size, sf_strerror (file)) ;
+               exit (1) ;
+               } ;
+       check_log_buffer_or_die (file, __LINE__) ;
+       sf_close (file) ;
+
+       if (cue_compare (write_cue, read_cue, cues_size, __LINE__) == SF_FALSE)
+       {       printf ("\n\nLine %d : cue_compare failed.\n\n", __LINE__) ;
+               exit (1) ;
+               } ;
+
+       free (write_cue) ;
+       free (read_cue) ;
+       unlink (filename) ;
+       puts ("ok") ;
+} /* cue_test_var */
+
 static void
 current_sf_info_test   (const char *filename)
 {      SNDFILE *outfile, *infile ;
@@ -1051,6 +1106,7 @@ broadcast_test (const char *filename, int filetype)
 
        print_test_name ("broadcast_test", filename) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate       = 11025 ;
        sfinfo.format           = filetype ;
        sfinfo.channels         = 1 ;
@@ -1084,7 +1140,7 @@ broadcast_test (const char *filename, int filetype)
        check_log_buffer_or_die (file, __LINE__) ;
        sf_close (file) ;
 
-       if (bc_read.version != 1)
+       if (bc_read.version != 2)
        {       printf ("\n\nLine %d : Read bad version number %d.\n\n", __LINE__, bc_read.version) ;
                exit (1) ;
                return ;
@@ -1413,6 +1469,7 @@ cart_test (const char *filename, int filetype)
 
        print_test_name ("cart_test", filename) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate       = 11025 ;
        sfinfo.format           = filetype ;
        sfinfo.channels         = 1 ;
index 85dbd35..c8f43c8 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
+#endif
 
 #include <math.h>
 
@@ -173,6 +177,7 @@ main (int argc, char *argv [])
                        "    Where <test> is one of:\n"
                        "        vorbis - test Ogg/Vorbis\n"
                        "        flac   - test FLAC\n"
+                       "        opus   - test Opus\n"
                        "        all    - perform all tests\n",
                        argv [0]) ;
                exit (0) ;
@@ -197,5 +202,10 @@ main (int argc, char *argv [])
                tests ++ ;
                } ;
 
+       if (all_tests || strcmp (argv [1], "opus") == 0)
+       {       compression_size_test (SF_FORMAT_OGG | SF_FORMAT_OPUS, "opus.opus") ;
+               tests ++ ;
+               } ;
+
        return 0 ;
 } /* main */
index 364ec86..6e39da6 100644 (file)
@@ -16,6 +16,8 @@
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+#include "sfconfig.h"
+
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
diff --git a/tests/cue_test.c b/tests/cue_test.c
new file mode 100644 (file)
index 0000000..d2fdae4
--- /dev/null
@@ -0,0 +1,135 @@
+
+#include "sfconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sndfile.h>
+
+
+static void *
+get_cues (const char *filename, double *sr)
+{
+    SNDFILE    *file;
+    SF_INFO    sfinfo;
+
+    unsigned int err, size;
+    uint32_t count = 0;
+    SF_CUES_VAR(0) *info;
+
+    if ((file = sf_open(filename, SFM_READ, &sfinfo)) == NULL)
+    {
+       printf("can't open file '%s'\n", filename);
+       exit(1);
+    }
+
+    printf("\n---- get cues of file '%s'\n", filename);
+
+    if ((err = sf_command(file, SFC_GET_CUE_COUNT, &count, sizeof(uint32_t))) == SF_FALSE)
+    {
+       if (sf_error(file))
+       {
+           printf("can't get cue info size for file '%s' (arg size %lu), err %s\n", 
+                  filename, sizeof(uint32_t), sf_strerror(file));
+           exit(2);
+       }
+       else
+           printf("no cue info for file '%s'\n", filename);
+       return NULL;
+    }
+       
+    size = sizeof(*info) + count * sizeof(SF_CUE_POINT);
+    printf("number of cues %d  size %d\n", count, size);
+
+    if (!(info = malloc(size)))
+       return NULL;
+
+    if (sf_command(file, SFC_GET_CUE, info, size) == SF_FALSE)
+    {
+       printf("can't get cue info of size %d for file '%s' error %s\n", 
+              size, filename, sf_strerror(file));
+       exit(3);
+    }
+
+    *sr = sfinfo.samplerate;
+    sf_close(file);
+
+    return info;
+}
+
+
+static void
+test_cues (const char *filename)
+{
+    unsigned int i;
+    double sr;
+    SF_CUES_VAR(0) *info = get_cues(filename, &sr);
+
+    if (info == NULL)
+       exit(1);
+    
+    for (i = 0; i < info->cue_count; i++)
+    {
+       int    pos = info->cue_points[i].position;
+       double t   = (double) pos / sr;
+       double expected = i < 8  ?  (double) i / 3.  :  10. / 3.;
+       double error = (double) fabs(t - expected);
+
+       printf("cue %02d: markerID %02d  position %6d  offset %6d (time %.3f  expected %.3f  diff %f)  label '%s'\n",
+              i, info->cue_points[i].indx, pos, info->cue_points[i].sample_offset, t, expected, error, info->cue_points[i].name);
+
+       if (error > 0.025)
+           exit(4);
+    }
+
+    free(info);
+}
+
+static void
+print_cues (const char *filename)
+{
+    unsigned int i;
+    double sr;
+    SF_CUES_VAR(0) *info = get_cues(filename, &sr);
+
+    if (info == NULL)
+       exit(1);
+    
+    for (i = 0; i < info->cue_count; i++)
+    {
+       int    pos    = info->cue_points[i].position;
+       int    indx   = info->cue_points[i].indx;
+       int    cstart = info->cue_points[i].chunk_start;
+       int    bstart = info->cue_points[i].block_start;
+       int    offset = info->cue_points[i].sample_offset;
+       const char *name = info->cue_points[i].name;
+       double t   = (double) pos / sr;
+
+       if (cstart != 0  ||  bstart != 0)
+           printf("cue %02d time %7.3f: markerID %02d  position %8d  chunk_start %d  block_start %d  offset %8d  label '%s'\n",
+                  i, t, indx, pos, offset, cstart, bstart, name);
+       else
+           printf("cue %02d  time %7.3f: markerID %02d  position %8d  offset %8d  label '%s'\n",
+                  i, t, indx, pos, offset, name);
+    }
+
+    free(info);
+}
+
+
+int
+main (int argc, char **argv)
+{
+    int i;
+    
+    if (argc > 1)
+       for (i = 1; i < argc; i++)
+           print_cues(argv[i]);
+    else
+    {
+       test_cues("clickpluck24.wav");
+       test_cues("clickpluck.wav");
+       test_cues("clickpluck.aiff");
+    }
+    return 0;
+}
index b94b6a2..03bd464 100644 (file)
@@ -16,6 +16,8 @@
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+#include       "sfconfig.h"
+
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <math.h>
index e9eef7c..c092844 100644 (file)
 */
 
 
-
+#include       "sfconfig.h"
 #include       <stdio.h>
 #include       <stdlib.h>
+#if HAVE_UNISTD_H
 #include       <unistd.h>
+#else
+#include       "sf_unistd.h"
+#endif
 #include       <string.h>
 #include       <math.h>
 
index 57bdfac..b2cae06 100644 (file)
@@ -25,6 +25,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 1cadc68..2e348e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2018 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
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #if OS_IS_WIN32
@@ -231,6 +234,40 @@ error_close_test (void)
        puts ("ok") ;
 } /* error_close_test */
 
+static void
+unrecognised_test (void)
+{      const char      *filename = "unrecognised.bin" ;
+       SNDFILE         *sndfile ;
+       SF_INFO         sfinfo ;
+       FILE            *file ;
+       int                     k ;
+
+       print_test_name (__func__, filename) ;
+
+       file = fopen (filename, "wb") ;
+       exit_if_true (file == NULL,
+               "\n\nLine %d : fopen ('%s') failed : %s\n", __LINE__, filename, strerror (errno)
+               ) ;
+       fputs ("Unrecognised file", file) ;
+       fclose (file) ;
+
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
+       sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
+
+       exit_if_true (sndfile != NULL,
+               "\n\nLine %d : SNDFILE* pointer (%p) should ne NULL.\n", __LINE__, sndfile
+               ) ;
+
+       k = sf_error (sndfile) ;
+       exit_if_true (k != SF_ERR_UNRECOGNISED_FORMAT,
+               "\n\nLine %d : error (%d) should have been SF_ERR_UNRECOGNISED_FORMAT (%d).\n",
+               __LINE__, k, SF_ERR_UNRECOGNISED_FORMAT
+               ) ;
+
+       unlink (filename) ;
+       puts ("ok") ;
+} /* unrecognised_test */
+
 int
 main (void)
 {
@@ -243,6 +280,8 @@ main (void)
        zero_length_test ("zero_length.wav") ;
        bad_wav_test ("bad_wav.wav") ;
 
+       unrecognised_test () ;
+
        return 0 ;
 } /* main */
 
index f671055..0c6fcf8 100644 (file)
@@ -25,6 +25,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
@@ -82,7 +84,7 @@ major_format_test (void)
 static void
 subtype_format_test (void)
 {      SF_FORMAT_INFO  info ;
-       int have_vorbis = 0 ;
+       int have_vorbis = 0 , have_opus = 0 ;
        int s, subtype_count ;
 
        print_test_name (__func__, NULL) ;
@@ -94,12 +96,17 @@ subtype_format_test (void)
                sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &info, sizeof (info)) ;
 
                have_vorbis = info.format == SF_FORMAT_VORBIS ? 1 : have_vorbis ;
+               have_opus = info.format == SF_FORMAT_OPUS ? 1 : have_opus ;
                } ;
 
        if (HAVE_EXTERNAL_XIPH_LIBS)
-               exit_if_true (have_vorbis == 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__) ;
+               exit_if_true (have_opus == 0, "\n\nLine %d : Ogg/Opus should be available.\n\n", __LINE__) ;
+               }
        else
-               exit_if_true (have_vorbis, "\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__) ;
+               exit_if_true (have_opus, "\n\nLine %d : Ogg/Opus should not be available.\n\n", __LINE__) ;
+               } ;
 
        puts ("ok") ;
 } /* subtype_format_test */
@@ -107,7 +114,7 @@ subtype_format_test (void)
 static void
 simple_format_test (void)
 {      SF_FORMAT_INFO  info ;
-       int have_flac = 0, have_ogg = 0, have_vorbis = 0 ;
+       int have_flac = 0, have_ogg = 0, have_vorbis = 0, have_opus = 0 ;
        int s, simple_count ;
 
        print_test_name (__func__, NULL) ;
@@ -136,6 +143,10 @@ simple_format_test (void)
                                have_vorbis = 1 ;
                                break ;
 
+                       case SF_FORMAT_OPUS :
+                               have_opus = 1 ;
+                               break ;
+
                        default :
                                break ;
                        } ;
@@ -146,11 +157,13 @@ simple_format_test (void)
        {       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__) ;
+               exit_if_true (have_opus == 0, "\n\nLine %d : Ogg/Opus 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__) ;
+               exit_if_true (have_opus, "\n\nLine %d : Ogg/Opus should not be available.\n\n", __LINE__) ;
                } ;
 
        puts ("ok") ;
index 8ec06c6..5c697ea 100644 (file)
 ** 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>
+#else
+#include "sf_unistd.h"
+#endif
 #include <math.h>
 #include <inttypes.h>
 
index fab0d9b..7258fa2 100644 (file)
@@ -1,6 +1,6 @@
 [+ AutoGen5 template c +]
 /*
-** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2017 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
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
@@ -119,6 +121,8 @@ main (int argc, char *argv [])
        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) ;
+
+       float_scaled_test       ("opus.opus", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_OPUS, -32.0) ;
 #endif
 
        float_scaled_test       ("replace_float.raw", allow_exit, SF_TRUE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ;
@@ -176,6 +180,7 @@ main (int argc, char *argv [])
        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) ;
+       double_scaled_test      ("opus.opus", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_OPUS, -32.0) ;
 #endif
 
        double_scaled_test      ("replace_double.raw", allow_exit, SF_TRUE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -201.0) ;
@@ -205,6 +210,7 @@ float_scaled_test (const char *filename, int allow_exit, int replace_float, int
 
        gen_windowed_sine_float (float_data, DFT_DATA_LENGTH, 0.9999) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate       = SAMPLE_RATE ;
        sfinfo.frames           = DFT_DATA_LENGTH ;
        sfinfo.channels         = 1 ;
@@ -257,6 +263,7 @@ double_scaled_test (const char *filename, int allow_exit, int replace_float, int
 
        gen_windowed_sine_double (double_data, DFT_DATA_LENGTH, 0.9999) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate       = SAMPLE_RATE ;
        sfinfo.frames           = DFT_DATA_LENGTH ;
        sfinfo.channels         = 1 ;
@@ -314,6 +321,7 @@ static void
 
        gen_windowed_sine_[+ (get "float_name") +] ([+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), 0.9999) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate       = SAMPLE_RATE ;
        sfinfo.frames           = ARRAY_LEN ([+ (get "int_name") +]_data) ;
        sfinfo.channels         = 1 ;
index a371c71..7ab71c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2011-2017 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
@@ -24,6 +24,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include "sndfile.h"
@@ -100,11 +102,16 @@ format_combo_test (void)
                        char filename [128] ;
                        int subtype_is_valid, check_is_valid ;
 
+                       memset (&info, 0, sizeof (info)) ;
                        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) ;
+                       /* Opus only works with a fixed set of sample rates. */
+                       if (subtype_fmt_info.format == SF_FORMAT_OPUS)
+                               sf_info_setup (&info, major_fmt_info.format | subtype_fmt_info.format, 24000, 1) ;
+                       else
+                               sf_info_setup (&info, major_fmt_info.format | subtype_fmt_info.format, 22050, 1) ;
 
                        check_is_valid = sf_format_check (&info) ;
 
index 653018b..87efbb4 100644 (file)
@@ -16,6 +16,8 @@
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+#include "sfconfig.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index 6545bb4..f4dd5b5 100644 (file)
@@ -1,6 +1,6 @@
 [+ AutoGen5 template c +]
 /*
-** Copyright (C) 2001-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2017 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
@@ -48,6 +48,7 @@
 #define LOG_BUFFER_SIZE        1024
 
 static void    update_header_test (const char *filename, int typemajor) ;
+static void    update_header_before_write_test (const char *filename, int typemajor) ;
 
 [+ FOR data_type
 +]static void  update_seek_[+ (get "name") +]_test     (const char *filename, int filetype) ;
@@ -226,6 +227,14 @@ main (int argc, char *argv [])
                test_count++ ;
                } ;
 
+       if (do_all || ! strcmp (argv [1], "flac"))
+       {       if (HAVE_EXTERNAL_XIPH_LIBS)
+                       update_header_before_write_test ("header.flac", SF_FORMAT_FLAC) ;
+               else
+                       puts ("    No FLAC tests because FLAC support was not compiled in.") ;
+               test_count++ ;
+               } ;
+
        if (test_count == 0)
        {       printf ("Mono : ************************************\n") ;
                printf ("Mono : *  No '%s' test defined.\n", argv [1]) ;
@@ -247,10 +256,10 @@ update_header_sub (const char *filename, int typemajor, int write_mode)
        SF_INFO         sfinfo ;
        int                     k ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        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__) ;
 
@@ -323,6 +332,36 @@ update_header_test (const char *filename, int typemajor)
        puts ("ok") ;
 } /* update_header_test */
 
+static void
+update_header_before_write_test (const char *filename, int typemajor)
+{
+       SNDFILE         *outfile ;
+       SF_INFO         sfinfo ;
+       int                     k ;
+
+       print_test_name ("update_header_before_write", filename) ;
+
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
+       sfinfo.samplerate = 44100 ;
+       sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
+       sfinfo.channels = 1 ;
+
+       outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+       /* FLAC can only write the header once; if the first call to sf_write() will
+       ** also attempt to write the header, it fails. FLAC-specific regression
+       */
+       sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
+
+       for (k = 0 ; k < BUFFER_LEN ; k++)
+               data_out [k] = k + 1 ;
+       test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
+
+       sf_close (outfile) ;
+       unlink (filename) ;
+       puts ("ok") ;
+} /* update_header_before_write_test */
+
 /*==============================================================================
 */
 
@@ -340,6 +379,7 @@ update_seek_[+ (get "name") +]_test (const char *filename, int filetype)
        memset (buffer, 0, sizeof (buffer)) ;
 
        /* Create sound outfile with no data. */
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.format = filetype | [+ (get "format") +] ;
        sfinfo.samplerate = 48000 ;
        sfinfo.channels = 2 ;
@@ -450,6 +490,7 @@ extra_header_test (const char *filename, int filetype)
 
        print_test_name ("extra_header_test", filename) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate = 44100 ;
        sfinfo.format = (filetype | SF_FORMAT_PCM_16) ;
        sfinfo.channels = 1 ;
@@ -540,4 +581,3 @@ extra_header_test (const char *filename, int filetype)
        return ;
 #endif
 } /* extra_header_test */
-
index 6d3e2f2..059fa68 100644 (file)
@@ -26,6 +26,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 328a589..4c97c90 100644 (file)
@@ -24,6 +24,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index b67d549..b265301 100644 (file)
@@ -24,6 +24,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #if HAVE_LOCALE_H
index c611f56..4862468 100644 (file)
@@ -26,6 +26,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 0d5a8f7..cca274c 100644 (file)
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
@@ -68,6 +70,8 @@ static void           check_comment (SNDFILE * file, int format, int lineno) ;
 
 static int             is_lossy (int filetype) ;
 
+static int             check_opus_version (SNDFILE *file) ;
+
 /*
 ** Force the start of these buffers to be double aligned. Sparc-solaris will
 ** choke if they are not.
@@ -220,6 +224,42 @@ main (int argc, char *argv [])
                test_count++ ;
                } ;
 
+       /* Lite remove start */
+       if (do_all || strcmp (argv [1], "wav_nmsadpcm") == 0)
+       {       lcomp_test_short        ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.37) ;
+               lcomp_test_int          ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.31) ;
+               lcomp_test_float        ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.34) ;
+               lcomp_test_double       ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.34) ;
+
+               lcomp_test_short        ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.15) ;
+               lcomp_test_int          ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.10) ;
+               lcomp_test_float        ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.14) ;
+               lcomp_test_double       ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.14) ;
+
+               lcomp_test_short        ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.036) ;
+               lcomp_test_int          ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.045) ;
+               lcomp_test_float        ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.035) ;
+               lcomp_test_double       ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.035) ;
+
+               sdlcomp_test_short      ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+               sdlcomp_test_int        ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+               sdlcomp_test_float      ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+               sdlcomp_test_double     ("nms_16.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+
+               sdlcomp_test_short      ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+               sdlcomp_test_int        ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+               sdlcomp_test_float      ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+               sdlcomp_test_double     ("nms_24.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+
+               sdlcomp_test_short      ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.017) ;
+               sdlcomp_test_int        ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.018) ;
+               sdlcomp_test_float      ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.018) ;
+               sdlcomp_test_double     ("nms_32.wav", SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_32, 1, 0.018) ;
+
+               test_count++ ;
+               } ;
+       /* Lite remove end */
+
        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) ;
@@ -375,6 +415,42 @@ main (int argc, char *argv [])
                test_count++ ;
                } ;
 
+       /* Lite remove start */
+       if (do_all || strcmp (argv [1], "raw_nmsadpcm") == 0)
+       {       lcomp_test_short        ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.37) ;
+               lcomp_test_int          ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.31) ;
+               lcomp_test_float        ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.34) ;
+               lcomp_test_double       ("raw.vce16", SF_FORMAT_RAW     | SF_FORMAT_NMS_ADPCM_16, 1, 0.34) ;
+
+               lcomp_test_short        ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.15) ;
+               lcomp_test_int          ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.10) ;
+               lcomp_test_float        ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.14) ;
+               lcomp_test_double       ("raw.vce24", SF_FORMAT_RAW     | SF_FORMAT_NMS_ADPCM_24, 1, 0.14) ;
+
+               lcomp_test_short        ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.036) ;
+               lcomp_test_int          ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.045) ;
+               lcomp_test_float        ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.035) ;
+               lcomp_test_double       ("raw.vce32", SF_FORMAT_RAW     | SF_FORMAT_NMS_ADPCM_32, 1, 0.035) ;
+
+               sdlcomp_test_short      ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+               sdlcomp_test_int        ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+               sdlcomp_test_float      ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+               sdlcomp_test_double     ("raw.vce16", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_16, 1, 0.16) ;
+
+               sdlcomp_test_short      ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+               sdlcomp_test_int        ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+               sdlcomp_test_float      ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+               sdlcomp_test_double     ("raw.vce24", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_24, 1, 0.06) ;
+
+               sdlcomp_test_short      ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.017) ;
+               sdlcomp_test_int        ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.018) ;
+               sdlcomp_test_float      ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.018) ;
+               sdlcomp_test_double     ("raw.vce32", SF_FORMAT_RAW | SF_FORMAT_NMS_ADPCM_32, 1, 0.018) ;
+
+               test_count++ ;
+               } ;
+       /* Lite remove end */
+
        if (do_all || strcmp (argv [1], "ogg_vorbis") == 0)
        {       if (HAVE_EXTERNAL_XIPH_LIBS)
                {       /* Don't do lcomp_test_XXX as the errors are too big. */
@@ -389,6 +465,20 @@ main (int argc, char *argv [])
                test_count++ ;
                } ;
 
+       if (do_all || strcmp (argv [1], "ogg_opus") == 0)
+       {       if (HAVE_EXTERNAL_XIPH_LIBS)
+               {       /* Don't do lcomp_test_XXX as the errors are too big. */
+                       sdlcomp_test_short      ("opus.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS, 1, 0.57) ;
+                       sdlcomp_test_int        ("opus.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS, 1, 0.54) ;
+                       sdlcomp_test_float      ("opus.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS, 1, 0.55) ;
+                       sdlcomp_test_double     ("opus.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS, 1, 0.55) ;
+                       }
+               else
+                       puts ("    No Ogg/Opus tests because Ogg/Opus 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) ;
@@ -1354,23 +1444,35 @@ channels = 1 ;
        /*      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
+       **
+       **      Opus only supports discrete sample rates. Choose supported 12000.
        */
        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)
+               if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") != NULL)
+               {       printf ("\n                                  Sample rate -> 32kHz    ") ;
+                       sfinfo.samplerate = 32000 ;
+                       }
+               else if (strstr (errstr, "Opus only supports sample rates of") != NULL)
+               {       printf ("\n                                  Sample rate -> 12kHz    ") ;
+                       sfinfo.samplerate = 12000 ;
+                       }
+               else
                {       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__) ;
                } ;
 
+       if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file))
+       {       sf_close (file) ;
+               return ;
+               } ;
+
        test_write_short_or_die (file, 0, orig, datalen, __LINE__) ;
        sf_set_string (file, SF_STR_COMMENT, long_comment) ;
        sf_close (file) ;
@@ -1562,23 +1664,35 @@ channels = 1 ;
        /*      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
+       **
+       **      Opus only supports discrete sample rates. Choose supported 12000.
        */
        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)
+               if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") != NULL)
+               {       printf ("\n                                  Sample rate -> 32kHz    ") ;
+                       sfinfo.samplerate = 32000 ;
+                       }
+               else if (strstr (errstr, "Opus only supports sample rates of") != NULL)
+               {       printf ("\n                                  Sample rate -> 12kHz    ") ;
+                       sfinfo.samplerate = 12000 ;
+                       }
+               else
                {       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__) ;
                } ;
 
+       if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file))
+       {       sf_close (file) ;
+               return ;
+               } ;
+
        test_writef_int_or_die (file, 0, orig, datalen, __LINE__) ;
        sf_set_string (file, SF_STR_COMMENT, long_comment) ;
        sf_close (file) ;
@@ -1642,7 +1756,10 @@ channels = 1 ;
                (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)
+               (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_G723_24 &&
+               (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_NMS_ADPCM_16 &&
+               (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_NMS_ADPCM_24 &&
+               (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_NMS_ADPCM_32)
                for (k = 0 ; k < sfinfo.frames - datalen ; k++)
                        if (abs (data [k]) > decay_response (k))
                        {       printf ("\n\nLine %d: Incorrect sample (#%" PRId64 " : abs (%d) should be < %d).\n", __LINE__, datalen + k, data [k], decay_response (k)) ;
@@ -1744,18 +1861,34 @@ sdlcomp_test_float      (const char *filename, int filetype, int channels, double mar
        int                             k, m, seekpos ;
        sf_count_t              datalen ;
        float                   *orig, *data, *smooth ;
-       double                  half_max_abs ;
+       double                  half_max_abs , scale ;
 
 channels = 1 ;
 
        print_test_name ("sdlcomp_test_float", filename) ;
 
-       if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
-       {       puts ("Not working for this format.") ;
-               return ;
-               } ;
+       switch ((filetype & SF_FORMAT_SUBMASK))
+       {       case SF_FORMAT_VORBIS :
+                       /*      Vorbis starts to loose fidelity with floating point values outside
+                       **      the range of approximately [-2000.0, 2000.0] (Determined
+                       **      experimentally, not know if it is a limitation of Vorbis or
+                       **      libvorbis.)
+                       */
+                       scale = 16.0 ; /* 32000/16 = 2000 */
+                       break ;
+
+               case SF_FORMAT_OPUS :
+                       /*      The Opus spec says that non-normalized floating point value
+                       **      support (extended dynamic range in its terms) is optional and
+                       **      cannot be relied upon.
+                       */
+                       scale = 32000.0 ; /* 32000/32000 = 1 */
+                       break ;
 
-printf ("** fix this ** ") ;
+               default :
+                       scale = 1.0 ;
+                       break ;
+               } ;
 
        datalen = BUFFER_SIZE ;
 
@@ -1763,16 +1896,48 @@ printf ("** fix this ** ") ;
        data = data_buffer.f ;
        smooth = smooth_buffer.f ;
 
-       gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+       gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, datalen) ;
        for (k = 0 ; k < datalen ; k++)
-               orig [k] = lrint (orig_buffer.d [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__) ;
+
+       /*      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
+       **
+       **      Opus only supports discrete sample rates. Choose supported 12000.
+       */
+       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 ("\n                                  Sample rate -> 32kHz    ") ;
+                       sfinfo.samplerate = 32000 ;
+                       }
+               else if (strstr (errstr, "Opus only supports sample rates of") != NULL)
+               {       printf ("\n                                  Sample rate -> 12kHz    ") ;
+                       sfinfo.samplerate = 12000 ;
+                       }
+               else
+               {       printf ("Line %d: sf_open_fd (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
+                       dump_log_buffer (NULL) ;
+                       exit (1) ;
+                       } ;
+
+               file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+               } ;
+
+       if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file))
+       {       sf_close (file) ;
+               return ;
+               } ;
+
        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) ;
@@ -1819,12 +1984,12 @@ printf ("** fix this ** ") ;
 
        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]) ;
+       {       if (error_function (data [k] * scale, smooth [k] * scale, margin))
+               {       printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) (data [k] * scale), (int) (smooth [k] * scale)) ;
                        oct_save_float (orig, smooth, datalen) ;
                        exit (1) ;
                        } ;
-               half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k])) ;
+               half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k] * scale)) ;
                } ;
 
        if (half_max_abs <= 0.0)
@@ -1861,8 +2026,8 @@ printf ("** fix this ** ") ;
                        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 (%" PRId64 ") : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) smooth [k], (int) data [k]) ;
+                               if (error_function (data [k] * scale, smooth [k] * scale, margin))
+                               {       printf ("\nLine %d: Incorrect sample C (#%d (%" PRId64 ") : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) (smooth [k] * scale), (int) (data [k] * scale)) ;
                                        for (m = 0 ; m < 10 ; m++)
                                                printf ("%d ", (int) data [k]) ;
                                        printf ("\n") ;
@@ -1879,8 +2044,8 @@ printf ("** fix this ** ") ;
                        } ;
                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]) ;
+               if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin))
+               {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_float failed (%d, %d).\n", __LINE__, (int) (orig [1] * scale), (int) (data [0] * scale)) ;
                        exit (1) ;
                        } ;
 
@@ -1892,8 +2057,8 @@ printf ("** fix this ** ") ;
                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) ;
+               if (error_function (data [0] * scale, orig [seekpos * channels] * scale, 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] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos + 1) ;
                        exit (1) ;
                        } ;
 
@@ -1901,8 +2066,8 @@ printf ("** fix this ** ") ;
                /* 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) ;
+               if (error_function (data [0] * scale, orig [seekpos * channels] * scale, 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] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos) ;
                        exit (1) ;
                        } ;
 
@@ -1922,8 +2087,8 @@ printf ("** fix this ** ") ;
                        } ;
 
                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]) ;
+               if (error_function (data [0] * scale, orig [5 * channels] * scale, margin))
+               {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_float failed (%f should be %f).\n", __LINE__, data [0] * scale, orig [5 * channels] * scale) ;
                        exit (1) ;
                        } ;
                } /* if (sfinfo.seekable) */
@@ -1940,14 +2105,32 @@ sdlcomp_test_double     (const char *filename, int filetype, int channels, double ma
        SF_INFO                 sfinfo ;
        int                             k, m, seekpos ;
        sf_count_t              datalen ;
-       double                  *orig, *data, *smooth, half_max_abs ;
+       double                  *orig, *data, *smooth, half_max_abs, scale ;
 
 channels = 1 ;
        print_test_name ("sdlcomp_test_double", filename) ;
 
-       if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
-       {       puts ("Not working for this format.") ;
-               return ;
+       switch ((filetype & SF_FORMAT_SUBMASK))
+       {       case SF_FORMAT_VORBIS :
+                       /*      Vorbis starts to loose fidelity with floating point values outside
+                       **      the range of approximately [-2000.0, 2000.0] (Determined
+                       **      experimentally, not know if it is a limitation of Vorbis or
+                       **      libvorbis.)
+                       */
+                       scale = 16.0 ; /* 32000/16 = 2000 */
+                       break ;
+
+               case SF_FORMAT_OPUS :
+                       /*      The Opus spec says that non-normalized floating point value
+                       **      support (extended dynamic range in its terms) is optional and
+                       **      cannot be relied upon.
+                       */
+                       scale = 32000.0 ; /* 32000/32000 = 1 */
+                       break ;
+
+               default :
+                       scale = 1.0 ;
+                       break ;
                } ;
 
        datalen = BUFFER_SIZE ;
@@ -1956,14 +2139,45 @@ channels = 1 ;
        data = data_buffer.d ;
        smooth = smooth_buffer.d ;
 
-       gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
+       gen_signal_double (orig_buffer.d, 32000.0 / scale, 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__) ;
+       /*      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
+       **
+       **      Opus only supports discrete sample rates. Choose supported 12000.
+       */
+       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 ("\n                                  Sample rate -> 32kHz    ") ;
+                       sfinfo.samplerate = 32000 ;
+                       }
+               else if (strstr (errstr, "Opus only supports sample rates of") != NULL)
+               {       printf ("\n                                  Sample rate -> 12kHz    ") ;
+                       sfinfo.samplerate = 12000 ;
+                       }
+               else
+               {       printf ("Line %d: sf_open_fd (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
+                       dump_log_buffer (NULL) ;
+                       exit (1) ;
+                       } ;
+
+               file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+               } ;
+
+       if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file))
+       {       sf_close (file) ;
+               return ;
+               } ;
+
        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) ;
@@ -2012,12 +2226,12 @@ channels = 1 ;
 
        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]) ;
+       {       if (error_function (data [k] * scale, smooth [k] * scale, margin))
+               {       printf ("\n\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) (data [k] * scale), (int) (smooth [k] * scale)) ;
                        oct_save_double (orig, smooth, datalen) ;
                        exit (1) ;
                        } ;
-               half_max_abs = LCT_MAX (half_max_abs, 0.5 * fabs (data [k])) ;
+               half_max_abs = LCT_MAX (half_max_abs, 0.5 * fabs (data [k] * scale)) ;
                } ;
 
        if (half_max_abs < 1.0)
@@ -2053,8 +2267,8 @@ channels = 1 ;
                        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 (%" PRId64 ") : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) smooth [k], (int) data [k]) ;
+                               if (error_function (data [k] * scale, smooth [k] * scale, margin))
+                               {       printf ("\nLine %d: Incorrect sample C (#%d (%" PRId64 ") : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) (smooth [k] * scale), (int) (data [k] * scale)) ;
                                        for (m = 0 ; m < 10 ; m++)
                                                printf ("%d ", (int) data [k]) ;
                                        printf ("\n") ;
@@ -2071,8 +2285,8 @@ channels = 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]) ;
+               if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin))
+               {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_double failed (%d, %d).\n", __LINE__, (int) (orig [1] * scale), (int) (data [0] * scale)) ;
                        exit (1) ;
                        } ;
 
@@ -2084,8 +2298,8 @@ channels = 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) ;
+               if (error_function (data [0] * scale, orig [seekpos * channels] * scale, 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] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos + 1) ;
                        exit (1) ;
                        } ;
 
@@ -2093,8 +2307,8 @@ channels = 1 ;
                /* 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) ;
+               if (error_function (data [0] * scale, orig [seekpos * channels] * scale, 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] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos) ;
                        exit (1) ;
                        } ;
 
@@ -2114,8 +2328,8 @@ channels = 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]) ;
+               if (error_function (data [0] * scale, orig [5 * channels] * scale, margin))
+               {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_double failed (%f should be %f).\n", __LINE__, data [0] * scale, orig [5 * channels] * scale) ;
                        exit (1) ;
                        } ;
                } /* if (sfinfo.seekable) */
@@ -2370,3 +2584,34 @@ is_lossy (int filetype)
        return 1 ;
 } /* is_lossy */
 
+
+static int
+check_opus_version (SNDFILE *file)
+{      char log_buf [256] ;
+       char *str, *p ;
+       const char *str_libopus = "Opus library version: " ;
+       int ver_major, ver_minor ;
+
+       sf_command (file, SFC_GET_LOG_INFO, log_buf, sizeof (log_buf)) ;
+       str = strstr (log_buf, str_libopus) ;
+       if (str)
+       {       str += strlen (str_libopus) ;
+               if ((p = strchr (str, '\n')))
+                       *p = '\0' ;
+               if (sscanf (str, "libopus %d.%d", &ver_major, &ver_minor) == 2)
+               {       /* Reject versions prior to 1.3 */
+                       if (ver_major > 1 || (ver_major == 1 && ver_minor >= 3))
+                       {       /*
+                               ** Make sure that the libopus in use is not fixed-point, as it
+                               ** sacrifices accuracy. libopus API documentation explicitly
+                               ** allows checking for this suffix to determine if it is.
+                               */
+                               if (!strstr (str, "-fixed"))
+                                       return 1 ;
+                               } ;
+                       } ;
+               } ;
+
+       printf ("skipping (%s)\n", str ? str : "unknown libopus version") ;
+       return 0 ;
+} /* check_opus_version */
index 90a9d01..31e93d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2017 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
@@ -52,6 +52,7 @@ static void   filesystem_full_test (int format) ;
 static void    permission_test (const char *filename, int typemajor) ;
 static void    wavex_amb_test (const char *filename) ;
 static void rf64_downgrade_test (const char *filename) ;
+static void rf64_long_file_downgrade_test (const char *filename) ;
 
 int
 main (int argc, char *argv [])
@@ -145,6 +146,9 @@ main (int argc, char *argv [])
                filesystem_full_test (SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
                permission_test ("readonly.rf64", SF_FORMAT_RF64) ;
                rf64_downgrade_test ("downgrade.wav") ;
+               /* Disable this by default, because it needs to write 4 gigabytes of data. */
+               if (SF_FALSE)
+                       rf64_long_file_downgrade_test ("no-downgrade.rf64") ;
                test_count++ ;
                } ;
 
@@ -256,17 +260,18 @@ zero_data_test (const char *filename, int format)
 
 static void
 filesystem_full_test (int format)
-{      SNDFILE         *file ;
+{
+#if (defined (WIN32) || defined (_WIN32))
+       (void) format ;
+       /* Can't run this test on Win32 so return. */
+       return ;
+#else
+       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 ;
 
@@ -300,6 +305,7 @@ filesystem_full_test (int format)
                } ;
 
        puts ("ok") ;
+#endif
 } /* filesystem_full_test */
 
 static void
@@ -307,8 +313,8 @@ permission_test (const char *filename, int typemajor)
 {
 #if (OS_IS_WIN32)
        /* Avoid compiler warnings. */
-       filename = filename ;
-       typemajor = typemajor ;
+       (void) filename ;
+       (void) typemajor ;
 
        /* Can't run this test on Win32 so return. */
        return ;
@@ -471,3 +477,57 @@ rf64_downgrade_test (const char *filename)
 
        return ;
 } /* rf64_downgrade_test */
+
+static void
+rf64_long_file_downgrade_test (const char *filename)
+{      static int      output  [BUFFER_LEN] ;
+       static int      input   [1] = { 0 } ;
+
+       SNDFILE         *file ;
+       SF_INFO         sfinfo ;
+       sf_count_t      output_frames = 0 ;
+
+       print_test_name (__func__, filename) ;
+
+       sf_info_clear (&sfinfo) ;
+
+       memset (output, 0, sizeof (output)) ;
+       output [0] = 0x1020304 ;
+
+       sfinfo.samplerate       = 44100 ;
+       sfinfo.frames           = ARRAY_LEN (output) ;
+       sfinfo.channels         = 1 ;
+       sfinfo.format           = SF_FORMAT_RF64 | SF_FORMAT_PCM_32 ;
+
+       file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
+
+       exit_if_true (sf_command (file, SFC_RF64_AUTO_DOWNGRADE, NULL, SF_TRUE) != SF_TRUE, "\n\nLine %d: sf_command failed.\n", __LINE__) ;
+
+       while (output_frames * sizeof (output [0]) < 0x100000000)
+       {       test_write_int_or_die (file, 0, output, ARRAY_LEN (output), __LINE__) ;
+               output_frames += ARRAY_LEN (output) ;
+               } ;
+
+       sf_close (file) ;
+
+       sf_info_clear (&sfinfo) ;
+
+       file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
+
+       exit_if_true (sfinfo.format != (SF_FORMAT_RF64 | SF_FORMAT_PCM_32), "\n\nLine %d: RF64 to WAV downgrade should have failed.\n", __LINE__) ;
+       exit_if_true (sfinfo.channels != 1, "\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
+       exit_if_true (sfinfo.frames != output_frames, "\n\nLine %d: Incorrect number of frames in file (%d should be %d).\n", __LINE__, (int) sfinfo.frames, (int) output_frames) ;
+
+       /* Check that the first sample read is the same as the first written. */
+       test_read_int_or_die (file, 0, input, ARRAY_LEN (input), __LINE__) ;
+       exit_if_true (input [0] != output [0], "\n\nLine %d: Bad first sample (0x%08x).\n", __LINE__, input [0]) ;
+
+       check_log_buffer_or_die (file, __LINE__) ;
+
+       sf_close (file) ;
+
+       puts ("ok") ;
+       unlink (filename) ;
+
+       return ;
+} /* rf64_long_file_downgrade_test */
diff --git a/tests/ogg_opus_test.c b/tests/ogg_opus_test.c
new file mode 100644 (file)
index 0000000..37532be
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+** Copyright (C) 2007-2018 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>
+#else
+#include "sf_unistd.h"
+#endif
+
+#include <math.h>
+#include <inttypes.h>
+#include <sndfile.h>
+
+#include "utils.h"
+
+#define        SAMPLE_RATE                     48000
+#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_opus_short_test (void)
+{      const char * filename = "ogg_opus_short.opus" ;
+
+       SNDFILE * file ;
+       SF_INFO sfinfo ;
+       short seek_data [10] ;
+       unsigned k ;
+
+       print_test_name ("ogg_opus_short_test", filename) ;
+
+       /* Generate float data. */
+       gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7F00) ;
+
+       /* Convert to short. */
+       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_OPUS ;
+       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_opus_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__) ;
+
+       /* Test seek to end of file. */
+       test_seek_or_die (file, 0, SEEK_END, sfinfo.frames, sfinfo.channels, __LINE__) ;
+
+       sf_close (file) ;
+
+       puts ("ok") ;
+
+       unlink (filename) ;
+} /* ogg_opus_short_test */
+
+static void
+ogg_opus_int_test (void)
+{      const char * filename = "ogg_opus_int.opus" ;
+
+       SNDFILE * file ;
+       SF_INFO sfinfo ;
+       int seek_data [10] ;
+       unsigned k ;
+
+       print_test_name ("ogg_opus_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_OPUS ;
+       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_opus_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_opus_int_test */
+
+static void
+ogg_opus_float_test (void)
+{      const char * filename = "ogg_opus_float.opus" ;
+
+       SNDFILE * file ;
+       SF_INFO sfinfo ;
+       float seek_data [10] ;
+
+       print_test_name ("ogg_opus_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_OPUS ;
+       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_opus_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_opus_float_test */
+
+static void
+ogg_opus_double_test (void)
+{      const char * filename = "ogg_opus_double.opus" ;
+
+       SNDFILE * file ;
+       SF_INFO sfinfo ;
+       double seek_data [10] ;
+
+       print_test_name ("ogg_opus_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_OPUS ;
+       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_opus_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_opus_double_test */
+
+
+static void
+ogg_opus_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_opus_stereo_seek_test */
+
+
+static void
+ogg_opus_original_samplerate_test (void)
+{      const char * filename = "ogg_opus_original_samplerate.opus" ;
+
+       SNDFILE * file ;
+       SF_INFO sfinfo ;
+       int original_samplerate = 54321 ;
+       sf_count_t frames ;
+
+       print_test_name ("ogg_opus_original_samplerate_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_OPUS ;
+       sfinfo.channels = 1 ;
+       sfinfo.samplerate = SAMPLE_RATE ;
+
+       /* Write the output file. */
+       file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
+       if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_TRUE)
+       {       printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE failed!\n") ;
+               exit (1) ;
+               } ;
+       test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ;
+       if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_FALSE)
+       {       printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE succeeded when it should have failed!") ;
+               exit (1) ;
+               } ;
+       sf_close (file) ;
+
+       /* Read the file in again. */
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
+
+       original_samplerate = 0 ;
+       file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+       if (sf_command (file, SFC_GET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_TRUE
+               || original_samplerate != 54321)
+       {       printf ("\nCommand SFC_GET_ORIGINAL_SAMPLERATE failed!\n") ;
+               exit (1) ;
+               } ;
+       test_read_double_or_die (file, 0, data_in.d, 8, __LINE__) ;
+       if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) == SF_TRUE)
+       {       printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE succeeded when it should have failed!\n") ;
+               exit (1) ;
+               } ;
+       sf_close (file) ;
+
+       /* Test changing the decoder. */
+       file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
+       frames = sfinfo.frames ;
+       original_samplerate = 16000 ;
+       if (sf_command (file, SFC_SET_ORIGINAL_SAMPLERATE, &original_samplerate, sizeof (original_samplerate)) != SF_TRUE)
+       {       printf ("\nCommand SFC_SET_ORIGINAL_SAMPLERATE failed!\n") ;
+               exit (1) ;
+               } ;
+       if (sf_command (file, SFC_GET_CURRENT_SF_INFO, &sfinfo, sizeof (sfinfo)))
+       {       printf ("\nCommand SFC_GET_CURRENT_SF_INFO failed!\n") ;
+               exit (1) ;
+               } ;
+       if (frames / (48000 / 16000) != sfinfo.frames)
+       {       printf ("\nIncorrect frame count! (%" PRId64 " vs %" PRId64")\n", frames / (48000 / 16000), sfinfo.frames) ;
+               exit (1) ;
+               } ;
+       test_read_double_or_die (file, 0, data_out.d, sfinfo.frames, __LINE__) ;
+
+       sf_close (file) ;
+
+       puts ("ok") ;
+
+       unlink (filename) ;
+} /* ogg_opus_original_samplerate_test */
+
+
+int
+main (void)
+{
+       if (HAVE_EXTERNAL_XIPH_LIBS)
+       {       ogg_opus_short_test () ;
+               ogg_opus_int_test () ;
+               ogg_opus_float_test () ;
+               ogg_opus_double_test () ;
+
+               ogg_opus_stereo_seek_test ("ogg_opus_seek.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS) ;
+               ogg_opus_original_samplerate_test () ;
+               }
+       else
+               puts ("    No Ogg/Opus tests because Ogg/Opus support was not compiled in.") ;
+
+       return 0 ;
+} /* main */
index 78d24b3..ba3d899 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
+#endif
 
 #include <math.h>
 
index 96aea93..11226fb 100644 (file)
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
@@ -690,14 +692,7 @@ pcm_test_double (const char *filename, int filetype, uint64_t hash, int replace_
 
        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)) ;
 
@@ -824,14 +819,7 @@ pcm_test_double (const char *filename, int filetype, uint64_t hash, int replace_
 
        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)) ;
 
index 765571f..3e1aa3d 100644 (file)
@@ -26,6 +26,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 8b19628..283af64 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2010-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+# Copyright (C) 2010-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 #
 # All rights reserved.
 #
@@ -42,7 +42,7 @@ 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
+       $CC -std=c99 -Werror -pedantic -I@top_srcdir@/src -I@abs_top_builddir@/src -I@abs_top_builddir@/include -c @top_srcdir@/tests/sfversion.c -o /dev/null
 
        # Check compiler return status.
        if test $? -ne 0 ; then
index 1bc1f43..9bb30cc 100644 (file)
@@ -1,6 +1,6 @@
 [+ AutoGen5 template c +]
 /*
-** Copyright (C) 2001-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2001-2017 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
@@ -56,7 +56,6 @@ typedef struct
        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) ;
@@ -95,9 +94,6 @@ 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) ;
 
@@ -129,6 +125,7 @@ pipe_read_test (int filetype, const char *ext)
        snprintf (filename, sizeof (filename), "pipe_in.%s", ext) ;
        print_test_name ("pipe_read_test", filename) ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.format = filetype | SF_FORMAT_PCM_16 ;
        sfinfo.channels = 1 ;
        sfinfo.samplerate = 44100 ;
@@ -140,7 +137,7 @@ pipe_read_test (int filetype, const char *ext)
        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) ;
+       snprintf (buffer, sizeof (buffer), "cat %s | ./tests/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) ;
@@ -161,7 +158,7 @@ pipe_write_test (const char *ext)
 
        print_test_name ("pipe_write_test", ext) ;
 
-       snprintf (buffer, sizeof (buffer), "./stdout_test %s | ./stdin_test %s ", ext, ext) ;
+       snprintf (buffer, sizeof (buffer), "./tests/stdout_test %s | ./tests/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) ;
@@ -331,6 +328,7 @@ pipe_test_others (FILETYPE* list1, FILETYPE* list2)
                        SF_INFO sfinfo ;
                        int retval ;
 
+                       memset (&sfinfo, 0, sizeof (sfinfo)) ;
                        sfinfo.format = info.format | SF_FORMAT_PCM_16 ;
                        sfinfo.channels = 1 ;
                        sfinfo.samplerate = 44100 ;
@@ -339,7 +337,7 @@ pipe_test_others (FILETYPE* list1, FILETYPE* list2)
                        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) ;
+                       snprintf (buffer, sizeof (buffer), "cat %s | ./tests/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) ;
@@ -360,15 +358,5 @@ pipe_test_others (FILETYPE* list1, FILETYPE* list2)
 /*==============================================================================
 */
 
-static int
-file_exists (const char *filename)
-{      struct stat buf ;
-
-       if (stat (filename, &buf))
-               return 0 ;
-
-       return 1 ;
-} /* file_exists */
-
 #endif
 
index 6728e36..be0f94d 100644 (file)
@@ -26,6 +26,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 39ddf57..ad59ce1 100644 (file)
@@ -27,6 +27,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 78a9f7f..497265c 100644 (file)
@@ -22,6 +22,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index b432e19..6caa77a 100644 (file)
@@ -16,6 +16,8 @@
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
+#include "sfconfig.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index a893915..651614a 100644 (file)
@@ -25,6 +25,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
@@ -149,7 +151,7 @@ stdin_test  (int typemajor, int count)
        else
                memset (&sfinfo, 0, sizeof (sfinfo)) ;
 
-       if ((file = sf_open_fd (STDIN_FILENO, SFM_READ, &sfinfo, SF_TRUE)) == NULL)
+       if ((file = sf_open_fd (fileno (stdin), SFM_READ, &sfinfo, SF_TRUE)) == NULL)
        {       fprintf (stderr, "sf_open_fd failed with error : ") ;
                puts (sf_strerror (NULL)) ;
                dump_log_buffer (NULL) ;
index 80a696c..a065a04 100644 (file)
@@ -29,6 +29,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sys/types.h>
@@ -61,7 +63,6 @@ main (void)
 
 
 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 [] =
@@ -74,9 +75,6 @@ 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]) ;
 
@@ -92,7 +90,7 @@ stdio_test (const char *filetype)
 
        print_test_name ("stdio_test", filetype) ;
 
-       snprintf (buffer, sizeof (buffer), "./stdout_test %s > stdio.%s", filetype, filetype) ;
+       snprintf (buffer, sizeof (buffer), "./tests/stdout_test %s > stdio.%s", filetype, filetype) ;
        if ((retval = system (buffer)))
        {       retval = WIFEXITED (retval) ? WEXITSTATUS (retval) : 1 ;
                printf ("%s : %s", buffer, (strerror (retval))) ;
@@ -105,7 +103,7 @@ stdio_test (const char *filetype)
                exit (1) ;
                } ;
 
-       snprintf (buffer, sizeof (buffer), "./stdin_test %s < stdio.%s", filetype, filetype) ;
+       snprintf (buffer, sizeof (buffer), "./tests/stdin_test %s < stdio.%s", filetype, filetype) ;
        if ((retval = system (buffer)))
        {       retval = WIFEXITED (retval) ? WEXITSTATUS (retval) : 1 ;
                printf ("%s : %s", buffer, (strerror (retval))) ;
@@ -139,15 +137,5 @@ file_length (const char *filename)
        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
 
index 9404698..a71ed64 100644 (file)
@@ -25,6 +25,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 572726f..70a0dfb 100644 (file)
@@ -26,6 +26,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include       <sndfile.h>
@@ -59,6 +61,7 @@ main (int argc, char *argv [])
                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 ("           opus - test adding strings to OPUS files\n") ;
                printf ("           all  - perform all tests\n") ;
                exit (1) ;
                } ;
@@ -112,12 +115,20 @@ main (int argc, char *argv [])
 
        if (do_all || ! strcmp (argv [1], "ogg"))
        {       if (HAVE_EXTERNAL_XIPH_LIBS)
-                       string_start_test ("vorbis.oga", SF_FORMAT_OGG) ;
+                       string_start_test ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS) ;
                else
                        puts ("    No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
                test_count++ ;
                } ;
 
+       if (do_all || ! strcmp (argv [1], "opus"))
+       {       if (HAVE_EXTERNAL_XIPH_LIBS)
+                       string_start_test ("opus.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS) ;
+               else
+                       puts ("    No Ogg/Opus tests because Ogg/Opus support was not compiled in.") ;
+               test_count++ ;
+               } ;
+
        if (do_all || ! strcmp (argv [1], "caf"))
        {       string_start_test ("strings.caf", SF_FORMAT_CAF) ;
                string_start_end_test ("strings.caf", SF_FORMAT_CAF) ;
@@ -338,11 +349,12 @@ string_start_end_test (const char *filename, int typemajor)
 } /* string_start_end_test */
 
 static void
-string_start_test (const char *filename, int typemajor)
+string_start_test (const char *filename, int formattype)
 {      const char      *cptr ;
        SNDFILE         *file ;
        SF_INFO         sfinfo ;
        int                     errors = 0 ;
+       int                     typemajor = SF_FORMAT_TYPEMASK & formattype ;
 
        print_test_name ("string_start_test", filename) ;
 
@@ -351,15 +363,20 @@ string_start_test (const char *filename, int typemajor)
        sfinfo.channels         = 1 ;
        sfinfo.frames           = 0 ;
 
-       switch (typemajor)
-       {       case SF_FORMAT_OGG :
-                       sfinfo.format = typemajor | SF_FORMAT_VORBIS ;
+       switch (formattype)
+       {       case SF_FORMAT_OGG | SF_FORMAT_OPUS :
+                       /* Opus only supports some discrete sample rates. */
+                       sfinfo.samplerate = 48000 ;
+                       break ;
+
+               case SF_FORMAT_OGG | SF_FORMAT_VORBIS :
                        break ;
 
                default :
-                       sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
+                       formattype |= SF_FORMAT_PCM_16 ;
                        break ;
                } ;
+       sfinfo.format = formattype ;
 
        file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
 
index e58149c..b06a178 100644 (file)
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/usr/bin/env sh
 
-# Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+# Copyright (C) 2008-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
 #
 # All rights reserved.
 #
 HOST_TRIPLET=@HOST_TRIPLET@
 PACKAGE_VERSION=@PACKAGE_VERSION@
 LIB_VERSION=$(echo $PACKAGE_VERSION | sed "s/[a-z].*//")
+ABS_TOP_SRCDIR=@abs_top_srcdir@
+PYTHON=@PYTHON@
 
-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@ | grep libsndfile | sed "s/-exp$//")
+sfversion=$(./tests/sfversion@EXEEXT@ | grep libsndfile | sed "s/-exp$//")
 
 if test "$sfversion" != libsndfile-$PACKAGE_VERSION ; then
        echo "Error : sfversion ($sfversion) and PACKAGE_VERSION ($PACKAGE_VERSION) don't match."
@@ -63,48 +47,44 @@ if test "$sfversion" != libsndfile-$PACKAGE_VERSION ; then
 # Force exit on errors.
 set -e
 
-# Generic-tests
-uname -a
-
 # Check the header file.
-sh pedantic-header-test.sh
+/usr/bin/env sh tests/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@ cue
-./command_test@EXEEXT@ current_sf_info
-./command_test@EXEEXT@ bext
-./command_test@EXEEXT@ bextch
-./command_test@EXEEXT@ chanmap
-./command_test@EXEEXT@ cart
-./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@
-./channel_test@EXEEXT@
+echo "Running unit tests from src/ directory of source code tree."
+./src/test_main@EXEEXT@
+
+echo
+echo "Running end-to-end tests from tests/ directory."
+
+./tests/error_test@EXEEXT@
+./tests/pcm_test@EXEEXT@
+./tests/ulaw_test@EXEEXT@
+./tests/alaw_test@EXEEXT@
+./tests/dwvw_test@EXEEXT@
+./tests/command_test@EXEEXT@ ver
+./tests/command_test@EXEEXT@ norm
+./tests/command_test@EXEEXT@ format
+./tests/command_test@EXEEXT@ peak
+./tests/command_test@EXEEXT@ trunc
+./tests/command_test@EXEEXT@ inst
+./tests/command_test@EXEEXT@ cue
+./tests/command_test@EXEEXT@ current_sf_info
+./tests/command_test@EXEEXT@ bext
+./tests/command_test@EXEEXT@ bextch
+./tests/command_test@EXEEXT@ chanmap
+./tests/command_test@EXEEXT@ cart
+./tests/floating_point_test@EXEEXT@
+./tests/checksum_test@EXEEXT@
+./tests/scale_clip_test@EXEEXT@
+./tests/headerless_test@EXEEXT@
+./tests/rdwr_test@EXEEXT@
+./tests/locale_test@EXEEXT@
+./tests/win32_ordinal_test@EXEEXT@
+./tests/external_libs_test@EXEEXT@
+./tests/format_check_test@EXEEXT@
+./tests/channel_test@EXEEXT@
 
 # The w64 G++ compiler requires an extra runtime DLL which we don't have,
 # so skip this test.
@@ -114,7 +94,7 @@ case "$HOST_TRIPLET" in
        i686-w64-mingw32)
                ;;
        *)
-               ./cpp_test@EXEEXT@
+               ./tests/cpp_test@EXEEXT@
                ;;
        esac
 
@@ -123,249 +103,269 @@ 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@
-./chunk_test@EXEEXT@ aiff
+./tests/write_read_test@EXEEXT@ aiff
+./tests/lossy_comp_test@EXEEXT@ aiff_ulaw
+./tests/lossy_comp_test@EXEEXT@ aiff_alaw
+./tests/lossy_comp_test@EXEEXT@ aiff_gsm610
+echo "----------------------------------------------------------------------"
+echo "  lossy_comp_test@EXEEXT@ aiff_ima"
+echo "----------------------------------------------------------------------"
+
+./tests/peak_chunk_test@EXEEXT@ aiff
+./tests/header_test@EXEEXT@ aiff
+./tests/misc_test@EXEEXT@ aiff
+./tests/string_test@EXEEXT@ aiff
+./tests/multi_file_test@EXEEXT@ aiff
+./tests/aiff_rw_test@EXEEXT@
+./tests/chunk_test@EXEEXT@ aiff
 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
+./tests/write_read_test@EXEEXT@ au
+./tests/lossy_comp_test@EXEEXT@ au_ulaw
+./tests/lossy_comp_test@EXEEXT@ au_alaw
+./tests/lossy_comp_test@EXEEXT@ au_g721
+./tests/lossy_comp_test@EXEEXT@ au_g723
+./tests/header_test@EXEEXT@ au
+./tests/misc_test@EXEEXT@ au
+./tests/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
-./chunk_test@EXEEXT@ caf
-./string_test@EXEEXT@ caf
-./long_read_write_test@EXEEXT@ alac
+./tests/write_read_test@EXEEXT@ caf
+./tests/lossy_comp_test@EXEEXT@ caf_ulaw
+./tests/lossy_comp_test@EXEEXT@ caf_alaw
+./tests/header_test@EXEEXT@ caf
+./tests/peak_chunk_test@EXEEXT@ caf
+./tests/misc_test@EXEEXT@ caf
+./tests/chunk_test@EXEEXT@ caf
+./tests/string_test@EXEEXT@ caf
+./tests/long_read_write_test@EXEEXT@ alac
 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
-./chunk_test@EXEEXT@ wav
+./tests/write_read_test@EXEEXT@ wav
+./tests/lossy_comp_test@EXEEXT@ wav_pcm
+./tests/lossy_comp_test@EXEEXT@ wav_ima
+./tests/lossy_comp_test@EXEEXT@ wav_msadpcm
+./tests/lossy_comp_test@EXEEXT@ wav_ulaw
+./tests/lossy_comp_test@EXEEXT@ wav_alaw
+./tests/lossy_comp_test@EXEEXT@ wav_gsm610
+./tests/lossy_comp_test@EXEEXT@ wav_g721
+./tests/peak_chunk_test@EXEEXT@ wav
+./tests/header_test@EXEEXT@ wav
+./tests/misc_test@EXEEXT@ wav
+./tests/string_test@EXEEXT@ wav
+./tests/multi_file_test@EXEEXT@ wav
+./tests/chunk_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
+./tests/write_read_test@EXEEXT@ w64
+./tests/lossy_comp_test@EXEEXT@ w64_ima
+./tests/lossy_comp_test@EXEEXT@ w64_msadpcm
+./tests/lossy_comp_test@EXEEXT@ w64_ulaw
+./tests/lossy_comp_test@EXEEXT@ w64_alaw
+./tests/lossy_comp_test@EXEEXT@ w64_gsm610
+./tests/header_test@EXEEXT@ w64
+./tests/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
-./string_test@EXEEXT@ rf64
-./peak_chunk_test@EXEEXT@ rf64
-./chunk_test@EXEEXT@ rf64
+./tests/write_read_test@EXEEXT@ rf64
+./tests/header_test@EXEEXT@ rf64
+./tests/misc_test@EXEEXT@ rf64
+./tests/string_test@EXEEXT@ rf64
+./tests/peak_chunk_test@EXEEXT@ rf64
+./tests/chunk_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@
+./tests/write_read_test@EXEEXT@ raw
+./tests/lossy_comp_test@EXEEXT@ raw_ulaw
+./tests/lossy_comp_test@EXEEXT@ raw_alaw
+./tests/lossy_comp_test@EXEEXT@ raw_gsm610
+./tests/lossy_comp_test@EXEEXT@ vox_adpcm
+./tests/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
+./tests/write_read_test@EXEEXT@ paf
+./tests/header_test@EXEEXT@ paf
+./tests/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
+./tests/write_read_test@EXEEXT@ svx
+./tests/header_test@EXEEXT@ svx
+./tests/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
+./tests/write_read_test@EXEEXT@ nist
+./tests/lossy_comp_test@EXEEXT@ nist_ulaw
+./tests/lossy_comp_test@EXEEXT@ nist_alaw
+./tests/header_test@EXEEXT@ nist
+./tests/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
+./tests/write_read_test@EXEEXT@ ircam
+./tests/lossy_comp_test@EXEEXT@ ircam_ulaw
+./tests/lossy_comp_test@EXEEXT@ ircam_alaw
+./tests/header_test@EXEEXT@ ircam
+./tests/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
+./tests/write_read_test@EXEEXT@ voc
+./tests/lossy_comp_test@EXEEXT@ voc_ulaw
+./tests/lossy_comp_test@EXEEXT@ voc_alaw
+./tests/header_test@EXEEXT@ voc
+./tests/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
+./tests/write_read_test@EXEEXT@ mat4
+./tests/header_test@EXEEXT@ mat4
+./tests/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
+./tests/write_read_test@EXEEXT@ mat5
+./tests/header_test@EXEEXT@ mat5
+./tests/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
+./tests/write_read_test@EXEEXT@ pvf
+./tests/header_test@EXEEXT@ pvf
+./tests/misc_test@EXEEXT@ pvf
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed tests on PVF files."
 echo "----------------------------------------------------------------------"
 
 # xi-tests
-./lossy_comp_test@EXEEXT@ xi_dpcm
+./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
+./tests/write_read_test@EXEEXT@ htk
+./tests/header_test@EXEEXT@ htk
+./tests/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
+./tests/write_read_test@EXEEXT@ avr
+./tests/header_test@EXEEXT@ avr
+./tests/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
+./tests/write_read_test@EXEEXT@ sds
+./tests/header_test@EXEEXT@ sds
+./tests/misc_test@EXEEXT@ sds
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed tests on SDS files."
 echo "----------------------------------------------------------------------"
 
 # sd2-tests
-./write_read_test@EXEEXT@ sd2
+./tests/write_read_test@EXEEXT@ sd2
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed tests on SD2 files."
 echo "----------------------------------------------------------------------"
 
 # wve-tests
-./lossy_comp_test@EXEEXT@ 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
+./tests/write_read_test@EXEEXT@ mpc2k
+./tests/header_test@EXEEXT@ mpc2k
+./tests/misc_test@EXEEXT@ mpc2k
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed tests on MPC 2000 files."
 echo "----------------------------------------------------------------------"
 
 # flac-tests
-./write_read_test@EXEEXT@ flac
-./compression_size_test@EXEEXT@ flac
-./string_test@EXEEXT@ flac
+./tests/write_read_test@EXEEXT@ flac
+./tests/compression_size_test@EXEEXT@ flac
+./tests/string_test@EXEEXT@ flac
+./tests/header_test@EXEEXT@ flac
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed tests on FLAC files."
 echo "----------------------------------------------------------------------"
 
 # vorbis-tests
-./ogg_test@EXEEXT@
-./compression_size_test@EXEEXT@ vorbis
-./lossy_comp_test@EXEEXT@ ogg_vorbis
-./string_test@EXEEXT@ ogg
-./misc_test@EXEEXT@ ogg
+./tests/ogg_test@EXEEXT@
+./tests/compression_size_test@EXEEXT@ vorbis
+./tests/lossy_comp_test@EXEEXT@ ogg_vorbis
+./tests/string_test@EXEEXT@ ogg
+./tests/misc_test@EXEEXT@ ogg
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed tests on OGG/VORBIS files."
 echo "----------------------------------------------------------------------"
 
+# opus-tests
+./tests/ogg_opus_test@EXEEXT@
+./tests/compression_size_test@EXEEXT@ opus
+./tests/lossy_comp_test@EXEEXT@ ogg_opus
+./tests/string_test@EXEEXT@ opus
+
+echo "----------------------------------------------------------------------"
+echo "  $sfversion passed tests on OPUS files."
+echo "----------------------------------------------------------------------"
+
 # io-tests
-./stdio_test@EXEEXT@
-./pipe_test@EXEEXT@
-./virtual_io_test@EXEEXT@
+./tests/stdio_test@EXEEXT@
+./tests/pipe_test@EXEEXT@
+./tests/virtual_io_test@EXEEXT@
 echo "----------------------------------------------------------------------"
 echo "  $sfversion passed stdio/pipe/vio tests."
 echo "----------------------------------------------------------------------"
 
+"${PYTHON}" "${ABS_TOP_SRCDIR}/src/binheader_writef_check.py" "${ABS_TOP_SRCDIR}/src"/*.c
+echo "----------------------------------------------------------------------"
+echo "  $sfversion passed binary header tests."
+echo "----------------------------------------------------------------------"
 
+"${PYTHON}" "${ABS_TOP_SRCDIR}/programs/test-sndfile-metadata-set.py" "${HOST_TRIPLET}"
+echo "----------------------------------------------------------------------"
+echo "  $sfversion passed sndfile metadata tests."
+echo "----------------------------------------------------------------------"
index fc0d497..9e0eba9 100644 (file)
@@ -24,6 +24,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>
index 096b758..7be35fa 100644 (file)
@@ -1,6 +1,6 @@
 [+ AutoGen5 template h c +]
 /*
-** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2002-2018 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
 extern "C" {
 #endif /* __cplusplus */
 
+#include "sfconfig.h"
+
 #include <stdint.h>
 #include <stdarg.h>
 
 #define        ARRAY_LEN(x)            ((int) (sizeof (x)) / (sizeof ((x) [0])))
 #define SIGNED_SIZEOF(x)       ((int64_t) (sizeof (x)))
 #define        NOT(x)                          (! (x))
-#define        ABS(x)                          ((x) >= 0 ? (x) : -(x))
+#define        ABS(x)                          ((x) >= 0 ? (x) : - (x))
 
 #define        PIPE_INDEX(x)   ((x) + 500)
 #define        PIPE_TEST_LEN   12345
@@ -61,7 +63,7 @@ void  write_mono_file (const char * filename, int format, int srate, float * outp
 #ifdef __GNUC__
 static inline void
 exit_if_true (int test, const char *format, ...)
-#if (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO)
+#if (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO && !defined (__clang__))
        __attribute__ ((format (gnu_printf, 2, 3))) ;
 #else
        __attribute__ ((format (printf, 2, 3))) ;
@@ -200,7 +202,7 @@ sf_count_t          file_length_fd (int fd) ;
 #define        M_PI            3.14159265358979323846264338
 #endif
 
-#define        LOG_BUFFER_SIZE         2048
+#define        LOG_BUFFER_SIZE         4096
 
 /*
 **     Neat solution to the Win32/OS2 binary file flage requirement.
@@ -237,6 +239,7 @@ create_short_sndfile (const char *filename, int format, int channels)
        SNDFILE *file ;
        SF_INFO sfinfo ;
 
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
        sfinfo.samplerate = 44100 ;
        sfinfo.channels = channels ;
        sfinfo.format = format ;
@@ -500,7 +503,7 @@ test_sf_format_or_die (const SF_INFO *info, int line_num)
 {      int res ;
 
        if ((res = sf_format_check (info)) != 1)
-       {       printf ("\n\nLine %d : sf_format_check returned error (%d)\n\n", line_num,res) ;
+       {       printf ("\n\nLine %d : sf_format_check returned error (%d)\n\n", line_num, res) ;
                exit (1) ;
                } ;
 
index 1aae063..854bc30 100644 (file)
@@ -87,7 +87,7 @@ 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
+       **      This will break badly for files over 2Gig in length, but
        **      is sufficient for testing.
        */
        if (vf->offset + count > vf->length)
index 49f7860..7c9adb1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 2006-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 2006-2017 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
@@ -31,6 +31,9 @@
 
 #include <string.h>
 #include <fcntl.h>
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
 #include <sys/types.h>
 
 #include "utils.h"
index b908db0..af87e12 100644 (file)
@@ -28,6 +28,8 @@
 
 #if HAVE_UNISTD_H
 #include <unistd.h>
+#else
+#include "sf_unistd.h"
 #endif
 
 #include <sndfile.h>