Merge tag 'upstream/1.2.0' into tizen_base 50/286050/1 accepted/tizen/base/20230201.083439
authorSeungbae Shin <seungbae.shin@samsung.com>
Tue, 27 Dec 2022 02:25:23 +0000 (11:25 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Tue, 27 Dec 2022 02:25:52 +0000 (11:25 +0900)
Change-Id: I5ab92fa565d7a7ad00de81d9165d52427286a0a9

43 files changed:
Building-for-Android.md
CHANGELOG.md
CMakeLists.txt
Makefile.am
README.md
Scripts/static-deps-build.mk
autogen.sh [deleted file]
cmake/FindLame.cmake [deleted file]
cmake/Findmp3lame.cmake [new file with mode: 0644]
cmake/SndFileChecks.cmake
cmake/SndFileConfig.cmake.in
configure.ac
docs/api.md
docs/command.md
docs/new_file_type_howto.md
include/sndfile.h [moved from include/sndfile.h.in with 99% similarity]
ossfuzz/ossfuzz.sh
packaging/libsndfile.spec
src/aiff.c
src/common.c
src/common.h
src/config.h.cmake
src/double64.c
src/file_io.c
src/flac.c
src/float32.c
src/g72x.c
src/gsm610.c
src/mpeg_decode.c
src/ogg.c
src/ogg.h
src/ogg_opus.c
src/ogg_vorbis.c
src/pcm.c
src/sndfile.c
src/svx.c
src/test_conversions.c
src/wav.c
src/wavlike.c
tests/cpp_test.cc
tests/error_test.c
tests/pedantic-header-test.sh.in
tests/utils.tpl

index c664281..eb5a0d3 100644 (file)
@@ -3,7 +3,7 @@
 Assuming the Android Ndk is installed at location `/path/to/toolchain`, building
 libsndfile for Android (arm-linux-androideabi) should be as simple as:
 ```
-./autogen.sh
+autoreconf -vif
 export ANDROID_TOOLCHAIN_HOME=/path/to/android/toolchain
 ./Scripts/android-configure.sh
 make
index 3719e0f..5014508 100644 (file)
@@ -5,7 +5,22 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
-## [Unreleased]
+## [1.2.0] - 2022-12-25
+
+### Fixed
+
+* Searching for LAME dependency with CMake build system (issue #821).
+* CMake build from Autotools tarball (issue #816).
+* Build on UWP platform (issue #824).
+* Fix signed integer overflow (issue #785).
+* Skipping large wav chunks on stdin (PR #819).
+
+### Removed
+
+* Maximum samplerate limit, thanks @drmpeg, @justacec (issue #850).
+  
+  In version 1.1.0, an artificial limit of 655350 Hz was created, but as it
+  turned out, this is not enough for some scenarios.
 
 ## [1.1.0] - 2022-03-27
 
index b1b49e9..dda2243 100644 (file)
@@ -35,7 +35,7 @@ if (BUILD_REGTEST)
        list (APPEND VCPKG_MANIFEST_FEATURES "regtest")
 endif ()
 
-project(libsndfile VERSION 1.1.0)
+project(libsndfile VERSION 1.2.0)
 
 #
 # Variables
@@ -174,7 +174,7 @@ set_package_properties (FLAC PROPERTIES
        DESCRIPTION "Free Lossless Audio Codec Library"
        PURPOSE "Enables FLAC support"
        )
-set_package_properties (Lame PROPERTIES
+set_package_properties (mp3lame PROPERTIES
        TYPE RECOMMENDED
        URL "https://lame.sourceforge.io/"
        DESCRIPTION "High quality MPEG Audio Layer III (MP3) encoder"
@@ -220,8 +220,6 @@ feature_summary (WHAT ALL)
 
 configure_file (src/config.h.cmake src/config.h)
 
-configure_file (include/sndfile.h.in include/sndfile.h)
-
 if (INSTALL_PKGCONFIG_MODULE)
 
        set (prefix ${CMAKE_INSTALL_PREFIX})
@@ -237,20 +235,7 @@ if (INSTALL_PKGCONFIG_MODULE)
        endif ()
        if (ENABLE_MPEG)
                set (EXTERNAL_MPEG_REQUIRE "libmpg123")
-               get_filename_component(LAME_WE ${LAME_LIBRARY} NAME_WE)
-               if (LAME_HIP_LIBRARY)
-                       get_filename_component(LAME_HIP_WE ${LAME_HIP_LIBRARY} NAME_WE)
-               endif ()
-               if (CMAKE_IMPORT_LIBRARY_PREFIX)
-                       string (REGEX REPLACE "^${CMAKE_IMPORT_LIBRARY_PREFIX}" "" LAME_WE_NO_PREFIX ${LAME_WE})
-                       if (LAME_HIP_LIBRARY)
-                               string (REGEX REPLACE "^${CMAKE_IMPORT_LIBRARY_PREFIX}" "" LAME_HIP_WE_NO_PREFIX ${LAME_HIP_WE})
-                       endif ()
-               endif ()
-               set (EXTERNAL_MPEG_LIBS "-l${LAME_WE_NO_PREFIX}")
-               if (LAME_HIP_LIBRARY)
-                       set (EXTERNAL_MPEG_LIBS "${MPEG_LIBS} -l${LAME_HIP_WE}")
-               endif ()
+               set (EXTERNAL_MPEG_LIBS "-lmp3lame")
        endif ()
 
        configure_file (sndfile.pc.in sndfile.pc @ONLY)
@@ -263,8 +248,8 @@ endif ()
 
 # Public libsndfile headers
 set (sndfile_HDRS
+       include/sndfile.h
        include/sndfile.hh
-       ${CMAKE_CURRENT_BINARY_DIR}/include/sndfile.h
        )
 
 #
@@ -411,7 +396,7 @@ target_link_libraries (sndfile
                $<$<AND:$<BOOL:${ENABLE_EXPERIMENTAL}>,$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>,$<BOOL:${HAVE_SPEEX}>>:Speex::Speex>
                $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Opus::opus>
                $<$<BOOL:${HAVE_MPEG}>:MPG123::libmpg123>
-               $<$<BOOL:${HAVE_MPEG}>:Lame::Lame>
+               $<$<BOOL:${HAVE_MPEG}>:mp3lame::mp3lame>
        )
 set_target_properties (sndfile PROPERTIES
        PUBLIC_HEADER "${sndfile_HDRS}"
index 18dc402..029d010 100644 (file)
@@ -24,6 +24,7 @@ cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \
        cmake/TestLargeFiles.cmake cmake/TestInline.c.in \
        cmake/FindOpus.cmake cmake/SndFileConfig.cmake.in \
        cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in \
+       cmake/Findmp3lame.cmake cmake/FindMpg123.cmake \
        cmake/SetupABIVersions.cmake
 
 pkgconfig_DATA = sndfile.pc
@@ -45,7 +46,7 @@ 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 \
+EXTRA_DIST += 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/make-static-lib-hidden-privates.sh \
        src/config.h.cmake
@@ -59,8 +60,7 @@ endif
 #===============================================================================
 
 lib_LTLIBRARIES = src/libsndfile.la
-include_HEADERS = include/sndfile.hh
-nodist_include_HEADERS = include/sndfile.h
+include_HEADERS = include/sndfile.h include/sndfile.hh
 src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_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)
index 82b0b39..f14afcd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ Similarly on Mac OS X, assuming [brew] is already installed:
 Once the build environment has been set up, building and testing libsndfile is
 as simple as:
 
-    ./autogen.sh
+    autoreconf -vif
     ./configure --enable-werror
     make
     make check
index a2c1969..bbf2f0d 100755 (executable)
@@ -95,7 +95,7 @@ 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)
+       (cd Build/$(ogg_version) && autoreconf -vif && CFLAGS=-fPIC ./configure $(config_options) --disable-crc && make all install)
 else
        echo "Ogg/CRC disabled"
        (cd Build && tar xf Tarballs/$(ogg_tarball))
@@ -110,7 +110,7 @@ Build/Stamp/install-libs : Build/Stamp/extract Build/Stamp/build-ogg
        touch $@
 
 configure : configure.ac
-       ./autogen.sh
+       autoreconf -vif
 
 Build/Stamp/configure : Build/Stamp/install-libs configure
        PKG_CONFIG_LIBDIR=Build/lib/pkgconfig ./configure
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755 (executable)
index dbdb5de..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/bin/sh
-# Run this to set up the build system: configure, makefiles, etc.
-# (based on the version in enlightenment's cvs)
-
-package="libsndfile"
-
-olddir=`pwd`
-srcdir=`dirname $0`
-test -z "$srcdir" && srcdir=.
-
-cd "$srcdir"
-DIE=0
-
-printf "checking for autogen ... "
-result="yes"
-(autogen --version) < /dev/null > /dev/null 2>&1 || {
-        echo
-        echo "You must have GNU autogen installed to compile $package."
-        echo "Download the appropriate package for your distribution,"
-        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
-               result="no"
-        DIE=1
-}
-echo $result
-
-printf "checking for autoconf ... "
-result="yes"
-(autoconf --version) < /dev/null > /dev/null 2>&1 || {
-        echo
-        echo "You must have autoconf installed to compile $package."
-        echo "Download the appropriate package for your distribution,"
-        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
-               result="no"
-        DIE=1
-}
-echo $result
-
-VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/"
-VERSIONMKMAJ="sed -e s/\([0-9][0-9]*\)[^0-9].*/\\1/"
-VERSIONMKMIN="sed -e s/.*[0-9][0-9]*\.//"
-
-# do we need automake?
-if test -r Makefile.am; then
-  AM_OPTIONS=`fgrep AUTOMAKE_OPTIONS Makefile.am`
-  AM_NEEDED=`echo $AM_OPTIONS | $VERSIONGREP`
-  if test x"$AM_NEEDED" = "x$AM_OPTIONS"; then
-    AM_NEEDED=""
-  fi
-  if test -z $AM_NEEDED; then
-    printf "checking for automake ... "
-    AUTOMAKE=automake
-    ACLOCAL=aclocal
-    if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then
-      echo "yes"
-    else
-      echo "no"
-      AUTOMAKE=
-    fi
-  else
-    printf "checking for automake $AM_NEEDED or later ... "
-    majneeded=`echo $AM_NEEDED | $VERSIONMKMAJ`
-    minneeded=`echo $AM_NEEDED | $VERSIONMKMIN`
-    for am in automake-$AM_NEEDED automake$AM_NEEDED \
-       automake automake-1.7 automake-1.8 automake-1.9 automake-1.10; do
-      ($am --version < /dev/null > /dev/null 2>&1) || continue
-      ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP`
-      maj=`echo $ver | $VERSIONMKMAJ`
-      min=`echo $ver | $VERSIONMKMIN`
-      if test $maj -eq $majneeded -a $min -ge $minneeded; then
-        AUTOMAKE=$am
-        echo $AUTOMAKE
-        break
-      fi
-    done
-    test -z $AUTOMAKE &&  echo "no"
-    printf "checking for aclocal $AM_NEEDED or later ... "
-    for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED \
-       aclocal aclocal-1.7 aclocal-1.8 aclocal-1.9 aclocal-1.10; do
-      ($ac --version < /dev/null > /dev/null 2>&1) || continue
-      ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP`
-      maj=`echo $ver | $VERSIONMKMAJ`
-      min=`echo $ver | $VERSIONMKMIN`
-      if test $maj -eq $majneeded -a $min -ge $minneeded; then
-        ACLOCAL=$ac
-        echo $ACLOCAL
-        break
-      fi
-    done
-    test -z $ACLOCAL && echo "no"
-  fi
-  test -z $AUTOMAKE || test -z $ACLOCAL && {
-        echo
-        echo "You must have automake installed to compile $package."
-        echo "Download the appropriate package for your distribution,"
-        echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
-        exit 1
-  }
-fi
-
-printf "checking for libtool ... "
-for LIBTOOLIZE in libtoolize glibtoolize nope; do
-  ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break
-done
-if test x$LIBTOOLIZE = xnope; then
-  echo "nope."
-  LIBTOOLIZE=libtoolize
-else
-  echo $LIBTOOLIZE
-fi
-($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
-       echo
-       echo "You must have libtool installed to compile $package."
-       echo "Download the appropriate package for your system,"
-       echo "or get the source from one of the GNU ftp sites"
-       echo "listed in http://www.gnu.org/order/ftp.html"
-       DIE=1
-}
-
-printf "checking for pkg-config ... "
-result="yes"
-(pkg-config --version) < /dev/null > /dev/null 2>&1 || {
-        echo
-        echo "You must have pkg-config installed to compile $package."
-        echo "Download the appropriate package for your distribution."
-               result="no"
-        DIE=1
-}
-echo $result
-
-
-printf "checking for python ... "
-result="yes"
-(python --version) < /dev/null > /dev/null 2>&1 || {
-        echo
-        echo "You must have Python installed to compile $package."
-        echo "Download the appropriate package for your distribution,"
-        echo "or get the source tarball at http://python.org/"
-               result="no"
-        DIE=1
-}
-echo $result
-
-if test "$DIE" -eq 1; then
-        exit 1
-fi
-
-echo "Generating configuration files for $package, please wait ... "
-
-echo "  $ACLOCAL $ACLOCAL_FLAGS"
-$ACLOCAL $ACLOCAL_FLAGS || exit 1
-echo "  $LIBTOOLIZE --automake --force"
-$LIBTOOLIZE --automake --force || exit 1
-echo "  autoheader"
-autoheader || exit 1
-echo "  $AUTOMAKE --add-missing $AUTOMAKE_FLAGS"
-$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1
-echo "  autoconf"
-autoconf || exit 1
-
-# Generate the src/cmake-config.h.in from src/config.h.in.
-# CMake process src/cmake-config.h to create src/config.h.
-rm -f src/config.h src/cmake-config.h
-
-cd $olddir
-
-if test -d .git/ ; then
-       fprecommit=.git/hooks/pre-commit
-       if test ! -f $fprecommit ; then
-               echo
-               echo "Installing git pre-commit hook for this project."
-               printf "#/bin/sh\nexec Scripts/git-pre-commit-hook\n" > $fprecommit
-               chmod u+x $fprecommit
-               echo
-               fi
-       fi
-
diff --git a/cmake/FindLame.cmake b/cmake/FindLame.cmake
deleted file mode 100644 (file)
index be32475..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-# - Find lame
-# Find the native lame includes and libraries
-#
-#  LAME_INCLUDE_DIRS - where to find lame.h, etc.
-#  LAME_LIBRARIES    - List of libraries when using lame.
-#  LAME_FOUND        - True if Lame found.
-
-if (LAME_INCLUDE_DIR)
-    # Already in cache, be silent
-    set(LAME_FIND_QUIETLY TRUE)
-endif ()
-
-find_path (LAME_INCLUDE_DIR lame/lame.h
-       HINTS
-               ${LAME_ROOT}
-       )
-
-# MSVC built lame may be named mp3lame_static.
-# The provided project files name the library with the lib prefix.
-
-find_library (LAME_LIBRARY
-       NAMES
-               mp3lame
-               mp3lame_static
-               libmp3lame
-               libmp3lame_static
-               libmp3lame-static
-       HINTS
-               ${LAME_ROOT}
-       )
-
-find_library (LAME_HIP_LIBRARY
-       NAMES
-               mpghip-static
-               libmpghip-static
-       HINTS
-               ${LAME_ROOT}
-       )
-
-# Handle the QUIETLY and REQUIRED arguments and set LAME_FOUND
-# to TRUE if all listed variables are TRUE.
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args (Lame
-       REQUIRED_VARS
-               LAME_LIBRARY
-               LAME_INCLUDE_DIR
-       )
-
-if (LAME_FOUND)
-       set (LAME_LIBRARIES ${LAME_LIBRARY} ${LAME_HIP_LIBRARY})
-       set (LAME_INCLUDE_DIRS ${LAME_INCLUDE_DIR})
-
-       if (NOT TARGET Lame::Lame)
-               add_library (Lame::Lame UNKNOWN IMPORTED)
-               set_target_properties (Lame::Lame PROPERTIES
-                       INTERFACE_INCLUDE_DIRECTORIES "${LAME_INCLUDE_DIRS}"
-                       IMPORTED_LOCATION "${LAME_LIBRARY}"
-               )
-               if (LAME_HIP_LIBRARY)
-                       set_property (TARGET Lame::Lame APPEND PROPERTY
-                               INTERFACE_LINK_LIBRARIES "${LAME_HIP_LIBRARY}")
-               endif ()
-       endif ()
-endif ()
-
-mark_as_advanced(LAME_INCLUDE_DIR LAME_LIBRARY LAME_HIP_LIBRARY)
diff --git a/cmake/Findmp3lame.cmake b/cmake/Findmp3lame.cmake
new file mode 100644 (file)
index 0000000..223dd08
--- /dev/null
@@ -0,0 +1,67 @@
+# - Find lame
+# Find the native lame includes and libraries
+#
+#  MP3LAME_INCLUDE_DIRS - where to find lame.h, etc.
+#  MP3LAME_LIBRARIES    - List of libraries when using lame.
+#  MP3LAME_FOUND        - True if Lame found.
+
+if (MP3LAME_INCLUDE_DIR)
+    # Already in cache, be silent
+    set(MP3LAME_FIND_QUIETLY TRUE)
+endif ()
+
+find_path (MP3LAME_INCLUDE_DIR lame/lame.h
+       HINTS
+               ${LAME_ROOT}
+       )
+
+# MSVC built lame may be named mp3lame_static.
+# The provided project files name the library with the lib prefix.
+
+find_library (MP3LAME_LIBRARY
+       NAMES
+               mp3lame
+               mp3lame_static
+               libmp3lame
+               libmp3lame_static
+               libmp3lame-static
+       HINTS
+               ${MP3LAME_ROOT}
+       )
+
+find_library (MP3LAME_HIP_LIBRARY
+       NAMES
+               mpghip-static
+               libmpghip-static
+       HINTS
+               ${MP3LAME_ROOT}
+       )
+
+# Handle the QUIETLY and REQUIRED arguments and set LAME_FOUND
+# to TRUE if all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args (mp3lame
+       REQUIRED_VARS
+               MP3LAME_LIBRARY
+               MP3LAME_INCLUDE_DIR
+       )
+
+if (MP3LAME_FOUND)
+       set (MP3LAME_LIBRARIES ${MP3LAME_LIBRARY} ${MP3LAME_HIP_LIBRARY})
+       set (MP3LAME_INCLUDE_DIRS ${MP3LAME_INCLUDE_DIR})
+
+       if (NOT TARGET mp3lame::mp3lame)
+               add_library (mp3lame::mp3lame UNKNOWN IMPORTED)
+               set_target_properties (mp3lame::mp3lame PROPERTIES
+                       INTERFACE_INCLUDE_DIRECTORIES "${MP3LAME_INCLUDE_DIRS}"
+                       IMPORTED_LOCATION "${MP3LAME_LIBRARY}"
+               )
+               if (MP3LAME_HIP_LIBRARY AND (NOT TARGET mp3lame::mpghip))
+                       add_library (mp3lame::mpghip STATIC IMPORTED)
+                       set_property (mp3lame::mpghip PROPERTY IMPORTED_LOCATION "${MP3LAME_HIP_LIBRARY}")
+                       set_property (TARGET mp3lame::mp3lame PROPERTY INTERFACE_LINK_LIBRARIES "mp3lame::mpghip")
+               endif ()
+       endif ()
+endif ()
+
+mark_as_advanced(MP3LAME_INCLUDE_DIR MP3LAME_LIBRARY MP3LAME_HIP_LIBRARY)
index f5d5994..19c7b4b 100644 (file)
@@ -16,13 +16,6 @@ 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)
@@ -56,9 +49,9 @@ else ()
        set (HAVE_EXTERNAL_XIPH_LIBS 0)
 endif ()
 
-find_package (Lame)
+find_package (mp3lame)
 find_package (Mpg123 1.25.10)
-if (LAME_FOUND AND (TARGET MPG123::libmpg123))
+if (TARGET mp3lame::mp3lame AND (TARGET MPG123::libmpg123))
        set (HAVE_MPEG_LIBS 1)
 else ()
        set (HAVE_MPEG_LIBS 0)
@@ -121,28 +114,6 @@ 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)
index 1d5463a..0c98e7e 100644 (file)
@@ -18,7 +18,7 @@ if (SndFile_WITH_EXTERNAL_LIBS AND NOT @BUILD_SHARED_LIBS@)
 endif ()
 
 if (SndFile_WITH_MPEG AND NOT @BUILD_SHARED_LIBS@)
-       find_dependency (Lame)
+       find_dependency (mp3lame)
        find_dependency (MPG123)
 endif ()
 
index e711c82..5769c07 100644 (file)
@@ -3,7 +3,7 @@ dnl Copyright (C) 1999-2022  Erik de Castro Lopo <erikd@mega-nerd.com>.
 dnl Require autoconf version >= 2.69
 AC_PREREQ([2.69])
 
-AC_INIT([libsndfile],[1.1.0],[sndfile@mega-nerd.com],
+AC_INIT([libsndfile],[1.2.0],[sndfile@mega-nerd.com],
                [libsndfile],[http://libsndfile.github.io/libsndfile/])
 
 dnl Check whether we want to set defaults for CFLAGS, CXXFLAGS, CPPFLAGS and LDFLAGS
@@ -88,7 +88,7 @@ dnl      to 0.
 dnl   This is libtool version of library, we add it to `--version-info` property.
 
 m4_define([lt_current], [1])
-m4_define([lt_revision], [34])
+m4_define([lt_revision], [35])
 m4_define([lt_age], [0])
 
 dnl This is ABI version for linker scripts, CMake uses the same format for
@@ -171,10 +171,8 @@ AC_ARG_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"])
+       [AS_HELP_STRING([--enable-ossfuzzers], [Whether to generate the fuzzers for OSS-Fuzz])])
+AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$enable_ossfuzzers" = "xyes"])
 
 AC_SUBST([LIB_FUZZING_ENGINE])
 AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
@@ -194,12 +192,6 @@ 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])
 
@@ -209,25 +201,12 @@ AS_IF([test "x$enable_largefile:$ac_cv_sizeof_off_t" = "xno: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.])
                ],
 
-       [linux-android*], [
-               TYPEOF_SF_COUNT_T="int64_t"
-               SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
-               SIZEOF_SF_COUNT_T=8
-               ],
-
        [
-               SIZEOF_SF_COUNT_T=0
                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
                        ], [
                                dnl Save the old sizeof (off_t) value  and then unset it to see if it
                                dnl changes when Large File Support is enabled.
@@ -246,43 +225,9 @@ AS_CASE([$host_os],
                                        ])
 
                                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_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_SUBST(SF_COUNT_MAX)
-
 AC_TYPE_SSIZE_T
 
 dnl ====================================================================================
@@ -734,6 +679,7 @@ AC_SUBST(SNDIO_LIBS)
 AC_SUBST(EXTERNAL_XIPH_CFLAGS)
 AC_SUBST(EXTERNAL_XIPH_LIBS)
 AC_SUBST(EXTERNAL_XIPH_REQUIRE)
+AC_SUBST(EXTERNAL_MPEG_LIBS)
 AC_SUBST(EXTERNAL_MPEG_REQUIRE)
 AC_SUBST(MPG123_CFLAGS)
 AC_SUBST(MPG123_LIBS)
@@ -744,7 +690,7 @@ AC_SUBST(TEST_BINDIR)
 
 AC_CONFIG_FILES([
        Makefile Octave/Makefile
-       src/version-metadata.rc include/sndfile.h
+       src/version-metadata.rc
        tests/test_wrapper.sh tests/pedantic-header-test.sh
        libsndfile.spec sndfile.pc
        Scripts/build-test-tarball.mk
index 7025443..047fb4a 100644 (file)
@@ -97,10 +97,9 @@ 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.
 
-**Note:** The libsndfile library will reject values â€‹â€‹for **samplerate** field
-that are greater than `655350` and values â€‹â€‹for field **channels** that are
-greater than `1024`. These values â€‹â€‹represent the maximum theoretical limit and
-may be less for specific formats.
+**Note:** The libsndfile library will reject values â€‹â€‹for field **channels** that
+are greater than `1024`. These value â€‹â€‹represent the maximum theoretical limit
+and may be less for specific formats.
 
 When opening a file for write, the caller must fill in structure members
 **samplerate**, **channels**, and **format**.
index 6d2133a..b5a76f6 100644 (file)
@@ -64,6 +64,7 @@ The available commands are as follows:
 | [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_GET_OGG_STREAM_SERIALNO](#sfc_get_ogg_stream_serialno)       | Get Ogg stream serial number.                           |
 | [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.                           |
@@ -81,8 +82,8 @@ The available commands are as follows:
 | [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_BITRATE_MODE](#sfc_get_bitrate_mode)                     | Get bitrate mode.
-| [SFC_SET_BITRATE_MODE](#sfc_set_bitrate_mode)                     | Set bitrate mode.
+| [SFC_GET_BITRATE_MODE](#sfc_get_bitrate_mode)                     | Get bitrate mode.                                       |
+| [SFC_SET_BITRATE_MODE](#sfc_set_bitrate_mode)                     | Set bitrate mode.                                       |
 
 ---
 
@@ -1273,6 +1274,30 @@ datasize
 
 0 on success and non-zero otherwise.
 
+## SFC_GET_OGG_STREAM_SERIALNO
+
+Get the Ogg stream serial number for files with the Ogg major format. Ogg
+stream serail numbers are a randomly chosen 32-bit value, used for
+differentiating logical Ogg streams.
+
+### Parameters
+
+sndfile
+: A valid SNDFILE* pointer
+
+cmd
+: SFC_SET_OGG_STREAM_SERIALNO
+
+data
+: A pointer to a 32-bit int value
+
+datasize
+: sizeof (int32_t) = 4
+
+### 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
index 0585394..bb42208 100644 (file)
@@ -55,7 +55,7 @@ to disable gcc optimisations and make debugging with gdb/ddd easier.
 
 Add a unique identifier for the new file type.
 
-Edit src/sndfile.h.in and find the enum containing the SF_FORMAT_XXX identifiers.
+Edit src/sndfile.h and find the enum containing the SF_FORMAT_XXX identifiers.
 Since you will be adding a major file type you should add your identifier to the
 top part of the list where the values are above 0x10000 in value. The easiest
 way to do this is to find the largest value in the list, add 0x10000 to it and
similarity index 99%
rename from include/sndfile.h.in
rename to include/sndfile.h
index 2bcbdb1..ed99208 100644 (file)
@@ -220,8 +220,11 @@ enum
 
        SFC_SET_VBR_ENCODING_QUALITY    = 0x1300,
        SFC_SET_COMPRESSION_LEVEL               = 0x1301,
+
+       /* Ogg format commands */
        SFC_SET_OGG_PAGE_LATENCY_MS             = 0x1302,
        SFC_SET_OGG_PAGE_LATENCY                = 0x1303,
+       SFC_GET_OGG_STREAM_SERIALNO             = 0x1306,
 
        SFC_GET_BITRATE_MODE                    = 0x1304,
        SFC_SET_BITRATE_MODE                    = 0x1305,
@@ -362,9 +365,9 @@ typedef     struct sf_private_tag   SNDFILE ;
 ** and the Microsoft compiler.
 */
 
-typedef @TYPEOF_SF_COUNT_T@    sf_count_t ;
+typedef int64_t                        sf_count_t ;
 #ifndef SF_COUNT_MAX
-#define SF_COUNT_MAX           @SF_COUNT_MAX@
+#define SF_COUNT_MAX   INT64_MAX
 #endif
 
 
index a4d98d9..7b3666f 100755 (executable)
@@ -23,7 +23,7 @@ apt-get -y install autoconf autogen automake libtool pkg-config python
 # libasound2-dev libflac-dev libogg-dev libopus-dev libvorbis-dev
 
 # Compile the fuzzer.
-./autogen.sh
+autoreconf -vif
 ./configure --disable-shared --enable-ossfuzzers
 make V=1
 
index 63a6f4a..a047201 100644 (file)
@@ -1,6 +1,6 @@
 %define __spec_check_pre exit 0
 Name:           libsndfile
-Version:        1.1.0
+Version:        1.2.0
 Release:        0
 License:        LGPL-2.1+
 Summary:        C library for reading and writing sound files
index df42d18..38920b2 100644 (file)
@@ -398,7 +398,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
        char            *cptr ;
        int                     instr_found = 0, mark_found = 0 ;
 
-       if (psf->filelength > SF_PLATFORM_S64 (0xffffffff))
+       if (psf->filelength > 0xFFFFFFFFLL)
                psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
 
        if ((paiff = psf->container_data) == NULL)
index c4ef4a6..b58c9db 100644 (file)
@@ -375,7 +375,7 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
                                        strptr = istr ;
                                        while (*strptr)
                                        {       c = *strptr++ ;
-                                               log_putchar (psf, c) ;
+                                               log_putchar (psf, psf_isprint (c) ? c : '.') ;
                                                } ;
                                        break ;
 
@@ -540,8 +540,6 @@ header_put_le_int (SF_PRIVATE *psf, int x)
        psf->header.ptr [psf->header.indx++] = (x >> 24) ;
 } /* header_put_le_int */
 
-#if (SIZEOF_SF_COUNT_T == 8)
-
 static inline void
 header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x)
 {      psf->header.ptr [psf->header.indx++] = (x >> 56) ;
@@ -566,10 +564,6 @@ header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
        psf->header.ptr [psf->header.indx++] = (x >> 56) ;
 } /* header_put_le_8byte */
 
-#else
-#error "SIZEOF_SF_COUNT_T != 8"
-#endif
-
 int
 psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
 {      va_list argptr ;
@@ -925,8 +919,22 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
 
                        if (psf->header.indx + position > psf->header.len)
                        {       /* Need to jump this without caching it. */
+                               position -= (psf->header.end - psf->header.indx) ;
                                psf->header.indx = psf->header.end ;
-                               psf_fseek (psf, position, SEEK_CUR) ;
+                               if (psf->is_pipe)
+                               {
+                                       /* seeking is not supported on pipe input, so we read instead */
+                                       size_t skip = position ;
+                                       while (skip)
+                                       {       char junk [16 * 1024] ;
+                                               size_t to_skip = SF_MIN (skip, sizeof (junk)) ;
+                                               psf_fread (junk, 1, to_skip, psf) ;
+                                               skip -= to_skip ;
+                                               }
+                                       }
+                               else
+                               {       psf_fseek (psf, position, SEEK_CUR) ;
+                                       }
                                break ;
                                } ;
 
@@ -1684,18 +1692,14 @@ psf_f2s_clip_array (const float *src, short *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFF))
                {       dest [i] = 0x7FFF ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x1000))
                {       dest [i] = -0x7FFF - 1 ;
                        continue ;
                        } ;
-#endif
 
                dest [i] = psf_lrintf (scaled_value) ;
                } ;
@@ -1722,18 +1726,14 @@ psf_d2s_clip_array (const double *src, short *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFF))
                {       dest [i] = 0x7FFF ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x1000))
                {       dest [i] = -0x7FFF - 1 ;
                        continue ;
                        } ;
-#endif
 
                dest [i] = psf_lrint (scaled_value) ;
                } ;
index cf2dc5f..d79f34a 100644 (file)
 #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)
-#elif (SIZEOF_LONG == 8)
-#      define  SF_PLATFORM_S64(x)              x##l
-#elif (SIZEOF_LONG_LONG == 8)
-#      define  SF_PLATFORM_S64(x)              x##ll
-#elif COMPILER_IS_GCC
-#      define  SF_PLATFORM_S64(x)              x##ll
-#elif OS_IS_WIN32
-#      define  SF_PLATFORM_S64(x)              x##I64
-#else
-#      error "Don't know how to define a 64 bit integer constant."
-#endif
-
 
 
 /*
 
 
 #define                SF_MAX_CHANNELS         1024
-/* Max FLAC sample rate : https://xiph.org/flac/format.html */
-#define                SF_MAX_SAMPLERATE       655350
-
 
 /*
 *      Macros for spliting the format file of SF_INFO into container type,
index 2872e7d..71fdb4f 100644 (file)
 /* 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 `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 `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
index df49a8f..0c79cd5 100644 (file)
@@ -496,9 +496,9 @@ d2s_clip_array (const double *src, int count, short *dest, double scale)
 {      for (int i = 0 ; i < count ; i++)
        {       double tmp = scale * src [i] ;
 
-               if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
+               if (tmp > 32767.0)
                        dest [i] = SHRT_MAX ;
-               else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
+               else if (tmp < -32768.0)
                        dest [i] = SHRT_MIN ;
                else
                        dest [i] = psf_lrint (tmp) ;
index 334ba2a..b7f7ed7 100644 (file)
@@ -505,7 +505,7 @@ psf_is_pipe (SF_PRIVATE *psf)
 static sf_count_t
 psf_get_filelen_fd (int fd)
 {
-#if (SIZEOF_OFF_T == 4 && SIZEOF_SF_COUNT_T == 8 && HAVE_FSTAT64)
+#if (SIZEOF_OFF_T == 4 && HAVE_FSTAT64)
        struct stat64 statbuf ;
 
        if (fstat64 (fd, &statbuf) == -1)
@@ -827,9 +827,6 @@ psf_open_handle (PSF_FILE * pfile)
                } ;
 
 #if defined (WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
-       if (!pfile->use_wchar)
-               return INVALID_HANDLE_VALUE ;
-
        CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ;
        cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ;
        cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ;
index 8bfa30f..6db7d3c 100644 (file)
 
 #define ENC_BUFFER_SIZE 8192
 
+/*
+** READ_LOOP_MAX_LEN is the maximum 'len' that will be passed to
+** flac_read_loop().  This is somewhat arbitrary, but must be less
+** than (UINT_MAX - FLAC__MAX_CHANNELS * FLAC__MAX_BLOCK_SIZE) to
+** avoid overflows, and must also be a multiple of the number of
+** channels (which is between 1 and 8.)
+*/
+#define READ_LOOP_MAX_LEN (0x10000 * 3 * 5 * 7)
+
 typedef enum
 {      PFLAC_PCM_SHORT = 50,
        PFLAC_PCM_INT = 51,
@@ -977,7 +986,7 @@ flac_read_flac2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
 
        while (total < len)
        {       pflac->ptr = ptr + total ;
-               readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
+               readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
                current = flac_read_loop (psf, readlen) ;
                if (current == 0)
                        break ;
@@ -997,7 +1006,7 @@ flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
 
        while (total < len)
        {       pflac->ptr = ptr + total ;
-               readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
+               readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
                current = flac_read_loop (psf, readlen) ;
                if (current == 0)
                        break ;
@@ -1017,7 +1026,7 @@ flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
 
        while (total < len)
        {       pflac->ptr = ptr + total ;
-               readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
+               readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
                current = flac_read_loop (psf, readlen) ;
                if (current == 0)
                        break ;
@@ -1037,7 +1046,7 @@ flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
 
        while (total < len)
        {       pflac->ptr = ptr + total ;
-               readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
+               readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
 
                current = flac_read_loop (psf, readlen) ;
                if (current == 0)
@@ -1182,11 +1191,11 @@ f2flac8_clip_array (const float *src, int32_t *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-               if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F))
+               if (scaled_value >= (1.0 * 0x7F))
                {       dest [i] = 0x7F ;
                        continue ;
                        } ;
-               if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10))
+               if (scaled_value <= (-8.0 * 0x10))
                {       dest [i] = -0x80 ;
                        continue ;
                        } ;
@@ -1204,11 +1213,11 @@ f2flac16_clip_array (const float *src, int32_t *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-               if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
+               if (scaled_value >= (1.0 * 0x7FFF))
                {       dest [i] = 0x7FFF ;
                        continue ;
                        } ;
-               if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
+               if (scaled_value <= (-8.0 * 0x1000))
                {       dest [i] = -0x8000 ;
                        continue ;
                        } ;
@@ -1224,12 +1233,12 @@ f2flac24_clip_array (const float *src, int32_t *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-               if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF))
+               if (scaled_value >= (1.0 * 0x7FFFFF))
                {       dest [i] = 0x7FFFFF ;
                        continue ;
                        } ;
 
-               if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000))
+               if (scaled_value <= (-8.0 * 0x100000))
                {       dest [i] = -0x800000 ;
                        continue ;
                        }
@@ -1313,11 +1322,11 @@ d2flac8_clip_array (const double *src, int32_t *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-               if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F))
+               if (scaled_value >= (1.0 * 0x7F))
                {       dest [i] = 0x7F ;
                        continue ;
                        } ;
-               if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10))
+               if (scaled_value <= (-8.0 * 0x10))
                {       dest [i] = -0x80 ;
                        continue ;
                        } ;
@@ -1335,11 +1344,11 @@ d2flac16_clip_array (const double *src, int32_t *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-               if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
+               if (scaled_value >= (1.0 * 0x7FFF))
                {       dest [i] = 0x7FFF ;
                        continue ;
                        } ;
-               if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
+               if (scaled_value <= (-8.0 * 0x1000))
                {       dest [i] = -0x8000 ;
                        continue ;
                        } ;
@@ -1357,11 +1366,11 @@ d2flac24_clip_array (const double *src, int32_t *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-               if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF))
+               if (scaled_value >= (1.0 * 0x7FFFFF))
                {       dest [i] = 0x7FFFFF ;
                        continue ;
                        } ;
-               if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000))
+               if (scaled_value <= (-8.0 * 0x100000))
                {       dest [i] = -0x800000 ;
                        continue ;
                        } ;
index 2e4d444..431e39b 100644 (file)
@@ -447,9 +447,9 @@ f2s_clip_array (const float *src, int count, short *dest, float scale)
 {      for (int i = 0 ; i < count ; i++)
        {       float tmp = scale * src [i] ;
 
-               if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
+               if (tmp > 32767.0)
                        dest [i] = SHRT_MAX ;
-               else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
+               else if (tmp < -32768.0)
                        dest [i] = SHRT_MIN ;
                else
                        dest [i] = psf_lrintf (tmp) ;
index 8698ebf..62e4005 100644 (file)
@@ -141,7 +141,7 @@ g72x_init (SF_PRIVATE * psf)
                else
                        pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
 
-               psf->sf.frames = pg72x->blocks_total * pg72x->samplesperblock ;
+               psf->sf.frames = (sf_count_t) pg72x->blocks_total * pg72x->samplesperblock ;
 
                psf_g72x_decode_block (psf, pg72x) ;
                }
index 77d4f1f..933f03f 100644 (file)
@@ -150,7 +150,7 @@ Need separate gsm_data structs for encode and decode.
                        pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
                        } ;
 
-               psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
+               psf->sf.frames = (sf_count_t) pgsm610->samplesperblock * pgsm610->blocks ;
 
                psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
 
index 20fac4f..582c5e1 100644 (file)
@@ -91,12 +91,9 @@ mpeg_dec_decode (SF_PRIVATE *psf, float *ptr, sf_count_t len)
 
        error = mpg123_read (pmp3d->pmh, (unsigned char *) ptr, len * sizeof (float), &done) ;
 
-       if (error == MPG123_OK)
+       if (error == MPG123_OK || error == MPG123_DONE)
                return done / sizeof (float) ;
 
-       if (error == MPG123_DONE)
-               return 0 ;
-
        if (error == MPG123_NEW_FORMAT)
        {       psf->error = SFE_MALFORMED_FILE ;
                return -1 ;
index 7a4a167..f3e92e1 100644 (file)
--- a/src/ogg.c
+++ b/src/ogg.c
@@ -165,6 +165,8 @@ ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
                return SFE_NOT_SEEKABLE ;
 
        buffer = ogg_sync_buffer (&odata->osync, psf->header.indx) ;
+       if (buffer == NULL)
+               return SFE_MALLOC_FAILED ;
        memcpy (buffer, psf->header.ptr, psf->header.indx) ;
        ogg_sync_wrote (&odata->osync, psf->header.indx) ;
 
@@ -297,6 +299,10 @@ ogg_sync_next_page (SF_PRIVATE * psf, ogg_page *og, sf_count_t readmax, sf_count
                else
                        nb_read = OGG_SYNC_READ_SIZE ;
                buffer = (unsigned char *) ogg_sync_buffer (&odata->osync, nb_read) ;
+               if (buffer == NULL)
+               {       psf->error = SFE_MALLOC_FAILED ;
+                       return -1 ;
+                       }
                read_ret = psf_fread (buffer, 1, nb_read, psf) ;
                if (read_ret == 0)
                        return psf->error ? -1 : 0 ;
@@ -447,7 +453,9 @@ ogg_sync_last_page_before (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t *gp_out
 } /* 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_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, uint64_t gp_rate)
 {      ogg_page page ;
        uint64_t gp ;
        sf_count_t d0, d1, d2 ;
@@ -614,7 +622,7 @@ ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t targe
                                if (buffering)
                                        ogg_stream_reset (&odata->ostream) ;
                                /* Check to see if the last packet continues. */
-                               if (page.header [27 + page.header [26] - 1] == 255)
+                               if (ogg_page_continues (&page))
                                {       ogg_page_search_continued_data (odata, &page) ;
                                        /*
                                        ** If we have a continued packet, remember the offset of
@@ -624,15 +632,15 @@ ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t targe
                                        ** 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 ;
+                                       /*
+                                       ** 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)
+                               if (target_gp - gp > gp_rate)
                                {       /* Out by over a second. Try another bisection. */
                                        break ;
                                        }
index 5c837a8..8b2927a 100644 (file)
--- a/src/ogg.h
+++ b/src/ogg.h
@@ -57,7 +57,36 @@ typedef struct
                                                                ((buf [base + 2] <<16) & 0xff0000) | \
                                                                ((buf [base + 1] << 8) & 0xff00) | \
                                                                (buf [base] & 0xff))
+/*-----------------------------------------------------------------------------------------------
+** Inline functions.
+*/
+
+/*
+** LibOgg documentation is noted as being bad by it's author.
+** Add some useful utility inline functions for introspecting Ogg pages.
+*/
+
+/* ogg_page_segments returns how many segments are in this page. */
+static inline int
+ogg_page_segments (ogg_page *pg)
+{      return (int) (pg->header [26]) ; }
 
+/* ogg_page_continues returns true if this page ends in a continued packet. */
+static inline int
+ogg_page_continues (ogg_page *pg)
+{      return pg->header [27 + pg->header [26] - 1] == 255 ;
+}
+
+/*-----------------------------------------------------------------------------------------------
+** Exported functions.
+*/
+
+/*
+** ogg_read_first_page loads the first Ogg page found in the file, and sets the
+** OGG_PRIVATE serialno to match the logical stream of the page. Data is read
+** without seeking backwards, loading any data present from psf->header into
+** the ogg_sync state first, so that this function works with pipes.
+*/
 int    ogg_read_first_page     (SF_PRIVATE *, OGG_PRIVATE *) ;
 
 /*
@@ -125,10 +154,16 @@ int ogg_stream_unpack_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) ;
 ** 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.
+** lowest granule positions of the file. begin and end are the file offset
+** range to search. gp_rate is an information hint so granule positions can
+** be correlated to playback time, so the search can figure out how close it
+** is, should be granule positions per second.
 */
 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) ;
+                                                               uint64_t target_gp,
+                                                               uint64_t pcm_start, uint64_t pcm_end,
+                                                               uint64_t *best_gp,
+                                                               sf_count_t begin, sf_count_t end,
+                                                               uint64_t gp_rate) ;
 
 #endif /* SF_SRC_OGG_H */
index dfa446e..c938362 100644 (file)
 #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
+** When encoding, we can choose the size of the Opus frames.
+** Valid values are 2.5, 5, 10, 20, 40, and 60 milliseconds.
+**
+** Frames smaller than 10ms can't use CELT (MDCT) mode.
+** Frames larger than 20ms "are only interesting at fairly low bitrates."
+**
+** We choose the suggested default of 20ms for high-fidelity audio, however,
+** maybe this could be user-selected, or triggered by bitrate command.
 ** 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.
+** The pre-roll is how long it takes for the decoder to converge. It converges
+** pretty quickly, to within -40db within 80ms. However, this also depends on
+** the signal. From experimentation, use the conservative pre-roll amount of
+** 660ms after which the output is 32-bit-exact with high probability.
 */
-#define OGG_OPUS_PREROLL (80 * 48) /* 80 milliseconds */
+#define OGG_OPUS_PREROLL (660 * 48) /* 660 milliseconds (33 packets of 20ms) */
 
 typedef struct
 {      uint8_t version ;
@@ -215,10 +225,12 @@ typedef struct
 {      uint32_t serialno ;
        OpusHeader header ;
 
-       /* Granule position before the current packet */
+       /* Encode: Granule position after the previous packet.
+        * Decode: Granule position after the current packet */
        uint64_t pkt_pos ;
 
-       /* Granule position at the end of the current page (encode: last completed) */
+       /* Encode: Granule position at the end of the previous page.
+        * Decode: Granule position at the end of the current page. */
        uint64_t pg_pos ;
 
        /* integer coefficient of (current sample rate) / 48000Hz */
@@ -291,9 +303,9 @@ static sf_count_t   ogg_opus_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_
 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 sf_count_t      ogg_opus_null_read (SF_PRIVATE *psf, sf_count_t offset) ;
+static sf_count_t      ogg_opus_page_seek_manual (SF_PRIVATE *psf, uint64_t target_gp) ;
+static int                     ogg_opus_page_seek_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) ;
@@ -409,27 +421,27 @@ ogg_opus_close (SF_PRIVATE *psf)
 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, "  OggOpus version  : %d\n", (int) h->version) ;
+       psf_log_printf (psf, "  Channels         : %d\n", (int) h->channels) ;
+       psf_log_printf (psf, "  Preskip          : %d samples @48kHz\n", (int) h->preskip) ;
+       psf_log_printf (psf, "  Input Samplerate : %d Hz\n", (int) h->input_samplerate) ;
+       psf_log_printf (psf, "  Gain             : %d.%d\n", (int) 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 ;
+               default :       psf_log_printf (psf, "%d (unknown or unsupported)\n", (int) 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, "   streams total   : %d\n", (int) h->nb_streams) ;
+               psf_log_printf (psf, "   streams coupled : %d\n", (int) 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]) ;
+                       psf_log_printf (psf, "%d,", (int) (h->stream_map [i])) ;
+               psf_log_printf (psf, "%d]\n", (int) (h->stream_map [i])) ;
                } ;
 } /* opus_print_header */
 
@@ -458,7 +470,7 @@ opus_read_header_packet (SF_PRIVATE *psf, OpusHeader *h, ogg_packet *opacket)
 
        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) ;
+       {       psf_log_printf (psf, "Opus : Unknown / unsupported embedding scheme version: %d.\n", (int) h->version) ;
                return SFE_UNIMPLEMENTED ;
                } ;
 
@@ -955,8 +967,8 @@ ogg_opus_unpack_next_page (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oo
                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) ;
+               psf_log_printf (psf, "Opus : Hole found appears to be of length %D samples.\n",
+                               (oopus->pkt_pos - last_page) / (uint64_t) 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
@@ -1050,7 +1062,7 @@ ogg_opus_read_refill (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
                        **      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_log_printf (psf, "Opus : Mid-stream 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 ;
                        } ;
@@ -1118,11 +1130,7 @@ ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
                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->u.encode.last_segments -= ogg_page_segments (&odata->opage) ;
                        oopus->pg_pos = oopus->pkt_pos ;
                        ogg_write_page (psf, &odata->opage) ;
                        }
@@ -1467,7 +1475,12 @@ ogg_opus_analyze_file (SF_PRIVATE *psf)
                {       psf->sf.frames = (oopus->u.decode.gp_end - oopus->u.decode.gp_start
                                - oopus->header.preskip) / oopus->sr_factor ;
                        } ;
-       }
+               } ;
+
+
+       psf_log_printf (psf, "  Granule pos offset  : %D\n", oopus->u.decode.gp_start) ;
+       if (oopus->u.decode.gp_end != (uint64_t) -1)
+               psf_log_printf (psf, "  Last Granule pos : %D\n", oopus->u.decode.gp_end) ;
 
        /* Go back to where we left off. */
        ogg_sync_fseek (psf, saved_offset, SEEK_SET) ;
@@ -1475,23 +1488,25 @@ ogg_opus_analyze_file (SF_PRIVATE *psf)
 } /* ogg_opus_analyze_file */
 
 /*
-** ogg_opus_seek_null_read
+** ogg_opus_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_opus_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 ;
 
+       total = (oopus->pkt_pos / oopus->sr_factor) - (oopus->len - oopus->loc) ;
        for ( ; total < offset ; )
-       {       if (oopus->loc == oopus->len)
+       {       sf_count_t readlen = SF_MIN ((int) (offset - total), (oopus->len - oopus->loc)) ;
+               if (readlen > 0)
+               {       total += readlen ;
+                       oopus->loc += readlen ;
+                       } ;
+               if (oopus->loc == oopus->len)
                {       if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
                                return total ;
                        /*
@@ -1500,22 +1515,18 @@ ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset)
                        */
                        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 */
+} /* ogg_opus_null_read */
 
 /*
+** ogg_opus_page_seek_search
+**
 ** 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_opus_page_seek_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 ;
@@ -1523,49 +1534,48 @@ ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp)
        uint64_t best_gp ;
        sf_count_t begin ;
        sf_count_t end ;
+       sf_count_t old_pos ;
        int ret ;
 
        best_gp = pcm_start = oopus->u.decode.gp_start ;
        pcm_end = oopus->u.decode.gp_end ;
        begin = psf->dataoffset ;
+       end = oopus->u.decode.last_offset ;
 
-       /* 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) ;
+       /* Search the Ogg stream for such a page */
+       old_pos = ogg_sync_ftell (psf) ;
+       ret = ogg_stream_seek_page_search (psf, odata, target_gp, pcm_start, pcm_end, &best_gp, begin, end, 48000) ;
+       if (ret != 0)
+       {       ogg_sync_fseek (psf, old_pos, SEEK_SET) ;
+               return ret ;
+               } ;
 
+       /* Load the page that contains our pre-roll target */
        oopus->loc = 0 ;
        oopus->len = 0 ;
        if ((ret = ogg_opus_unpack_next_page (psf, odata, oopus)) != 1)
                return ret ;
        oopus->pkt_pos = best_gp ;
+
+       /* Reset the decoder (gain settings survive the reset) */
        opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_RESET_STATE) ;
-       /* Gain decoder settings survive resets. */
 
        return 0 ;
-} /* ogg_opus_seek_page_search */
+} /* ogg_opus_page_seek_search */
 
+/*
+** ogg_opus_page_seek_manual
+**
+** Seek to the beginning of the Ogg stream and read pages until we find one with
+** a granule position at or before our target.
+*/
 static sf_count_t
-ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp)
+ogg_opus_page_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) ;
@@ -1582,13 +1592,13 @@ ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp)
                } ;
 
        return 1 ;
-} /* ogg_opus_seek_manual */
+} /* ogg_opus_page_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 ;
+{      OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+       OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
+       uint64_t target_gp, current_gp ;
        int ret ;
 
        /* Only support seeking in read mode. */
@@ -1597,28 +1607,40 @@ ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
                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 ;
+       /* Figure out the current position granule pos. Use the start of the
+        * current buffer, to avoid backwards seeking if the target is on the page
+        * but before the current locaiton. */
+       oopus->loc = 0 ;
+       current_gp = oopus->pkt_pos - (uint64_t) (oopus->len * oopus->sr_factor) ;
+
+       /* Calculate the target granule pos. This includes the decoder delay and
+        * the file granule position offset. */
+       target_gp = offset * oopus->sr_factor ;
+       target_gp += oopus->u.decode.gp_start ;
+       target_gp += oopus->header.preskip ;
+
+       /* Check if we need to do a page seek. */
+       if (target_gp < current_gp || target_gp - current_gp > OGG_OPUS_PREROLL)
+       {       uint64_t preroll_gp ;
+
+               /* For a page seek, use an earlier target granule pos, giving the
+                * decoder samples to converge before the actual target. */
+               if (target_gp >= OGG_OPUS_PREROLL + oopus->u.decode.gp_start + (uint64_t) oopus->header.preskip)
+               {       preroll_gp = target_gp - OGG_OPUS_PREROLL ;
+                       }
+               else
+               {       preroll_gp = oopus->u.decode.gp_start + (uint64_t) 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 (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_page_seek_manual (psf, preroll_gp) ;
+                       }
+               else
+               {       ret = ogg_opus_page_seek_search (psf, preroll_gp) ;
                        if (ret < 0)
                        {       /*
                                ** Page seek failed, what to do? Could be bad data. We can
@@ -1626,7 +1648,7 @@ ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
                                ** from the beginning has the advantage of finding where the
                                ** file goes bad.
                                */
-                               ret = ogg_opus_seek_manual (psf, target_gp) ;
+                               ret = ogg_opus_page_seek_manual (psf, preroll_gp) ;
                                if (ret < 0)
                                {       /*
                                        ** If were here, and there is no error, we can be pretty
@@ -1638,13 +1660,29 @@ ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
                                        } ;
                                } ;
                        } ;
+
+               /*
+               ** Skip over packets on the found page that are before our pre-roll
+               ** target to avoid unnecessary decoding, and make decoder convergence
+               ** independent of page boundaries for more visible errors.
+               */
+               for ( ; odata->pkt_indx != odata->pkt_len ; )
+               {       ogg_packet *ppkt = &odata->pkt [odata->pkt_indx] ;
+                       int nsamp = opus_packet_get_nb_samples (ppkt->packet, ppkt->bytes, 48000) ;
+                       if (oopus->pkt_pos + nsamp < preroll_gp)
+                       {       oopus->pkt_pos += nsamp ;
+                               odata->pkt_indx++ ;
+                               }
+                       else
+                               break ;
+                       } ;
                } ;
 
        /*
        ** 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) ;
+       offset = ogg_opus_null_read (psf, target_gp / oopus->sr_factor) ;
        return offset - ((oopus->header.preskip + oopus->u.decode.gp_start) / oopus->sr_factor) ;
 
 } /* ogg_opus_seek */
@@ -1733,6 +1771,13 @@ ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize)
                        *((int *) data) = oopus->header.input_samplerate ;
                        return SF_TRUE ;
 
+               case SFC_GET_OGG_STREAM_SERIALNO :
+                       if (data == NULL || datasize != sizeof (int32_t))
+                               return SF_FALSE ;
+
+                       *((int32_t *) data) = odata->ostream.serialno ;
+                       return SF_TRUE ;
+
                default :
                        break ;
        }
index fb826ed..dec4a25 100644 (file)
@@ -274,9 +274,9 @@ vorbis_read_header (SF_PRIVATE *psf)
                ogg_sync_fseek (psf, saved_offset, SEEK_SET) ;
                }
 
-       psf_log_printf (psf, "PCM offset  : %d\n", vdata->pcm_start) ;
+       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) ;
+               psf_log_printf (psf, "PCM end     : %D\n", vdata->pcm_end) ;
        else
                psf_log_printf (psf, "PCM end     : unknown\n") ;
 
@@ -567,7 +567,8 @@ ogg_vorbis_open (SF_PRIVATE *psf)
 
 static int
 vorbis_command (SF_PRIVATE *psf, int command, void * data, int datasize)
-{      VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+{      OGG_PRIVATE* odata = psf->container_data ;
+       VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
 
        switch (command)
        {       case SFC_SET_COMPRESSION_LEVEL :
@@ -585,6 +586,13 @@ vorbis_command (SF_PRIVATE *psf, int command, void * data, int datasize)
                        psf_log_printf (psf, "%s : Setting SFC_SET_VBR_ENCODING_QUALITY to %f.\n", __func__, vdata->quality) ;
                        return SF_TRUE ;
 
+               case SFC_GET_OGG_STREAM_SERIALNO :
+                       if (data == NULL || datasize != sizeof (int32_t))
+                               return SF_FALSE ;
+
+                       *((int32_t *) data) = odata->ostream.serialno ;
+                       return SF_TRUE ;
+
                default :
                        return SF_FALSE ;
                } ;
@@ -947,7 +955,7 @@ vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp)
        search_target_gp = search_target_gp < target_gp ? target_gp - search_target_gp : 0 ;
 
        ret = ogg_stream_seek_page_search (psf, odata, search_target_gp, vdata->pcm_start,
-                       vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page) ;
+                       vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page, vdata->vinfo.rate) ;
        if (ret < 0)
                return ret ;
 
index 7e5fdf6..d7dc82c 100644 (file)
--- a/src/pcm.c
+++ b/src/pcm.c
@@ -1786,18 +1786,14 @@ f2sc_clip_array (const float *src, signed char *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       dest [i] = 127 ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       dest [i] = -128 ;
                        continue ;
                        } ;
-#endif
 
                dest [i] = psf_lrintf (scaled_value) >> 24 ;
                } ;
@@ -1849,18 +1845,14 @@ f2uc_clip_array (const float *src, unsigned char *dest, int count, int normalize
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       dest [i] = 0xFF ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       dest [i] = 0 ;
                        continue ;
                        } ;
-#endif
 
                dest [i] = (psf_lrintf (scaled_value) >> 24) + 128 ;
                } ;
@@ -1920,20 +1912,16 @@ f2bes_clip_array (const float *src, short *dest, int count, int normalize)
        for (int i = 0 ; i < count ; i++)
        {       ucptr = (unsigned char*) &dest [i] ;
                scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       ucptr [1] = 0xFF ;
                        ucptr [0] = 0x7F ;
                        continue ;
                } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       ucptr [1] = 0x00 ;
                        ucptr [0] = 0x80 ;
                        continue ;
                        } ;
-#endif
 
                value = psf_lrintf (scaled_value) ;
                ucptr [1] = value >> 16 ;
@@ -1995,20 +1983,16 @@ f2les_clip_array (const float *src, short *dest, int count, int normalize)
        for (int i = 0 ; i < count ; i++)
        {       ucptr = (unsigned char*) &dest [i] ;
                scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       ucptr [0] = 0xFF ;
                        ucptr [1] = 0x7F ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       ucptr [0] = 0x00 ;
                        ucptr [1] = 0x80 ;
                        continue ;
                        } ;
-#endif
 
                value = psf_lrintf (scaled_value) ;
                ucptr [0] = value >> 16 ;
@@ -2378,18 +2362,14 @@ d2sc_clip_array (const double *src, signed char *dest, int count, int normalize)
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       dest [i] = 127 ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       dest [i] = -128 ;
                        continue ;
                        } ;
-#endif
 
                dest [i] = psf_lrintf (scaled_value) >> 24 ;
                } ;
@@ -2441,18 +2421,14 @@ d2uc_clip_array (const double *src, unsigned char *dest, int count, int normaliz
 
        for (int i = 0 ; i < count ; i++)
        {       scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       dest [i] = 255 ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       dest [i] = 0 ;
                        continue ;
                        } ;
-#endif
 
                dest [i] = (psf_lrint (src [i] * normfact) >> 24) + 128 ;
                } ;
@@ -2512,20 +2488,16 @@ d2bes_clip_array (const double *src, short *dest, int count, int normalize)
        for (int i = 0 ; i < count ; i++)
        {       ucptr = (unsigned char*) &dest [i] ;
                scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       ucptr [1] = 0xFF ;
                        ucptr [0] = 0x7F ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       ucptr [1] = 0x00 ;
                        ucptr [0] = 0x80 ;
                        continue ;
                        } ;
-#endif
 
                value = psf_lrint (scaled_value) ;
                ucptr [1] = value >> 16 ;
@@ -2587,20 +2559,16 @@ d2les_clip_array (const double *src, short *dest, int count, int normalize)
        for (int i = 0 ; i < count ; i++)
        {       ucptr = (unsigned char*) &dest [i] ;
                scaled_value = src [i] * normfact ;
-#if CPU_CLIPS_POSITIVE == 0
                if (scaled_value >= (1.0 * 0x7FFFFFFF))
                {       ucptr [0] = 0xFF ;
                        ucptr [1] = 0x7F ;
                        continue ;
                        } ;
-#endif
-#if CPU_CLIPS_NEGATIVE == 0
                if (scaled_value <= (-8.0 * 0x10000000))
                {       ucptr [0] = 0x00 ;
                        ucptr [1] = 0x80 ;
                        continue ;
                        } ;
-#endif
 
                value = psf_lrint (scaled_value) ;
                ucptr [0] = value >> 16 ;
index 88d7e68..5ffb8f8 100644 (file)
@@ -2772,6 +2772,17 @@ format_from_extension (SF_PRIVATE *psf)
 } /* format_from_extension */
 
 static int
+identify_mpeg (uint32_t marker)
+{      if ((marker & MAKE_MARKER (0xFF, 0xE0, 0, 0)) == MAKE_MARKER (0xFF, 0xE0, 0, 0) && /* Frame sync */
+               (marker & MAKE_MARKER (0, 0x18, 0, 0)) != MAKE_MARKER (0, 0x08, 0, 0) && /* Valid MPEG version */
+               (marker & MAKE_MARKER (0, 0x06, 0, 0)) != MAKE_MARKER (0, 0, 0, 0) && /* Valid layer description */
+               (marker & MAKE_MARKER (0, 0, 0xF0, 0)) != MAKE_MARKER (0, 0, 0xF0, 0) && /* Valid bitrate */
+               (marker & MAKE_MARKER (0, 0, 0x0C, 0)) != MAKE_MARKER (0, 0, 0x0C, 0)) /* Valid samplerate */
+               return SF_FORMAT_MPEG ;
+       return 0 ;
+} /* identify_mpeg */
+
+static int
 guess_file_type (SF_PRIVATE *psf)
 {      uint32_t buffer [3], format ;
 
@@ -2872,13 +2883,6 @@ retry:
        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 (0xFF, 0xE0, 0, 0)) == MAKE_MARKER (0xFF, 0xE0, 0, 0) && /* Frame sync */
-               (buffer [0] & MAKE_MARKER (0, 0x18, 0, 0)) != MAKE_MARKER (0, 0x08, 0, 0) && /* Valid MPEG version */
-               (buffer [0] & MAKE_MARKER (0, 0x06, 0, 0)) != MAKE_MARKER (0, 0, 0, 0) && /* Valid layer description */
-               (buffer [0] & MAKE_MARKER (0, 0, 0xF0, 0)) != MAKE_MARKER (0, 0, 0xF0, 0) && /* Valid bitrate */
-               (buffer [0] & MAKE_MARKER (0, 0, 0x0C, 0)) != MAKE_MARKER (0, 0, 0x0C, 0)) /* Valid samplerate */
-               return SF_FORMAT_MPEG ;
-
        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") ;
@@ -2887,6 +2891,10 @@ retry:
                return 0 ;
                } ;
 
+       /* ID3v2 tags + MPEG */
+       if (psf->id3_header.len > 0 && (format = identify_mpeg (buffer [0])) != 0)
+               return format ;
+
        /* Turtle Beach SMP 16-bit */
        if (buffer [0] == MAKE_MARKER ('S', 'O', 'U', 'N') && buffer [1] == MAKE_MARKER ('D', ' ', 'S', 'A'))
                return 0 ;
@@ -2898,17 +2906,23 @@ retry:
        if (buffer [0] == MAKE_MARKER ('a', 'j', 'k', 'g'))
                return 0 /*-SF_FORMAT_SHN-*/ ;
 
-       /* This must be the last one. */
+       /* This must be (almost) the last one. */
        if (psf->filelength > 0 && (format = try_resource_fork (psf)) != 0)
                return format ;
 
+       /* MPEG with no ID3v2 tags. Only have the MPEG sync header for
+        * identification and it is quite brief, and prone to false positives.
+        * Check for this last, even after resource forks. */
+       if (psf->id3_header.len == 0 && (format = identify_mpeg (buffer [0])) != 0)
+               return format ;
+
        return 0 ;
 } /* guess_file_type */
 
 
 static int
 validate_sfinfo (SF_INFO *sfinfo)
-{      if ((sfinfo->samplerate < 1) || (sfinfo->samplerate > SF_MAX_SAMPLERATE))
+{      if (sfinfo->samplerate < 1)
                return 0 ;
        if (sfinfo->frames < 0)
                return 0 ;
index a6b7232..342b006 100644 (file)
--- a/src/svx.c
+++ b/src/svx.c
@@ -134,7 +134,7 @@ svx_read_header     (SF_PRIVATE *psf)
        int                             filetype = 0, parsestage = 0, done = 0 ;
        int                     bytecount = 0, channels ;
 
-       if (psf->filelength > SF_PLATFORM_S64 (0xffffffff))
+       if (psf->filelength > 0xFFFFFFFFLL)
                psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
 
        memset (&vhdr, 0, sizeof (vhdr)) ;
index f6ee36e..f717fa5 100644 (file)
@@ -44,7 +44,7 @@ conversion_test (char endian)
 {
        SF_PRIVATE      sf_private, *psf ;
        const char * filename = "conversion.bin" ;
-       int64_t i64 = SF_PLATFORM_S64 (0x0123456789abcdef), t64 = 0 ;
+       int64_t i64 = 0x0123456789ABCDEFLL, t64 = 0 ;
        char format_str [16] ;
        char test_name [64] ;
        char i8 = 12, t8 = 0 ;
index ec3814e..2cc704e 100644 (file)
--- a/src/wav.c
+++ b/src/wav.c
@@ -302,7 +302,7 @@ wav_read_header     (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
        uint32_t        marker, chunk_size = 0, RIFFsize = 0, done = 0 ;
        int                     parsestage = 0, error, format = 0 ;
 
-       if (psf->is_pipe == 0 && psf->filelength > SF_PLATFORM_S64 (0xffffffff))
+       if (psf->is_pipe == 0 && psf->filelength > 0xFFFFFFFFLL)
                psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
 
        if ((wpriv = psf->container_data) == NULL)
index a3388d7..7acdc80 100644 (file)
@@ -902,6 +902,9 @@ wavlike_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize)
                bytes += psf_binheader_readf (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
                } ;
 
+       if (bytes < chunksize)
+               psf_log_printf (psf, "  %d trailing bytes in cart chunk.\n", chunksize - bytes) ;
+
        return 0 ;
 } /* wavlike_read_cart_chunk */
 
@@ -981,7 +984,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                switch (chunk)
                {       case adtl_MARKER :
                        case INFO_MARKER :
-                                       /* These markers don't contain anything, not even a chunk lebgth. */
+                                       /* These markers don't contain anything, not even a chunk length. */
                                        psf_log_printf (psf, "  %M\n", chunk) ;
                                        continue ;
 
@@ -1003,10 +1006,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                                        **      the rest of the chunk is garbage.
                                        */
                                        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) ;
-                                       psf_log_printf (psf, "    *** Offset is now : 0x%X\n", psf_fseek (psf, 0, SEEK_CUR)) ;
-                                       return 0 ;
+                                       goto cleanup_subchunk_parse ;
 
                        default :
                                        break ;
@@ -1029,7 +1029,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                        case ITRK_MARKER :
                                        bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
                                        chunk_size += (chunk_size & 1) ;
-                                       if (chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
+                                       if (chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length)
                                        {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
                                                goto cleanup_subchunk_parse ;
                                                } ;
@@ -1045,7 +1045,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                                                bytesread += psf_binheader_readf (psf, "44", &chunk_size, &mark_id) ;
                                                chunk_size -= 4 ;
                                                chunk_size += (chunk_size & 1) ;
-                                               if (chunk_size < 1 || chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
+                                               if (chunk_size < 1 || chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length)
                                                {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
                                                        goto cleanup_subchunk_parse ;
                                                        } ;
@@ -1076,7 +1076,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                        case note_MARKER :
                                        bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
                                        chunk_size += (chunk_size & 1) ;
-                                       if (chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
+                                       if (chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length)
                                        {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
                                                goto cleanup_subchunk_parse ;
                                                } ;
@@ -1087,16 +1087,14 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
                        default :
                                        bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
                                        chunk_size += (chunk_size & 1) ;
-                                       psf_log_printf (psf, "    *** %M : %u\n", chunk, chunk_size) ;
                                        if (bytesread + chunk_size > chunk_length)
-                                       {       bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread + 4) ;
-                                               continue ;
+                                       {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
+                                               goto cleanup_subchunk_parse ;
                                                }
                                        else
+                                       {       psf_log_printf (psf, "    %M : %u\n", chunk, chunk_size) ;
                                                bytesread += psf_binheader_readf (psf, "j", chunk_size) ;
-
-                                       if (chunk_size >= chunk_length)
-                                               return 0 ;
+                                               } ;
                                        break ;
                        } ;
 
index 6e39da6..e05a737 100644 (file)
@@ -106,7 +106,7 @@ check_title (const SndfileHandle & file, const char * filename)
        title = file.getString (SF_STR_TITLE) ;
 
        if (title == NULL)
-       {       printf ("\n\n%s %d : Error : No title.\n\n", __func__, __LINE__) ;
+       {       printf ("\n\n%s %d : Error : No title for %s.\n\n", __func__, __LINE__, filename) ;
                exit (1) ;
                } ;
 
index 495d88b..9cdabf4 100644 (file)
@@ -175,6 +175,45 @@ bad_wav_test (const char * filename)
 } /* bad_wav_test */
 
 static void
+wav_list_recover_test (const char * filename)
+{      SNDFILE         *sndfile ;
+       SF_INFO         sfinfo ;
+
+       FILE            *file ;
+       const char      data [] =
+               "RIFF" "J\000\000\000"
+               "WAVE" "fmt " "\020\000\000\000" "\001\000\001\000D\254\000\000\210X\001\000\002\000\020\000"
+               "LIST" "\014\000\000\000" "test" "\010\000\000\000" "1234" /* test is 4 bytes short inside LIST container */
+               "data" "\004\000\000\000" "abcd" ;
+
+       print_test_name (__func__, filename) ;
+
+       if ((file = fopen (filename, "w")) == NULL)
+       {       printf ("\n\nLine %d : fopen returned NULL.\n", __LINE__) ;
+               exit (1) ;
+               } ;
+
+       exit_if_true (fwrite (data, sizeof (data) - 1, 1, file) != 1, "\n\nLine %d : fwrite failed.\n", __LINE__) ;
+       fclose (file) ;
+
+       memset (&sfinfo, 0, sizeof (sfinfo)) ;
+       sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
+
+       if (!sndfile)
+       {       printf ("\n\nLine %d : expected recovery from bogus LIST content.\n", __LINE__) ;
+               exit (1) ;
+               } ;
+
+       if (sfinfo.frames != 2)
+       {       printf ("\n\nLine %d : Should have read data chunk with 2 stereo frames, got %ld.\n\n", __LINE__, (long)sfinfo.frames) ;
+               exit (1) ;
+               } ;
+
+       unlink (filename) ;
+       puts ("ok") ;
+} /* wav_list_recover_test */
+
+static void
 error_close_test (void)
 {      static short buffer [SHORT_BUFFER] ;
        const char      *filename = "error_close.wav" ;
@@ -266,6 +305,7 @@ main (void)
        no_file_test ("no_file.wav") ;
        zero_length_test ("zero_length.wav") ;
        bad_wav_test ("bad_wav.wav") ;
+       wav_list_recover_test ("list_recover.wav") ;
 
        unrecognised_test () ;
 
index 283af64..561628d 100644 (file)
@@ -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_srcdir@/src -I@abs_top_builddir@/src -I@abs_top_builddir@/include -c @top_srcdir@/tests/sfversion.c -o /dev/null
+       $CC -std=c99 -Werror -pedantic -I@top_srcdir@/src -I@abs_top_builddir@/src -I@top_srcdir@/include -c @top_srcdir@/tests/sfversion.c -o /dev/null
 
        # Check compiler return status.
        if test $? -ne 0 ; then
index c68e3a2..0d1cd8b 100644 (file)
@@ -193,6 +193,7 @@ sf_count_t          file_length_fd (int fd) ;
 #include <string.h>
 #include <ctype.h>
 #include <math.h>
+#include <float.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 
@@ -215,6 +216,28 @@ sf_count_t         file_length_fd (int fd) ;
 #define O_BINARY 0
 #endif
 
+
+/*
+**      Compare for equality, with epsilon
+*/
+static inline int
+equals_short (const short a, const short b)
+{        return (a == b);
+} /* equals_short */
+static inline int
+equals_int (const int a, const int b)
+{        return (a == b);
+} /* equals_int */
+static inline int
+equals_float (const float a, const float b)
+{        return (fabsf(a - b) <= FLT_EPSILON);
+} /* equals_float */
+static inline int
+equals_double (const double a, const double b)
+{       return (fabs(a - b) <= DBL_EPSILON);
+} /* equals_double */
+
+
 [+ FOR float_type +]
 void
 gen_windowed_sine_[+ (get "name") +] ([+ (get "name") +] *data, int len, double maximum)
@@ -752,8 +775,8 @@ compare_[+ (get "io_element") +]_or_die (const [+ (get "io_element") +] *expecte
        unsigned k ;
 
        for (k = 0 ; k < count ; k++)
-               if (expected [k] != actual [k])
-               {       printf ("\n\nLine %d : Error at index %d, got " [+ (get "format_str") +] ", should be " [+ (get "format_str") +] ".\n\n", line_num, k, actual [k], expected [k]) ;
+               if (!equals_[+ (get "io_element") +](expected [k], actual [k]))
+               {       printf ("\n\nLine %d : Error at index %d, got " [+ (get "format_str") +] ", should be " [+ (get "format_str") +] "(delta=" [+ (get "format_str") +] " ).\n\n", line_num, k, actual [k], expected [k], actual [k] - expected [k]) ;
                        exit (1) ;
                        } ;