diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index edbbc233..4c24215a 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -18,34 +18,38 @@ jobs: ubuntu-clang-cmake-shared, macos-cmake, macos-cmake-shared, - windows-vs2019-x64, - windows-vs2019-x64-shared, - windows-vs2019-Win32, - windows-vs2019-Win32-shared + windows-vs2022-x64, + windows-vs2022-x64-shared, + windows-vs2022-Win32, + windows-vs2022-Win32-shared ] include: - name: ubuntu-gcc-autotools os: ubuntu-latest cc: gcc cxx: g++ + autotools-options: --enable-werror build-system: autotools - name: ubuntu-clang-autotools os: ubuntu-latest cc: clang cxx: clang++ + autotools-options: --enable-werror build-system: autotools - name: ubuntu-gcc-ossfuzz os: ubuntu-latest cc: gcc cxx: g++ + autotools-options: --enable-werror build-system: ossfuzz - name: macos-autotools os: macos-latest cc: clang cxx: clang++ + autotools-options: --enable-werror build-system: autotools - name: ubuntu-gcc-cmake @@ -117,22 +121,22 @@ jobs: -DCMAKE_C_FLAGS="-Wall -Wextra" -DCMAKE_VERBOSE_MAKEFILE=ON - - name: windows-vs2019-x64 + - name: windows-vs2022-x64 os: windows-latest triplet: 'x64-windows-static' build-system: cmake - cmake-generator: 'Visual Studio 16 2019' + cmake-generator: 'Visual Studio 17 2022' cmake-options: >- -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$:Debug> -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake - - name: windows-vs2019-x64-shared + - name: windows-vs2022-x64-shared os: windows-latest triplet: 'x64-windows-static' build-system: cmake - cmake-generator: 'Visual Studio 16 2019' + cmake-generator: 'Visual Studio 17 2022' cmake-options: >- -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$:Debug> -DBUILD_SHARED_LIBS=ON @@ -143,11 +147,11 @@ jobs: -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake - - name: windows-vs2019-Win32 + - name: windows-vs2022-Win32 os: windows-latest triplet: 'x86-windows-static' build-system: cmake - cmake-generator: 'Visual Studio 16 2019' + cmake-generator: 'Visual Studio 17 2022' cmake-options: >- -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$:Debug> -DCMAKE_GENERATOR_PLATFORM=Win32 @@ -155,11 +159,11 @@ jobs: -DVCPKG_TARGET_TRIPLET=x86-windows-static -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake - - name: windows-vs2019-Win32-shared + - name: windows-vs2022-Win32-shared os: windows-latest triplet: 'x86-windows-static' build-system: cmake - cmake-generator: 'Visual Studio 16 2019' + cmake-generator: 'Visual Studio 17 2022' cmake-options: >- -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$:Debug> -DCMAKE_GENERATOR_PLATFORM=Win32 @@ -179,16 +183,25 @@ jobs: - name: Install MacOS dependencies if: startsWith(matrix.os,'macos') run: | - brew install automake autogen speex + brew install automake autogen speex mpg123 - - name: Install Lunux dependencies + - name: Install Linux dependencies if: startsWith(matrix.os,'ubuntu') - run: sudo apt-get install -y autogen ninja-build libogg-dev libvorbis-dev libflac-dev libopus-dev libasound2-dev libsqlite3-dev libspeex-dev + run: sudo apt-get update -y && sudo apt-get install -y autogen ninja-build libogg-dev libvorbis-dev libflac-dev libopus-dev libasound2-dev libsqlite3-dev libspeex-dev libmp3lame-dev libmpg123-dev - - name: Install Windows dependencies + - name: Setup NuGet Credentials + env: + VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite' if: startsWith(matrix.os,'windows') - run: | - vcpkg install libvorbis libflac opus sqlite3 speex --triplet ${{matrix.triplet}} + shell: 'bash' + run: > + `vcpkg fetch nuget | tail -n 1` + sources add + -source "https://nuget.pkg.github.com/libsndfile/index.json" + -storepasswordincleartext + -name "GitHub" + -username "evpobr" + -password "${{ secrets.GITHUB_TOKEN }}" - name: Configure, build and test with Autotools env: @@ -196,17 +209,18 @@ jobs: CXX: ${{ matrix.cxx }} if: startsWith(matrix.build-system,'autotools') run: | - ./autogen.sh + autoreconf -vif if [[ "${CC}" == "clang" ]]; then - ./configure --enable-werror && make clean all check && make distcheck + ./configure --enable-werror && make distcheck else - Scripts/asan-configure.sh --enable-werror && make clean all check && make distcheck + Scripts/asan-configure.sh --enable-werror && make distcheck fi - name: Configure, build and test with CMake env: CC: ${{ matrix.cc }} CXX: ${{ matrix.cxx }} + VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite' if: startsWith(matrix.build-system,'cmake') run: | mkdir build diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 00000000..58ef9c4a --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,26 @@ +name: CIFuzz +on: [pull_request] +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'libsndfile' + dry-run: false + language: c + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'libsndfile' + fuzz-seconds: 600 + dry-run: false + language: c + - name: Upload Crash + uses: actions/upload-artifact@v1 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/.gitignore b/.gitignore index 91f3f47c..05f79a93 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ build-test-tarball.mk config.log config.status configure +configure~ doc/AUTHORS doc/ChangeLog doc/NEWS @@ -62,7 +63,7 @@ examples/sndfile-loopify examples/sndfile-to-text examples/sndfilehandle include/sndfile.h -libsndfile-1.0.* +libsndfile-*.tar.xz libsndfile-testsuite-* libsndfile.spec libtool diff --git a/BUILD.gn b/BUILD.gn index 11e8524f..6f00df43 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -93,6 +93,7 @@ ohos_source_set("sndfile_sources") { "src/mat4.c", "src/mat5.c", "src/mpc2k.c", + "src/mpeg.c", "src/ms_adpcm.c", "src/nist.c", "src/nms_adpcm.c", diff --git a/Building-for-Android.md b/Building-for-Android.md index 72b302d4..eb5a0d35 100644 --- a/Building-for-Android.md +++ b/Building-for-Android.md @@ -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 @@ -15,3 +15,32 @@ by setting them before the script is run. Since I (erikd), do almost zero Android development, I am happy accept patches for this documentation and script to improve its utility for real Android developers. + +--- + +## Using CMake + +(Tested on Linux) + +For convenience, export the following variables: + +``` +export ANDROID_ABI=arm64-v8a +export ANDROID_PLATFORM_API_LEVEL=29 +export NDK_ROOT=/path/to/android/ndk +``` + +Set `ANDROID_ABI`, `ANDROID_PLATFORM_API_LEVEL` according to your target system. Now cd into the libsndfile root directory, and run + +``` +cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ANDROID_ABI -DANDROID_PLATFORM=$ANDROID_PLATFORM_API_LEVEL +``` + +cd into `build` and run make + +``` +cd build +make [-j ] +``` + +This will build libsndfile for android. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..5014508f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,147 @@ +# Changelog + +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). + +## [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 + +### Added + +* MPEG Encode/Decode Support. + + Uses libmpg123 for decode, liblame for encode. Encoding and decoding support + is independent of each other and is split into separate files. MPEG support + is generalized as subformats, `SF_FORMAT_MPEG_LAYER`(I,II,III) so that it + might be used by other containers (`MPEG1WAVEFORMAT` for example), but also + contains a major format `SF_FORMAT_MPEG` for 'mp3 files.' + + Encoding Status: + * Layer III encoding + * ID3v1 writing + * ID3v2 writing + * Lame/Xing Tag writing + * Bitrate selection command + * VBR or CBR + + Decoding Status: + * Layers I/II/III decoding + * ID3v1 reading + * ID3v2 reading + * Seeking +* New fuzzer for OSS-Fuzz, thanks @DavidKorczynski. +* This `CHANGELOG.md`. All notable changes to this project will be documented in + this file. The old `NEWS` file has been renamed to `NEWS.OLD` and is no longer + updated. +* Add support for decoding MPEG III Audio in WAV files. +* `SECURITY.md` file to give people instructions for reporting security + vulnerabilities, thanks @zidingz. +* Support for [Vcpkg manifest mode](https://vcpkg.readthedocs.io/en/latest/users/manifests/). + + If you have problems with manifest mode, disable it with `VCPKG_MANIFEST_MODE` + switch. +* [Export CMake targets from the build tree (PR #802)](https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html#exporting-targets-from-the-build-tree) +* CIFuzz fuzzer, thanks to @AdamKorcz (PR #796) + +### Changed + +* `SFC_SET_DITHER_ON_READ` and `SFC_SET_DITHER_ON_WRITE` enums comments in + public header, thanks @SmiVan (issue #677). +* `ENABLE_SNDFILE_WINDOWS_PROTOTYPES` define is deprecated and not needed + anymore. + + Previously, in order for the [`sf_wchar_open`()](http://libsndfile.github.io/libsndfile/api.html#open) + function to become available on the Windows platform, it was required to + perform certain actions: + + ```c + #include + #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 + #including + ``` + + These steps are no longer required and the `sf_wchar_open`() function is + always available on the Windows platform. +* Use UTF-8 as internal path encoding on Windows platform. + + This is an internal change to unify and simplify the handling of file paths. + + On the Windows platform, the file path is always converted to UTF-8 and + converted to UTF-16 only for calls to WinAPI functions. + + The behavior of the functions for opening files on other platforms does not + change. +* Switch to .xz over .bz2 for release tarballs. +* Disable static builds using Autotools by default. If you want static + libraries, pass --enable-static to ./configure + +### Fixed + +* Typo in `docs/index.md`. +* Typo in `programs/sndfile-convert.c`, thanks @fjl. +* Memory leak in `caf_read_header`(), credit to OSS-Fuzz ([issue 30375](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30375)). +* Stack overflow in `guess_file_type`(), thanks @bobsayshilol, credit to + OSS-Fuzz ([issue 29339](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29339)). +* Abort in fuzzer, thanks @bobsayshilol, credit to OSS-Fuzz + ([issue 26257](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26257)). +* Infinite loop in `svx_read_header`(), thanks @bobsayshilol, credit to OSS-Fuzz + ([issue 25442](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25442)). +* GCC and Clang pedantic warnings, thanks @bobsayshilol. +* Normalisation issue when scaling floating point data to `int` in + `replace_read_f2i`(), thanks @bobsayshilol, (issue #702). +* Missing samples when doing a partial read of Ogg file from index till the end + of file, thanks @arthurt (issue #643). +* sndfile-salvage: Handle files > 4 GB on Windows OS +* Undefined shift in `dyn_get_32bit`(), credit to OSS-Fuzz + ([issue 27366](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27366)). +* Integer overflow in `nms_adpcm_update`(), credit to OSS-Fuzz + ([issue 25522](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25522)). +* Integer overflow in `psf_log_printf`(), credit to OSS-Fuzz + ([issue 28441](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28441)), + ([issue 25624](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25624)). +* ABI version incompatibility between Autotools and CMake build on Apple + platforms. + + Now ABI must be compatible with Autotools builds. Note that this change + requires CMake >= 3.17 for building dylib on Apple platforms. + +* Fix build with Autotools + MinGW toolchain on Windows platform. + + See https://github.com/msys2/MINGW-packages/issues/5803 for details. + +### Security + +* Heap buffer overflow in `wavlike_ima_decode_block`(), thanks @bobsayshilol, + credit to OSS-Fuzz ([issue 25530](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25530)). +* Heap buffer overflow in `msadpcm_decode_block`(), thanks @bobsayshilol, + credit to OSS-Fuzz ([issue 26803](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26803)). +* Heap buffer overflow in `psf_binheader_readf`(), thanks @bobsayshilol, + credit to OSS-Fuzz ([issue 26026](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26026)). +* Index out of bounds in `psf_nms_adpcm_decode_block`(), credit to OSS-Fuzz + ([issue 25561](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25561)). +* Heap buffer overflow in `flac_buffer_copy`(), thanks @yuawn, @bobsayshilol. +* Heap buffer overflow in `copyPredictorTo24`(), thanks @bobsayshilol, + credit to OSS-Fuzz ([issue 27503](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27503)). +* Uninitialized variable in `psf_binheader_readf`(), thanks @shao-hua-li, + credit to OSS-Fuzz ([issue 25364](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25364)). + +[Unreleased]: https://github.com/libsndfile/libsndfile/compare/1.1.0...HEAD +[1.1.0]: https://github.com/libsndfile/libsndfile/compare/1.0.31...1.1.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index de98145f..dda22431 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,27 @@ if (POLICY CMP0091) endif () endif () -project(libsndfile VERSION 1.0.31) +option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON) +if (ENABLE_EXTERNAL_LIBS) + list (APPEND VCPKG_MANIFEST_FEATURES "external-libs") +endif () + +option (ENABLE_MPEG "Enable MPEG codecs" ON) +if (ENABLE_MPEG) + list (APPEND VCPKG_MANIFEST_FEATURES "mpeg") +endif () + +option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF) +if (ENABLE_EXPERIMENTAL) + list (APPEND VCPKG_MANIFEST_FEATURES "speex") +endif () + +option (BUILD_REGTEST "Build regtest" OFF) +if (BUILD_REGTEST) + list (APPEND VCPKG_MANIFEST_FEATURES "regtest") +endif () + +project(libsndfile VERSION 1.2.0) # # Variables @@ -54,7 +74,6 @@ endif () option (BUILD_PROGRAMS "Build programs" ON) option (BUILD_EXAMPLES "Build examples" ON) option (ENABLE_CPACK "Enable CPack support" ON) -option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF) option (ENABLE_BOW_DOCS "Enable black-on-white html docs" OFF) if (MSVC AND (DEFINED ENABLE_STATIC_RUNTIME)) option (ENABLE_STATIC_RUNTIME "Enable static runtime" ${ENABLE_STATIC_RUNTIME}) @@ -75,9 +94,16 @@ endif () include(SndFileChecks) +if (ENABLE_EXTERNAL_LIBS AND NOT (Vorbis_FOUND OR FLAC_FOUND OR OPUS_FOUND)) + set (ENABLE_EXTERNAL_LIBS OFF) +endif() +if(ENABLE_MPEG AND (NOT HAVE_MPEG_LIBS)) + set (ENABLE_MPEG OFF) +endif() +if (BUILD_REGTEST AND (NOT SQLITE3_FOUND)) + set (BUILD_REGTEST OFF) +endif() -cmake_dependent_option (BUILD_REGTEST "Build regtest" ON "SQLITE3_FOUND" OFF) -cmake_dependent_option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON "Vorbis_FOUND;FLAC_FOUND;OPUS_FOUND" OFF) cmake_dependent_option (ENABLE_CPU_CLIP "Enable tricky cpu specific clipper" ON "CPU_CLIPS_POSITIVE;CPU_CLIPS_NEGATIVE" OFF) if (NOT ENABLE_CPU_CLIP) set (CPU_CLIPS_POSITIVE FALSE) @@ -104,11 +130,12 @@ set (HAVE_ALSA_ASOUNDLIB_H ${ALSA_FOUND}) set (HAVE_SNDIO_H ${SNDIO_FOUND}) set (ENABLE_EXPERIMENTAL_CODE ${ENABLE_EXPERIMENTAL}) +set (HAVE_MPEG ${ENABLE_MPEG}) set (HAVE_SPEEX ${ENABLE_EXPERIMENTAL}) -set (HAVE_OPUS ${ENABLE_EXPERIMENTAL}) add_feature_info (BUILD_SHARED_LIBS BUILD_SHARED_LIBS "build shared libraries") add_feature_info (ENABLE_EXTERNAL_LIBS ENABLE_EXTERNAL_LIBS "enable FLAC, Vorbis, and Opus codecs") +add_feature_info (ENABLE_MPEG ENABLE_MPEG "enable MPEG audio (including mp3) codecs") add_feature_info (ENABLE_EXPERIMENTAL ENABLE_EXPERIMENTAL "enable experimental code") add_feature_info (BUILD_TESTING BUILD_TESTING "build tests") add_feature_info (BUILD_REGTEST BUILD_REGTEST "build regtest") @@ -147,6 +174,18 @@ set_package_properties (FLAC PROPERTIES DESCRIPTION "Free Lossless Audio Codec Library" PURPOSE "Enables FLAC support" ) +set_package_properties (mp3lame PROPERTIES + TYPE RECOMMENDED + URL "https://lame.sourceforge.io/" + DESCRIPTION "High quality MPEG Audio Layer III (MP3) encoder" + PURPOSE "Enables MPEG layer III (MP3) writing support" + ) +set_package_properties (MPG123 PROPERTIES + TYPE RECOMMENDED + URL "https://www.mpg123.de/" + DESCRIPTION "MPEG Audio Layer I/II/III decoder" + PURPOSE "Enables MPEG Audio reading support" + ) set_package_properties(Opus PROPERTIES TYPE RECOMMENDED URL "www.opus-codec.org/" @@ -181,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}) @@ -196,6 +233,10 @@ if (INSTALL_PKGCONFIG_MODULE) set (EXTERNAL_XIPH_REQUIRE "${EXTERNAL_XIPH_REQUIRE} speex") endif () endif () + if (ENABLE_MPEG) + set (EXTERNAL_MPEG_REQUIRE "libmpg123") + set (EXTERNAL_MPEG_LIBS "-lmp3lame") + endif () configure_file (sndfile.pc.in sndfile.pc @ONLY) @@ -207,8 +248,8 @@ endif () # Public libsndfile headers set (sndfile_HDRS + include/sndfile.h include/sndfile.hh - ${CMAKE_CURRENT_BINARY_DIR}/include/sndfile.h ) # @@ -247,6 +288,7 @@ add_library (sndfile src/ogg.c src/chanmap.h src/chanmap.c + src/id3.h src/id3.c $<$:src/windows.c> src/sndfile.c @@ -284,8 +326,12 @@ add_library (sndfile src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c + src/ogg_vcomment.h src/ogg_vcomment.c src/nms_adpcm.c + src/mpeg.c + src/mpeg_decode.c + src/mpeg_l3_encode.c src/GSM610/config.h src/GSM610/gsm.h src/GSM610/gsm610_priv.h @@ -349,6 +395,8 @@ target_link_libraries (sndfile $<$:FLAC::FLAC> $<$,$,$>:Speex::Speex> $<$:Opus::opus> + $<$:MPG123::libmpg123> + $<$:mp3lame::mp3lame> ) set_target_properties (sndfile PROPERTIES PUBLIC_HEADER "${sndfile_HDRS}" @@ -368,6 +416,28 @@ endif () if (BUILD_SHARED_LIBS) + # + # ABI version of library. + # + + # + # Read libtool version from `configure.ac` and set libsndfile ABI version: + # + # SNDFILE_ABI_VERSION_MAJOR + # SNDFILE_ABI_VERSION_MINOR + # SNDFILE_ABI_VERSION_PATCH + # SNDFILE_ABI_VERSION + # + # and Mach-O current and compatibility versions: + # + # SNDFILE_MACHO_CURRENT_VERSION + # SNDFILE_MACHO_COMPATIBILITY_VERSION + # + + include (SetupABIVersions) + + setup_abi_versions() + if (WIN32) set (VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set (GEN_TOOL cmake) @@ -380,11 +450,23 @@ if (BUILD_SHARED_LIBS) target_sources (sndfile PRIVATE ${PROJECT_BINARY_DIR}/src/version-metadata.rc) endif () + set_target_properties (sndfile PROPERTIES - SOVERSION ${PROJECT_VERSION_MAJOR} - VERSION ${PROJECT_VERSION} + SOVERSION ${SNDFILE_ABI_VERSION_MAJOR} + VERSION ${SNDFILE_ABI_VERSION} ) + if (APPLE) + if (NOT (CMAKE_VERSION VERSION_LESS 3.17)) + set_target_properties (sndfile PROPERTIES + MACHO_CURRENT_VERSION ${SNDFILE_MACHO_CURRENT_VERSION} + MACHO_COMPATIBILITY_VERSION ${SNDFILE_MACHO_COMPATIBILITY_VERSION} + ) + else () + message (FATAL_ERROR "Apple platform requires cmake >= 3.17 to build dylib.") + endif () + endif () + # Symbol files generation if (WIN32) @@ -404,7 +486,7 @@ if (BUILD_SHARED_LIBS) if (DEFINED SYMBOL_OS) add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${PROJECT_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${SNDFILE_ABI_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} COMMENT "Generating ${SYMBOL_FILENAME}..." ) @@ -647,6 +729,11 @@ if (BUILD_EXAMPLES) $<$:m> ) +# generate + + add_executable (generate examples/generate.c) + target_link_libraries (generate PRIVATE sndfile) + # sndfilehandle add_executable (sndfilehandle examples/sndfilehandle.cc) @@ -658,6 +745,7 @@ if (BUILD_EXAMPLES) make_sine sfprocess list_formats + generate sndfilehandle ) @@ -716,6 +804,8 @@ if (ENABLE_PACKAGE_CONFIG) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) + export (EXPORT SndFileTargets NAMESPACE SndFile:: FILE ${PROJECT_BINARY_DIR}/SndFileTargets.cmake) + include (CMakePackageConfigHelpers) if (ENABLE_EXTERNAL_LIBS) @@ -724,8 +814,19 @@ if (ENABLE_PACKAGE_CONFIG) set (SndFile_WITH_EXTERNAL_LIBS 0) endif () + if(ENABLE_MPEG) + set (SndFile_WITH_MPEG 1) + else () + set (SndFile_WITH_MPEG 0) + endif () + set (INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig.cmake + INSTALL_DESTINATION ${PROJECT_BINARY_DIR} + INSTALL_PREFIX ${PROJECT_BINARY_DIR} + PATH_VARS INCLUDE_INSTALL_DIR + ) + configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig2.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} PATH_VARS INCLUDE_INSTALL_DIR ) @@ -735,9 +836,13 @@ if (ENABLE_PACKAGE_CONFIG) NAMESPACE SndFile:: DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig2.cmake + RENAME SndFileConfig.cmake + DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} + ) install( FILES - ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} ) @@ -1181,6 +1286,14 @@ if (BUILD_TESTING) $<$:m> ) + add_executable (mpeg_test tests/mpeg_test.c) + target_link_libraries (mpeg_test + PRIVATE + sndfile + test_utils + $<$:m> + ) + add_executable (stdin_test tests/stdin_test.c) target_link_libraries (stdin_test PRIVATE @@ -1412,6 +1525,10 @@ if (BUILD_TESTING) add_test (lossy_comp_test_ogg_opus lossy_comp_test ogg_opus) add_test (string_test_opus string_test opus) + ### mpeg-tests ### + add_test (mpeg_test mpeg_test) + add_test (compression_size_test_mpeg compression_size_test mpeg) + ### io-tests add_test (stdio_test stdio_test) add_test (pipe_test pipe_test) @@ -1467,5 +1584,8 @@ if (BUILD_TESTING) endif () if (ENABLE_CPACK) + if ((NOT CPACK_PACKAGE_VERSION) AND CPACK_PACKAGE_VERSION_STAGE) + set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_FULL}") + endif () include (CPack) endif () diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index afdcb55e..0bf14b76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,30 @@ * Patches should always be submitted via a either Github "pull request" or a via emailed patches created using "git format-patch". * Patches for new features should include tests and documentation. +* Commit messages should follow the ["How to Write a Git Commit Message"](https://chris.beams.io/posts/git-commit/) guide: + 1. Separate subject from body with a blank line + 2. Limit the subject line to 50 characters + 3. Capitalize the subject line + 4. Do not end the subject line with a period + 5. Use the imperative mood in the subject line + 6. Wrap the body at 72 characters + 7. Use the body to explain what and why vs. how + + Additional rule: the commit message may contain a prefix. The prefix must + contain the name of the feature or source file related to the commit and must + end with a colon followed by the message body. + + Examples of good commit messages: + 1. Fix typo + 2. Update CHANGELOG.md + 3. Add ACT file format support + 4. ogg_vorbis: Fix granule position when seeking Vorbis streams + + Examples of bad commit messages: + 1. Fixed bug (rule 5) + 2. update docs (rule 3) + 3. Add very cool feature. (rule 4) + * Patches to fix bugs should either pass all tests, or modify the tests in some sane way. * When a new feature is added for a particular file format and that feature diff --git a/Makefile.am b/Makefile.am index 0b8bfa14..7bd00d3a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,8 +13,8 @@ endif endif EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \ - Scripts/linux-to-win-cross-configure.sh \ - CMakeLists.txt $(cmake_files) Win32 + NEWS.OLD CHANGELOG.md Scripts/linux-to-win-cross-configure.sh \ + CMakeLists.txt $(cmake_files) Win32 SECURITY.md cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \ cmake/CMakeAutoGen.cmake cmake/CMakeAutoGenScript.cmake \ @@ -23,7 +23,9 @@ cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \ cmake/SndFileChecks.cmake cmake/TestInline.cmake \ cmake/TestLargeFiles.cmake cmake/TestInline.c.in \ cmake/FindOpus.cmake cmake/SndFileConfig.cmake.in \ - cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in + cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in \ + cmake/Findmp3lame.cmake cmake/FindMpg123.cmake \ + cmake/SetupABIVersions.cmake pkgconfig_DATA = sndfile.pc @@ -44,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/GSM610/README src/GSM610/COPYRIGHT src/GSM610/ChangeLog \ src/G72x/README src/G72x/README.original src/G72x/ChangeLog \ @@ -60,28 +62,27 @@ endif #=============================================================================== lib_LTLIBRARIES = src/libsndfile.la -include_HEADERS = include/sndfile.hh -nodist_include_HEADERS = include/sndfile.h -src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) +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) src_libsndfile_la_SOURCES = src/sndfile.c src/aiff.c src/au.c src/avr.c src/caf.c src/dwd.c src/flac.c src/g72x.c src/htk.c src/ircam.c \ src/macos.c src/mat4.c src/mat5.c src/nist.c src/paf.c src/pvf.c src/raw.c src/rx2.c src/sd2.c \ src/sds.c src/svx.c src/txw.c src/voc.c src/wve.c src/w64.c src/wavlike.c src/wav.c src/xi.c src/mpc2k.c src/rf64.c \ - src/ogg_vorbis.c src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c src/ogg_vcomment.c \ - src/common.h src/sfconfig.h src/sfendian.h src/wavlike.h src/sf_unistd.h src/ogg.h src/chanmap.h src/ogg_vcomment.h + src/ogg.c src/ogg.h src/ogg_vorbis.c src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c src/ogg_vcomment.c src/ogg_vcomment.h \ + src/common.h src/sfconfig.h src/sfendian.h src/wavlike.h src/sf_unistd.h src/chanmap.h src/mpeg.c nodist_src_libsndfile_la_SOURCES = $(nodist_include_HEADERS) src_libsndfile_la_LIBADD = src/GSM610/libgsm.la src/G72x/libg72x.la src/ALAC/libalac.la \ - src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm + src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm $(MPEG_LIBS) EXTRA_src_libsndfile_la_DEPENDENCIES = $(SYMBOL_FILES) noinst_LTLIBRARIES = src/libcommon.la -src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) +src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_CFLAGS) src_libcommon_la_SOURCES = src/common.c src/file_io.c src/command.c src/pcm.c src/ulaw.c src/alaw.c \ src/float32.c src/double64.c src/ima_adpcm.c src/ms_adpcm.c src/gsm610.c src/dwvw.c src/vox_adpcm.c \ src/interleave.c src/strings.c src/dither.c src/cart.c src/broadcast.c src/audio_detect.c \ - src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/ogg.c src/chanmap.c \ - src/windows.c src/id3.c src/nms_adpcm.c $(WIN_VERSION_FILE) + src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/chanmap.c \ + src/windows.c src/id3.c src/id3.h src/nms_adpcm.c src/mpeg_decode.c src/mpeg_l3_encode.c src/mpeg.h $(WIN_VERSION_FILE) check_PROGRAMS = src/test_main src_test_main_SOURCES = src/test_main.c src/test_main.h src/test_conversions.c src/test_float.c src/test_endswap.c \ @@ -135,19 +136,19 @@ src_ALAC_libalac_la_SOURCES = src/ALAC/ALACAudioTypes.h src/ALAC/ALACBitUtilitie SYMBOL_SCRIPT = $(top_srcdir)/src/create_symbols_file.py src/Symbols.gnu-binutils: $(SYMBOL_SCRIPT) - $(PYTHON) $(SYMBOL_SCRIPT) linux $(VERSION) > $(top_srcdir)/$@ + $(PYTHON) $(SYMBOL_SCRIPT) linux $(ABI_VERSION) > $(top_srcdir)/$@ src/Symbols.darwin: $(SYMBOL_SCRIPT) - $(PYTHON) $(SYMBOL_SCRIPT) darwin $(VERSION) > $(top_srcdir)/$@ + $(PYTHON) $(SYMBOL_SCRIPT) darwin $(ABI_VERSION) > $(top_srcdir)/$@ src/libsndfile-1.def: $(SYMBOL_SCRIPT) - $(PYTHON) $(SYMBOL_SCRIPT) win32 $(VERSION) > $(top_srcdir)/$@ + $(PYTHON) $(SYMBOL_SCRIPT) win32 $(ABI_VERSION) > $(top_srcdir)/$@ src/Symbols.os2: $(SYMBOL_SCRIPT) - $(PYTHON) $(SYMBOL_SCRIPT) os2 $(VERSION) > $(top_srcdir)/$@ + $(PYTHON) $(SYMBOL_SCRIPT) os2 $(ABI_VERSION) > $(top_srcdir)/$@ src/Symbols.static: $(SYMBOL_SCRIPT) - $(PYTHON) $(SYMBOL_SCRIPT) static $(VERSION) > $(top_srcdir)/$@ + $(PYTHON) $(SYMBOL_SCRIPT) static $(ABI_VERSION) > $(top_srcdir)/$@ #=============================================================================== # Building windows resource files (if needed). @@ -221,7 +222,8 @@ check_PROGRAMS += tests/sfversion tests/floating_point_test tests/write_read_tes tests/locale_test tests/win32_ordinal_test tests/ogg_test tests/compression_size_test \ tests/checksum_test tests/external_libs_test tests/rdwr_test tests/format_check_test $(CPP_TEST) \ tests/channel_test tests/long_read_write_test tests/stdin_test tests/stdout_test \ - tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test + tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test \ + tests/mpeg_test BUILT_SOURCES += \ tests/write_read_test.c \ @@ -377,6 +379,9 @@ tests_cpp_test_LDADD = src/libsndfile.la tests_checksum_test_SOURCES = tests/checksum_test.c tests/utils.c tests/utils.h tests_checksum_test_LDADD = src/libsndfile.la +tests_mpeg_test_SOURCES = tests/mpeg_test.c tests/utils.c tests/utils.h +tests_mpeg_test_LDADD = src/libsndfile.la + # Lite remove start tests_dwvw_test_SOURCES = tests/dwvw_test.c tests/utils.c tests/utils.h tests_dwvw_test_LDADD = src/libsndfile.la @@ -457,7 +462,8 @@ endif if USE_OSSFUZZERS noinst_PROGRAMS += \ - ossfuzz/sndfile_fuzzer + ossfuzz/sndfile_fuzzer \ + ossfuzz/sndfile_alt_fuzzer noinst_LTLIBRARIES += \ ossfuzz/libstandaloneengine.la @@ -468,6 +474,11 @@ ossfuzz_sndfile_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG) ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD) +ossfuzz_sndfile_alt_fuzzer_SOURCES = ossfuzz/sndfile_alt_fuzzer.cc +ossfuzz_sndfile_alt_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG) +ossfuzz_sndfile_alt_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static +ossfuzz_sndfile_alt_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD) + ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS) diff --git a/NEWS b/NEWS.OLD similarity index 100% rename from NEWS rename to NEWS.OLD diff --git a/README b/README index 93b4b29a..3ad4b34c 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is libsndfile, 1.0.29 +This is libsndfile, 1.1.0 libsndfile is a library of C routines for reading and writing files containing sampled audio data. diff --git a/README.md b/README.md index c12bc1a9..f14afcd6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ for details. ## Hacking The canonical source code repository for libsndfile is at -[http://libsndfile.github.io/libsndfile/][github]. +. You can grab the source code using: @@ -33,19 +33,20 @@ below. Setting up a build environment for libsndfile on Debian or Ubuntu is as simple as: sudo apt install autoconf autogen automake build-essential libasound2-dev \ - libflac-dev libogg-dev libtool libvorbis-dev libopus-dev pkg-config python + libflac-dev libogg-dev libtool libvorbis-dev libopus-dev libmp3lame-dev \ + libmpg123-dev pkg-config python For other Linux distributions or any of the *BSDs, the setup should be similar although the package install tools and package names may be slightly different. Similarly on Mac OS X, assuming [brew] is already installed: - brew install autoconf autogen automake flac libogg libtool libvorbis opus pkg-config + brew install autoconf autogen automake flac libogg libtool libvorbis opus mpg123 pkg-config 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 @@ -134,6 +135,8 @@ You can pass additional options with `/D=` when you run `ON` by default. Setting `BUILD_SHARED_LIBS` to `ON` disables this option. * `ENABLE_EXTERNAL_LIBS` - enable Ogg, Vorbis, FLAC and Opus support. This option is available and set to `ON` if all dependency libraries were found. +* `ENABLE_MPEG` - MP3 support. This option is available and set to `ON` if all + dependency libraries were found. * `ENABLE_CPU_CLIP` - enable tricky cpu specific clipper. Enabled and set to `ON` when CPU clips negative\positive. Don't touch it if you are not sure * `ENABLE_BOW_DOCS` - enable black-on-white documentation theme, `OFF` by @@ -232,7 +235,7 @@ You can find related option in Visual Studio project properties: C/C++ -> Code Generation -> Runtime Library -Dynamic version of system CRT library is defaut and it means that end user needs +Dynamic version of system CRT library is default and it means that end user needs to have the same runtime library installed on his system. Most likely it is so, but if it is not, the user will see this error message using libsndfile DLL: @@ -270,21 +273,35 @@ have standard option `CMAKE_MSVC_RUNTIME_LIBRARY` now. Second advice is about Ogg, Vorbis FLAC and Opus support. Searching external libraries under Windows is a little bit tricky. The best way is to use -[Vcpkg](https://github.com/Microsoft/vcpkg). You need to install static libogg, -libvorbis, libflac and libopus libraries: +[Vcpkg](https://github.com/Microsoft/vcpkg). - vcpkg install libogg:x64-windows-static libvorbis:x64-windows-static - libflac:x64-windows-static opus:x64-windows-static libogg:x86-windows-static - libvorbis:x86-windows-static libflac:x86-windows-static opus:x86-windows-static - -Then and add this parameter to cmake command line: +Install Vcpkg and then add this parameter to cmake command line: -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake -You also need to set `VCPKG_TARGET_TRIPLET` because you use static libraries: +You also need to set `VCPKG_TARGET_TRIPLET` if you want to use static libraries: -DVCPKG_TARGET_TRIPLET=x64-windows-static +Then you need to install static libogg, libvorbis, libflac, libopus, mpg123 and +mp3lame Vcpkg packages. + +After 1.1.0beta2 you don't need to install dependencies manually. Libsndfile +now supports [Vcpkg manifest mode](https://vcpkg.readthedocs.io/en/latest/users/manifests/) +and all dependencies are installed automatically. + +However, you can turn off the manifest mode and return to the classic mode using +the `VCPKG_MANIFEST_MODE` parameter from the command line: + + -DVCPKG_MANIFEST_MODE=OFF + +In classic mode, you need to install the required libraries manually: + + vcpkg install libvorbis:x64-windows-static libflac:x64-windows-static + opus:x64-windows-static mp3lame:x86-windows-static mpg123:x86-windows-static + libvorbis:x86-windows-static libflac:x86-windows-static + opus:x86-windows-static mp3lame:x86-windows-static mpg123:x86-windows-static + **Note**: Use must use the same CRT library for external libraries and the libsndfile library itself. For `*-static` triplets Vcpkg uses [static CRT](https://vcpkg.readthedocs.io/en/latest/users/triplets/). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..a32393d7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 1.1.x | :white_check_mark: | + +## Reporting a Vulnerability + +Please send report privately to evpobry@gmail.com, and include how would you like to be credited. diff --git a/Scripts/static-deps-build.mk b/Scripts/static-deps-build.mk index a2c19694..bbf2f0d7 100755 --- a/Scripts/static-deps-build.mk +++ b/Scripts/static-deps-build.mk @@ -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 index dbdb5ded..00000000 --- a/autogen.sh +++ /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/FindMpg123.cmake b/cmake/FindMpg123.cmake new file mode 100644 index 00000000..88b16224 --- /dev/null +++ b/cmake/FindMpg123.cmake @@ -0,0 +1,64 @@ +# - Find mpg123 +# Find the native mpg123 includes and libraries +# +# MPG123_INCLUDE_DIRS - where to find mpg123.h, etc. +# MPG123_LIBRARIES - List of libraries when using mpg123. +# MPG123_FOUND - True if Mpg123 found. + +if (MPG123_INCLUDE_DIR) + # Already in cache, be silent + set(MPG123_FIND_QUIETLY TRUE) +endif () + +find_package (PkgConfig QUIET) +pkg_check_modules(PC_MPG123 QUIET libmpg123>=1.25.10) + +set (MPG123_VERSION ${PC_MPG123_VERSION}) + +find_path (MPG123_INCLUDE_DIR mpg123.h + HINTS + ${PC_MPG123_INCLUDEDIR} + ${PC_MPG123_INCLUDE_DIRS} + ${MPG123_ROOT} + ) + +# MSVC built mpg123 may be named mpg123_static. +# The provided project files name the library with the lib prefix. + +find_library (MPG123_LIBRARY + NAMES + mpg123 + mpg123_static + libmpg123 + libmpg123_static + HINTS + ${PC_MPG123_LIBDIR} + ${PC_MPG123_LIBRARY_DIRS} + ${MPG123_ROOT} + ) + +# Handle the QUIETLY and REQUIRED arguments and set MPG123_FOUND +# to TRUE if all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args (Mpg123 + REQUIRED_VARS + MPG123_LIBRARY + MPG123_INCLUDE_DIR + VERSION_VAR + MPG123_VERSION + ) + +if (MPG123_FOUND) + set (MPG123_LIBRARIES ${MPG123_LIBRARY}) + set (MPG123_INCLUDE_DIRS ${MPG123_INCLUDE_DIR}) + + if (NOT TARGET MPG123::libmpg123) + add_library (MPG123::libmpg123 UNKNOWN IMPORTED) + set_target_properties (MPG123::libmpg123 PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MPG123_INCLUDE_DIRS}" + IMPORTED_LOCATION "${MPG123_LIBRARIES}" + ) + endif () +endif () + +mark_as_advanced(MPG123_INCLUDE_DIR MPG123_LIBRARY) diff --git a/cmake/Findmp3lame.cmake b/cmake/Findmp3lame.cmake new file mode 100644 index 00000000..223dd08f --- /dev/null +++ b/cmake/Findmp3lame.cmake @@ -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) diff --git a/cmake/SetupABIVersions.cmake b/cmake/SetupABIVersions.cmake new file mode 100644 index 00000000..331a2bd9 --- /dev/null +++ b/cmake/SetupABIVersions.cmake @@ -0,0 +1,56 @@ +# Inspiration: https://github.com/ros2-dotnet/Fast-RTPS + +macro (SETUP_ABI_VERSIONS) + + file (STRINGS ${PROJECT_SOURCE_DIR}/configure.ac CONFIGURE_AC_CONTENT) + file (STRINGS + configure.ac + SNDFILE_LT_CURRENT_TMP + REGEX "^m4_define\\(\\[?lt_current\\]?, *\\[?[0-9]+\\]?\\)" + ) + string (REGEX REPLACE "m4_define\\(\\[?lt_current\\]?, *\\[?([0-9]+)\\]?\\)" + "\\1" + SNDFILE_LT_CURRENT + ${SNDFILE_LT_CURRENT_TMP} + ) + + file (STRINGS + configure.ac + SNDFILE_LT_REVISION_TMP + REGEX "^m4_define\\(\\[?lt_revision\\]?, *\\[?[0-9]+\\]?\\)" + ) + string (REGEX REPLACE "m4_define\\(\\[?lt_revision\\]?, *\\[?([0-9]+)\\]?\\)" + "\\1" + SNDFILE_LT_REVISION + ${SNDFILE_LT_REVISION_TMP} + ) + + file (STRINGS + configure.ac + SNDFILE_LT_AGE_TMP + REGEX "^m4_define\\(\\[?lt_age\\]?, *\\[?[0-9]+\\]?\\)" + ) + string (REGEX REPLACE "m4_define\\(\\[?lt_age\\]?, *\\[?([0-9]+)\\]?\\)" + "\\1" + SNDFILE_LT_AGE + ${SNDFILE_LT_AGE_TMP} + ) + + # + # Calculate CMake compatible ABI version from libtool version. + # + + math (EXPR SNDFILE_ABI_VERSION_MAJOR "${SNDFILE_LT_CURRENT} - ${SNDFILE_LT_AGE}") + set (SNDFILE_ABI_VERSION_MINOR ${SNDFILE_LT_AGE}) + set (SNDFILE_ABI_VERSION_PATCH ${SNDFILE_LT_REVISION}) + set (SNDFILE_ABI_VERSION "${SNDFILE_ABI_VERSION_MAJOR}.${SNDFILE_ABI_VERSION_MINOR}.${SNDFILE_ABI_VERSION_PATCH}") + + # + # Apple platform current and compatibility versions. + # + + math (EXPR SNDFILE_MACHO_CURRENT_VERSION_MAJOR "${SNDFILE_ABI_VERSION_MAJOR} + ${SNDFILE_ABI_VERSION_MINOR} + 1") + set (SNDFILE_MACHO_CURRENT_VERSION "${SNDFILE_MACHO_CURRENT_VERSION_MAJOR}.${SNDFILE_ABI_VERSION_PATCH}.0") + set (SNDFILE_MACHO_COMPATIBILITY_VERSION "${SNDFILE_MACHO_CURRENT_VERSION_MAJOR}.0.0") + +endmacro (SETUP_ABI_VERSIONS) diff --git a/cmake/SndFileChecks.cmake b/cmake/SndFileChecks.cmake index 9b52d152..19c7b4b9 100644 --- a/cmake/SndFileChecks.cmake +++ b/cmake/SndFileChecks.cmake @@ -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,6 +49,14 @@ else () set (HAVE_EXTERNAL_XIPH_LIBS 0) endif () +find_package (mp3lame) +find_package (Mpg123 1.25.10) +if (TARGET mp3lame::mp3lame AND (TARGET MPG123::libmpg123)) + set (HAVE_MPEG_LIBS 1) +else () + set (HAVE_MPEG_LIBS 0) +endif() + find_package (Speex) find_package (SQLite3) @@ -70,6 +71,7 @@ check_include_file (sys/time.h HAVE_SYS_TIME_H) check_include_file (sys/types.h HAVE_SYS_TYPES_H) check_include_file (unistd.h HAVE_UNISTD_H) check_include_file (immintrin.h HAVE_IMMINTRIN_H) +check_include_file (stdbool.h HAVE_STDBOOL_H) check_cpu_arch_x86 (CPU_IS_X86) check_cpu_arch_x64 (CPU_IS_X64) @@ -112,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) diff --git a/cmake/SndFileConfig.cmake.in b/cmake/SndFileConfig.cmake.in index e33c56bd..0c98e7e2 100644 --- a/cmake/SndFileConfig.cmake.in +++ b/cmake/SndFileConfig.cmake.in @@ -4,6 +4,7 @@ set(SndFile_VERSION_MINOR @PROJECT_VERSION_MINOR@) set(SndFile_VERSION_PATCH @PROJECT_VERSION_PATCH@) set (SndFile_WITH_EXTERNAL_LIBS @SndFile_WITH_EXTERNAL_LIBS@) +set (SndFile_WITH_MPEG @SndFile_WITH_MPEG@) @PACKAGE_INIT@ @@ -16,6 +17,11 @@ if (SndFile_WITH_EXTERNAL_LIBS AND NOT @BUILD_SHARED_LIBS@) find_dependency (Opus) endif () +if (SndFile_WITH_MPEG AND NOT @BUILD_SHARED_LIBS@) + find_dependency (mp3lame) + find_dependency (MPG123) +endif () + include (${CMAKE_CURRENT_LIST_DIR}/SndFileTargets.cmake) set_and_check (SndFile_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") diff --git a/configure.ac b/configure.ac index 78a79da5..7b4fa61b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,9 @@ -dnl Copyright (C) 1999-2021 Erik de Castro Lopo . +dnl Copyright (C) 1999-2022 Erik de Castro Lopo . dnl Require autoconf version >= 2.69 AC_PREREQ([2.69]) -AC_INIT([libsndfile],[1.0.31],[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 @@ -30,7 +30,7 @@ AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([src/config.h]) -AM_INIT_AUTOMAKE([1.14 foreign dist-bzip2 no-dist-gzip serial-tests subdir-objects]) +AM_INIT_AUTOMAKE([1.14 foreign dist-xz no-dist-gzip serial-tests subdir-objects]) AM_SILENT_RULES([yes]) dnl ==================================================================================== @@ -57,7 +57,7 @@ AC_LANG_POP([C++]) AC_PROG_SED AM_PROG_AR -LT_INIT([win32-dll]) +LT_INIT([disable-static win32-dll]) LT_PROG_RC AC_PROG_INSTALL @@ -84,17 +84,29 @@ dnl 5. If any interfaces have been added since the last public release, then i dnl age. dnl 6. If any interfaces have been removed since the last public release, then set age dnl to 0. -SHARED_VERSION_INFO="1:31:0" + +dnl This is libtool version of library, we add it to `--version-info` property. + +m4_define([lt_current], [1]) +m4_define([lt_revision], [35]) +m4_define([lt_age], [0]) + +dnl This is ABI version for linker scripts, CMake uses the same format for +dnl VERSION property of shared library. +dnl The formula is: c:r:a -> c-a:a:r + +m4_define([abi_version_major], [m4_eval(lt_current - lt_age)]) +m4_define([abi_version_minor], [lt_age]) +m4_define([abi_version_patch], [lt_revision]) dnl ------------------------------------------------------------------------------------ -AC_HEADER_STDC - AC_CHECK_HEADERS([endian.h]) AC_CHECK_HEADERS([byteswap.h]) AC_CHECK_HEADERS([locale.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([immintrin.h]) +AC_CHECK_HEADERS([stdbool.h]) AC_HEADER_SYS_WAIT @@ -129,9 +141,6 @@ AC_DEFINE_UNQUOTED([ENABLE_EXPERIMENTAL_CODE], [${EXPERIMENTAL_CODE}], [Set to 1 AC_ARG_ENABLE([werror], [AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])]) -AC_ARG_ENABLE([stack-smash-protection], - [AS_HELP_STRING([--enable-stack-smash-protection], [Enable GNU GCC stack smash protection])]) - AC_ARG_ENABLE([cpu-clip], [AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])]) @@ -147,6 +156,9 @@ AC_ARG_ENABLE([alsa], AC_ARG_ENABLE([external-libs], [AS_HELP_STRING([--disable-external-libs], [disable use of FLAC, Ogg and Vorbis [[default=no]]])]) +AC_ARG_ENABLE([mpeg], + [AS_HELP_STRING([--disable-mpeg], [disable use of LAME/MPG123 for MPEG (MP3) [[defaults=no]]])]) + AC_ARG_ENABLE(octave, [AS_HELP_STRING([--enable-octave], [enable building of GNU Octave module])]) @@ -159,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"]) @@ -182,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]) @@ -197,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. @@ -234,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 ==================================================================================== @@ -374,8 +331,8 @@ AS_IF([test -n "$PKG_CONFIG"], [ fi ], [ AS_ECHO([""]) - AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg and]]) - AC_MSG_WARN([[*** libvorbis) is either missing (possibly only the development]]) + AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg,]]) + AC_MSG_WARN([[*** libvorbis and libopus) is either missing (possibly only the development]]) AC_MSG_WARN([[*** headers) or is of an unsupported version.]]) AC_MSG_WARN([[***]]) AC_MSG_WARN([[*** Unfortunately, for ease of maintenance, the external libs]]) @@ -387,6 +344,53 @@ AS_IF([test -n "$PKG_CONFIG"], [ AC_DEFINE_UNQUOTED([HAVE_EXTERNAL_XIPH_LIBS], [$HAVE_EXTERNAL_XIPH_LIBS], [Will be set to 1 if flac, ogg, vorbis, and opus are available.]) +dnl ==================================================================================== +dnl Check for MPEG libraris liblame + +ac_cv_lame="no" +ac_cv_mpg123="no" +HAVE_MPEG=0 +EXTERNAL_MPEG_REQUIRE="" +EXTERNAL_MPEG_LIBS="" + +AS_IF([test -n "$PKG_CONFIG"], [ + AS_IF([test "x$enable_mpeg" = "xno"], [ + AC_MSG_WARN([[*** MPEG (Lame/MPG123) disabled. ***]]) + ], [ + AC_CHECK_HEADER(lame/lame.h, + lame_header_found="yes", + lame_header_found="no") + AC_SEARCH_LIBS(lame_set_VBR_q, [lame mp3lame], [lame_lib_found="yes"], [lame_lib_found="no"]) + AS_IF([test "x$lame_lib_found$lame_header_found" = "xyesyes"], [ + ac_cv_lame="yes" + ], [ + AC_MSG_WARN([["MPEG support selected but external Lame library cannot be found.]]) + ]) + + PKG_CHECK_MOD_VERSION([MPG123], [libmpg123 >= 1.25.10], [ + ac_cv_mpg123="yes" + ], [ + AC_MSG_WARN([["MPEG support selected but external MPG123 library cannot be found.]]) + ]) + + AS_IF([test "x$ac_cv_lame$ac_cv_mpg123" = "xyesyes"], [ + enable_mpeg="yes" + HAVE_MPEG=1 + EXTERNAL_MPEG_REQUIRE="libmpg123" + EXTERNAL_MPEG_LIBS="-lmp3lame" + MPEG_CFLAGS="$MPG123_CFLAGS" + MPEG_LIBS="$MPG123_LIBS" + ], [ + enable_mpeg="no" + AS_ECHO([""]) + AC_MSG_WARN([[*** MPEG support disabled.]]) + AS_ECHO([""]) + ]) + ]) + ]) + +AC_DEFINE_UNQUOTED([HAVE_MPEG], [$HAVE_MPEG], [Will be set to 1 if lame, mpg123 mpeg support is available.]) + dnl ==================================================================================== dnl Check for libsqlite3 (only used in regtest). @@ -574,18 +578,24 @@ AS_IF([test "x$enable_werror" = "xyes"], [ AC_LANG_POP([C++]) ]) -common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self -Wno-format-truncation" -AX_APPEND_COMPILE_FLAGS([${common_flags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS]) +common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self" +common_cflags="${common_flags}" +dnl Clang doesn't know about -Wno-format-truncation +dnl and would spew tons of warnings otherwise. +AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [ + common_cflags+=" -Wno-format-truncation" + ]) +common_cxxflags="${common_flags}" +AS_IF([test "x$ax_cv_cxx_compiler_vendor" = "xgnu"], [ + common_cxxflags+=" -Wno-format-truncation" + ]) + +AX_APPEND_COMPILE_FLAGS([${common_cflags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS]) AC_LANG_PUSH([C++]) -AX_APPEND_COMPILE_FLAGS([${common_flags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS]) +AX_APPEND_COMPILE_FLAGS([${common_cxxflags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS]) AC_LANG_POP([C++]) -AS_IF([test "x$enable_stack_smash_protection" = "xyes"], [ - XIPH_GCC_STACK_PROTECTOR - XIPH_GXX_STACK_PROTECTOR - ]) - AS_IF([test "x$enable_test_coverage" = "xyes"], [ AX_APPEND_COMPILE_FLAGS([-coverage], [CFLAGS]) ]) @@ -638,7 +648,7 @@ AS_IF([test "$HOST_TRIPLET" = "x86_64-w64-mingw32"], [ OS_SPECIFIC_LINKS=" -static-libgcc $OS_SPECIFIC_LINKS" ]) -WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/p.*//" -e "s/\./,/g"` +WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/pre.*//" -e "s/beta.*//" -e "s/\./,/g"` AS_IF([test "x$enable_static" = "xno"], [ @@ -657,7 +667,8 @@ AC_SUBST(HTML_BGCOLOUR) AC_SUBST(HTML_FGCOLOUR) AC_SUBST(SHLIB_VERSION_ARG) -AC_SUBST(SHARED_VERSION_INFO) +AC_SUBST([SHARED_VERSION_INFO], [lt_current:lt_revision:lt_age]) +AC_SUBST([ABI_VERSION], [abi_version_major.abi_version_minor.abi_version_patch]) AC_SUBST(CLEAN_VERSION) AC_SUBST(VERSION_MAJOR) AC_SUBST(GEN_TOOL) @@ -665,6 +676,7 @@ AC_SUBST(GEN_TOOL) AC_SUBST(WIN_RC_VERSION) AC_SUBST(HAVE_EXTERNAL_XIPH_LIBS) +AC_SUBST(HAVE_MPEG) AC_SUBST(OS_SPECIFIC_CFLAGS) AC_SUBST(OS_SPECIFIC_LINKS) AC_SUBST(SNDIO_LIBS) @@ -672,12 +684,18 @@ 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) +AC_SUBST(MPEG_CFLAGS) +AC_SUBST(MPEG_LIBS) AC_SUBST(SRC_BINDIR) 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 @@ -717,6 +735,7 @@ AC_MSG_RESULT([ Experimental code : ................... ${enable_experimental:-no} Using ALSA in example programs : ...... ${enable_alsa:-no} External FLAC/Ogg/Vorbis/Opus : ....... ${enable_external_libs:-no} + External MPEG Lame/MPG123 : ........... ${enable_mpeg:-no} Building Octave interface : ........... ${OCTAVE_BUILD} Tools : @@ -725,7 +744,6 @@ AC_MSG_RESULT([ CXX Compiler Vendor is : .............. ${ax_cv_cxx_compiler_vendor} (${ax_cv_cxx_compiler_version}) Sanitizer enabled : ................... ${enable_sanitizer:-no} - Stack smash protection : .............. ${enable_stack_smash_protection:-no} Installation directories : diff --git a/docs/FAQ.md b/docs/FAQ.md index cca4714d..e7c98e25 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -438,10 +438,12 @@ Use CMake project. ## Q20 : Why doesn't libsndfile support MP3? {#Q020} -In the past, MP3 was not supported because the technology behind MP3 was +~~In the past, MP3 was not supported because the technology behind MP3 was patented. Those patents have now expired and there is an [open ticket](https://github.com/libsndfile/libsndfile/issues/258) to implement -MP3 support. +MP3 support.~~ + +**Update :** Starting from version 1.1.0 libsndfile supports MP3 format. ## Q21 : How do I use libsndfile in a closed source or commercial program and comply with the license? {#Q021} diff --git a/docs/_config.yml b/docs/_config.yml index c9f19d76..b3b6ea99 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,6 +1,6 @@ --- author: "The libsndfile team" -version: "1.0.31" +version: "1.1.0" markdown: kramdown plugins: diff --git a/docs/_layouts/home.html b/docs/_layouts/home.html index 5a20c136..6c8119d1 100644 --- a/docs/_layouts/home.html +++ b/docs/_layouts/home.html @@ -12,7 +12,7 @@ title: libsndfile home page History -+- Features -+- Similar or related projects -+- - News + News
Development -+- Programming interface -+- diff --git a/docs/api.md b/docs/api.md index f009b74d..047fb4ab 100644 --- a/docs/api.md +++ b/docs/api.md @@ -97,6 +97,10 @@ 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 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**. @@ -107,74 +111,78 @@ value. The currently understood formats are listed in *sndfile.h* as follows and also include bitmasks for separating major and minor file types. Not all combinations of endian-ness and major and minor file types are valid. -| Name | Value | Description | -|:-----------------------|:-----------|:-------------------------------------------| -| **Major formats.** | -| SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). | -| SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). | -| SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). | -| SF_FORMAT_RAW | 0x040000 | RAW PCM data. | -| SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. | -| SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. | -| SF_FORMAT_NIST | 0x070000 | Sphere NIST format. | -| SF_FORMAT_VOC | 0x080000 | VOC files. | -| SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL | -| SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV | -| SF_FORMAT_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 | -| SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 | -| SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format | -| SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument | -| SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format | -| SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard | -| SF_FORMAT_AVR | 0x120000 | Audio Visual Research | -| SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX | -| SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 | -| SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format | -| SF_FORMAT_CAF | 0x180000 | Core Audio File format | -| SF_FORMAT_WVE | 0x190000 | Psion WVE format | -| SF_FORMAT_OGG | 0x200000 | Xiph OGG container | -| SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler | -| SF_FORMAT_RF64 | 0x220000 | RF64 WAV file | -| **Subtypes.** | -| SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data | -| SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data | -| SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data | -| SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data | -| SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) | -| SF_FORMAT_FLOAT | 0x0006 | 32 bit float data | -| SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data | -| SF_FORMAT_ULAW | 0x0010 | U-Law encoded. | -| SF_FORMAT_ALAW | 0x0011 | A-Law encoded. | -| SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. | -| SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. | -| SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. | -| SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM | -| SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. | -| SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. | -| SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. | -| SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. | -| SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. | -| SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. | -| SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. | -| SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. | -| SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. | -| SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. | -| SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) | -| SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) | -| SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. | -| SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. | -| SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). | -| SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). | -| SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). | -| SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). | -| **Endian-ness options.** | -| SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. | -| SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. | -| SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. | -| SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. | -| SF_FORMAT_SUBMASK | 0x0000FFFF | | -| SF_FORMAT_TYPEMASK | 0x0FFF0000 | | -| SF_FORMAT_ENDMASK | 0x30000000 | | +| Name | Value | Description | +|:-------------------------|:-----------|:-------------------------------------------| +| **Major formats.** | +| SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). | +| SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). | +| SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). | +| SF_FORMAT_RAW | 0x040000 | RAW PCM data. | +| SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. | +| SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. | +| SF_FORMAT_NIST | 0x070000 | Sphere NIST format. | +| SF_FORMAT_VOC | 0x080000 | VOC files. | +| SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL | +| SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV | +| SF_FORMAT_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 | +| SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 | +| SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format | +| SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument | +| SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format | +| SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard | +| SF_FORMAT_AVR | 0x120000 | Audio Visual Research | +| SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX | +| SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 | +| SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format | +| SF_FORMAT_CAF | 0x180000 | Core Audio File format | +| SF_FORMAT_WVE | 0x190000 | Psion WVE format | +| SF_FORMAT_OGG | 0x200000 | Xiph OGG container | +| SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler | +| SF_FORMAT_RF64 | 0x220000 | RF64 WAV file | +| SF_FORMAT_MPEG | 0x230000 | MPEG-1/2 audio stream | +| **Subtypes.** | +| SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data | +| SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data | +| SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data | +| SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data | +| SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) | +| SF_FORMAT_FLOAT | 0x0006 | 32 bit float data | +| SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data | +| SF_FORMAT_ULAW | 0x0010 | U-Law encoded. | +| SF_FORMAT_ALAW | 0x0011 | A-Law encoded. | +| SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. | +| SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. | +| SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. | +| SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM | +| SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. | +| SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. | +| SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. | +| SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. | +| SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. | +| SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. | +| SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. | +| SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. | +| SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. | +| SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. | +| SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) | +| SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) | +| SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. | +| SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. | +| SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). | +| SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). | +| SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). | +| SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). | +| SF_FORMAT_MPEG_LAYER_I | 0x0080 | MPEG-1 Audio Layer I. | +| SF_FORMAT_MPEG_LAYER_II | 0x0081 | MPEG-1 Audio Layer II. | +| SF_FORMAT_MPEG_LAYER_III | 0x0082 | MPEG-2 Audio Layer III. | +| **Endian-ness options.** | +| SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. | +| SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. | +| SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. | +| SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. | +| SF_FORMAT_SUBMASK | 0x0000FFFF | | +| SF_FORMAT_TYPEMASK | 0x0FFF0000 | | +| SF_FORMAT_ENDMASK | 0x30000000 | | Every call to **sf_open**() should be matched with a call to [**sf_close**()](#close) to free up memory allocated during the call to **sf_open**(). diff --git a/docs/command.md b/docs/command.md index 5e6606fb..b5a76f6d 100644 --- a/docs/command.md +++ b/docs/command.md @@ -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,6 +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. | --- @@ -1271,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 @@ -1927,3 +1954,63 @@ Returns SF_TRUE on success, SF_FALSE otherwise. On write, can only succeed if no data has been written. On read, if successful, [SFC_GET_CURRENT_SF_INFO](#sfc_get_current_sf_info) should be called to determine the new frames count and samplerate + +## SFC_GET_BITRATE_MODE + +Get bitrate mode. + +The bitrate mode is one of: + +| Name | Value | Description | +|:-------------------------|:------|:------------------| +| SF_BITRATE_MODE_CONSTANT | 800 | Constant bitrate. | +| SF_BITRATE_MODE_AVERAGE | 801 | Average bitrate. | +| SF_BITRATE_MODE_VARIABLE | 802 | Variable bitrate. | + +### Parameters + +sndfile +: A valid SNDFILE* pointer + +cmd +: SFC_GET_BITRATE_MODE + +data +: NULL + +datasize +: anything + +### Return value + +Returns one of `SF_BITRATE_MODE_XXX` on success, `-1` otherwise. + +## SFC_SET_BITRATE_MODE + +Set bitrate mode. + +The bitrate mode is one of: + +| Name | Value | Description | +|:-------------------------|:------|:------------------| +| SF_BITRATE_MODE_CONSTANT | 800 | Constant bitrate. | +| SF_BITRATE_MODE_AVERAGE | 801 | Average bitrate. | +| SF_BITRATE_MODE_VARIABLE | 802 | Variable bitrate. | + +### Parameters + +sndfile +: A valid SNDFILE* pointer + +cmd +: SFC_SET_BITRATE_MODE + +data +: pointer to an integer + +datasize +: sizeof (int) + +### Return value + +Returns `SF_TRUE` on success, `SF_FALSE` otherwise. diff --git a/docs/development.md b/docs/development.md index c5b39de4..068e910a 100644 --- a/docs/development.md +++ b/docs/development.md @@ -9,7 +9,7 @@ interested in helping can raise an issue on Github. The main repository can be found on Github: - + and includes [instuctions](https://github.com/libsndfile/libsndfile/blob/master/README.md) on how to build libsndfile from the Git repo. diff --git a/docs/formats.md b/docs/formats.md index 13bab526..1d96737d 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -40,11 +40,12 @@ From version 1.0.18, libsndfile also reads and writes From version 1.0.29, libsndfile can read and write [Ogg/Opus](https://opus-codec.org/). +From version 1.1.0, libsndfile can read and write MP3. + Some of the file formats I am also interested in adding are: - Kurzweil K2000 sampler files. - Ogg Speex. -- MPEG Layer 3 (commonly known as MP3) Other file formats may also be added on request. diff --git a/docs/index.md b/docs/index.md index 3779fdfd..b6663352 100644 --- a/docs/index.md +++ b/docs/index.md @@ -142,6 +142,8 @@ Here is the release history for libsndfile: problems, delete old generated sndfile.h from $(top_builddir)/src. * Version 1.0.31 (January 24 2021) Bugfix release. Fix multiple memory leaks reported by OSS-Fuzz. More SSE2-optimized functions for x86 and amd64. +* Version 1.1.0 (March 27 2022) Minor release, backward compatible with previous + releases. Added long-awaited MP3 support. Numerous improvements and bugfixes. ## Similar or Related Projects @@ -194,7 +196,7 @@ long as you abide by [the license](http://www.gnu.org/copyleft/lesser.html). Check latest version on [GitHub Releases page](https://github.com/libsndfile/libsndfile/releases/). -Binatries and source packages are signed by current releaser David Seifert aka +Binaries and source packages are signed by current releaser David Seifert aka @SoapGentoo. You can verify signatures with his public GPG key: ``` diff --git a/docs/new_file_type_howto.md b/docs/new_file_type_howto.md index 05853946..bb422081 100644 --- a/docs/new_file_type_howto.md +++ b/docs/new_file_type_howto.md @@ -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 diff --git a/examples/generate.c b/examples/generate.c index dade7d90..9b59f4ad 100644 --- a/examples/generate.c +++ b/examples/generate.c @@ -118,7 +118,7 @@ encode_file (const char *infilename, const char *outfilename, int filetype) exit (1) ; } ; - while ((readcount = sf_read_float (infile, buffer, BUFFER_LEN)) > 0) + while ((readcount = (int) sf_read_float (infile, buffer, BUFFER_LEN)) > 0) sf_write_float (outfile, buffer, readcount) ; sf_close (infile) ; diff --git a/examples/make_sine.c b/examples/make_sine.c index 76f35b0b..b905b2af 100644 --- a/examples/make_sine.c +++ b/examples/make_sine.c @@ -74,12 +74,12 @@ main (void) if (sfinfo.channels == 1) { for (k = 0 ; k < SAMPLE_COUNT ; k++) - buffer [k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ; + buffer [k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ; } else if (sfinfo.channels == 2) { for (k = 0 ; k < SAMPLE_COUNT ; k++) - { buffer [2 * k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ; - buffer [2 * k + 1] = AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI) ; + { buffer [2 * k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ; + buffer [2 * k + 1] = (int) (AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI)) ; } ; } else diff --git a/examples/sfprocess.c b/examples/sfprocess.c index 1c141a49..ce1bda8a 100644 --- a/examples/sfprocess.c +++ b/examples/sfprocess.c @@ -98,19 +98,21 @@ main (void) if (sfinfo.channels > MAX_CHANNELS) { printf ("Not able to process more than %d channels\n", MAX_CHANNELS) ; + sf_close (infile) ; return 1 ; } ; /* Open the output file. */ if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo))) { printf ("Not able to open output file %s.\n", outfilename) ; puts (sf_strerror (NULL)) ; + sf_close (infile) ; return 1 ; } ; /* While there are.frames in the input file, read them, process ** them and write them to the output file. */ - while ((readcount = sf_read_double (infile, data, BUFFER_LEN))) + while ((readcount = (int) sf_read_double (infile, data, BUFFER_LEN))) { process_data (data, readcount, sfinfo.channels) ; sf_write_double (outfile, data, readcount) ; } ; diff --git a/examples/sndfile-loopify.c b/examples/sndfile-loopify.c index b0aded4a..12b6b6bb 100644 --- a/examples/sndfile-loopify.c +++ b/examples/sndfile-loopify.c @@ -46,12 +46,6 @@ #define BUFFER_LEN (1 << 14) - -typedef struct -{ char *infilename, *outfilename ; - SF_INFO infileinfo, outfileinfo ; -} OptionData ; - const char * program_name (const char * argv0) ; static void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ; static void add_instrument_data (SNDFILE *outfile, const SF_INFO * in_info) ; @@ -105,6 +99,7 @@ main (int argc, char * argv []) /* Open the output file. */ if ((outfile = sf_open (outfilename, SFM_WRITE, &out_sfinfo)) == NULL) { printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ; + sf_close (infile) ; return 1 ; } ; @@ -143,7 +138,7 @@ sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) readcount = frames ; while (readcount > 0) - { readcount = sf_readf_int (infile, data, frames) ; + { readcount = (int) sf_readf_int (infile, data, frames) ; sf_writef_int (outfile, data, readcount) ; } ; diff --git a/examples/sndfile-to-text.c b/examples/sndfile-to-text.c index d5d0ec97..58ee0694 100644 --- a/examples/sndfile-to-text.c +++ b/examples/sndfile-to-text.c @@ -60,15 +60,21 @@ print_usage (char *progname) } /* print_usage */ -static void +static int convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precision) -{ float buf [BLOCK_SIZE] ; +{ float *buf ; sf_count_t frames ; int k, m, readcount ; + buf = malloc (BLOCK_SIZE * sizeof (float)) ; + if (buf == NULL) + { printf ("Error : Out of memory.\n\n") ; + return 1 ; + } ; + frames = BLOCK_SIZE / channels ; - while ((readcount = sf_readf_float (infile, buf, frames)) > 0) + while ((readcount = (int) sf_readf_float (infile, buf, frames)) > 0) { for (k = 0 ; k < readcount ; k++) { for (m = 0 ; m < channels ; m++) if (full_precision) @@ -79,7 +85,9 @@ convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precis } ; } ; - return ; + free (buf) ; + + return 0 ; } /* convert_to_text */ int @@ -89,6 +97,7 @@ main (int argc, char * argv []) FILE *outfile = NULL ; SF_INFO sfinfo ; int full_precision = 0 ; + int ret = 1 ; progname = strrchr (argv [0], '/') ; progname = progname ? progname + 1 : argv [0] ; @@ -97,7 +106,7 @@ main (int argc, char * argv []) { case 4 : if (!strcmp ("--full-precision", argv [3])) { print_usage (progname) ; - return 1 ; + goto cleanup ; } ; full_precision = 1 ; argv++ ; @@ -105,7 +114,7 @@ main (int argc, char * argv []) break ; default: print_usage (progname) ; - return 1 ; + goto cleanup ; } ; infilename = argv [1] ; @@ -114,19 +123,19 @@ main (int argc, char * argv []) if (strcmp (infilename, outfilename) == 0) { printf ("Error : Input and output filenames are the same.\n\n") ; print_usage (progname) ; - return 1 ; + goto cleanup ; } ; if (infilename [0] == '-') { printf ("Error : Input filename (%s) looks like an option.\n\n", infilename) ; print_usage (progname) ; - return 1 ; + goto cleanup ; } ; if (outfilename [0] == '-') { printf ("Error : Output filename (%s) looks like an option.\n\n", outfilename) ; print_usage (progname) ; - return 1 ; + goto cleanup ; } ; memset (&sfinfo, 0, sizeof (sfinfo)) ; @@ -134,23 +143,26 @@ main (int argc, char * argv []) if ((infile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL) { printf ("Not able to open input file %s.\n", infilename) ; puts (sf_strerror (NULL)) ; - return 1 ; + goto cleanup ; } ; /* Open the output file. */ if ((outfile = fopen (outfilename, "w")) == NULL) { printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ; - return 1 ; + goto cleanup ; } ; fprintf (outfile, "# Converted from file %s.\n", infilename) ; fprintf (outfile, "# Channels %d, Sample rate %d\n", sfinfo.channels, sfinfo.samplerate) ; - convert_to_text (infile, outfile, sfinfo.channels, full_precision) ; + ret = convert_to_text (infile, outfile, sfinfo.channels, full_precision) ; + +cleanup : sf_close (infile) ; - fclose (outfile) ; + if (outfile != NULL) + fclose (outfile) ; - return 0 ; + return ret ; } /* main */ diff --git a/include/sndfile.h b/include/sndfile.h index f0e65010..ed992083 100644 --- a/include/sndfile.h +++ b/include/sndfile.h @@ -1,33 +1,33 @@ /* - * Copyright (C) 1999-2016 Erik de Castro Lopo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** Copyright (C) 1999-2016 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* - * sndfile.h -- system-wide definitions - * - * API documentation is in the doc/ directory of the source code tarball - * and at http://libsndfile.github.io/libsndfile/api.html. +** sndfile.h -- system-wide definitions +** +** API documentation is in the doc/ directory of the source code tarball +** and at http://libsndfile.github.io/libsndfile/api.html. */ #ifndef SNDFILE_H #define SNDFILE_H /* This is the version 1.0.X header file. */ -#define SNDFILE_1 +#define SNDFILE_1 #include #include @@ -35,783 +35,851 @@ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif /* __cplusplus */ /* The following file types can be read and written. - * A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise - * ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and - * SF_FORMAT_SUBMASK can be used to separate the major and minor file - * types. +** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise +** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and +** SF_FORMAT_SUBMASK can be used to separate the major and minor file +** types. */ -enum { - /* Major formats. */ - SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ - SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ - SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ - SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ - SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ - SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ - SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ - SF_FORMAT_VOC = 0x080000, /* VOC files. */ - SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ - SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ - SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ - SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ - SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ - SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ - SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ - SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ - SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ - SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ - SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ - SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ - SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ - SF_FORMAT_WVE = 0x190000, /* Psion WVE format */ - SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ - SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ - SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ - SF_FORMAT_MPEG = 0x230000, /* MPEG-1/2 audio stream */ - /* Subtypes from here on. */ - SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ - SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ - SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ - SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ - SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ - SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ - SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ - SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ - SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ - SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ - SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ - SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ - SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ - SF_FORMAT_NMS_ADPCM_16 = 0x0022, /* 16kbs NMS G721-variant encoding. */ - SF_FORMAT_NMS_ADPCM_24 = 0x0023, /* 24kbs NMS G721-variant encoding. */ - SF_FORMAT_NMS_ADPCM_32 = 0x0024, /* 32kbs NMS G721-variant encoding. */ - SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ - SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ - SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ - SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ - SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ - SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ - SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */ - SF_FORMAT_OPUS = 0x0064, /* Xiph/Skype Opus encoding. */ - SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */ - SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */ - SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */ - SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */ - SF_FORMAT_MPEG_LAYER_I = 0x0080, /* MPEG-1 Audio Layer I */ - SF_FORMAT_MPEG_LAYER_II = 0x0081, /* MPEG-1 Audio Layer II */ - SF_FORMAT_MPEG_LAYER_III = 0x0082, /* MPEG-2 Audio Layer III */ - /* Endian-ness options. */ - SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ - SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ - SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ - SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ - SF_FORMAT_SUBMASK = 0x0000FFFF, - SF_FORMAT_TYPEMASK = 0x0FFF0000, - SF_FORMAT_ENDMASK = 0x30000000 -}; +enum +{ /* Major formats. */ + SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ + SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ + SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ + SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ + SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ + SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ + SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ + SF_FORMAT_VOC = 0x080000, /* VOC files. */ + SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ + SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ + SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ + SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ + SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ + SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ + SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ + SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ + SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ + SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ + SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ + SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ + SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ + SF_FORMAT_WVE = 0x190000, /* Psion WVE format */ + SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ + SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ + SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ + SF_FORMAT_MPEG = 0x230000, /* MPEG-1/2 audio stream */ + + /* Subtypes from here on. */ + + SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ + SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ + SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ + SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ + + SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ + + SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ + SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ + + SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ + SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ + SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ + SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ + + SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ + SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ + + SF_FORMAT_NMS_ADPCM_16 = 0x0022, /* 16kbs NMS G721-variant encoding. */ + SF_FORMAT_NMS_ADPCM_24 = 0x0023, /* 24kbs NMS G721-variant encoding. */ + SF_FORMAT_NMS_ADPCM_32 = 0x0024, /* 32kbs NMS G721-variant encoding. */ + + SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ + SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ + SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ + + SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ + + SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ + SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ + + SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */ + SF_FORMAT_OPUS = 0x0064, /* Xiph/Skype Opus encoding. */ + + SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */ + SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */ + SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */ + SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */ + + SF_FORMAT_MPEG_LAYER_I = 0x0080, /* MPEG-1 Audio Layer I */ + SF_FORMAT_MPEG_LAYER_II = 0x0081, /* MPEG-1 Audio Layer II */ + SF_FORMAT_MPEG_LAYER_III = 0x0082, /* MPEG-2 Audio Layer III */ + + /* Endian-ness options. */ + + SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ + SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ + SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ + SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ + + SF_FORMAT_SUBMASK = 0x0000FFFF, + SF_FORMAT_TYPEMASK = 0x0FFF0000, + SF_FORMAT_ENDMASK = 0x30000000 +} ; /* - * The following are the valid command numbers for the sf_command() - * interface. The use of these commands is documented in the file - * command.html in the doc directory of the source code distribution. +** The following are the valid command numbers for the sf_command() +** interface. The use of these commands is documented in the file +** command.html in the doc directory of the source code distribution. */ -enum { - SFC_GET_LIB_VERSION = 0x1000, - SFC_GET_LOG_INFO = 0x1001, - SFC_GET_CURRENT_SF_INFO = 0x1002, - SFC_GET_NORM_DOUBLE = 0x1010, - SFC_GET_NORM_FLOAT = 0x1011, - SFC_SET_NORM_DOUBLE = 0x1012, - SFC_SET_NORM_FLOAT = 0x1013, - SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, - SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, - SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, - SFC_GET_SIMPLE_FORMAT = 0x1021, - SFC_GET_FORMAT_INFO = 0x1028, - SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, - SFC_GET_FORMAT_MAJOR = 0x1031, - SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, - SFC_GET_FORMAT_SUBTYPE = 0x1033, - SFC_CALC_SIGNAL_MAX = 0x1040, - SFC_CALC_NORM_SIGNAL_MAX = 0x1041, - SFC_CALC_MAX_ALL_CHANNELS = 0x1042, - SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, - SFC_GET_SIGNAL_MAX = 0x1044, - SFC_GET_MAX_ALL_CHANNELS = 0x1045, - SFC_SET_ADD_PEAK_CHUNK = 0x1050, - SFC_UPDATE_HEADER_NOW = 0x1060, - SFC_SET_UPDATE_HEADER_AUTO = 0x1061, - SFC_FILE_TRUNCATE = 0x1080, - SFC_SET_RAW_START_OFFSET = 0x1090, - /* Commands reserved for dithering, which is not implemented. */ - SFC_SET_DITHER_ON_WRITE = 0x10A0, - SFC_SET_DITHER_ON_READ = 0x10A1, - SFC_GET_DITHER_INFO_COUNT = 0x10A2, - SFC_GET_DITHER_INFO = 0x10A3, - SFC_GET_EMBED_FILE_INFO = 0x10B0, - SFC_SET_CLIPPING = 0x10C0, - SFC_GET_CLIPPING = 0x10C1, - SFC_GET_CUE_COUNT = 0x10CD, - SFC_GET_CUE = 0x10CE, - SFC_SET_CUE = 0x10CF, - SFC_GET_INSTRUMENT = 0x10D0, - SFC_SET_INSTRUMENT = 0x10D1, - SFC_GET_LOOP_INFO = 0x10E0, - SFC_GET_BROADCAST_INFO = 0x10F0, - SFC_SET_BROADCAST_INFO = 0x10F1, - SFC_GET_CHANNEL_MAP_INFO = 0x1100, - SFC_SET_CHANNEL_MAP_INFO = 0x1101, - SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110, - /* Support for Wavex Ambisonics Format */ - SFC_WAVEX_SET_AMBISONIC = 0x1200, - SFC_WAVEX_GET_AMBISONIC = 0x1201, - /* - * RF64 files can be set so that on-close, writable files that have less - * than 4GB of data in them are converted to RIFF/WAV, as per EBU - * recommendations. - */ - SFC_RF64_AUTO_DOWNGRADE = 0x1210, - SFC_SET_VBR_ENCODING_QUALITY = 0x1300, - SFC_SET_COMPRESSION_LEVEL = 0x1301, - SFC_SET_OGG_PAGE_LATENCY_MS = 0x1302, - SFC_SET_OGG_PAGE_LATENCY = 0x1303, - SFC_GET_BITRATE_MODE = 0x1302, - SFC_SET_BITRATE_MODE = 0x1303, - /* Cart Chunk support */ - SFC_SET_CART_INFO = 0x1400, - SFC_GET_CART_INFO = 0x1401, - /* Opus files original samplerate metadata */ - SFC_SET_ORIGINAL_SAMPLERATE = 0x1500, - SFC_GET_ORIGINAL_SAMPLERATE = 0x1501, - /* Following commands for testing only. */ - SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, - /* - * These SFC_SET_ADD_* values are deprecated and will disappear at some - * time in the future. They are guaranteed to be here up to and - * including version 1.0.8 to avoid breakage of existing software. - * They currently do nothing and will continue to do nothing. - */ - SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051, - SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, - SFC_SET_ADD_DITHER_ON_READ = 0x1071 -}; - /* - * String types that can be set and read from files. Not all file types - * support this and even the file types which support one, may not support - * all string types. - */ -enum { - SF_STR_TITLE = 0x01, - SF_STR_COPYRIGHT = 0x02, - SF_STR_SOFTWARE = 0x03, - SF_STR_ARTIST = 0x04, - SF_STR_COMMENT = 0x05, - SF_STR_DATE = 0x06, - SF_STR_ALBUM = 0x07, - SF_STR_LICENSE = 0x08, - SF_STR_TRACKNUMBER = 0x09, - SF_STR_GENRE = 0x10 -}; +enum +{ SFC_GET_LIB_VERSION = 0x1000, + SFC_GET_LOG_INFO = 0x1001, + SFC_GET_CURRENT_SF_INFO = 0x1002, + + + SFC_GET_NORM_DOUBLE = 0x1010, + SFC_GET_NORM_FLOAT = 0x1011, + SFC_SET_NORM_DOUBLE = 0x1012, + SFC_SET_NORM_FLOAT = 0x1013, + SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, + SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, + + SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, + SFC_GET_SIMPLE_FORMAT = 0x1021, + + SFC_GET_FORMAT_INFO = 0x1028, + + SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, + SFC_GET_FORMAT_MAJOR = 0x1031, + SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, + SFC_GET_FORMAT_SUBTYPE = 0x1033, + + SFC_CALC_SIGNAL_MAX = 0x1040, + SFC_CALC_NORM_SIGNAL_MAX = 0x1041, + SFC_CALC_MAX_ALL_CHANNELS = 0x1042, + SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, + SFC_GET_SIGNAL_MAX = 0x1044, + SFC_GET_MAX_ALL_CHANNELS = 0x1045, + + SFC_SET_ADD_PEAK_CHUNK = 0x1050, + + SFC_UPDATE_HEADER_NOW = 0x1060, + SFC_SET_UPDATE_HEADER_AUTO = 0x1061, + + SFC_FILE_TRUNCATE = 0x1080, + + SFC_SET_RAW_START_OFFSET = 0x1090, + + /* Commands reserved for dithering, which is not implemented. */ + SFC_SET_DITHER_ON_WRITE = 0x10A0, + SFC_SET_DITHER_ON_READ = 0x10A1, + + SFC_GET_DITHER_INFO_COUNT = 0x10A2, + SFC_GET_DITHER_INFO = 0x10A3, + + SFC_GET_EMBED_FILE_INFO = 0x10B0, + + SFC_SET_CLIPPING = 0x10C0, + SFC_GET_CLIPPING = 0x10C1, + + SFC_GET_CUE_COUNT = 0x10CD, + SFC_GET_CUE = 0x10CE, + SFC_SET_CUE = 0x10CF, + + SFC_GET_INSTRUMENT = 0x10D0, + SFC_SET_INSTRUMENT = 0x10D1, + + SFC_GET_LOOP_INFO = 0x10E0, + + SFC_GET_BROADCAST_INFO = 0x10F0, + SFC_SET_BROADCAST_INFO = 0x10F1, + + SFC_GET_CHANNEL_MAP_INFO = 0x1100, + SFC_SET_CHANNEL_MAP_INFO = 0x1101, + + SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110, + + /* Support for Wavex Ambisonics Format */ + SFC_WAVEX_SET_AMBISONIC = 0x1200, + SFC_WAVEX_GET_AMBISONIC = 0x1201, + + /* + ** RF64 files can be set so that on-close, writable files that have less + ** than 4GB of data in them are converted to RIFF/WAV, as per EBU + ** recommendations. + */ + SFC_RF64_AUTO_DOWNGRADE = 0x1210, + + 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, + + /* Cart Chunk support */ + SFC_SET_CART_INFO = 0x1400, + SFC_GET_CART_INFO = 0x1401, + + /* Opus files original samplerate metadata */ + SFC_SET_ORIGINAL_SAMPLERATE = 0x1500, + SFC_GET_ORIGINAL_SAMPLERATE = 0x1501, + + /* Following commands for testing only. */ + SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, + + /* + ** These SFC_SET_ADD_* values are deprecated and will disappear at some + ** time in the future. They are guaranteed to be here up to and + ** including version 1.0.8 to avoid breakage of existing software. + ** They currently do nothing and will continue to do nothing. + */ + SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051, + + SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, + SFC_SET_ADD_DITHER_ON_READ = 0x1071 +} ; + /* - * Use the following as the start and end index when doing metadata - * transcoding. +** String types that can be set and read from files. Not all file types +** support this and even the file types which support one, may not support +** all string types. */ -#define SF_STR_FIRST SF_STR_TITLE -#define SF_STR_LAST SF_STR_GENRE +enum +{ SF_STR_TITLE = 0x01, + SF_STR_COPYRIGHT = 0x02, + SF_STR_SOFTWARE = 0x03, + SF_STR_ARTIST = 0x04, + SF_STR_COMMENT = 0x05, + SF_STR_DATE = 0x06, + SF_STR_ALBUM = 0x07, + SF_STR_LICENSE = 0x08, + SF_STR_TRACKNUMBER = 0x09, + SF_STR_GENRE = 0x10 +} ; -enum { - /* True and false */ - SF_FALSE = 0, - SF_TRUE = 1, - /* Modes for opening files. */ - SFM_READ = 0x10, - SFM_WRITE = 0x20, - SFM_RDWR = 0x30, +/* +** Use the following as the start and end index when doing metadata +** transcoding. +*/ - SF_AMBISONIC_NONE = 0x40, - SF_AMBISONIC_B_FORMAT = 0x41 -}; +#define SF_STR_FIRST SF_STR_TITLE +#define SF_STR_LAST SF_STR_GENRE + +enum +{ /* True and false */ + SF_FALSE = 0, + SF_TRUE = 1, + + /* Modes for opening files. */ + SFM_READ = 0x10, + SFM_WRITE = 0x20, + SFM_RDWR = 0x30, + + SF_AMBISONIC_NONE = 0x40, + SF_AMBISONIC_B_FORMAT = 0x41 +} ; /* Public error values. These are guaranteed to remain unchanged for the duration - * of the library major version number. - * There are also a large number of private error numbers which are internal to - * the library which can change at any time. +** of the library major version number. +** There are also a large number of private error numbers which are internal to +** the library which can change at any time. */ -enum { - SF_ERR_NO_ERROR = 0, - SF_ERR_UNRECOGNISED_FORMAT = 1, - SF_ERR_SYSTEM = 2, - SF_ERR_MALFORMED_FILE = 3, - SF_ERR_UNSUPPORTED_ENCODING = 4 -}; +enum +{ SF_ERR_NO_ERROR = 0, + SF_ERR_UNRECOGNISED_FORMAT = 1, + SF_ERR_SYSTEM = 2, + SF_ERR_MALFORMED_FILE = 3, + SF_ERR_UNSUPPORTED_ENCODING = 4 +} ; /* Channel map values (used with SFC_SET/GET_CHANNEL_MAP). */ -enum { - SF_CHANNEL_MAP_INVALID = 0, - SF_CHANNEL_MAP_MONO = 1, - SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */ - SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */ - SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */ - SF_CHANNEL_MAP_FRONT_LEFT, - SF_CHANNEL_MAP_FRONT_RIGHT, - SF_CHANNEL_MAP_FRONT_CENTER, - SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */ - SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */ - SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */ - SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */ - SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */ - SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */ - SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */ - SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */ - SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */ - SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */ - SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */ - SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */ - SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */ - SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */ - SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */ - SF_CHANNEL_MAP_AMBISONIC_B_W, - SF_CHANNEL_MAP_AMBISONIC_B_X, - SF_CHANNEL_MAP_AMBISONIC_B_Y, - SF_CHANNEL_MAP_AMBISONIC_B_Z, - SF_CHANNEL_MAP_MAX -}; +enum +{ SF_CHANNEL_MAP_INVALID = 0, + SF_CHANNEL_MAP_MONO = 1, + SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */ + SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */ + SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */ + SF_CHANNEL_MAP_FRONT_LEFT, + SF_CHANNEL_MAP_FRONT_RIGHT, + SF_CHANNEL_MAP_FRONT_CENTER, + SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */ + SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */ + SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */ + SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */ + SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */ + SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */ + SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */ + SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */ + SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */ + SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */ + SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */ + SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */ + SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */ + SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */ + SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */ + + SF_CHANNEL_MAP_AMBISONIC_B_W, + SF_CHANNEL_MAP_AMBISONIC_B_X, + SF_CHANNEL_MAP_AMBISONIC_B_Y, + SF_CHANNEL_MAP_AMBISONIC_B_Z, + + SF_CHANNEL_MAP_MAX +} ; /* Bitrate mode values (for use with SFC_GET/SET_BITRATE_MODE) */ -enum { - SF_BITRATE_MODE_CONSTANT = 0, - SF_BITRATE_MODE_AVERAGE, - SF_BITRATE_MODE_VARIABLE -}; +enum +{ SF_BITRATE_MODE_CONSTANT = 0, + SF_BITRATE_MODE_AVERAGE, + SF_BITRATE_MODE_VARIABLE +} ; /* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ -typedef struct sf_private_tag SNDFILE; +typedef struct sf_private_tag SNDFILE ; /* The following typedef is system specific and is defined when libsndfile is - * compiled. sf_count_t will be a 64 bit value when the underlying OS allows - * 64 bit file offsets. - * On windows, we need to allow the same header file to be compiler by both GCC - * and the Microsoft compiler. +** compiled. sf_count_t will be a 64 bit value when the underlying OS allows +** 64 bit file offsets. +** On windows, we need to allow the same header file to be compiler by both GCC +** and the Microsoft compiler. */ -typedef int64_t sf_count_t; +typedef int64_t sf_count_t ; #ifndef SF_COUNT_MAX -#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL +#define SF_COUNT_MAX INT64_MAX #endif /* A pointer to a SF_INFO structure is passed to sf_open () and filled in. - * On write, the SF_INFO structure is filled in by the user and passed into - * sf_open (). +** On write, the SF_INFO structure is filled in by the user and passed into +** sf_open (). */ -struct SF_INFO { - sf_count_t frames; /* Used to be called samples. Changed to avoid confusion. */ - int samplerate; - int channels; - int format; - int sections; - int seekable; -}; +struct SF_INFO +{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ + int samplerate ; + int channels ; + int format ; + int sections ; + int seekable ; +} ; -typedef struct SF_INFO SF_INFO; +typedef struct SF_INFO SF_INFO ; /* The SF_FORMAT_INFO struct is used to retrieve information about the sound - * file formats libsndfile supports using the sf_command () interface. - * - * Using this interface will allow applications to support new file formats - * and encoding types when libsndfile is upgraded, without requiring - * re-compilation of the application. - * - * Please consult the libsndfile documentation (particularly the information - * on the sf_command () interface) for examples of its use. +** file formats libsndfile supports using the sf_command () interface. +** +** Using this interface will allow applications to support new file formats +** and encoding types when libsndfile is upgraded, without requiring +** re-compilation of the application. +** +** Please consult the libsndfile documentation (particularly the information +** on the sf_command () interface) for examples of its use. */ -typedef struct { - int format; - const char *name; - const char *extension; -} SF_FORMAT_INFO; +typedef struct +{ int format ; + const char *name ; + const char *extension ; +} SF_FORMAT_INFO ; /* - * Enums and typedefs for adding dither on read and write. - * Reserved for future implementation. +** Enums and typedefs for adding dither on read and write. +** Reserved for future implementation. */ -enum { - SFD_DEFAULT_LEVEL = 0, - SFD_CUSTOM_LEVEL = 0x40000000, - SFD_NO_DITHER = 500, - SFD_WHITE = 501, - SFD_TRIANGULAR_PDF = 502 -}; +enum +{ SFD_DEFAULT_LEVEL = 0, + SFD_CUSTOM_LEVEL = 0x40000000, -typedef struct { - int type; - double level; - const char *name; -} SF_DITHER_INFO; + SFD_NO_DITHER = 500, + SFD_WHITE = 501, + SFD_TRIANGULAR_PDF = 502 +} ; - /* Struct used to retrieve information about a file embedded within a - * larger file. See SFC_GET_EMBED_FILE_INFO. - */ +typedef struct +{ int type ; + double level ; + const char *name ; +} SF_DITHER_INFO ; -typedef struct { - sf_count_t offset; - sf_count_t length; -} SF_EMBED_FILE_INFO; +/* Struct used to retrieve information about a file embedded within a +** larger file. See SFC_GET_EMBED_FILE_INFO. +*/ + +typedef struct +{ sf_count_t offset ; + sf_count_t length ; +} SF_EMBED_FILE_INFO ; /* - * Struct used to retrieve cue marker information from a file +** Struct used to retrieve cue marker information from a file */ -typedef struct { - int32_t indx; - uint32_t position; - int32_t fcc_chunk; - int32_t chunk_start; - int32_t block_start; - uint32_t sample_offset; - char name [256]; -} SF_CUE_POINT; +typedef struct +{ int32_t indx ; + uint32_t position ; + int32_t fcc_chunk ; + int32_t chunk_start ; + int32_t block_start ; + uint32_t sample_offset ; + char name [256] ; +} SF_CUE_POINT ; -#define SF_CUES_VAR(count) \ - struct \ - { \ - uint32_t cue_count; \ - SF_CUE_POINT cue_points [count]; \ - } +#define SF_CUES_VAR(count) \ + struct \ + { uint32_t cue_count ; \ + SF_CUE_POINT cue_points [count] ; \ + } -typedef SF_CUES_VAR (100) SF_CUES; +typedef SF_CUES_VAR (100) SF_CUES ; /* - * Structs used to retrieve music sample information from a file. +** Structs used to retrieve music sample information from a file. */ -enum { - /* - * The loop mode field in SF_INSTRUMENT will be one of the following. - */ - SF_LOOP_NONE = 800, - SF_LOOP_FORWARD, - SF_LOOP_BACKWARD, - SF_LOOP_ALTERNATING -}; +enum +{ /* + ** The loop mode field in SF_INSTRUMENT will be one of the following. + */ + SF_LOOP_NONE = 800, + SF_LOOP_FORWARD, + SF_LOOP_BACKWARD, + SF_LOOP_ALTERNATING +} ; -typedef struct { - int gain; - char basenote, detune; - char velocity_lo, velocity_hi; - char key_lo, key_hi; - int loop_count; +typedef struct +{ int gain ; + char basenote, detune ; + char velocity_lo, velocity_hi ; + char key_lo, key_hi ; + int loop_count ; - struct { - int mode; - uint32_t start; - uint32_t end; - uint32_t count; - } loops [16]; /* make variable in a sensible way */ -} SF_INSTRUMENT; - -/* Struct used to retrieve loop information from a file. */ -typedef struct { - short time_sig_num; /* any positive integer > 0 */ - short time_sig_den; /* any positive power of 2 > 0 */ - int loop_mode; /* see SF_LOOP enum */ - - int num_beats; /* this is NOT the amount of quarter notes !!! */ - /* a full bar of 4/4 is 4 beats */ - /* a full bar of 7/8 is 7 beats */ - - float bpm; /* suggestion, as it can be calculated using other fields: */ - /* file's length, file's sampleRate and our time_sig_den */ - /* -> bpms are always the amount of _quarter notes_ per minute */ - - int root_key; /* MIDI note, or -1 for None */ - int future [6]; -} SF_LOOP_INFO; + struct + { int mode ; + uint32_t start ; + uint32_t end ; + uint32_t count ; + } loops [16] ; /* make variable in a sensible way */ +} SF_INSTRUMENT ; -/* Struct used to retrieve broadcast (EBU) information from a file. - * Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. + +/* Struct used to retrieve loop information from a file.*/ +typedef struct +{ + short time_sig_num ; /* any positive integer > 0 */ + short time_sig_den ; /* any positive power of 2 > 0 */ + int loop_mode ; /* see SF_LOOP enum */ + + int num_beats ; /* this is NOT the amount of quarter notes !!!*/ + /* a full bar of 4/4 is 4 beats */ + /* a full bar of 7/8 is 7 beats */ + + float bpm ; /* suggestion, as it can be calculated using other fields:*/ + /* file's length, file's sampleRate and our time_sig_den*/ + /* -> bpms are always the amount of _quarter notes_ per minute */ + + int root_key ; /* MIDI note, or -1 for None */ + int future [6] ; +} SF_LOOP_INFO ; + + +/* Struct used to retrieve broadcast (EBU) information from a file. +** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. */ -#define SF_BROADCAST_INFO_VAR(coding_hist_size) \ - struct \ - { \ - char description [256]; \ - char originator [32]; \ - char originator_reference [32]; \ - char origination_date [10]; \ - char origination_time [8]; \ - uint32_t time_reference_low; \ - uint32_t time_reference_high; \ - short version; \ - char umid [64]; \ - int16_t loudness_value; \ - int16_t loudness_range; \ - int16_t max_true_peak_level; \ - int16_t max_momentary_loudness; \ - int16_t max_shortterm_loudness; \ - char reserved [180]; \ - uint32_t coding_history_size; \ - char coding_history [coding_hist_size]; \ - } +#define SF_BROADCAST_INFO_VAR(coding_hist_size) \ + struct \ + { char description [256] ; \ + char originator [32] ; \ + char originator_reference [32] ; \ + char origination_date [10] ; \ + char origination_time [8] ; \ + uint32_t time_reference_low ; \ + uint32_t time_reference_high ; \ + short version ; \ + char umid [64] ; \ + int16_t loudness_value ; \ + int16_t loudness_range ; \ + int16_t max_true_peak_level ; \ + int16_t max_momentary_loudness ; \ + int16_t max_shortterm_loudness ; \ + char reserved [180] ; \ + uint32_t coding_history_size ; \ + char coding_history [coding_hist_size] ; \ + } /* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */ -typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO; +typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ; -struct SF_CART_TIMER { - char usage [4]; - int32_t value; -}; +struct SF_CART_TIMER +{ char usage [4] ; + int32_t value ; +} ; -typedef struct SF_CART_TIMER SF_CART_TIMER; +typedef struct SF_CART_TIMER SF_CART_TIMER ; -#define SF_CART_INFO_VAR(p_tag_text_size) \ - struct \ - { \ - char version [4]; \ - char title [64]; \ - char artist [64]; \ - char cut_id [64]; \ - char client_id [64]; \ - char category [64]; \ - char classification [64]; \ - char out_cue [64]; \ - char start_date [10]; \ - char start_time [8]; \ - char end_date [10]; \ - char end_time [8]; \ - char producer_app_id [64]; \ - char producer_app_version [64]; \ - char user_def [64]; \ - int32_t level_reference; \ - SF_CART_TIMER post_timers [8]; \ - char reserved [276]; \ - char url [1024]; \ - uint32_t tag_text_size; \ - char tag_text [p_tag_text_size]; \ - } +#define SF_CART_INFO_VAR(p_tag_text_size) \ + struct \ + { char version [4] ; \ + char title [64] ; \ + char artist [64] ; \ + char cut_id [64] ; \ + char client_id [64] ; \ + char category [64] ; \ + char classification [64] ; \ + char out_cue [64] ; \ + char start_date [10] ; \ + char start_time [8] ; \ + char end_date [10] ; \ + char end_time [8] ; \ + char producer_app_id [64] ; \ + char producer_app_version [64] ; \ + char user_def [64] ; \ + int32_t level_reference ; \ + SF_CART_TIMER post_timers [8] ; \ + char reserved [276] ; \ + char url [1024] ; \ + uint32_t tag_text_size ; \ + char tag_text [p_tag_text_size] ; \ + } -typedef SF_CART_INFO_VAR (256) SF_CART_INFO; +typedef SF_CART_INFO_VAR (256) SF_CART_INFO ; -/* Virtual I/O functionality. */ +/* Virtual I/O functionality. */ -typedef sf_count_t (*sf_vio_get_filelen) (void *user_data); -typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data); -typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data); -typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data); -typedef sf_count_t (*sf_vio_tell) (void *user_data); +typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; +typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; +typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_tell) (void *user_data) ; -struct SF_VIRTUAL_IO { - sf_vio_get_filelen get_filelen; - sf_vio_seek seek; - sf_vio_read read; - sf_vio_write write; - sf_vio_tell tell; -}; +struct SF_VIRTUAL_IO +{ sf_vio_get_filelen get_filelen ; + sf_vio_seek seek ; + sf_vio_read read ; + sf_vio_write write ; + sf_vio_tell tell ; +} ; -typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO; +typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ; /* Open the specified file for read, write or both. On error, this will - * return a NULL pointer. To find the error number, pass a NULL SNDFILE - * to sf_strerror (). - * All calls to sf_open() should be matched with a call to sf_close(). +** return a NULL pointer. To find the error number, pass a NULL SNDFILE +** to sf_strerror (). +** All calls to sf_open() should be matched with a call to sf_close(). */ -SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo); +SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; /* Use the existing file descriptor to create a SNDFILE object. If close_desc - * is TRUE, the file descriptor will be closed when sf_close() is called. If - * it is FALSE, the descriptor will not be closed. - * When passed a descriptor like this, the library will assume that the start - * of file header is at the current file offset. This allows sound files within - * larger container files to be read and/or written. - * On error, this will return a NULL pointer. To find the error number, pass a - * NULL SNDFILE to sf_strerror (). - * All calls to sf_open_fd() should be matched with a call to sf_close(). +** is TRUE, the file descriptor will be closed when sf_close() is called. If +** it is FALSE, the descriptor will not be closed. +** When passed a descriptor like this, the library will assume that the start +** of file header is at the current file offset. This allows sound files within +** larger container files to be read and/or written. +** On error, this will return a NULL pointer. To find the error number, pass a +** NULL SNDFILE to sf_strerror (). +** All calls to sf_open_fd() should be matched with a call to sf_close(). */ -SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc); +SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; -SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data); +SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; /* sf_error () returns a error number which can be translated to a text - * string using sf_error_number(). +** string using sf_error_number(). */ -int sf_error (SNDFILE *sndfile); +int sf_error (SNDFILE *sndfile) ; /* sf_strerror () returns to the caller a pointer to the current error message for - * the given SNDFILE. +** the given SNDFILE. */ -const char* sf_strerror (SNDFILE *sndfile); +const char* sf_strerror (SNDFILE *sndfile) ; /* sf_error_number () allows the retrieval of the error string for each internal - * error number. - * +** error number. +** */ -const char* sf_error_number (int errnum); +const char* sf_error_number (int errnum) ; /* The following two error functions are deprecated but they will remain in the - * library for the foreseeable future. The function sf_strerror() should be used - * in their place. +** library for the foreseeable future. The function sf_strerror() should be used +** in their place. */ -int sf_perror (SNDFILE *sndfile); -int sf_error_str (SNDFILE *sndfile, char* str, size_t len); +int sf_perror (SNDFILE *sndfile) ; +int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; /* Allow the caller to retrieve information from or change aspects of the - * library behaviour. +** library behaviour. */ -int sf_command (SNDFILE *sndfile, int command, void *data, int datasize); +int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ -int sf_format_check (const SF_INFO *info); +int sf_format_check (const SF_INFO *info) ; /* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses - * the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as - * stdio.h function fseek (). - * An offset of zero with whence set to SEEK_SET will position the - * read / write pointer to the first data sample. - * On success sf_seek returns the current position in (multi-channel) - * samples from the start of the file. - * Please see the libsndfile documentation for moving the read pointer - * separately from the write pointer on files open in mode SFM_RDWR. - * On error all of these functions return -1. +** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as +** stdio.h function fseek (). +** An offset of zero with whence set to SEEK_SET will position the +** read / write pointer to the first data sample. +** On success sf_seek returns the current position in (multi-channel) +** samples from the start of the file. +** Please see the libsndfile documentation for moving the read pointer +** separately from the write pointer on files open in mode SFM_RDWR. +** On error all of these functions return -1. */ -enum { - SF_SEEK_SET = SEEK_SET, - SF_SEEK_CUR = SEEK_CUR, - SF_SEEK_END = SEEK_END -}; +enum +{ SF_SEEK_SET = SEEK_SET, + SF_SEEK_CUR = SEEK_CUR, + SF_SEEK_END = SEEK_END +} ; + +sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; -sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence); /* Functions for retrieving and setting string data within sound files. - * Not all file types support this features; AIFF and WAV do. For both - * functions, the str_type parameter must be one of the SF_STR_* values - * defined above. - * On error, sf_set_string() returns non-zero while sf_get_string() - * returns NULL. +** Not all file types support this features; AIFF and WAV do. For both +** functions, the str_type parameter must be one of the SF_STR_* values +** defined above. +** On error, sf_set_string() returns non-zero while sf_get_string() +** returns NULL. */ -int sf_set_string (SNDFILE *sndfile, int str_type, const char* str); +int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; -const char* sf_get_string (SNDFILE *sndfile, int str_type); +const char* sf_get_string (SNDFILE *sndfile, int str_type) ; /* Return the library version string. */ -const char * sf_version_string (void); +const char * sf_version_string (void) ; /* Return the current byterate at this point in the file. The byte rate in this - * case is the number of bytes per second of audio data. For instance, for a - * stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate - * would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec. - * For some file formats the returned value will be accurate and exact, for some - * it will be a close approximation, for some it will be the average bitrate for - * the whole file and for some it will be a time varying value that was accurate - * when the file was most recently read or written. - * To get the bitrate, multiple this value by 8. - * Returns -1 for unknown. +** case is the number of bytes per second of audio data. For instance, for a +** stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate +** would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec. +** For some file formats the returned value will be accurate and exact, for some +** it will be a close approximation, for some it will be the average bitrate for +** the whole file and for some it will be a time varying value that was accurate +** when the file was most recently read or written. +** To get the bitrate, multiple this value by 8. +** Returns -1 for unknown. */ -int sf_current_byterate (SNDFILE *sndfile); +int sf_current_byterate (SNDFILE *sndfile) ; /* Functions for reading/writing the waveform data of a sound file. */ -sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes); -sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes); +sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ; + /* Functions for reading and writing the data chunk in terms of frames. - * The number of items actually read/written = frames * number of channels. - * sf_xxxx_raw read/writes the raw data bytes from/to the file - * sf_xxxx_short passes data in the native short format - * sf_xxxx_int passes data in the native int format - * sf_xxxx_float passes data in the native float format - * sf_xxxx_double passes data in the native double format - * All of these read/write function return number of frames read/written. +** The number of items actually read/written = frames * number of channels. +** sf_xxxx_raw read/writes the raw data bytes from/to the file +** sf_xxxx_short passes data in the native short format +** sf_xxxx_int passes data in the native int format +** sf_xxxx_float passes data in the native float format +** sf_xxxx_double passes data in the native double format +** All of these read/write function return number of frames read/written. */ -sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames); -sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames); +sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; +sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ; -sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames); -sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames); +sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; +sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ; -sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames); -sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames); +sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; +sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ; -sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames); -sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames); +sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; +sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ; /* Functions for reading and writing the data chunk in terms of items. - * Otherwise similar to above. - * All of these read/write function return number of items read/written. +** Otherwise similar to above. +** All of these read/write function return number of items read/written. */ -sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items); -sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items); +sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ; -sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items); -sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items); +sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ; -sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items); -sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items); +sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; -sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items); -sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items); +sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; +sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ; /* Close the SNDFILE and clean up all memory allocations associated with this - * file. - * Returns 0 on success, or an error number. +** file. +** Returns 0 on success, or an error number. */ -int sf_close (SNDFILE *sndfile); +int sf_close (SNDFILE *sndfile) ; /* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file - * to force the writing of data to disk. If the file is opened SFM_READ - * no action is taken. +** to force the writing of data to disk. If the file is opened SFM_READ +** no action is taken. */ -void sf_write_sync (SNDFILE *sndfile); +void sf_write_sync (SNDFILE *sndfile) ; + + /* The function sf_wchar_open() is Windows Only! - * Open a file passing in a Windows Unicode filename. Otherwise, this is - * the same as sf_open(). +** Open a file passing in a Windows Unicode filename. Otherwise, this is +** the same as sf_open(). */ #ifdef _WIN32 -SNDFILE* sf_wchar_open (const wchar_t *wpath, int mode, SF_INFO *sfinfo); +SNDFILE* sf_wchar_open (const wchar_t *wpath, int mode, SF_INFO *sfinfo) ; #endif + + + /* Getting and setting of chunks from within a sound file. - * - * These functions allow the getting and setting of chunks within a sound file - * (for those formats which allow it). - * - * These functions fail safely. Specifically, they will not allow you to overwrite - * existing chunks or add extra versions of format specific reserved chunks but - * should allow you to retrieve any and all chunks (may not be implemented for - * all chunks or all file formats). +** +** These functions allow the getting and setting of chunks within a sound file +** (for those formats which allow it). +** +** These functions fail safely. Specifically, they will not allow you to overwrite +** existing chunks or add extra versions of format specific reserved chunks but +** should allow you to retrieve any and all chunks (may not be implemented for +** all chunks or all file formats). */ -struct SF_CHUNK_INFO { - char id [64]; /* The chunk identifier. */ - unsigned id_size; /* The size of the chunk identifier. */ - unsigned datalen; /* The size of that data. */ - void *data; /* Pointer to the data. */ -}; +struct SF_CHUNK_INFO +{ char id [64] ; /* The chunk identifier. */ + unsigned id_size ; /* The size of the chunk identifier. */ + unsigned datalen ; /* The size of that data. */ + void *data ; /* Pointer to the data. */ +} ; -typedef struct SF_CHUNK_INFO SF_CHUNK_INFO; +typedef struct SF_CHUNK_INFO SF_CHUNK_INFO ; /* Set the specified chunk info (must be done before any audio data is written - * to the file). This will fail for format specific reserved chunks. - * The chunk_info->data pointer must be valid until the file is closed. - * Returns SF_ERR_NO_ERROR on success or non-zero on failure. +** to the file). This will fail for format specific reserved chunks. +** The chunk_info->data pointer must be valid until the file is closed. +** Returns SF_ERR_NO_ERROR on success or non-zero on failure. */ -int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info); +int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ; /* - * An opaque structure to an iterator over the all chunks of a given id +** An opaque structure to an iterator over the all chunks of a given id */ -typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR; +typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ; /* Get an iterator for all chunks matching chunk_info. - * The iterator will point to the first chunk matching chunk_info. - * Chunks are matching, if (chunk_info->id) matches the first - * (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle. - * If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle - * is returned. - * The values of chunk_info->datalen and chunk_info->data are ignored. - * If no matching chunks are found in the sndfile, NULL is returned. - * The returned iterator will stay valid until one of the following occurs - * a) The sndfile is closed. - * b) A new chunk is added using sf_set_chunk(). - * c) Another chunk iterator function is called on the same SNDFILE* handle - * that causes the iterator to be modified. - * The memory for the iterator belongs to the SNDFILE* handle and is freed when - * sf_close() is called. +** The iterator will point to the first chunk matching chunk_info. +** Chunks are matching, if (chunk_info->id) matches the first +** (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle. +** If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle +** is returned. +** The values of chunk_info->datalen and chunk_info->data are ignored. +** If no matching chunks are found in the sndfile, NULL is returned. +** The returned iterator will stay valid until one of the following occurs: +** a) The sndfile is closed. +** b) A new chunk is added using sf_set_chunk(). +** c) Another chunk iterator function is called on the same SNDFILE* handle +** that causes the iterator to be modified. +** The memory for the iterator belongs to the SNDFILE* handle and is freed when +** sf_close() is called. */ -SF_CHUNK_ITERATOR * sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info); +SF_CHUNK_ITERATOR * +sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ; /* Iterate through chunks by incrementing the iterator. - * Increments the iterator and returns a handle to the new one. - * After this call, iterator will no longer be valid, and you must use the - * newly returned handle from now on. - * The returned handle can be used to access the next chunk matching - * the criteria as defined in sf_get_chunk_iterator(). - * If iterator points to the last chunk, this will free all resources - * associated with iterator and return NULL. - * The returned iterator will stay valid until sf_get_chunk_iterator_next - * is called again, the sndfile is closed or a new chunk us added. +** Increments the iterator and returns a handle to the new one. +** After this call, iterator will no longer be valid, and you must use the +** newly returned handle from now on. +** The returned handle can be used to access the next chunk matching +** the criteria as defined in sf_get_chunk_iterator(). +** If iterator points to the last chunk, this will free all resources +** associated with iterator and return NULL. +** The returned iterator will stay valid until sf_get_chunk_iterator_next +** is called again, the sndfile is closed or a new chunk us added. */ -SF_CHUNK_ITERATOR * sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator); +SF_CHUNK_ITERATOR * +sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ; + /* Get the size of the specified chunk. - * If the specified chunk exists, the size will be returned in the - * datalen field of the SF_CHUNK_INFO struct. - * Additionally, the id of the chunk will be copied to the id - * field of the SF_CHUNK_INFO struct and it's id_size field will - * be updated accordingly. - * If the chunk doesn't exist chunk_info->datalen will be zero, and the - * id and id_size fields will be undefined. - * The function will return SF_ERR_NO_ERROR on success or non-zero on - * failure. +** If the specified chunk exists, the size will be returned in the +** datalen field of the SF_CHUNK_INFO struct. +** Additionally, the id of the chunk will be copied to the id +** field of the SF_CHUNK_INFO struct and it's id_size field will +** be updated accordingly. +** If the chunk doesn't exist chunk_info->datalen will be zero, and the +** id and id_size fields will be undefined. +** The function will return SF_ERR_NO_ERROR on success or non-zero on +** failure. */ -int sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info); +int +sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ; /* Get the specified chunk data. - * If the specified chunk exists, up to chunk_info->datalen bytes of - * the chunk data will be copied into the chunk_info->data buffer - * (allocated by the caller) and the chunk_info->datalen field - * updated to reflect the size of the data. The id and id_size - * field will be updated according to the retrieved chunk - * If the chunk doesn't exist chunk_info->datalen will be zero, and the - * id and id_size fields will be undefined. - * The function will return SF_ERR_NO_ERROR on success or non-zero on - * failure. +** If the specified chunk exists, up to chunk_info->datalen bytes of +** the chunk data will be copied into the chunk_info->data buffer +** (allocated by the caller) and the chunk_info->datalen field +** updated to reflect the size of the data. The id and id_size +** field will be updated according to the retrieved chunk +** If the chunk doesn't exist chunk_info->datalen will be zero, and the +** id and id_size fields will be undefined. +** The function will return SF_ERR_NO_ERROR on success or non-zero on +** failure. */ -int sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info); +int +sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ; + #ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ +} /* extern "C" */ +#endif /* __cplusplus */ -#endif /* SNDFILE_H */ +#endif /* SNDFILE_H */ diff --git a/include/sndfile.h.in b/include/sndfile.h.in deleted file mode 100644 index 917ff4b5..00000000 --- a/include/sndfile.h.in +++ /dev/null @@ -1,872 +0,0 @@ -/* -** Copyright (C) 1999-2016 Erik de Castro Lopo -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* -** sndfile.h -- system-wide definitions -** -** API documentation is in the doc/ directory of the source code tarball -** and at http://libsndfile.github.io/libsndfile/api.html. -*/ - -#ifndef SNDFILE_H -#define SNDFILE_H - -/* This is the version 1.0.X header file. */ -#define SNDFILE_1 - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* The following file types can be read and written. -** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise -** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and -** SF_FORMAT_SUBMASK can be used to separate the major and minor file -** types. -*/ - -enum -{ /* Major formats. */ - SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ - SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ - SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ - SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ - SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ - SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ - SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ - SF_FORMAT_VOC = 0x080000, /* VOC files. */ - SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ - SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ - SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ - SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ - SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ - SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ - SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ - SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ - SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ - SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ - SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ - SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ - SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ - SF_FORMAT_WVE = 0x190000, /* Psion WVE format */ - SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ - SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ - SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ - - /* Subtypes from here on. */ - - SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ - SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ - SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ - SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ - - SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ - - SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ - SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ - - SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ - SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ - SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ - SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ - - SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ - SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ - - SF_FORMAT_NMS_ADPCM_16 = 0x0022, /* 16kbs NMS G721-variant encoding. */ - SF_FORMAT_NMS_ADPCM_24 = 0x0023, /* 24kbs NMS G721-variant encoding. */ - SF_FORMAT_NMS_ADPCM_32 = 0x0024, /* 32kbs NMS G721-variant encoding. */ - - SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ - SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ - SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ - - SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ - - SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ - SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ - - SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */ - SF_FORMAT_OPUS = 0x0064, /* Xiph/Skype Opus encoding. */ - - SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */ - SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */ - SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */ - SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */ - - /* Endian-ness options. */ - - SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ - SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ - SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ - SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ - - SF_FORMAT_SUBMASK = 0x0000FFFF, - SF_FORMAT_TYPEMASK = 0x0FFF0000, - SF_FORMAT_ENDMASK = 0x30000000 -} ; - -/* -** The following are the valid command numbers for the sf_command() -** interface. The use of these commands is documented in the file -** command.html in the doc directory of the source code distribution. -*/ - -enum -{ SFC_GET_LIB_VERSION = 0x1000, - SFC_GET_LOG_INFO = 0x1001, - SFC_GET_CURRENT_SF_INFO = 0x1002, - - - SFC_GET_NORM_DOUBLE = 0x1010, - SFC_GET_NORM_FLOAT = 0x1011, - SFC_SET_NORM_DOUBLE = 0x1012, - SFC_SET_NORM_FLOAT = 0x1013, - SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, - SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, - - SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, - SFC_GET_SIMPLE_FORMAT = 0x1021, - - SFC_GET_FORMAT_INFO = 0x1028, - - SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, - SFC_GET_FORMAT_MAJOR = 0x1031, - SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, - SFC_GET_FORMAT_SUBTYPE = 0x1033, - - SFC_CALC_SIGNAL_MAX = 0x1040, - SFC_CALC_NORM_SIGNAL_MAX = 0x1041, - SFC_CALC_MAX_ALL_CHANNELS = 0x1042, - SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, - SFC_GET_SIGNAL_MAX = 0x1044, - SFC_GET_MAX_ALL_CHANNELS = 0x1045, - - SFC_SET_ADD_PEAK_CHUNK = 0x1050, - - SFC_UPDATE_HEADER_NOW = 0x1060, - SFC_SET_UPDATE_HEADER_AUTO = 0x1061, - - SFC_FILE_TRUNCATE = 0x1080, - - SFC_SET_RAW_START_OFFSET = 0x1090, - - SFC_SET_DITHER_ON_WRITE = 0x10A0, - SFC_SET_DITHER_ON_READ = 0x10A1, - - SFC_GET_DITHER_INFO_COUNT = 0x10A2, - SFC_GET_DITHER_INFO = 0x10A3, - - SFC_GET_EMBED_FILE_INFO = 0x10B0, - - SFC_SET_CLIPPING = 0x10C0, - SFC_GET_CLIPPING = 0x10C1, - - SFC_GET_CUE_COUNT = 0x10CD, - SFC_GET_CUE = 0x10CE, - SFC_SET_CUE = 0x10CF, - - SFC_GET_INSTRUMENT = 0x10D0, - SFC_SET_INSTRUMENT = 0x10D1, - - SFC_GET_LOOP_INFO = 0x10E0, - - SFC_GET_BROADCAST_INFO = 0x10F0, - SFC_SET_BROADCAST_INFO = 0x10F1, - - SFC_GET_CHANNEL_MAP_INFO = 0x1100, - SFC_SET_CHANNEL_MAP_INFO = 0x1101, - - SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110, - - /* Support for Wavex Ambisonics Format */ - SFC_WAVEX_SET_AMBISONIC = 0x1200, - SFC_WAVEX_GET_AMBISONIC = 0x1201, - - /* - ** RF64 files can be set so that on-close, writable files that have less - ** than 4GB of data in them are converted to RIFF/WAV, as per EBU - ** recommendations. - */ - SFC_RF64_AUTO_DOWNGRADE = 0x1210, - - SFC_SET_VBR_ENCODING_QUALITY = 0x1300, - SFC_SET_COMPRESSION_LEVEL = 0x1301, - SFC_SET_OGG_PAGE_LATENCY_MS = 0x1302, - SFC_SET_OGG_PAGE_LATENCY = 0x1303, - - /* Cart Chunk support */ - SFC_SET_CART_INFO = 0x1400, - SFC_GET_CART_INFO = 0x1401, - - /* Opus files original samplerate metadata */ - SFC_SET_ORIGINAL_SAMPLERATE = 0x1500, - SFC_GET_ORIGINAL_SAMPLERATE = 0x1501, - - /* Following commands for testing only. */ - SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, - - /* - ** These SFC_SET_ADD_* values are deprecated and will disappear at some - ** time in the future. They are guaranteed to be here up to and - ** including version 1.0.8 to avoid breakage of existing software. - ** They currently do nothing and will continue to do nothing. - */ - SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051, - - SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, - SFC_SET_ADD_DITHER_ON_READ = 0x1071 -} ; - - -/* -** String types that can be set and read from files. Not all file types -** support this and even the file types which support one, may not support -** all string types. -*/ - -enum -{ SF_STR_TITLE = 0x01, - SF_STR_COPYRIGHT = 0x02, - SF_STR_SOFTWARE = 0x03, - SF_STR_ARTIST = 0x04, - SF_STR_COMMENT = 0x05, - SF_STR_DATE = 0x06, - SF_STR_ALBUM = 0x07, - SF_STR_LICENSE = 0x08, - SF_STR_TRACKNUMBER = 0x09, - SF_STR_GENRE = 0x10 -} ; - -/* -** Use the following as the start and end index when doing metadata -** transcoding. -*/ - -#define SF_STR_FIRST SF_STR_TITLE -#define SF_STR_LAST SF_STR_GENRE - -enum -{ /* True and false */ - SF_FALSE = 0, - SF_TRUE = 1, - - /* Modes for opening files. */ - SFM_READ = 0x10, - SFM_WRITE = 0x20, - SFM_RDWR = 0x30, - - SF_AMBISONIC_NONE = 0x40, - SF_AMBISONIC_B_FORMAT = 0x41 -} ; - -/* Public error values. These are guaranteed to remain unchanged for the duration -** of the library major version number. -** There are also a large number of private error numbers which are internal to -** the library which can change at any time. -*/ - -enum -{ SF_ERR_NO_ERROR = 0, - SF_ERR_UNRECOGNISED_FORMAT = 1, - SF_ERR_SYSTEM = 2, - SF_ERR_MALFORMED_FILE = 3, - SF_ERR_UNSUPPORTED_ENCODING = 4 -} ; - - -/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP). -*/ - -enum -{ SF_CHANNEL_MAP_INVALID = 0, - SF_CHANNEL_MAP_MONO = 1, - SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */ - SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */ - SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */ - SF_CHANNEL_MAP_FRONT_LEFT, - SF_CHANNEL_MAP_FRONT_RIGHT, - SF_CHANNEL_MAP_FRONT_CENTER, - SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */ - SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */ - SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */ - SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */ - SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */ - SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */ - SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */ - SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */ - SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */ - SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */ - SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */ - SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */ - SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */ - SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */ - SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */ - - SF_CHANNEL_MAP_AMBISONIC_B_W, - SF_CHANNEL_MAP_AMBISONIC_B_X, - SF_CHANNEL_MAP_AMBISONIC_B_Y, - SF_CHANNEL_MAP_AMBISONIC_B_Z, - - SF_CHANNEL_MAP_MAX -} ; - - -/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ - -typedef struct SNDFILE_tag SNDFILE ; - -/* The following typedef is system specific and is defined when libsndfile is -** compiled. sf_count_t will be a 64 bit value when the underlying OS allows -** 64 bit file offsets. -** On windows, we need to allow the same header file to be compiler by both GCC -** and the Microsoft compiler. -*/ - -typedef @TYPEOF_SF_COUNT_T@ sf_count_t ; -#ifndef SF_COUNT_MAX -#define SF_COUNT_MAX @SF_COUNT_MAX@ -#endif - - -/* A pointer to a SF_INFO structure is passed to sf_open () and filled in. -** On write, the SF_INFO structure is filled in by the user and passed into -** sf_open (). -*/ - -struct SF_INFO -{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ - int samplerate ; - int channels ; - int format ; - int sections ; - int seekable ; -} ; - -typedef struct SF_INFO SF_INFO ; - -/* The SF_FORMAT_INFO struct is used to retrieve information about the sound -** file formats libsndfile supports using the sf_command () interface. -** -** Using this interface will allow applications to support new file formats -** and encoding types when libsndfile is upgraded, without requiring -** re-compilation of the application. -** -** Please consult the libsndfile documentation (particularly the information -** on the sf_command () interface) for examples of its use. -*/ - -typedef struct -{ int format ; - const char *name ; - const char *extension ; -} SF_FORMAT_INFO ; - -/* -** Enums and typedefs for adding dither on read and write. -** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE -** and SFC_SET_DITHER_ON_READ. -*/ - -enum -{ SFD_DEFAULT_LEVEL = 0, - SFD_CUSTOM_LEVEL = 0x40000000, - - SFD_NO_DITHER = 500, - SFD_WHITE = 501, - SFD_TRIANGULAR_PDF = 502 -} ; - -typedef struct -{ int type ; - double level ; - const char *name ; -} SF_DITHER_INFO ; - -/* Struct used to retrieve information about a file embedded within a -** larger file. See SFC_GET_EMBED_FILE_INFO. -*/ - -typedef struct -{ sf_count_t offset ; - sf_count_t length ; -} SF_EMBED_FILE_INFO ; - -/* -** Struct used to retrieve cue marker information from a file -*/ - -typedef struct -{ int32_t indx ; - uint32_t position ; - int32_t fcc_chunk ; - int32_t chunk_start ; - int32_t block_start ; - uint32_t sample_offset ; - char name [256] ; -} SF_CUE_POINT ; - -#define SF_CUES_VAR(count) \ - struct \ - { uint32_t cue_count ; \ - SF_CUE_POINT cue_points [count] ; \ - } - -typedef SF_CUES_VAR (100) SF_CUES ; - -/* -** Structs used to retrieve music sample information from a file. -*/ - -enum -{ /* - ** The loop mode field in SF_INSTRUMENT will be one of the following. - */ - SF_LOOP_NONE = 800, - SF_LOOP_FORWARD, - SF_LOOP_BACKWARD, - SF_LOOP_ALTERNATING -} ; - -typedef struct -{ int gain ; - char basenote, detune ; - char velocity_lo, velocity_hi ; - char key_lo, key_hi ; - int loop_count ; - - struct - { int mode ; - uint32_t start ; - uint32_t end ; - uint32_t count ; - } loops [16] ; /* make variable in a sensible way */ -} SF_INSTRUMENT ; - - - -/* Struct used to retrieve loop information from a file.*/ -typedef struct -{ - short time_sig_num ; /* any positive integer > 0 */ - short time_sig_den ; /* any positive power of 2 > 0 */ - int loop_mode ; /* see SF_LOOP enum */ - - int num_beats ; /* this is NOT the amount of quarter notes !!!*/ - /* a full bar of 4/4 is 4 beats */ - /* a full bar of 7/8 is 7 beats */ - - float bpm ; /* suggestion, as it can be calculated using other fields:*/ - /* file's length, file's sampleRate and our time_sig_den*/ - /* -> bpms are always the amount of _quarter notes_ per minute */ - - int root_key ; /* MIDI note, or -1 for None */ - int future [6] ; -} SF_LOOP_INFO ; - - -/* Struct used to retrieve broadcast (EBU) information from a file. -** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. -*/ -#define SF_BROADCAST_INFO_VAR(coding_hist_size) \ - struct \ - { char description [256] ; \ - char originator [32] ; \ - char originator_reference [32] ; \ - char origination_date [10] ; \ - char origination_time [8] ; \ - uint32_t time_reference_low ; \ - uint32_t time_reference_high ; \ - short version ; \ - char umid [64] ; \ - int16_t loudness_value ; \ - int16_t loudness_range ; \ - int16_t max_true_peak_level ; \ - int16_t max_momentary_loudness ; \ - int16_t max_shortterm_loudness ; \ - char reserved [180] ; \ - uint32_t coding_history_size ; \ - char coding_history [coding_hist_size] ; \ - } - -/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */ -typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ; - -struct SF_CART_TIMER -{ char usage [4] ; - int32_t value ; -} ; - -typedef struct SF_CART_TIMER SF_CART_TIMER ; - -#define SF_CART_INFO_VAR(p_tag_text_size) \ - struct \ - { char version [4] ; \ - char title [64] ; \ - char artist [64] ; \ - char cut_id [64] ; \ - char client_id [64] ; \ - char category [64] ; \ - char classification [64] ; \ - char out_cue [64] ; \ - char start_date [10] ; \ - char start_time [8] ; \ - char end_date [10] ; \ - char end_time [8] ; \ - char producer_app_id [64] ; \ - char producer_app_version [64] ; \ - char user_def [64] ; \ - int32_t level_reference ; \ - SF_CART_TIMER post_timers [8] ; \ - char reserved [276] ; \ - char url [1024] ; \ - uint32_t tag_text_size ; \ - char tag_text [p_tag_text_size] ; \ - } - -typedef SF_CART_INFO_VAR (256) SF_CART_INFO ; - -/* Virtual I/O functionality. */ - -typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; -typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; -typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; -typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; -typedef sf_count_t (*sf_vio_tell) (void *user_data) ; - -struct SF_VIRTUAL_IO -{ sf_vio_get_filelen get_filelen ; - sf_vio_seek seek ; - sf_vio_read read ; - sf_vio_write write ; - sf_vio_tell tell ; -} ; - -typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ; - - -/* Open the specified file for read, write or both. On error, this will -** return a NULL pointer. To find the error number, pass a NULL SNDFILE -** to sf_strerror (). -** All calls to sf_open() should be matched with a call to sf_close(). -*/ - -SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; - - -/* Use the existing file descriptor to create a SNDFILE object. If close_desc -** is TRUE, the file descriptor will be closed when sf_close() is called. If -** it is FALSE, the descriptor will not be closed. -** When passed a descriptor like this, the library will assume that the start -** of file header is at the current file offset. This allows sound files within -** larger container files to be read and/or written. -** On error, this will return a NULL pointer. To find the error number, pass a -** NULL SNDFILE to sf_strerror (). -** All calls to sf_open_fd() should be matched with a call to sf_close(). - -*/ - -SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; - -SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; - - -/* sf_error () returns a error number which can be translated to a text -** string using sf_error_number(). -*/ - -int sf_error (SNDFILE *sndfile) ; - - -/* sf_strerror () returns to the caller a pointer to the current error message for -** the given SNDFILE. -*/ - -const char* sf_strerror (SNDFILE *sndfile) ; - - -/* sf_error_number () allows the retrieval of the error string for each internal -** error number. -** -*/ - -const char* sf_error_number (int errnum) ; - - -/* The following two error functions are deprecated but they will remain in the -** library for the foreseeable future. The function sf_strerror() should be used -** in their place. -*/ - -int sf_perror (SNDFILE *sndfile) ; -int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; - - -/* Allow the caller to retrieve information from or change aspects of the -** library behaviour. -*/ - -int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; - - -/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ - -int sf_format_check (const SF_INFO *info) ; - - -/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses -** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as -** stdio.h function fseek (). -** An offset of zero with whence set to SEEK_SET will position the -** read / write pointer to the first data sample. -** On success sf_seek returns the current position in (multi-channel) -** samples from the start of the file. -** Please see the libsndfile documentation for moving the read pointer -** separately from the write pointer on files open in mode SFM_RDWR. -** On error all of these functions return -1. -*/ - -enum -{ SF_SEEK_SET = SEEK_SET, - SF_SEEK_CUR = SEEK_CUR, - SF_SEEK_END = SEEK_END -} ; - -sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; - - -/* Functions for retrieving and setting string data within sound files. -** Not all file types support this features; AIFF and WAV do. For both -** functions, the str_type parameter must be one of the SF_STR_* values -** defined above. -** On error, sf_set_string() returns non-zero while sf_get_string() -** returns NULL. -*/ - -int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; - -const char* sf_get_string (SNDFILE *sndfile, int str_type) ; - - -/* Return the library version string. */ - -const char * sf_version_string (void) ; - -/* Return the current byterate at this point in the file. The byte rate in this -** case is the number of bytes per second of audio data. For instance, for a -** stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate -** would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec. -** For some file formats the returned value will be accurate and exact, for some -** it will be a close approximation, for some it will be the average bitrate for -** the whole file and for some it will be a time varying value that was accurate -** when the file was most recently read or written. -** To get the bitrate, multiple this value by 8. -** Returns -1 for unknown. -*/ -int sf_current_byterate (SNDFILE *sndfile) ; - -/* Functions for reading/writing the waveform data of a sound file. -*/ - -sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; -sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ; - - -/* Functions for reading and writing the data chunk in terms of frames. -** The number of items actually read/written = frames * number of channels. -** sf_xxxx_raw read/writes the raw data bytes from/to the file -** sf_xxxx_short passes data in the native short format -** sf_xxxx_int passes data in the native int format -** sf_xxxx_float passes data in the native float format -** sf_xxxx_double passes data in the native double format -** All of these read/write function return number of frames read/written. -*/ - -sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; -sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ; - -sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; -sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ; - -sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; -sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ; - -sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; -sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ; - - -/* Functions for reading and writing the data chunk in terms of items. -** Otherwise similar to above. -** All of these read/write function return number of items read/written. -*/ - -sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; -sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ; - -sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; -sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ; - -sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; -sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; - -sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; -sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ; - - -/* Close the SNDFILE and clean up all memory allocations associated with this -** file. -** Returns 0 on success, or an error number. -*/ - -int sf_close (SNDFILE *sndfile) ; - - -/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file -** to force the writing of data to disk. If the file is opened SFM_READ -** no action is taken. -*/ - -void sf_write_sync (SNDFILE *sndfile) ; - - - -/* The function sf_wchar_open() is Windows Only! -** Open a file passing in a Windows Unicode filename. Otherwise, this is -** the same as sf_open(). -** -** In order for this to work, you need to do the following: -** -** #include -** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 -** #including -*/ - -#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES) -SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ; -#endif - - - - -/* Getting and setting of chunks from within a sound file. -** -** These functions allow the getting and setting of chunks within a sound file -** (for those formats which allow it). -** -** These functions fail safely. Specifically, they will not allow you to overwrite -** existing chunks or add extra versions of format specific reserved chunks but -** should allow you to retrieve any and all chunks (may not be implemented for -** all chunks or all file formats). -*/ - -struct SF_CHUNK_INFO -{ char id [64] ; /* The chunk identifier. */ - unsigned id_size ; /* The size of the chunk identifier. */ - unsigned datalen ; /* The size of that data. */ - void *data ; /* Pointer to the data. */ -} ; - -typedef struct SF_CHUNK_INFO SF_CHUNK_INFO ; - -/* Set the specified chunk info (must be done before any audio data is written -** to the file). This will fail for format specific reserved chunks. -** The chunk_info->data pointer must be valid until the file is closed. -** Returns SF_ERR_NO_ERROR on success or non-zero on failure. -*/ -int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ; - -/* -** An opaque structure to an iterator over the all chunks of a given id -*/ -typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ; - -/* Get an iterator for all chunks matching chunk_info. -** The iterator will point to the first chunk matching chunk_info. -** Chunks are matching, if (chunk_info->id) matches the first -** (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle. -** If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle -** is returned. -** The values of chunk_info->datalen and chunk_info->data are ignored. -** If no matching chunks are found in the sndfile, NULL is returned. -** The returned iterator will stay valid until one of the following occurs: -** a) The sndfile is closed. -** b) A new chunk is added using sf_set_chunk(). -** c) Another chunk iterator function is called on the same SNDFILE* handle -** that causes the iterator to be modified. -** The memory for the iterator belongs to the SNDFILE* handle and is freed when -** sf_close() is called. -*/ -SF_CHUNK_ITERATOR * -sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ; - -/* Iterate through chunks by incrementing the iterator. -** Increments the iterator and returns a handle to the new one. -** After this call, iterator will no longer be valid, and you must use the -** newly returned handle from now on. -** The returned handle can be used to access the next chunk matching -** the criteria as defined in sf_get_chunk_iterator(). -** If iterator points to the last chunk, this will free all resources -** associated with iterator and return NULL. -** The returned iterator will stay valid until sf_get_chunk_iterator_next -** is called again, the sndfile is closed or a new chunk us added. -*/ -SF_CHUNK_ITERATOR * -sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ; - - -/* Get the size of the specified chunk. -** If the specified chunk exists, the size will be returned in the -** datalen field of the SF_CHUNK_INFO struct. -** Additionally, the id of the chunk will be copied to the id -** field of the SF_CHUNK_INFO struct and it's id_size field will -** be updated accordingly. -** If the chunk doesn't exist chunk_info->datalen will be zero, and the -** id and id_size fields will be undefined. -** The function will return SF_ERR_NO_ERROR on success or non-zero on -** failure. -*/ -int -sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ; - -/* Get the specified chunk data. -** If the specified chunk exists, up to chunk_info->datalen bytes of -** the chunk data will be copied into the chunk_info->data buffer -** (allocated by the caller) and the chunk_info->datalen field -** updated to reflect the size of the data. The id and id_size -** field will be updated according to the retrieved chunk -** If the chunk doesn't exist chunk_info->datalen will be zero, and the -** id and id_size fields will be undefined. -** The function will return SF_ERR_NO_ERROR on success or non-zero on -** failure. -*/ -int -sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ; - - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - -#endif /* SNDFILE_H */ diff --git a/include/sndfile.hh b/include/sndfile.hh index ae9af3f3..a8db0de8 100644 --- a/include/sndfile.hh +++ b/include/sndfile.hh @@ -47,6 +47,8 @@ ** ** API documentation is in the doc/ directory of the source code tarball ** and at http://libsndfile.github.io/libsndfile/api.html. +** +** This file is intended to compile with C++98 and newer. */ #ifndef SNDFILE_HH @@ -57,10 +59,10 @@ #include #include // for std::nothrow -#if __cplusplus < 201100 -#ifndef nullptr -#define nullptr NULL -#endif +#if ((defined (_MSC_VER) && (_MSC_VER >= 1600)) || (__cplusplus >= 201100L)) +#define SF_NULL nullptr +#else +#define SF_NULL NULL #endif class SndfileHandle @@ -78,7 +80,7 @@ class SndfileHandle public : /* Default constructor */ - SndfileHandle (void) : p (nullptr) {} ; + SndfileHandle (void) : p (SF_NULL) {} ; SndfileHandle (const char *path, int mode = SFM_READ, int format = 0, int channels = 0, int samplerate = 0) ; SndfileHandle (std::string const & path, int mode = SFM_READ, @@ -88,8 +90,8 @@ class SndfileHandle SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ, int format = 0, int channels = 0, int samplerate = 0) ; -#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES - SndfileHandle (LPCWSTR wpath, int mode = SFM_READ, +#ifdef _WIN32 + SndfileHandle (const wchar_t *wpath, int mode = SFM_READ, int format = 0, int channels = 0, int samplerate = 0) ; #endif @@ -99,9 +101,9 @@ class SndfileHandle SndfileHandle & operator = (const SndfileHandle &rhs) ; /* Mainly for debugging/testing. */ - int refCount (void) const { return (p == nullptr) ? 0 : p->ref ; } + int refCount (void) const { return (p == SF_NULL) ? 0 : p->ref ; } - operator bool () const { return (p != nullptr) ; } + operator bool () const { return (p != SF_NULL) ; } bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; } @@ -161,20 +163,20 @@ class SndfileHandle inline SndfileHandle::SNDFILE_ref::SNDFILE_ref (void) -: sf (nullptr), sfinfo (), ref (1) +: sf (SF_NULL), sfinfo (), ref (1) {} inline SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void) -{ if (sf != nullptr) sf_close (sf) ; } +{ if (sf != SF_NULL) sf_close (sf) ; } inline SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate) -: p (nullptr) +: p (SF_NULL) { p = new (std::nothrow) SNDFILE_ref () ; - if (p != nullptr) + if (p != SF_NULL) { p->ref = 1 ; p->sfinfo.frames = 0 ; @@ -192,11 +194,11 @@ SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, in inline SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate) -: p (nullptr) +: p (SF_NULL) { p = new (std::nothrow) SNDFILE_ref () ; - if (p != nullptr) + if (p != SF_NULL) { p->ref = 1 ; p->sfinfo.frames = 0 ; @@ -214,14 +216,14 @@ SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int c inline SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate) -: p (nullptr) +: p (SF_NULL) { if (fd < 0) return ; p = new (std::nothrow) SNDFILE_ref () ; - if (p != nullptr) + if (p != SF_NULL) { p->ref = 1 ; p->sfinfo.frames = 0 ; @@ -239,11 +241,11 @@ SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int ch inline SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate) -: p (nullptr) +: p (SF_NULL) { p = new (std::nothrow) SNDFILE_ref () ; - if (p != nullptr) + if (p != SF_NULL) { p->ref = 1 ; p->sfinfo.frames = 0 ; @@ -261,7 +263,7 @@ SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mod inline SndfileHandle::~SndfileHandle (void) -{ if (p != nullptr && -- p->ref == 0) +{ if (p != SF_NULL && -- p->ref == 0) delete p ; } /* SndfileHandle destructor */ @@ -269,7 +271,7 @@ SndfileHandle::~SndfileHandle (void) inline SndfileHandle::SndfileHandle (const SndfileHandle &orig) : p (orig.p) -{ if (p != nullptr) +{ if (p != SF_NULL) ++ p->ref ; } /* SndfileHandle copy constructor */ @@ -278,11 +280,11 @@ SndfileHandle::operator = (const SndfileHandle &rhs) { if (&rhs == this) return *this ; - if (p != nullptr && -- p->ref == 0) + if (p != SF_NULL && -- p->ref == 0) delete p ; p = rhs.p ; - if (p != nullptr) + if (p != SF_NULL) ++ p->ref ; return *this ; @@ -407,30 +409,30 @@ SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes) inline SNDFILE * SndfileHandle::rawHandle (void) -{ return (p ? p->sf : nullptr) ; } +{ return (p ? p->sf : SF_NULL) ; } inline SNDFILE * SndfileHandle::takeOwnership (void) { - if (p == nullptr || (p->ref != 1)) - return nullptr ; + if (p == SF_NULL || (p->ref != 1)) + return SF_NULL ; SNDFILE * sf = p->sf ; - p->sf = nullptr ; + p->sf = SF_NULL ; delete p ; - p = nullptr ; + p = SF_NULL ; return sf ; } -#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES +#ifdef _WIN32 inline -SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate) -: p (nullptr) +SndfileHandle::SndfileHandle (const wchar_t *wpath, int mode, int fmt, int chans, int srate) +: p (SF_NULL) { p = new (std::nothrow) SNDFILE_ref () ; - if (p != nullptr) + if (p != SF_NULL) { p->ref = 1 ; p->sfinfo.frames = 0 ; diff --git a/m4/ax_add_fortify_source.m4 b/m4/ax_add_fortify_source.m4 index d443814b..7e153127 100644 --- a/m4/ax_add_fortify_source.m4 +++ b/m4/ax_add_fortify_source.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html +# https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html # =========================================================================== # # SYNOPSIS @@ -9,9 +9,9 @@ # DESCRIPTION # # Check whether -D_FORTIFY_SOURCE=2 can be added to CPPFLAGS without macro -# redefinition warnings. Some distributions (such as Gentoo Linux) enable -# _FORTIFY_SOURCE globally in their compilers, leading to unnecessary -# warnings in the form of +# redefinition warnings, other cpp warnings or linker. Some distributions +# (such as Gentoo Linux) enable _FORTIFY_SOURCE globally in their +# compilers, leading to unnecessary warnings in the form of # # :0:0: error: "_FORTIFY_SOURCE" redefined [-Werror] # : note: this is the location of the previous definition @@ -20,34 +20,61 @@ # _FORTIFY_SOURCE is already defined, and if not, adds -D_FORTIFY_SOURCE=2 # to CPPFLAGS. # +# Newer mingw-w64 msys2 package comes with a bug in +# headers-git-7.0.0.5546.d200317d-1. It broke -D_FORTIFY_SOURCE support, +# and would need -lssp or -fstack-protector. See +# https://github.com/msys2/MINGW-packages/issues/5803. Try to actually +# link it. +# # LICENSE # # Copyright (c) 2017 David Seifert +# Copyright (c) 2019 Reini Urban # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 1 +#serial 4 AC_DEFUN([AX_ADD_FORTIFY_SOURCE],[ + ac_save_cflags=$CFLAGS + ac_cwerror_flag=yes + AX_CHECK_COMPILE_FLAG([-Werror],[CFLAGS="$CFLAGS -Werror"]) AC_MSG_CHECKING([whether to add -D_FORTIFY_SOURCE=2 to CPPFLAGS]) AC_LINK_IFELSE([ - AC_LANG_SOURCE( + AC_LANG_PROGRAM([], [[ - int main() { #ifndef _FORTIFY_SOURCE return 0; #else this_is_an_error; #endif - } ]] - )], [ - AC_MSG_RESULT([yes]) - CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" - ], [ - AC_MSG_RESULT([no]) - ]) + )], + AC_LINK_IFELSE([ + AC_LANG_SOURCE([[ + #define _FORTIFY_SOURCE 2 + #include + int main() { + char *s = " "; + strcpy(s, "x"); + return strlen(s)-1; + } + ]] + )], + [ + AC_MSG_RESULT([yes]) + CFLAGS=$ac_save_cflags + CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" + ], [ + AC_MSG_RESULT([no]) + CFLAGS=$ac_save_cflags + ], + ), + [ + AC_MSG_RESULT([no]) + CFLAGS=$ac_save_cflags + ]) ]) diff --git a/m4/extra_pkg.m4 b/m4/extra_pkg.m4 index ce4ecb8e..8a04c359 100644 --- a/m4/extra_pkg.m4 +++ b/m4/extra_pkg.m4 @@ -55,10 +55,10 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [puts ("")])], pkg_link= CFLAGS=$pkg_link_saved_CFLAGS LIBS=$pkg_link_saved_LIBS -if test $pkg_link = no ; then - $as_echo_n "link failed ... " +AS_IF([test x$pkg_link = xno], [ + AS_ECHO_N(["link failed ... "]) pkg_failed=yes - fi +]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. diff --git a/m4/mkoctfile_version.m4 b/m4/mkoctfile_version.m4 index c17333ea..04a58e57 100644 --- a/m4/mkoctfile_version.m4 +++ b/m4/mkoctfile_version.m4 @@ -16,7 +16,7 @@ AC_DEFUN([OCTAVE_MKOCTFILE_VERSION], AC_ARG_WITH(mkoctfile, - AC_HELP_STRING([--with-mkoctfile], [choose the mkoctfile version]), + AS_HELP_STRING([--with-mkoctfile], [choose the mkoctfile version]), [ with_mkoctfile=$withval ]) test -z "$with_mkoctfile" && with_mkoctfile=mkoctfile diff --git a/m4/octave.m4 b/m4/octave.m4 index 88d5a5b9..fda043d0 100644 --- a/m4/octave.m4 +++ b/m4/octave.m4 @@ -29,7 +29,7 @@ AC_DEFUN([AC_OCTAVE_VERSION], [ AC_ARG_WITH(octave, - AC_HELP_STRING([--with-octave], [choose the octave version]), + AS_HELP_STRING([--with-octave], [choose the octave version]), [ with_octave=$withval ]) test -z "$with_octave" && with_octave=octave @@ -63,7 +63,7 @@ AC_DEFUN([AC_OCTAVE_CONFIG_VERSION], [ AC_ARG_WITH(octave-config, - AC_HELP_STRING([--with-octave-config], [choose the octave-config version]), + AS_HELP_STRING([--with-octave-config], [choose the octave-config version]), [ with_octave_config=$withval ]) test -z "$with_octave_config" && with_octave_config=octave-config diff --git a/m4/stack_protect.m4 b/m4/stack_protect.m4 deleted file mode 100644 index bf27e6e7..00000000 --- a/m4/stack_protect.m4 +++ /dev/null @@ -1,73 +0,0 @@ -dnl Copyright (C) 2013 Xiph.org Foundation -dnl -dnl Redistribution and use in source and binary forms, with or without -dnl modification, are permitted provided that the following conditions -dnl are met: -dnl -dnl - Redistributions of source code must retain the above copyright -dnl notice, this list of conditions and the following disclaimer. -dnl -dnl - Redistributions in binary form must reproduce the above copyright -dnl notice, this list of conditions and the following disclaimer in the -dnl documentation and/or other materials provided with the distribution. -dnl -dnl - Neither the name of the Xiph.org Foundation nor the names of its -dnl contributors may be used to endorse or promote products derived from -dnl this software without specific prior written permission. -dnl -dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -dnl ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR -dnl CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -dnl EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -dnl PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -dnl PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -dnl LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -dnl NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -dnl Want to know of GCC stack protector works, botfor the C and for the C++ -dnl compiler. -dnl -dnl Just checking if the compiler accepts the required CFLAGSs is not enough -dnl because we have seen at least one instance where this check was -dnl in-sufficient. -dnl -dnl Instead, try to compile and link a test program with the stack protector -dnl flags. If that works, we use it. - -AC_DEFUN([XIPH_GCC_STACK_PROTECTOR], -[AC_LANG_ASSERT(C) - AC_MSG_CHECKING([if $CC supports stack smash protection]) - xiph_stack_check_old_cflags="$CFLAGS" - SSP_FLAGS="-fstack-protector --param ssp-buffer-size=4" - CFLAGS=$SSP_FLAGS - AC_TRY_LINK([ - #include - ], - [puts("Hello, World!"); return 0;], - AC_MSG_RESULT([yes]) - CFLAGS="$xiph_stack_check_old_cflags $SSP_FLAGS", - AC_MSG_RESULT([no]) - CFLAGS="$xiph_stack_check_old_cflags" - ) -])# XIPH_GCC_STACK_PROTECTOR - -AC_DEFUN([XIPH_GXX_STACK_PROTECTOR], -[AC_LANG_PUSH([C++]) - AC_MSG_CHECKING([if $CXX supports stack smash protection]) - xiph_stack_check_old_cflags="$CFLAGS" - SSP_FLAGS="-fstack-protector --param ssp-buffer-size=4" - CFLAGS=$SSP_FLAGS - AC_TRY_LINK([ - #include - ], - [puts("Hello, World!"); return 0;], - AC_MSG_RESULT([yes]) - CFLAGS="$xiph_stack_check_old_cflags $SSP_FLAGS", - AC_MSG_RESULT([no]) - CFLAGS="$xiph_stack_check_old_cflags" - ) - AC_LANG_POP([C++]) -])# XIPH_GXX_STACK_PROTECTOR diff --git a/man/sndfile-play.1 b/man/sndfile-play.1 index f36d1315..4d570eaf 100644 --- a/man/sndfile-play.1 +++ b/man/sndfile-play.1 @@ -1,4 +1,4 @@ -.Dd November 2, 2014 +.Dd September 10, 2021 .Dt SNDFILE-PLAY 1 .Os .Sh NAME @@ -19,6 +19,8 @@ ALSA or OSS sndio .It FreeBSD /dev/dsp (OSS) +.It NetBSD +/dev/audio .It Solaris /dev/audio .It MacOSX 10.6 diff --git a/ossfuzz/ossfuzz.sh b/ossfuzz/ossfuzz.sh index b93d4fcc..7b3666ff 100755 --- a/ossfuzz/ossfuzz.sh +++ b/ossfuzz/ossfuzz.sh @@ -23,9 +23,10 @@ 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 # Copy the fuzzer to the output directory. cp -v ossfuzz/sndfile_fuzzer $OUT/ +cp -v ossfuzz/sndfile_alt_fuzzer $OUT/ diff --git a/ossfuzz/sndfile_alt_fuzzer.cc b/ossfuzz/sndfile_alt_fuzzer.cc new file mode 100644 index 00000000..e69fcdf3 --- /dev/null +++ b/ossfuzz/sndfile_alt_fuzzer.cc @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include + +#include "sndfile_fuzz_header.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ // One byte is needed for deciding which function to target. + if (size == 0) + return 0 ; + + const uint8_t decider = *data ; + data += 1 ; + size -= 1 ; + + SF_INFO sndfile_info ; + VIO_DATA vio_data ; + SF_VIRTUAL_IO vio ; + SNDFILE *sndfile = NULL ; + int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ; + if (err) + goto EXIT_LABEL ; + + // Just the right number of channels. Create some buffer space for reading. + switch (decider % 3) + { case 0 : + { + short* read_buffer = NULL ; + read_buffer = (short*)malloc(sizeof(short) * size); + if (read_buffer == NULL) + abort() ; + + while (sf_read_short(sndfile, read_buffer, size)) + { + // Do nothing with the data. + } + free(read_buffer) ; + } + break ; + case 1 : + { + int* read_buffer = NULL ; + read_buffer = (int*)malloc(sizeof(int) * size) ; + if (read_buffer == NULL) + abort() ; + + while (sf_read_int(sndfile, read_buffer, size)) + { + // Do nothing with the data. + } + free(read_buffer) ; + } + break ; + case 2 : + { + double* read_buffer = NULL ; + read_buffer = (double*)malloc(sizeof(double) * size) ; + if (read_buffer == NULL) + abort() ; + + while (sf_read_double(sndfile, read_buffer, size)) + { + // Do nothing with the data. + } + free(read_buffer) ; + } + break ; + default : + break ; + } ; + + EXIT_LABEL: + if (sndfile != NULL) + sf_close(sndfile); + + return 0 ; +} diff --git a/ossfuzz/sndfile_fuzz_header.h b/ossfuzz/sndfile_fuzz_header.h new file mode 100644 index 00000000..898aec44 --- /dev/null +++ b/ossfuzz/sndfile_fuzz_header.h @@ -0,0 +1,119 @@ +#ifndef SNDFILE_FUZZ_HEADER_H +#define SNDFILE_FUZZ_HEADER_H + +typedef struct +{ + sf_count_t offset ; + sf_count_t length ; + const unsigned char *data ; +} VIO_DATA ; + +static sf_count_t vfget_filelen (void *user_data) +{ VIO_DATA *vf = (VIO_DATA *)user_data ; + return vf->length ; +} + +static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data) +{ + VIO_DATA *vf = (VIO_DATA *)user_data ; + sf_count_t new_offset ; + + switch (whence) + { case SEEK_SET : + new_offset = offset ; + break ; + + case SEEK_CUR : + new_offset = vf->offset + offset ; + break ; + + case SEEK_END : + new_offset = vf->length + offset ; + break ; + + default : + break ; + } + + /* Ensure you can't seek outside the data */ + if (new_offset > vf->length) + { /* Trying to seek past the end of the data */ + printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");" + " whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n", + new_offset, vf->length, whence, vf->offset, offset) ; + new_offset = vf->length ; + } + else if (new_offset < 0) + { /* Trying to seek before the start of the data */ + printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset" + "(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n", + new_offset, whence, vf->offset, vf->length, offset) ; + new_offset = 0 ; + } + vf->offset = new_offset ; + + return vf->offset ; +} + +static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data) +{ VIO_DATA *vf = (VIO_DATA *)user_data ; + + if (vf->offset + count > vf->length) + count = vf->length - vf->offset ; + + memcpy(ptr, vf->data + vf->offset, count) ; + vf->offset += count ; + + return count ; +} + +static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data) +{ + (void)ptr ; + (void)count ; + (void)user_data ; + + // Cannot write to this virtual file. + return 0; +} + +static sf_count_t vftell (void *user_data) +{ VIO_DATA *vf = (VIO_DATA *)user_data ; + + return vf->offset ; +} + +int sf_init_file(const uint8_t *data, + size_t size, + SNDFILE **sndfile, + VIO_DATA *vio_data, + SF_VIRTUAL_IO *vio, SF_INFO *sndfile_info) +{ float* read_buffer = NULL ; + + // Initialize the virtual IO structure. + vio->get_filelen = vfget_filelen ; + vio->seek = vfseek ; + vio->read = vfread ; + vio->write = vfwrite ; + vio->tell = vftell ; + + // Initialize the VIO user data. + vio_data->data = data ; + vio_data->length = size ; + vio_data->offset = 0 ; + + memset(sndfile_info, 0, sizeof(SF_INFO)) ; + + // Try and open the virtual file. + *sndfile = sf_open_virtual(vio, SFM_READ, sndfile_info, vio_data) ; + + if (sndfile_info->channels == 0) + return -1 ; + + if (sndfile_info->channels > 1024 * 1024) + return -1 ; + + return 0; +} + +#endif diff --git a/ossfuzz/sndfile_fuzzer.cc b/ossfuzz/sndfile_fuzzer.cc index 3c850730..2a3d6934 100644 --- a/ossfuzz/sndfile_fuzzer.cc +++ b/ossfuzz/sndfile_fuzzer.cc @@ -5,151 +5,35 @@ #include #include -typedef struct -{ - sf_count_t offset; - sf_count_t length; - const unsigned char *data; -} VIO_DATA; - -static sf_count_t vfget_filelen (void *user_data) -{ - VIO_DATA *vf = (VIO_DATA *)user_data; - return vf->length; -} - -static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data) -{ - VIO_DATA *vf = (VIO_DATA *)user_data; - sf_count_t new_offset; - - switch (whence) - { - case SEEK_SET: - new_offset = offset; - break ; - - case SEEK_CUR: - new_offset = vf->offset + offset; - break ; - - case SEEK_END: - new_offset = vf->length + offset; - break; - - default: - break; - } - - /* Ensure you can't seek outside the data */ - if (new_offset > vf->length) - { - /* Trying to seek past the end of the data */ - printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");" - " whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n", - new_offset, vf->length, whence, vf->offset, offset); - new_offset = vf->length; - } - else if (new_offset < 0) - { - /* Trying to seek before the start of the data */ - printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset" - "(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n", - new_offset, whence, vf->offset, vf->length, offset); - new_offset = 0; - } - vf->offset = new_offset; - - return vf->offset; -} - -static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data) -{ - VIO_DATA *vf = (VIO_DATA *)user_data; - - if (vf->offset + count > vf->length) - { - count = vf->length - vf->offset; - } - - memcpy(ptr, vf->data + vf->offset, count); - vf->offset += count; - - return count; -} - -static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data) -{ - (void)ptr; - (void)count; - (void)user_data; - - // Cannot write to this virtual file. - return 0; -} - -static sf_count_t vftell (void *user_data) -{ VIO_DATA *vf = (VIO_DATA *)user_data; - - return vf->offset; -} +#include "sndfile_fuzz_header.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - VIO_DATA vio_data; - SF_VIRTUAL_IO vio; - SF_INFO sndfile_info; - SNDFILE *sndfile = NULL; - float* read_buffer = NULL; +{ VIO_DATA vio_data ; + SF_VIRTUAL_IO vio ; + SF_INFO sndfile_info ; + SNDFILE *sndfile = NULL ; + float* read_buffer = NULL ; - // Initialize the virtual IO structure. - vio.get_filelen = vfget_filelen; - vio.seek = vfseek; - vio.read = vfread; - vio.write = vfwrite; - vio.tell = vftell; + int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ; + if (err) + goto EXIT_LABEL ; - // Initialize the VIO user data. - vio_data.data = data; - vio_data.length = size; - vio_data.offset = 0; + // Just the right number of channels. Create some buffer space for reading. + read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels); + if (read_buffer == NULL) + abort() ; - memset(&sndfile_info, 0, sizeof(SF_INFO)); - - // Try and open the virtual file. - sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data); - - if (sndfile_info.channels == 0) - { - // No sound channels in file. - goto EXIT_LABEL; - } - else if (sndfile_info.channels > 1024 * 1024) - { - // Too many channels to handle. - goto EXIT_LABEL; - } - - // Just the right number of channels. Create some buffer space for reading. - read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels); - if (read_buffer == NULL) - { - abort(); - } - - while (sf_readf_float(sndfile, read_buffer, 1)) - { - // Do nothing with the data. - } + while (sf_readf_float(sndfile, read_buffer, 1)) + { + // Do nothing with the data. + } EXIT_LABEL: - if (sndfile != NULL) - { - sf_close(sndfile); - } + if (sndfile != NULL) + sf_close(sndfile) ; - free(read_buffer); + free(read_buffer) ; - return 0; + return 0 ; } diff --git a/programs/common.c b/programs/common.c index fb479f09..7ff0d41a 100644 --- a/programs/common.c +++ b/programs/common.c @@ -73,7 +73,7 @@ sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize { data [k] /= max ; if (!isfinite (data [k])) /* infinite or NaN */ - return 1; + return 1 ; } sf_writef_double (outfile, data, readcount) ; } ; @@ -91,7 +91,7 @@ sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) readcount = frames ; while (readcount > 0) - { readcount = sf_readf_int (infile, data, frames) ; + { readcount = (int) sf_readf_int (infile, data, frames) ; sf_writef_int (outfile, data, readcount) ; } ; @@ -119,6 +119,7 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET { case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : + case SF_FORMAT_MPEG_LAYER_III : break ; default : @@ -177,7 +178,7 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET /* Special case for coding_history because we may want to append. */ if (info->coding_history != NULL) { if (info->coding_hist_append) - { int slen = strlen (binfo.coding_history) ; + { int slen = (int) strlen (binfo.coding_history) ; while (slen > 1 && isspace (binfo.coding_history [slen - 1])) slen -- ; @@ -189,7 +190,7 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET memset (binfo.coding_history, 0, sizeof (binfo.coding_history)) ; memcpy (binfo.coding_history, info->coding_history, slen) ; - binfo.coding_history_size = slen ; + binfo.coding_history_size = (uint32_t) slen ; } ; } ; @@ -339,11 +340,12 @@ static OUTPUT_FORMAT_MAP format_map [] = { "caf", 0, SF_FORMAT_CAF }, { "wve", 0, SF_FORMAT_WVE }, { "prc", 0, SF_FORMAT_WVE }, - { "ogg", 0, SF_FORMAT_OGG }, { "oga", 0, SF_FORMAT_OGG }, + { "ogg", 0, SF_FORMAT_OGG | SF_FORMAT_VORBIS }, { "opus", 0, SF_FORMAT_OGG | SF_FORMAT_OPUS }, { "mpc", 0, SF_FORMAT_MPC2K }, { "rf64", 0, SF_FORMAT_RF64 }, + { "mp3", 0, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III }, } ; /* format_map */ int @@ -453,6 +455,7 @@ sfe_container_name (int format) case SF_FORMAT_OGG : return "OGG" ; case SF_FORMAT_MPC2K : return "MPC2K" ; case SF_FORMAT_RF64 : return "RF64" ; + case SF_FORMAT_MPEG : return "MPEG" ; default : break ; } ; @@ -491,6 +494,9 @@ sfe_codec_name (int format) case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ; case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ; case SF_FORMAT_OPUS : return "Opus" ; + case SF_FORMAT_MPEG_LAYER_I : return "MPEG layer 1" ; + case SF_FORMAT_MPEG_LAYER_II : return "MPEG layer 2" ; + case SF_FORMAT_MPEG_LAYER_III : return "MPEG layer 3" ; default : break ; } ; return "unknown" ; diff --git a/programs/sndfile-concat.c b/programs/sndfile-concat.c index 3a02a94d..49380fd0 100644 --- a/programs/sndfile-concat.c +++ b/programs/sndfile-concat.c @@ -143,7 +143,7 @@ concat_data_fp (SNDFILE *wfile, SNDFILE *rofile, int channels) sf_seek (wfile, 0, SEEK_END) ; while (readcount > 0) - { readcount = sf_readf_double (rofile, data, frames) ; + { readcount = (int) sf_readf_double (rofile, data, frames) ; sf_writef_double (wfile, data, readcount) ; } ; @@ -161,7 +161,7 @@ concat_data_int (SNDFILE *wfile, SNDFILE *rofile, int channels) sf_seek (wfile, 0, SEEK_END) ; while (readcount > 0) - { readcount = sf_readf_int (rofile, data, frames) ; + { readcount = (int) sf_readf_int (rofile, data, frames) ; sf_writef_int (wfile, data, readcount) ; } ; diff --git a/programs/sndfile-convert.c b/programs/sndfile-convert.c index 5aa4fdfb..b9468624 100644 --- a/programs/sndfile-convert.c +++ b/programs/sndfile-convert.c @@ -281,7 +281,7 @@ main (int argc, char * argv []) continue ; } ; - printf ("Error : Not able to decode argunment '%s'.\n", argv [k]) ; + printf ("Error : Not able to decode argument '%s'.\n", argv [k]) ; exit (1) ; } ; @@ -354,7 +354,10 @@ main (int argc, char * argv []) || (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT) || (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT) || (infileminor == SF_FORMAT_OPUS) || (outfileminor == SF_FORMAT_OPUS) - || (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS)) + || (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS) + || (infileminor == SF_FORMAT_MPEG_LAYER_I) + || (infileminor == SF_FORMAT_MPEG_LAYER_II) + || (infileminor == SF_FORMAT_MPEG_LAYER_III) || (outfileminor == SF_FORMAT_MPEG_LAYER_III)) { if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0) { printf ("Error : Not able to decode input file %s.\n", infilename) ; return 1 ; @@ -388,7 +391,7 @@ copy_metadata (SNDFILE *outfile, SNDFILE *infile, int channels) memset (&binfo, 0, sizeof (binfo)) ; if (channels < ARRAY_LEN (chanmap)) - { size_t size = channels * sizeof (chanmap [0]) ; + { int size = channels * sizeof (chanmap [0]) ; if (sf_command (infile, SFC_GET_CHANNEL_MAP_INFO, chanmap, size) == SF_TRUE) sf_command (outfile, SFC_SET_CHANNEL_MAP_INFO, chanmap, size) ; diff --git a/programs/sndfile-deinterleave.c b/programs/sndfile-deinterleave.c index 616761e4..42d47509 100644 --- a/programs/sndfile-deinterleave.c +++ b/programs/sndfile-deinterleave.c @@ -65,43 +65,48 @@ static void deinterleave_double (STATE * state) ; int main (int argc, char **argv) -{ STATE state ; +{ STATE *state = NULL ; SF_INFO sfinfo ; char pathname [512], ext [32], *cptr ; - int ch, double_split ; + int ch, double_split, ret = 1 ; if (argc != 2) { if (argc != 1) puts ("\nError : need a single input file.\n") ; usage_exit () ; + goto cleanup ; } ; - memset (&state, 0, sizeof (state)) ; + state = calloc (1, sizeof (*state)) ; + if (!state) + { printf ("\nError : Out of memory.\n") ; + goto cleanup ; + } ; memset (&sfinfo, 0, sizeof (sfinfo)) ; - if ((state.infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL) + if ((state->infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL) { printf ("\nError : Not able to open input file '%s'\n%s\n", argv [1], sf_strerror (NULL)) ; - exit (1) ; + goto cleanup ; } ; if (sfinfo.channels < 2) { printf ("\nError : Input file '%s' only has one channel.\n", argv [1]) ; - exit (1) ; + goto cleanup ; } ; if (sfinfo.channels > MAX_CHANNELS) { printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n", argv [1], sfinfo.channels, MAX_CHANNELS) ; - exit (1) ; + goto cleanup ; } ; - state.channels = sfinfo.channels ; + state->channels = sfinfo.channels ; sfinfo.channels = 1 ; if (snprintf (pathname, sizeof (pathname), "%s", argv [1]) > (int) sizeof (pathname)) { printf ("\nError : Length of provided filename '%s' exceeds MAX_PATH (%d).\n", argv [1], (int) sizeof (pathname)) ; - exit (1) ; + goto cleanup ; } ; if ((cptr = strrchr (pathname, '.')) == NULL) @@ -114,7 +119,7 @@ main (int argc, char **argv) printf ("Input file : %s\n", pathname) ; puts ("Output files :") ; - for (ch = 0 ; ch < state.channels ; ch++) + for (ch = 0 ; ch < state->channels ; ch++) { char filename [520] ; size_t count ; @@ -124,9 +129,9 @@ main (int argc, char **argv) { printf ("File name truncated to %s\n", filename) ; } ; - if ((state.outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) + if ((state->outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) { printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ; - exit (1) ; + goto cleanup ; } ; printf (" %s\n", filename) ; @@ -145,16 +150,24 @@ main (int argc, char **argv) } ; if (double_split) - deinterleave_double (&state) ; + deinterleave_double (state) ; else - deinterleave_int (&state) ; + deinterleave_int (state) ; - sf_close (state.infile) ; - for (ch = 0 ; ch < MAX_CHANNELS ; ch++) - if (state.outfile [ch] != NULL) - sf_close (state.outfile [ch]) ; + ret = 0 ; - return 0 ; +cleanup : + + if (state != NULL) + { sf_close (state->infile) ; + for (ch = 0 ; ch < MAX_CHANNELS ; ch++) + if (state->outfile [ch] != NULL) + sf_close (state->outfile [ch]) ; + } ; + + free (state) ; + + return ret ; } /* main */ /*------------------------------------------------------------------------------ @@ -170,7 +183,6 @@ usage_exit (void) "a_00.wav, a_01.wav and so on.\n" ) ; printf ("Using %s.\n\n", sf_version_string ()) ; - exit (1) ; } /* usage_exit */ static void @@ -179,7 +191,7 @@ deinterleave_int (STATE * state) int ch, k ; do - { read_len = sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ; + { read_len = (int) sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ; for (ch = 0 ; ch < state->channels ; ch ++) { for (k = 0 ; k < read_len ; k++) @@ -197,7 +209,7 @@ deinterleave_double (STATE * state) int ch, k ; do - { read_len = sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ; + { read_len = (int) sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ; for (ch = 0 ; ch < state->channels ; ch ++) { for (k = 0 ; k < read_len ; k++) diff --git a/programs/sndfile-info.c b/programs/sndfile-info.c index e0e48821..ae446549 100644 --- a/programs/sndfile-info.c +++ b/programs/sndfile-info.c @@ -110,8 +110,6 @@ main (int argc, char *argv []) ** Print version and usage. */ -static double data [BUFFER_LEN] ; - static void usage_exit (const char *progname) { printf ("Usage :\n %s ...\n", progname) ; @@ -167,6 +165,8 @@ calc_decibels (SF_INFO * sfinfo, double max) case SF_FORMAT_FLOAT : case SF_FORMAT_DOUBLE : + case SF_FORMAT_VORBIS : + case SF_FORMAT_OPUS : decibels = max / 1.0 ; break ; @@ -313,7 +313,9 @@ instrument_dump (const char *filename) printf (" Loop points : %d\n", inst.loop_count) ; for (k = 0 ; k < inst.loop_count ; k++) - printf (" %-2d Mode : %s Start : %6d End : %6d Count : %6d\n", k, str_of_type (inst.loops [k].mode), inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ; + printf (" %-2d Mode : %s Start : %6" PRIu32 " End : %6" PRIu32 + " Count : %6" PRIu32 "\n", k, str_of_type (inst.loops [k].mode), + inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ; putchar ('\n') ; return 0 ; diff --git a/programs/sndfile-interleave.c b/programs/sndfile-interleave.c index 4c044431..2b44efb2 100644 --- a/programs/sndfile-interleave.c +++ b/programs/sndfile-interleave.c @@ -60,46 +60,54 @@ typedef struct } STATE ; -static void usage_exit (void) ; +static void print_usage (void) ; static void interleave_int (STATE * state) ; static void interleave_double (STATE * state) ; int main (int argc, char **argv) -{ STATE state ; +{ STATE *state = NULL ; SF_INFO sfinfo ; int k, double_merge = 0 ; + int ret = 1 ; if (argc < 5) { if (argc > 1) puts ("\nError : need at least 2 input files.") ; - usage_exit () ; + print_usage () ; + goto cleanup ; } ; if (strcmp (argv [argc - 2], "-o") != 0) { puts ("\nError : second last command line parameter should be '-o'.\n") ; - usage_exit () ; + print_usage () ; + goto cleanup ; } ; if (argc - 3 > MAX_INPUTS) { printf ("\nError : Cannot handle more than %d input channels.\n\n", MAX_INPUTS) ; - exit (1) ; + goto cleanup ; + } ; + + state = calloc (1, sizeof (STATE)) ; + if (state == NULL) + { puts ("\nError : out of memory.\n") ; + goto cleanup ; } ; - memset (&state, 0, sizeof (state)) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; for (k = 1 ; k < argc - 2 ; k++) { - if ((state.infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL) + if ((state->infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL) { printf ("\nError : Not able to open input file '%s'\n%s\n", argv [k], sf_strerror (NULL)) ; - exit (1) ; + goto cleanup ; } ; if (sfinfo.channels != 1) { printf ("\bError : Input file '%s' should be mono (has %d channels).\n", argv [k], sfinfo.channels) ; - exit (1) ; + goto cleanup ; } ; switch (sfinfo.format & SF_FORMAT_SUBMASK) @@ -113,28 +121,36 @@ main (int argc, char **argv) break ; } ; - state.channels ++ ; + state->channels ++ ; } ; - sfinfo.channels = state.channels ; + sfinfo.channels = state->channels ; sfinfo.format = sfe_file_type_of_ext (argv [argc - 1], sfinfo.format) ; - if ((state.outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) + if ((state->outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) { printf ("Not able to open output file '%s'\n%s\n", argv [argc - 1], sf_strerror (NULL)) ; - exit (1) ; + goto cleanup ; } ; if (double_merge) - interleave_double (&state) ; + interleave_double (state) ; else - interleave_int (&state) ; + interleave_int (state) ; - for (k = 0 ; k < MAX_INPUTS ; k++) - if (state.infile [k] != NULL) - sf_close (state.infile [k]) ; - sf_close (state.outfile) ; + ret = 0 ; - return 0 ; +cleanup : + + if (state != NULL) + { for (k = 0 ; k < MAX_INPUTS ; k++) + if (state->infile [k] != NULL) + sf_close (state->infile [k]) ; + sf_close (state->outfile) ; + } + + free (state) ; + + return ret ; } /* main */ /*------------------------------------------------------------------------------ @@ -142,12 +158,11 @@ main (int argc, char **argv) static void -usage_exit (void) +print_usage (void) { puts ("\nUsage : sndfile-interleave ... -o \n") ; puts ("Merge two or more mono files into a single multi-channel file.\n") ; printf ("Using %s.\n\n", sf_version_string ()) ; - exit (1) ; -} /* usage_exit */ +} /* print_usage */ static void @@ -159,7 +174,7 @@ interleave_int (STATE * state) { max_read_len = 0 ; for (ch = 0 ; ch < state->channels ; ch ++) - { read_len = sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ; + { read_len = (int) sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ; if (read_len < BUFFER_LEN) memset (state->din.i + read_len, 0, sizeof (state->din.i [0]) * (BUFFER_LEN - read_len)) ; @@ -185,7 +200,7 @@ interleave_double (STATE * state) { max_read_len = 0 ; for (ch = 0 ; ch < state->channels ; ch ++) - { read_len = sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ; + { read_len = (int) sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ; if (read_len < BUFFER_LEN) memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ; diff --git a/programs/sndfile-play.c b/programs/sndfile-play.c index cd5cc278..16aaf4d2 100644 --- a/programs/sndfile-play.c +++ b/programs/sndfile-play.c @@ -64,7 +64,7 @@ #elif HAVE_SNDIO_H #include -#elif (defined (sun) && defined (unix)) +#elif (defined (sun) && defined (unix)) || defined(__NetBSD__) #include #include #include @@ -328,10 +328,12 @@ alsa_write_float (snd_pcm_t *alsa_dev, float *data, int frames, int channels) return 0 ; break ; +#if defined ESTRPIPE && ESTRPIPE != EPIPE case -ESTRPIPE : fprintf (stderr, "alsa_write_float: Suspend event.n") ; return 0 ; break ; +#endif case -EIO : puts ("alsa_write_float: EIO") ; @@ -727,7 +729,7 @@ sndio_play (int argc, char *argv []) ** Solaris. */ -#if (defined (sun) && defined (unix)) /* ie Solaris */ +#if (defined (sun) && defined (unix)) || defined(__NetBSD__) static void solaris_play (int argc, char *argv []) @@ -764,8 +766,6 @@ solaris_play (int argc, char *argv []) audio_info.play.channels = sfinfo.channels ; audio_info.play.precision = 16 ; audio_info.play.encoding = AUDIO_ENCODING_LINEAR ; - audio_info.play.gain = AUDIO_MAX_GAIN ; - audio_info.play.balance = AUDIO_MID_BALANCE ; if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info))) { perror ("ioctl (AUDIO_SETINFO) failed") ; @@ -807,7 +807,7 @@ solaris_play (int argc, char *argv []) return ; } /* solaris_play */ -#endif /* Solaris */ +#endif /* Solaris or NetBSD */ /*============================================================================== ** Main function. @@ -845,7 +845,7 @@ main (int argc, char *argv []) opensoundsys_play (argc, argv) ; #elif HAVE_SNDIO_H sndio_play (argc, argv) ; -#elif (defined (sun) && defined (unix)) +#elif (defined (sun) && defined (unix)) || defined(__NetBSD__) solaris_play (argc, argv) ; #elif (OS_IS_WIN32 == 1) win32_play (argc, argv) ; diff --git a/programs/sndfile-salvage.c b/programs/sndfile-salvage.c index 9c21d523..1a76dc3a 100644 --- a/programs/sndfile-salvage.c +++ b/programs/sndfile-salvage.c @@ -56,6 +56,12 @@ #define NOT(x) (! (x)) +#ifndef _WIN32 +typedef off_t sf_off_t ; +#else +typedef long long sf_off_t ; +#endif + static void usage_exit (const char *progname) ; static void salvage_file (const char * broken_wav, const char * fixed_w64) ; @@ -74,8 +80,8 @@ main (int argc, char *argv []) /*============================================================================== */ -static void lseek_or_die (int fd, off_t offset, int whence) ; -static sf_count_t get_file_length (int fd, const char * name) ; +static void lseek_or_die (int fd, sf_off_t offset, int whence) ; +static sf_off_t get_file_length (int fd, const char * name) ; static sf_count_t find_data_offset (int fd, int format) ; static void copy_data (int fd, SNDFILE * sndfile, int readsize) ; @@ -180,9 +186,13 @@ salvage_file (const char * broken_wav, const char * fixed_w64) */ static void -lseek_or_die (int fd, off_t offset, int whence) +lseek_or_die (int fd, sf_off_t offset, int whence) { +#ifndef _WIN32 if (lseek (fd, offset, whence) < 0) +#else + if (_lseeki64 (fd, offset, whence) < 0) +#endif { printf ("lseek failed : %s\n", strerror (errno)) ; exit (1) ; } ; @@ -191,9 +201,14 @@ lseek_or_die (int fd, off_t offset, int whence) } /* lseek_or_die */ -static sf_count_t +static sf_off_t get_file_length (int fd, const char * name) -{ struct stat sbuf ; +{ +#ifndef _WIN32 + struct stat sbuf ; +#else + struct _stat64 sbuf ; +#endif if (sizeof (sbuf.st_size) != 8) { puts ("Error : sizeof (sbuf.st_size) != 8. Was program compiled with\n" @@ -201,7 +216,11 @@ get_file_length (int fd, const char * name) exit (1) ; } ; +#ifndef _WIN32 if (fstat (fd, &sbuf) != 0) +#else + if (_fstat64 (fd, &sbuf) != 0) +#endif { printf ("Error : fstat ('%s') failed : %s\n", name, strerror (errno)) ; exit (1) ; } ; @@ -233,7 +252,7 @@ find_data_offset (int fd, int format) exit (1) ; } ; - slen = strlen (target) ; + slen = (int) strlen (target) ; lseek_or_die (fd, 0, SEEK_SET) ; diff --git a/regtest/database.c b/regtest/database.c index 1048ebb0..1f4c8d7b 100644 --- a/regtest/database.c +++ b/regtest/database.c @@ -267,14 +267,14 @@ db_check_all (REG_DB * db_handle) int db_list_all (REG_DB * db_handle) { - printf ("%s : %p\n", __func__, db_handle) ; + printf ("%s : %p\n", __func__, (void *) db_handle) ; return 0 ; } /* db_list_all */ int db_del_entry (REG_DB * db_handle, const char * entry) { - printf ("%s : %p %s\n", __func__, db_handle, entry) ; + printf ("%s : %p %s\n", __func__, (void *) db_handle, entry) ; return 0 ; } /* db_del_entry */ @@ -428,7 +428,7 @@ static void get_filename_pathname (REGTEST_DB * db, const char *filepath) { const char * basename = db_basename (filepath) ; - int slen ; + size_t slen ; /* Test for a relative path */ diff --git a/sndfile.pc.in b/sndfile.pc.in index 961cf93c..6b884537 100644 --- a/sndfile.pc.in +++ b/sndfile.pc.in @@ -6,7 +6,8 @@ includedir=@includedir@ Name: sndfile Description: A library for reading and writing audio files Requires: -Requires.private: @EXTERNAL_XIPH_REQUIRE@ +Requires.private: @EXTERNAL_XIPH_REQUIRE@ @EXTERNAL_MPEG_REQUIRE@ Version: @VERSION@ Libs: -L${libdir} -lsndfile +Libs.private: @EXTERNAL_MPEG_LIBS@ Cflags: -I${includedir} diff --git a/src/ALAC/ag_dec.c b/src/ALAC/ag_dec.c index e7e4c62a..37671d24 100644 --- a/src/ALAC/ag_dec.c +++ b/src/ALAC/ag_dec.c @@ -42,6 +42,8 @@ #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/ALAC/ag_enc.c b/src/ALAC/ag_enc.c index 2b1df194..4737b96e 100644 --- a/src/ALAC/ag_enc.c +++ b/src/ALAC/ag_enc.c @@ -44,6 +44,8 @@ #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/ALAC/alac_codec.h b/src/ALAC/alac_codec.h index c73347d1..e762b279 100644 --- a/src/ALAC/alac_codec.h +++ b/src/ALAC/alac_codec.h @@ -48,7 +48,7 @@ typedef struct alac_decoder_s { int32_t mPredictor [ALAC_FRAME_LENGTH] ; uint16_t mShiftBuffer [ALAC_FRAME_LENGTH] ; - } ; + } u ; uint32_t mNumChannels ; } ALAC_DECODER ; diff --git a/src/ALAC/alac_decoder.c b/src/ALAC/alac_decoder.c index 6c124e65..46d33306 100644 --- a/src/ALAC/alac_decoder.c +++ b/src/ALAC/alac_decoder.c @@ -110,7 +110,7 @@ alac_decoder_init (ALAC_DECODER *p, void * inMagicCookie, uint32_t inMagicCookie RequireAction (p->mConfig.compatibleVersion <= kALACVersion, return kALAC_IncompatibleVersion ;) ; RequireAction ((p->mConfig.bitDepth >= 8 && p->mConfig.bitDepth <= 32), return kALAC_BadBitWidth ;) ; - RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->mPredictor != NULL), + RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->u.mPredictor != NULL), status = kALAC_MemFullError ; goto Exit ;) ; } else @@ -247,18 +247,18 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u // decompress set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; - status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits1) ; + status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ; RequireNoErr (status, goto Exit ;) ; if (modeU == 0) { - unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; + unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; } else { // the special "numActive == 31" mode can be done in-place - unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; - unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; + unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ; + unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; } } else @@ -300,7 +300,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u //Assert (shift <= 16) ; for (i = 0 ; i < numSamples ; i++) - p->mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; + p->u.mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; } // convert 32-bit integers into output buffer @@ -318,14 +318,14 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u case 24: out32 = sampleBuffer + channelIndex ; if (bytesShifted != 0) - copyPredictorTo24Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; + copyPredictorTo24Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; else copyPredictorTo24 (p->mMixBufferU, out32, numChannels, numSamples) ; break ; case 32: out32 = sampleBuffer + channelIndex ; if (bytesShifted != 0) - copyPredictorTo32Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; + copyPredictorTo32Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; else copyPredictorTo32 (p->mMixBufferU, out32, numChannels, numSamples) ; break ; @@ -408,34 +408,34 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u // decompress and run predictor for "left" channel set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; - status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits1) ; + status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ; RequireNoErr (status, goto Exit ;) ; if (modeU == 0) { - unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; + unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; } else { // the special "numActive == 31" mode can be done in-place - unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; - unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; + unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ; + unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; } // decompress and run predictor for "right" channel set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorV) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; - status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits2) ; + status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits2) ; RequireNoErr (status, goto Exit ;) ; if (modeV == 0) { - unpc_block (p->mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; + unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; } else { // the special "numActive == 31" mode can be done in-place - unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; - unpc_block (p->mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; + unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ; + unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; } } else @@ -488,8 +488,8 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u for (i = 0 ; i < (numSamples * 2) ; i += 2) { - p->mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; - p->mShiftBuffer [i + 1] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; + p->u.mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; + p->u.mShiftBuffer [i + 1] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; } } @@ -508,12 +508,12 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u case 24: out32 = sampleBuffer + channelIndex ; unmix24 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, - mixBits, mixRes, p->mShiftBuffer, bytesShifted) ; + mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ; break ; case 32: out32 = sampleBuffer + channelIndex ; unmix32 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, - mixBits, mixRes, p->mShiftBuffer, bytesShifted) ; + mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ; break ; } @@ -554,7 +554,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u } } -#if 0 // ! DEBUG +#if 1 // ! DEBUG // if we've decoded all of our channels, bail (but not in debug b/c we want to know if we're seeing bad bits) // - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits if (channelIndex >= numChannels) diff --git a/src/ALAC/dp_dec.c b/src/ALAC/dp_dec.c index 4f5bc1d6..0d1c10d5 100644 --- a/src/ALAC/dp_dec.c +++ b/src/ALAC/dp_dec.c @@ -34,6 +34,8 @@ #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/ALAC/dp_enc.c b/src/ALAC/dp_enc.c index ad098a4f..01db8d40 100644 --- a/src/ALAC/dp_enc.c +++ b/src/ALAC/dp_enc.c @@ -33,6 +33,8 @@ #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/ALAC/shift.h b/src/ALAC/shift.h index 7c2d6f69..bce404d2 100644 --- a/src/ALAC/shift.h +++ b/src/ALAC/shift.h @@ -18,6 +18,8 @@ #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/G72x/g72x_priv.h b/src/G72x/g72x_priv.h index e418fb75..6a194ec3 100644 --- a/src/G72x/g72x_priv.h +++ b/src/G72x/g72x_priv.h @@ -108,6 +108,8 @@ void private_init_state (G72x_STATE *state_ptr) ; #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/GSM610/gsm610_priv.h b/src/GSM610/gsm610_priv.h index dc95e3a0..7ffaddc1 100644 --- a/src/GSM610/gsm610_priv.h +++ b/src/GSM610/gsm610_priv.h @@ -294,6 +294,8 @@ extern int16_t gsm_FAC [8] ; #if __GNUC__ #define ALWAYS_INLINE __attribute__ ((always_inline)) +#elif defined _MSC_VER +#define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE #endif diff --git a/src/aiff.c b/src/aiff.c index d872a892..4c662454 100644 --- a/src/aiff.c +++ b/src/aiff.c @@ -234,7 +234,7 @@ static int aiff_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * itera int aiff_open (SF_PRIVATE *psf) { COMM_CHUNK comm_fmt ; - int error, subformat ; + int error = 0, subformat ; memset (&comm_fmt, 0, sizeof (comm_fmt)) ; @@ -404,7 +404,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) @@ -507,7 +507,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) return SFE_MALLOC_FAILED ; - /* read in rest of PEAK chunk. */ + /* Read in rest of PEAK chunk. */ psf_binheader_readf (psf, "E44", &(psf->peak_info->version), &(psf->peak_info->timestamp)) ; if (psf->peak_info->version != 1) @@ -1003,7 +1003,7 @@ aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ubuf.scbuf [0] = 0 ; /* The COMM chunk has an int aligned to an odd word boundary. Some - ** procesors are not able to deal with this (ie bus fault) so we have + ** processors are not able to deal with this (ie bus fault) so we have ** to take special care. */ diff --git a/src/alac.c b/src/alac.c index f83dd2fa..a6668f36 100644 --- a/src/alac.c +++ b/src/alac.c @@ -51,12 +51,12 @@ typedef struct /* Can't have a decoder and an encoder at the same time so stick - ** them in an un-named union. + ** them in a union. */ union { ALAC_DECODER decoder ; ALAC_ENCODER encoder ; - } ; + } u ; char enctmpname [512] ; FILE *enctmp ; @@ -169,7 +169,7 @@ alac_close (SF_PRIVATE *psf) plac = psf->codec_data ; if (psf->file.mode == SFM_WRITE) - { ALAC_ENCODER *penc = &plac->encoder ; + { ALAC_ENCODER *penc = &plac->u.encoder ; SF_CHUNK_INFO chunk_info ; sf_count_t readcount ; uint8_t kuki_data [1024] ; @@ -268,14 +268,14 @@ alac_reader_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) /* Read in the ALAC cookie data and pass it to the init function. */ kuki_size = alac_kuki_read (psf, info->kuki_offset, u.kuki, sizeof (u.kuki)) ; - if ((error = alac_decoder_init (&plac->decoder, u.kuki, kuki_size)) != ALAC_noErr) + if ((error = alac_decoder_init (&plac->u.decoder, u.kuki, kuki_size)) != ALAC_noErr) { psf_log_printf (psf, "*** alac_decoder_init() returned %s. ***\n", alac_error_string (error)) ; return SFE_INTERNAL ; } ; - if (plac->decoder.mNumChannels != (unsigned) psf->sf.channels) - { psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->decoder.mNumChannels, psf->sf.channels) ; + if (plac->u.decoder.mNumChannels != (unsigned) psf->sf.channels) + { psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->u.decoder.mNumChannels, psf->sf.channels) ; return SFE_INTERNAL ; } ; @@ -357,7 +357,7 @@ alac_writer_init (SF_PRIVATE *psf) return SFE_ALAC_FAIL_TMPFILE ; } ; - alac_encoder_init (&plac->encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ; + alac_encoder_init (&plac->u.encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ; return 0 ; } /* alac_writer_init */ @@ -402,7 +402,7 @@ alac_reader_calc_frames (SF_PRIVATE *psf, ALAC_PRIVATE *plac) static int alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac) -{ ALAC_DECODER *pdec = &plac->decoder ; +{ ALAC_DECODER *pdec = &plac->u.decoder ; uint32_t packet_size ; BitBuffer bit_buffer ; @@ -437,7 +437,7 @@ alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac) static int alac_encode_block (ALAC_PRIVATE *plac) -{ ALAC_ENCODER *penc = &plac->encoder ; +{ ALAC_ENCODER *penc = &plac->u.encoder ; uint32_t num_bytes = 0 ; alac_encode (penc, plac->partial_block_frames, plac->buffer, plac->byte_buffer, &num_bytes) ; @@ -471,7 +471,7 @@ alac_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) break ; readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; - readcount = readcount > len ? len : readcount ; + readcount = readcount > len ? (int) len : readcount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -501,7 +501,7 @@ alac_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) break ; readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; - readcount = readcount > len ? len : readcount ; + readcount = readcount > len ? (int) len : readcount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -534,7 +534,7 @@ alac_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) break ; readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; - readcount = readcount > len ? len : readcount ; + readcount = readcount > len ? (int) len : readcount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -567,7 +567,7 @@ alac_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) break ; readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; - readcount = readcount > len ? len : readcount ; + readcount = readcount > len ? (int) len : readcount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -648,7 +648,7 @@ alac_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) while (len > 0) { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; - writecount = (writecount == 0 || writecount > len) ? len : writecount ; + writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -679,7 +679,7 @@ alac_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) while (len > 0) { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; - writecount = (writecount == 0 || writecount > len) ? len : writecount ; + writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -713,7 +713,7 @@ alac_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) while (len > 0) { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; - writecount = (writecount == 0 || writecount > len) ? len : writecount ; + writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -746,7 +746,7 @@ alac_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) while (len > 0) { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; - writecount = (writecount == 0 || writecount > len) ? len : writecount ; + writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; iptr = plac->buffer + plac->partial_block_frames * plac->channels ; @@ -824,6 +824,8 @@ alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t UNUSED (pakt_offset)) pakt_size = chunk_info.datalen ; chunk_info.data = pakt_data = malloc (pakt_size + 5) ; + if (!chunk_info.data) + return NULL ; if ((bcount = psf->get_chunk_data (psf, chunk_iterator, &chunk_info)) != SF_ERR_NO_ERROR) { while (chunk_iterator) @@ -850,7 +852,7 @@ alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t UNUSED (pakt_offset)) count ++ ; if (count > 5 || bcount + count > pakt_size) - { printf ("%s %d : Ooops! count %d bcount %d\n", __func__, __LINE__, count, bcount) ; + { printf ("%s %d : Ooops! count %" PRIi32 " bcount %" PRIu32 "\n", __func__, __LINE__, count, bcount) ; value = 0 ; break ; } ; diff --git a/src/alaw.c b/src/alaw.c index 6e0a7946..4be642e5 100644 --- a/src/alaw.c +++ b/src/alaw.c @@ -292,69 +292,69 @@ unsigned char alaw_encode [2048 + 1] = static inline void alaw2s_array (unsigned char *buffer, int count, short *ptr) -{ while (--count >= 0) - ptr [count] = alaw_decode [(int) buffer [count]] ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = alaw_decode [(int) buffer [i]] ; } /* alaw2s_array */ static inline void alaw2i_array (unsigned char *buffer, int count, int *ptr) -{ while (--count >= 0) - ptr [count] = ((uint32_t) alaw_decode [(int) buffer [count]]) << 16 ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = ((uint32_t) alaw_decode [(int) buffer [i]]) << 16 ; } /* alaw2i_array */ static inline void alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) -{ while (--count >= 0) - ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = normfact * alaw_decode [(int) buffer [i]] ; } /* alaw2f_array */ static inline void alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) -{ while (--count >= 0) - ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = normfact * alaw_decode [(int) buffer [i]] ; } /* alaw2d_array */ static inline void s2alaw_array (const short *ptr, int count, unsigned char *buffer) -{ while (--count >= 0) - { if (ptr [count] >= 0) - buffer [count] = alaw_encode [ptr [count] / 16] ; +{ for (int i = 0 ; i < count ; i++) + { if (ptr [i] >= 0) + buffer [i] = alaw_encode [ptr [i] / 16] ; else - buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ; + buffer [i] = 0x7F & alaw_encode [ptr [i] / -16] ; } ; } /* s2alaw_array */ static inline void i2alaw_array (const int *ptr, int count, unsigned char *buffer) -{ while (--count >= 0) - { if (ptr [count] == INT_MIN) - buffer [count] = alaw_encode [INT_MAX >> (16 + 4)] ; - else if (ptr [count] >= 0) - buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ; +{ for (int i = 0 ; i < count ; i++) + { if (ptr [i] == INT_MIN) + buffer [i] = alaw_encode [INT_MAX >> (16 + 4)] ; + else if (ptr [i] >= 0) + buffer [i] = alaw_encode [ptr [i] >> (16 + 4)] ; else - buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ; + buffer [i] = 0x7F & alaw_encode [- ptr [i] >> (16 + 4)] ; } ; } /* i2alaw_array */ static inline void f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) -{ while (--count >= 0) - { if (ptr [count] >= 0) - buffer [count] = alaw_encode [psf_lrintf (normfact * ptr [count])] ; +{ for (int i = 0 ; i < count ; i++) + { if (ptr [i] >= 0) + buffer [i] = alaw_encode [psf_lrintf (normfact * ptr [i])] ; else - buffer [count] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [count])] ; + buffer [i] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [i])] ; } ; } /* f2alaw_array */ static inline void d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) -{ while (--count >= 0) - { if (!isfinite (ptr [count])) - buffer [count] = 0 ; - else if (ptr [count] >= 0) - buffer [count] = alaw_encode [psf_lrint (normfact * ptr [count])] ; +{ for (int i = 0 ; i < count ; i++) + { if (!isfinite (ptr [i])) + buffer [i] = 0 ; + else if (ptr [i] >= 0) + buffer [i] = alaw_encode [psf_lrint (normfact * ptr [i])] ; else - buffer [count] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [count])] ; + buffer [i] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [i])] ; } ; } /* d2alaw_array */ @@ -372,7 +372,7 @@ alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; alaw2s_array (ubuf.ucbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -394,7 +394,7 @@ alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; alaw2i_array (ubuf.ucbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -419,7 +419,7 @@ alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; alaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -443,7 +443,7 @@ alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; alaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -469,7 +469,7 @@ alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -491,7 +491,7 @@ alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -516,7 +516,7 @@ alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; f2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -541,7 +541,7 @@ alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; d2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; diff --git a/src/avr.c b/src/avr.c index bd6b00f4..6c78ff69 100644 --- a/src/avr.c +++ b/src/avr.c @@ -28,8 +28,6 @@ #define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T')) #define AVR_HDR_SIZE 128 -#define SFE_AVR_X 666 - /* ** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu) ** @@ -116,7 +114,7 @@ avr_read_header (SF_PRIVATE *psf) psf_log_printf (psf, "%M\n", hdr.marker) ; if (hdr.marker != TWOBIT_MARKER) - return SFE_AVR_X ; + return SFE_AVR_NOT_AVR ; psf_log_printf (psf, " Name : %s\n", hdr.name) ; @@ -145,7 +143,7 @@ avr_read_header (SF_PRIVATE *psf) default : psf_log_printf (psf, "Error : bad rez/sign combination.\n") ; - return SFE_AVR_X ; + return SFE_AVR_BAD_REZ_SIGN ; } ; psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ; diff --git a/src/broadcast.c b/src/broadcast.c index 16575bb5..aad5f880 100644 --- a/src/broadcast.c +++ b/src/broadcast.c @@ -84,7 +84,7 @@ broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datas /* Force coding_history_size to be even. */ len = strlen (psf->broadcast_16k->coding_history) ; len += (len & 1) ? 1 : 0 ; - psf->broadcast_16k->coding_history_size = len ; + psf->broadcast_16k->coding_history_size = (uint32_t) len ; /* Currently writing this version. */ psf->broadcast_16k->version = 2 ; @@ -146,7 +146,7 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO * break ; default : - snprintf (chnstr, sizeof (chnstr), "%uchn", psfinfo->channels) ; + snprintf (chnstr, sizeof (chnstr), "%dchn", psfinfo->channels) ; break ; } ; @@ -180,7 +180,7 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO * } ; count = snprintf (added_history, added_history_max, - "A=PCM,F=%u,W=%d,M=%s,T=%s-%s\r\n", + "A=PCM,F=%d,W=%d,M=%s,T=%s-%s\r\n", psfinfo->samplerate, width, chnstr, PACKAGE_NAME, PACKAGE_VERSION) ; if (count >= added_history_max) diff --git a/src/caf.c b/src/caf.c index 45b1dba8..a886bf56 100644 --- a/src/caf.c +++ b/src/caf.c @@ -66,10 +66,6 @@ #define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8))) -#define SFE_CAF_NOT_CAF 666 -#define SFE_CAF_NO_DESC 667 -#define SFE_CAF_BAD_PEAK 668 - /*------------------------------------------------------------------------------ ** Typedefs. */ @@ -411,11 +407,16 @@ caf_read_header (SF_PRIVATE *psf) { case peak_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) - { psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; + { psf_binheader_readf (psf, "j", (size_t) chunk_size) ; psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; return SFE_CAF_BAD_PEAK ; } ; + if (psf->peak_info) + { psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ; + free (psf->peak_info) ; + psf->peak_info = NULL ; + } ; if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) return SFE_MALLOC_FAILED ; @@ -442,7 +443,7 @@ caf_read_header (SF_PRIVATE *psf) case chan_MARKER : if (chunk_size < 12) { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; - psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; + psf_binheader_readf (psf, "j", (size_t) chunk_size) ; break ; } @@ -454,7 +455,7 @@ caf_read_header (SF_PRIVATE *psf) case free_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; - psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; + psf_binheader_readf (psf, "j", (size_t) chunk_size) ; break ; case data_MARKER : @@ -479,14 +480,14 @@ caf_read_header (SF_PRIVATE *psf) if (psf->datalength + psf->dataoffset < psf->filelength) psf->dataend = psf->datalength + psf->dataoffset ; - psf_binheader_readf (psf, "j", make_size_t (psf->datalength)) ; + psf_binheader_readf (psf, "j", (size_t) psf->datalength) ; have_data = 1 ; break ; case kuki_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ; - psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; + psf_binheader_readf (psf, "j", (size_t) chunk_size) ; break ; case pakt_MARKER : @@ -518,7 +519,7 @@ caf_read_header (SF_PRIVATE *psf) psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ; pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ; - psf_binheader_readf (psf, "j", make_size_t (chunk_size) - 24) ; + psf_binheader_readf (psf, "j", (size_t) chunk_size - 24) ; break ; case info_MARKER : @@ -537,7 +538,7 @@ caf_read_header (SF_PRIVATE *psf) default : psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ; - psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; + psf_binheader_readf (psf, "j", (size_t) chunk_size) ; break ; } ; @@ -845,7 +846,7 @@ caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size) if ((buf = malloc (chunk_size + 1)) == NULL) return (psf->error = SFE_MALLOC_FAILED) ; - psf_binheader_readf (psf, "E4b", &count, buf, make_size_t (chunk_size)) ; + psf_binheader_readf (psf, "E4b", &count, buf, (size_t) chunk_size) ; psf_log_printf (psf, " count: %u\n", count) ; /* Force terminate `buf` to make sure. */ diff --git a/src/cart.c b/src/cart.c index a56ed60e..8b00eab1 100644 --- a/src/cart.c +++ b/src/cart.c @@ -79,7 +79,7 @@ cart_var_set (SF_PRIVATE *psf, const SF_CART_INFO * info, size_t datasize) len = strlen (psf->cart_16k->tag_text) ; len += (len & 1) ? 1 : 2 ; - psf->cart_16k->tag_text_size = len ; + psf->cart_16k->tag_text_size = (uint32_t) len ; return SF_TRUE ; } /* cart_var_set */ diff --git a/src/chunk.c b/src/chunk.c index 471c5a44..08411d3e 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -75,7 +75,7 @@ psf_get_chunk_iterator (SF_PRIVATE * psf, const char * marker_str) hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ; memcpy (psf->iterator->id, marker_str, marker_len) ; - psf->iterator->id_size = marker_len ; + psf->iterator->id_size = (unsigned) marker_len ; psf->iterator->hash = hash ; } @@ -112,6 +112,9 @@ psf_store_read_chunk (READ_CHUNKS * pchk, const READ_CHUNK * rchunk) { pchk->used = 0 ; pchk->count = 20 ; pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ; + if (!pchk->chunks) + { return SFE_MALLOC_FAILED ; + } ; } else if (pchk->used > pchk->count) return SFE_INTERNAL ; @@ -208,7 +211,7 @@ psf_store_read_chunk_str (READ_CHUNKS * pchk, const char * marker_str, sf_count_ rchunk.offset = offset ; rchunk.len = len ; - rchunk.id_size = marker_len > 64 ? 64 : marker_len ; + rchunk.id_size = marker_len > 64 ? 64 : (unsigned) marker_len ; memcpy (rchunk.id, marker_str, rchunk.id_size) ; return psf_store_read_chunk (pchk, &rchunk) ; @@ -227,6 +230,9 @@ psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info) { pchk->used = 0 ; pchk->count = 20 ; pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ; + if (!pchk->chunks) + { return SFE_MALLOC_FAILED ; + } ; } else if (pchk->used >= pchk->count) { WRITE_CHUNK * old_ptr = pchk->chunks ; diff --git a/src/command.c b/src/command.c index 15037ab5..d4837dab 100644 --- a/src/command.c +++ b/src/command.c @@ -61,6 +61,12 @@ static SF_FORMAT_INFO const simple_formats [] = }, #endif +#if HAVE_MPEG + { SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, + "MPEG Layer 3", "mp3" + }, +#endif + { SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, "OKI Dialogic VOX ADPCM", "vox" }, @@ -133,6 +139,9 @@ static SF_FORMAT_INFO const major_formats [] = { SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" }, { SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" }, { SF_FORMAT_MPC2K, "MPC (Akai MPC 2k)", "mpc" }, +#if HAVE_MPEG + { SF_FORMAT_MPEG, "MPEG-1/2 Audio", "m1a" }, +#endif #if HAVE_EXTERNAL_XIPH_LIBS { SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" }, #endif @@ -215,6 +224,12 @@ static SF_FORMAT_INFO subtype_formats [] = { SF_FORMAT_OPUS, "Opus", NULL }, #endif +#if HAVE_MPEG + { SF_FORMAT_MPEG_LAYER_I, "MPEG Layer I", "mp1" }, + { SF_FORMAT_MPEG_LAYER_II, "MPEG Layer II", "mp2" }, + { SF_FORMAT_MPEG_LAYER_III, "MPEG Layer III", "mp3" }, +#endif + { SF_FORMAT_ALAC_16, "16 bit ALAC", NULL }, { SF_FORMAT_ALAC_20, "20 bit ALAC", NULL }, { SF_FORMAT_ALAC_24, "24 bit ALAC", NULL }, @@ -309,7 +324,7 @@ psf_calc_signal_max (SF_PRIVATE *psf, int normalize) len = ARRAY_LEN (ubuf.dbuf) - (ARRAY_LEN (ubuf.dbuf) % psf->sf.channels) ; for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */) - { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; + { readcount = (int) sf_read_double ((SNDFILE*) psf, data, len) ; for (k = 0 ; k < readcount ; k++) { temp = fabs (data [k]) ; max_val = temp > max_val ? temp : max_val ; @@ -354,7 +369,7 @@ psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) chan = 0 ; readcount = len ; while (readcount > 0) - { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; + { readcount = (int) sf_read_double ((SNDFILE*) psf, data, len) ; for (k = 0 ; k < readcount ; k++) { temp = fabs (data [k]) ; peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ; diff --git a/src/common.c b/src/common.c index c9737a92..b58c9db5 100644 --- a/src/common.c +++ b/src/common.c @@ -103,8 +103,8 @@ log_putchar (SF_PRIVATE *psf, char ch) void psf_log_printf (SF_PRIVATE *psf, const char *format, ...) { va_list ap ; - uint32_t u ; - int d, tens, shift, width, width_specifier, left_align, slen ; + uint32_t u, tens ; + int d, shift, width, width_specifier, left_align, slen, precision ; char c, *strptr, istr [5], lead_char, sign_char ; va_start (ap, format) ; @@ -153,6 +153,12 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) while ((c = *format++) && isdigit (c)) width_specifier = width_specifier * 10 + (c - '0') ; + precision = 0 ; + if (c == '.') + { while ((c = *format++) && isdigit (c)) + precision = precision * 10 + (c - '0') ; + } ; + switch (c) { case 0 : /* NULL character. */ va_end (ap) ; @@ -162,12 +168,15 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) strptr = va_arg (ap, char *) ; if (strptr == NULL) break ; - slen = strlen (strptr) ; + if (precision > 0) + slen = strnlen (strptr, precision) ; + else + slen = strlen (strptr) ; width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ; if (left_align == SF_FALSE) while (width_specifier -- > 0) log_putchar (psf, ' ') ; - while (*strptr) + while (slen--) log_putchar (psf, *strptr++) ; while (width_specifier -- > 0) log_putchar (psf, ' ') ; @@ -177,15 +186,19 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) d = va_arg (ap, int) ; if (d < 0) - { d = -d ; - sign_char = '-' ; + { sign_char = '-' ; if (lead_char != '0' && left_align == SF_FALSE) width_specifier -- ; - } ; + + u = - ((unsigned) d) ; + } + else + { u = (unsigned) d ; + } tens = 1 ; width = 1 ; - while (d / tens >= 10) + while (u / tens >= 10) { tens *= 10 ; width ++ ; } ; @@ -215,8 +228,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) log_putchar (psf, lead_char) ; while (tens > 0) - { log_putchar (psf, '0' + d / tens) ; - d %= tens ; + { log_putchar (psf, '0' + u / tens) ; + u %= tens ; tens /= 10 ; } ; @@ -225,7 +238,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) break ; case 'D': /* sf_count_t */ - { sf_count_t D, Tens ; + { sf_count_t D ; + uint64_t U, Tens ; D = va_arg (ap, sf_count_t) ; @@ -235,13 +249,19 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) log_putchar (psf, '0') ; break ; } - if (D < 0) - { log_putchar (psf, '-') ; - D = -D ; - } ; + else + { if (D < 0) + { log_putchar (psf, '-') ; + U = -((uint64_t) D) ; + } + else + { U = (uint64_t) D; + } + } + Tens = 1 ; width = 1 ; - while (D / Tens >= 10) + while (U / Tens >= 10) { Tens *= 10 ; width ++ ; } ; @@ -252,8 +272,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...) } ; while (Tens > 0) - { log_putchar (psf, '0' + D / Tens) ; - D %= Tens ; + { log_putchar (psf, '0' + U / Tens) ; + U %= Tens ; Tens /= 10 ; } ; } ; @@ -355,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 ; @@ -520,36 +540,30 @@ 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) ; - psf->header.ptr [psf->header.indx++] = (x >> 48) ; - psf->header.ptr [psf->header.indx++] = (x >> 40) ; - psf->header.ptr [psf->header.indx++] = (x >> 32) ; - psf->header.ptr [psf->header.indx++] = (x >> 24) ; - psf->header.ptr [psf->header.indx++] = (x >> 16) ; - psf->header.ptr [psf->header.indx++] = (x >> 8) ; - psf->header.ptr [psf->header.indx++] = x ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) x ; } /* header_put_be_8byte */ static inline void header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x) -{ psf->header.ptr [psf->header.indx++] = x ; - psf->header.ptr [psf->header.indx++] = (x >> 8) ; - psf->header.ptr [psf->header.indx++] = (x >> 16) ; - psf->header.ptr [psf->header.indx++] = (x >> 24) ; - psf->header.ptr [psf->header.indx++] = (x >> 32) ; - psf->header.ptr [psf->header.indx++] = (x >> 40) ; - psf->header.ptr [psf->header.indx++] = (x >> 48) ; +{ psf->header.ptr [psf->header.indx++] = (unsigned char) x ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ; + psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ; 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 ; @@ -571,7 +585,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) while ((c = *format++)) { if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16)) - return count ; + break ; switch (c) { case ' ' : /* Do nothing. Just used to space out format string. */ @@ -687,7 +701,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) size = strlen (strptr) + 1 ; if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1))) - return count ; + break ; if (psf->rwf_endian == SF_ENDIAN_BIG) header_put_be_int (psf, size + (size & 1)) ; @@ -708,7 +722,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) strptr = va_arg (argptr, char *) ; size = strlen (strptr) ; if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1))) - return count ; + break ; if (psf->rwf_endian == SF_ENDIAN_BIG) header_put_be_int (psf, size) ; else @@ -728,7 +742,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) size = (size > 254) ? 254 : size ; if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size)) - return count ; + break ; header_put_byte (psf, size) ; memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ; @@ -741,7 +755,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) size = va_arg (argptr, size_t) ; if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) - return count ; + break ; memcpy (&(psf->header.ptr [psf->header.indx]), bindata, size) ; psf->header.indx += size ; @@ -752,7 +766,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) size = va_arg (argptr, size_t) ; if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) - return count ; + break ; count += size ; while (size) @@ -773,7 +787,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) size = va_arg (argptr, size_t) ; if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) - return count ; + break ; psf->header.indx += size ; count += size ; @@ -783,7 +797,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) size = va_arg (argptr, size_t) ; if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size)) - return count ; + break ; psf->header.indx = size ; break ; @@ -877,7 +891,7 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence) psf_bump_header_allocation (psf, position) ; if (position > psf->header.len) { /* Too much header to cache so just seek instead. */ - psf->header.indx = psf->header.end ; + psf->header.indx = psf->header.end = 0 ; psf_fseek (psf, position, whence) ; return ; } ; @@ -905,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 ; } ; @@ -954,7 +982,7 @@ int psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) { va_list argptr ; sf_count_t *countptr, countdata ; - unsigned char *ucptr, sixteen_bytes [16] ; + unsigned char *ucptr, sixteen_bytes [16] = { 0 } ; unsigned int *intptr, intdata ; unsigned short *shortptr ; char *charptr ; @@ -971,7 +999,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) while ((c = *format++)) { if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16)) - return count ; + break ; switch (c) { case 'e' : /* All conversions are now from LE to host. */ @@ -1098,7 +1126,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) memset (charptr, 0, count) ; if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, count)) - return 0 ; + break ; byte_count += header_gets (psf, charptr, count) ; break ; @@ -1127,6 +1155,10 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) byte_count += count ; break ; + case '!' : /* Clear buffer, forcing re-read. */ + psf->header.end = psf->header.indx = 0 ; + break ; + default : psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; psf->error = SFE_INTERNAL ; @@ -1221,6 +1253,37 @@ psf_log_SF_INFO (SF_PRIVATE *psf) /*======================================================================================== */ +int +psf_isprint (int ch) +{ return (ch >= ' ' && ch <= '~') ; +} /* psf_isprint */ + +void +psf_strlcat (char *dest, size_t n, const char *src) +{ strncat (dest, src, n - strlen (dest) - 1) ; + dest [n - 1] = 0 ; +} /* psf_strlcat */ + +void +psf_strlcpy (char *dest, size_t n, const char *src) +{ strncpy (dest, src, n - 1) ; + dest [n - 1] = 0 ; +} /* psf_strlcpy */ + +/*======================================================================================== +*/ + +void * +psf_memdup (const void *src, size_t n) +{ if (src == NULL) + return NULL ; + + void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ; + if (mem != NULL) + memcpy (mem, src, n) ; + return mem ; +} /* psf_memdup */ + void* psf_memset (void *s, int c, sf_count_t len) { char *ptr ; @@ -1246,7 +1309,11 @@ psf_memset (void *s, int c, sf_count_t len) ** bodgy something up instead. */ +#ifdef _MSC_VER typedef SF_CUES_VAR (0) SF_CUES_0 ; +#else +typedef SF_CUES_VAR () SF_CUES_0 ; +#endif /* calculate size of SF_CUES struct given number of cues */ #define SF_CUES_VAR_SIZE(count) (sizeof (SF_CUES_0) + count * sizeof (SF_CUE_POINT)) @@ -1257,8 +1324,9 @@ typedef SF_CUES_VAR (0) SF_CUES_0 ; SF_CUES * psf_cues_alloc (uint32_t cue_count) { SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ; - - pcues->cue_count = cue_count ; + if (pcues) + { pcues->cue_count = cue_count ; + } ; return pcues ; } /* psf_cues_alloc */ @@ -1527,6 +1595,7 @@ str_of_major_format (int format) CASE_NAME (SF_FORMAT_CAF) ; CASE_NAME (SF_FORMAT_WVE) ; CASE_NAME (SF_FORMAT_OGG) ; + CASE_NAME (SF_FORMAT_MPEG) ; default : break ; } ; @@ -1563,6 +1632,9 @@ str_of_minor_format (int format) CASE_NAME (SF_FORMAT_DPCM_8) ; CASE_NAME (SF_FORMAT_DPCM_16) ; CASE_NAME (SF_FORMAT_VORBIS) ; + CASE_NAME (SF_FORMAT_MPEG_LAYER_I) ; + CASE_NAME (SF_FORMAT_MPEG_LAYER_II) ; + CASE_NAME (SF_FORMAT_MPEG_LAYER_III) ; default : break ; } ; @@ -1606,8 +1678,8 @@ psf_f2s_array (const float *src, short *dest, int count, int normalize) { float normfact ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrintf (src [i] * normfact) ; return ; } /* psf_f2s_array */ @@ -1618,18 +1690,18 @@ psf_f2s_clip_array (const float *src, short *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x8000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) - { dest [count] = 0x7FFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFF)) + { dest [i] = 0x7FFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) - { dest [count] = 0x8000 ; + if (scaled_value <= (-8.0 * 0x1000)) + { dest [i] = -0x7FFF - 1 ; continue ; } ; - dest [count] = psf_lrintf (scaled_value) ; + dest [i] = psf_lrintf (scaled_value) ; } ; return ; @@ -1640,8 +1712,8 @@ psf_d2s_array (const double *src, short *dest, int count, int normalize) { double normfact ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrint (src [i] * normfact) ; return ; } /* psf_f2s_array */ @@ -1652,18 +1724,18 @@ psf_d2s_clip_array (const double *src, short *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x8000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) - { dest [count] = 0x7FFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFF)) + { dest [i] = 0x7FFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) - { dest [count] = 0x8000 ; + if (scaled_value <= (-8.0 * 0x1000)) + { dest [i] = -0x7FFF - 1 ; continue ; } ; - dest [count] = psf_lrint (scaled_value) ; + dest [i] = psf_lrint (scaled_value) ; } ; return ; @@ -1675,8 +1747,8 @@ psf_f2i_array (const float *src, int *dest, int count, int normalize) { float normfact ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrintf (src [i] * normfact) ; return ; } /* psf_f2i_array */ @@ -1687,18 +1759,22 @@ psf_f2i_clip_array (const float *src, int *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count] = 0x7FFFFFFF ; + 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] = 0x7FFFFFFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count] = 0x80000000 ; +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i] = 0x80000000 ; continue ; } ; +#endif - dest [count] = psf_lrintf (scaled_value) ; + dest [i] = psf_lrintf (scaled_value) ; } ; return ; @@ -1709,8 +1785,8 @@ psf_d2i_array (const double *src, int *dest, int count, int normalize) { double normfact ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrint (src [i] * normfact) ; return ; } /* psf_f2i_array */ @@ -1721,18 +1797,22 @@ psf_d2i_clip_array (const double *src, int *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count] = 0x7FFFFFFF ; + 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] = 0x7FFFFFFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count] = 0x80000000 ; +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i] = 0x80000000 ; continue ; } ; +#endif - dest [count] = psf_lrint (scaled_value) ; + dest [i] = psf_lrint (scaled_value) ; } ; return ; diff --git a/src/common.h b/src/common.h index 08360d06..c7747c5c 100644 --- a/src/common.h +++ b/src/common.h @@ -23,6 +23,9 @@ #include #include +#if HAVE_STDBOOL_H +#include +#endif #if HAVE_INTTYPES_H #include @@ -47,20 +50,6 @@ #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 - /* @@ -99,24 +88,8 @@ #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) -#define NOT(x) (! (x)) - -#if COMPILER_IS_GCC -#define SF_MAX(x, y) ({ \ - typeof (x) sf_max_x1 = (x) ; \ - typeof (y) sf_max_y1 = (y) ; \ - (void) (&sf_max_x1 == &sf_max_y1) ; \ - sf_max_x1 > sf_max_y1 ? sf_max_x1 : sf_max_y1 ; }) - -#define SF_MIN(x, y) ({ \ - typeof (x) sf_min_x2 = (x) ; \ - typeof (y) sf_min_y2 = (y) ; \ - (void) (&sf_min_x2 == &sf_min_y2) ; \ - sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; }) -#else #define SF_MAX(a, b) ((a) > (b) ? (a) : (b)) #define SF_MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif #define COMPILE_TIME_ASSERT(e) (sizeof (struct { int : - !! (e) ; })) @@ -124,7 +97,6 @@ #define SF_MAX_CHANNELS 1024 - /* * Macros for spliting the format file of SF_INFO into container type, ** codec type and endian-ness. @@ -307,6 +279,12 @@ typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ; typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ; +typedef struct +{ sf_count_t offset ; + sf_count_t len ; + unsigned minor_version ; +} ID3V2_HEADER_INFO ; + #if SIZEOF_WCHAR_T == 2 typedef wchar_t sfwchar_t ; #else @@ -314,20 +292,13 @@ typedef int16_t sfwchar_t ; #endif -static inline void * -psf_memdup (const void *src, size_t n) -{ void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ; - return memcpy (mem, src, n) ; -} /* psf_memdup */ +void *psf_memdup (const void *src, size_t n) ; /* ** This version of isprint specifically ignores any locale info. Its used for ** determining which characters can be printed in things like hexdumps. */ -static inline int -psf_isprint (int ch) -{ return (ch >= ' ' && ch <= '~') ; -} /* psf_isprint */ +int psf_isprint (int ch) ; /*======================================================================================= ** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the @@ -337,36 +308,23 @@ psf_isprint (int ch) typedef struct { - union - { char c [SF_FILENAME_LEN] ; - sfwchar_t wc [SF_FILENAME_LEN] ; - } path ; - - union - { char c [SF_FILENAME_LEN] ; - sfwchar_t wc [SF_FILENAME_LEN] ; - } dir ; - - union - { char c [SF_FILENAME_LEN / 4] ; - sfwchar_t wc [SF_FILENAME_LEN / 4] ; - } name ; + char path [SF_FILENAME_LEN] ; + char dir [SF_FILENAME_LEN] ; + char name [SF_FILENAME_LEN / 4] ; #if USE_WINDOWS_API /* ** These fields can only be used in src/file_io.c. ** They are basically the same as a windows file HANDLE. */ - void *handle, *hsaved ; - - int use_wchar ; + void *handle, *hsaved ; #else /* These fields can only be used in src/file_io.c. */ - int filedes, savedes ; + int filedes, savedes ; #endif - int do_not_close_descriptor ; - int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ + int do_not_close_descriptor ; + int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ } PSF_FILE ; @@ -390,13 +348,6 @@ typedef union typedef struct sf_private_tag { - /* Canary in a coal mine. */ - union - { /* Place a double here to encourage double alignment. */ - double d [2] ; - char c [16] ; - } canary ; - PSF_FILE file, rsrc ; char syserr [SF_SYSERR_LEN] ; @@ -554,6 +505,8 @@ typedef struct sf_private_tag int (*get_chunk_data) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ; int cpu_flags ; + + ID3V2_HEADER_INFO id3_header ; } SF_PRIVATE ; @@ -768,6 +721,17 @@ enum SFE_OPUS_BAD_SAMPLERATE, + SFE_CAF_NOT_CAF, + SFE_CAF_NO_DESC, + SFE_CAF_BAD_PEAK, + + SFE_AVR_NOT_AVR, + SFE_AVR_BAD_REZ_SIGN, + + SFE_MPC_NO_MARKER, + + SFE_MPEG_BAD_SAMPLERATE, + SFE_MAX_ERROR /* This must be last in list. */ } ; @@ -883,6 +847,8 @@ int psf_fclose (SF_PRIVATE *psf) ; int psf_open_rsrc (SF_PRIVATE *psf) ; int psf_close_rsrc (SF_PRIVATE *psf) ; +int psf_copy_filename (SF_PRIVATE *psf, const char *path) ; + /* void psf_fclearerr (SF_PRIVATE *psf) ; int psf_ferror (SF_PRIVATE *psf) ; @@ -921,10 +887,10 @@ int ogg_pcm_open (SF_PRIVATE *psf) ; int ogg_opus_open (SF_PRIVATE *psf) ; int ogg_open (SF_PRIVATE *psf) ; +int mpeg_open (SF_PRIVATE *psf) ; /* In progress. Do not currently work. */ -int mpeg_open (SF_PRIVATE *psf) ; int rx2_open (SF_PRIVATE *psf) ; int txw_open (SF_PRIVATE *psf) ; int wve_open (SF_PRIVATE *psf) ; @@ -946,6 +912,7 @@ int vox_adpcm_init (SF_PRIVATE *psf) ; int flac_init (SF_PRIVATE *psf) ; int g72x_init (SF_PRIVATE * psf) ; int alac_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ; +int mpeg_init (SF_PRIVATE *psf, int bitrate_mode, int write_metadata) ; int dither_init (SF_PRIVATE *psf, int mode) ; @@ -971,17 +938,6 @@ int psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITER int psf_find_write_chunk (WRITE_CHUNKS * pchk, const char * marker) ; -static inline int -fourcc_to_marker (const SF_CHUNK_INFO * chunk_info) -{ const unsigned char * cptr ; - - if (chunk_info->id_size != 4) - return 0 ; - - cptr = (const unsigned char *) chunk_info->id ; - return (cptr [3] << 24) + (cptr [2] << 16) + (cptr [1] << 8) + cptr [0] ; -} /* fourcc_to_marker */ - /*------------------------------------------------------------------------------------ ** Functions that work like OpenBSD's strlcpy/strlcat to replace strncpy/strncat. ** @@ -994,17 +950,8 @@ fourcc_to_marker (const SF_CHUNK_INFO * chunk_info) ** compiler errors if code is carelessly converted from one to the other. */ -static inline void -psf_strlcat (char *dest, size_t n, const char *src) -{ strncat (dest, src, n - strlen (dest) - 1) ; - dest [n - 1] = 0 ; -} /* psf_strlcat */ - -static inline void -psf_strlcpy (char *dest, size_t n, const char *src) -{ strncpy (dest, src, n - 1) ; - dest [n - 1] = 0 ; -} /* psf_strlcpy */ +void psf_strlcat (char *dest, size_t n, const char *src) ; +void psf_strlcpy (char *dest, size_t n, const char *src) ; /*------------------------------------------------------------------------------------ ** SIMD optimized math functions. @@ -1061,6 +1008,7 @@ typedef struct int audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ; int id3_skip (SF_PRIVATE * psf) ; +const char *id3_lookup_v1_genre (int number) ; void alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet) ; diff --git a/src/config.h.cmake b/src/config.h.cmake index c33bcbc8..71fdb4f2 100644 --- a/src/config.h.cmake +++ b/src/config.h.cmake @@ -43,6 +43,9 @@ /* Will be set to 1 if flac, ogg and vorbis are available. */ #cmakedefine01 HAVE_EXTERNAL_XIPH_LIBS +/* Will be set to 1 if lame and mpg123 are available. */ +#cmakedefine01 HAVE_MPEG + /* Define to 1 if you have the `floor' function. */ #cmakedefine01 HAVE_FLOOR @@ -175,6 +178,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine01 HAVE_IMMINTRIN_H +/* Define to 1 if you have the header file. */ +#cmakedefine01 HAVE_STDBOOL_H + /* Define to 1 if you have the `vsnprintf' function. */ #cmakedefine01 HAVE_VSNPRINTF @@ -217,9 +223,6 @@ /* 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@ @@ -247,9 +250,6 @@ /* 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@ @@ -265,9 +265,6 @@ /* 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 diff --git a/src/dither.c b/src/dither.c index a36705e5..b0ef7311 100644 --- a/src/dither.c +++ b/src/dither.c @@ -242,7 +242,7 @@ dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len) dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; - thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ; + thiswrite = (int) pdither->write_short (psf, (short*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) @@ -288,7 +288,7 @@ dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len) dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; - thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ; + thiswrite = (int) pdither->write_int (psf, (int*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) @@ -327,13 +327,13 @@ dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len) bufferlen = sizeof (pdither->buffer) / (sizeof (float)) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : (float) len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; writecount /= psf->sf.channels ; writecount *= psf->sf.channels ; dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; - thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ; + thiswrite = (int) pdither->write_float (psf, (float*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) @@ -373,13 +373,13 @@ dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len) bufferlen = sizeof (pdither->buffer) / sizeof (double) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : (double) len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; writecount /= psf->sf.channels ; writecount *= psf->sf.channels ; dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; - thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ; + thiswrite = (int) pdither->write_double (psf, (double*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) diff --git a/src/double64.c b/src/double64.c index fb6d468c..0c79cd58 100644 --- a/src/double64.c +++ b/src/double64.c @@ -486,71 +486,71 @@ double64_get_capability (SF_PRIVATE *psf) static void d2s_array (const double *src, int count, short *dest, double scale) -{ while (--count >= 0) - { dest [count] = psf_lrint (scale * src [count]) ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrint (scale * src [i]) ; } ; } /* d2s_array */ static void d2s_clip_array (const double *src, int count, short *dest, double scale) -{ while (--count >= 0) - { double tmp = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { double tmp = scale * src [i] ; - if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) - dest [count] = SHRT_MAX ; - else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0) - dest [count] = SHRT_MIN ; + if (tmp > 32767.0) + dest [i] = SHRT_MAX ; + else if (tmp < -32768.0) + dest [i] = SHRT_MIN ; else - dest [count] = psf_lrint (tmp) ; + dest [i] = psf_lrint (tmp) ; } ; } /* d2s_clip_array */ static void d2i_array (const double *src, int count, int *dest, double scale) -{ while (--count >= 0) - { dest [count] = psf_lrint (scale * src [count]) ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrint (scale * src [i]) ; } ; } /* d2i_array */ static void d2i_clip_array (const double *src, int count, int *dest, double scale) -{ while (--count >= 0) - { float tmp = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { float tmp = scale * src [i] ; if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) - dest [count] = INT_MAX ; + dest [i] = INT_MAX ; else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) - dest [count] = INT_MIN ; + dest [i] = INT_MIN ; else - dest [count] = psf_lrint (tmp) ; + dest [i] = psf_lrint (tmp) ; } ; } /* d2i_clip_array */ static inline void d2f_array (const double *src, int count, float *dest) -{ while (--count >= 0) - { dest [count] = src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = src [i] ; } ; } /* d2f_array */ static inline void s2d_array (const short *src, double *dest, int count, double scale) -{ while (--count >= 0) - { dest [count] = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = scale * src [i] ; } ; } /* s2d_array */ static inline void i2d_array (const int *src, double *dest, int count, double scale) -{ while (--count >= 0) - { dest [count] = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = scale * src [i] ; } ; } /* i2d_array */ static inline void f2d_array (const float *src, double *dest, int count) -{ while (--count >= 0) - { dest [count] = src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = src [i] ; } ; } /* f2d_array */ @@ -572,7 +572,7 @@ host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, readcount) ; @@ -602,7 +602,7 @@ host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; @@ -628,7 +628,7 @@ host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, readcount) ; @@ -695,7 +695,7 @@ host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -726,7 +726,7 @@ host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -755,7 +755,7 @@ host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -785,7 +785,7 @@ host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) endswap_double_copy (ubuf.dbuf, ptr + total, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -811,7 +811,7 @@ replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; @@ -841,7 +841,7 @@ replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; @@ -869,7 +869,7 @@ replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; @@ -899,7 +899,7 @@ replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, readcount) ; @@ -940,7 +940,7 @@ replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -973,7 +973,7 @@ replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1001,7 +1001,7 @@ replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1034,7 +1034,7 @@ replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_double_array (ubuf.dbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1049,15 +1049,15 @@ replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) static void d2bd_read (double *buffer, int count) -{ while (--count >= 0) - { buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ; +{ for (int i = 0 ; i < count ; i++) + { buffer [i] = DOUBLE64_READ ((unsigned char *) &buffer [i]) ; } ; } /* d2bd_read */ static void bd2d_write (double *buffer, int count) -{ while (--count >= 0) - { DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; +{ for (int i = 0 ; i < count ; i++) + { DOUBLE64_WRITE (buffer [i], (unsigned char*) &buffer [i]) ; } ; } /* bd2d_write */ diff --git a/src/dwd.c b/src/dwd.c index af4d9f0e..a15750d4 100644 --- a/src/dwd.c +++ b/src/dwd.c @@ -115,9 +115,9 @@ dwd_close (SF_PRIVATE * UNUSED (psf)) ** No assumptions are made about the packing of this struct. */ typedef struct -{ unsigned char major, minor, compression, channels, bitwidth ; - unsigned short srate, maxval ; - unsigned int id, datalen, frames, offset ; +{ uint8_t major, minor, compression, channels, bitwidth ; + uint16_t srate, maxval ; + uint32_t id, datalen, frames, offset ; } DWD_HEADER ; static int @@ -173,7 +173,7 @@ dwd_read_header (SF_PRIVATE *psf) if (psf->filelength != dwdh.offset + dwdh.datalen) { psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; - dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ; + dwdh.datalen = (uint32_t) (psf->filelength - dwdh.offset) ; } else psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; diff --git a/src/dwvw.c b/src/dwvw.c index 13985ad7..a015fceb 100644 --- a/src/dwvw.c +++ b/src/dwvw.c @@ -198,7 +198,7 @@ dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = iptr [k] >> 16 ; @@ -255,7 +255,7 @@ dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (float) (iptr [k]) ; @@ -287,7 +287,7 @@ dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (iptr [k]) ; @@ -377,7 +377,7 @@ dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) /* Load bits in bit reseviour. */ while (pdwvw->bit_count < bit_count) { if (pdwvw->b.index >= pdwvw->b.end) - { pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ; + { pdwvw->b.end = (int) psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ; pdwvw->b.index = 0 ; } ; @@ -569,7 +569,7 @@ dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = arith_shift_left (ptr [total + k], 16) ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; @@ -626,7 +626,7 @@ dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = psf_lrintf (normfact * ptr [total + k]) ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; @@ -658,7 +658,7 @@ dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = psf_lrint (normfact * ptr [total + k]) ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; diff --git a/src/file_io.c b/src/file_io.c index 9cd9379c..b7f7ed77 100644 --- a/src/file_io.c +++ b/src/file_io.c @@ -76,6 +76,34 @@ static void psf_log_syserr (SF_PRIVATE *psf, int error) ; +int +psf_copy_filename (SF_PRIVATE *psf, const char *path) +{ const char *ccptr ; + char *cptr ; + + if (strlen (path) > 1 && strlen (path) - 1 >= sizeof (psf->file.path)) + { psf->error = SFE_FILENAME_TOO_LONG ; + return psf->error ; + } ; + + snprintf (psf->file.path, sizeof (psf->file.path), "%s", path) ; + if ((ccptr = strrchr (path, '/')) || (ccptr = strrchr (path, '\\'))) + ccptr ++ ; + else + ccptr = path ; + + snprintf (psf->file.name, sizeof (psf->file.name), "%s", ccptr) ; + + /* Now grab the directory. */ + snprintf (psf->file.dir, sizeof (psf->file.dir), "%s", path) ; + if ((cptr = strrchr (psf->file.dir, '/')) || (cptr = strrchr (psf->file.dir, '\\'))) + cptr [1] = 0 ; + else + psf->file.dir [0] = 0 ; + + return 0 ; +} /* psf_copy_filename */ + #if (USE_WINDOWS_API == 0) /*------------------------------------------------------------------------------ @@ -132,9 +160,9 @@ psf_open_rsrc (SF_PRIVATE *psf) return 0 ; /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ - count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/..namedfork/rsrc", psf->file.path.c) ; + count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s/..namedfork/rsrc", psf->file.path) ; psf->error = SFE_NO_ERROR ; - if (count < sizeof (psf->rsrc.path.c)) + if (count < sizeof (psf->rsrc.path)) { if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE)) @@ -153,9 +181,9 @@ psf_open_rsrc (SF_PRIVATE *psf) ** Now try for a resource fork stored as a separate file in the same ** directory, but preceded with a dot underscore. */ - count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ; + count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s._%s", psf->file.dir, psf->file.name) ; psf->error = SFE_NO_ERROR ; - if (count < sizeof (psf->rsrc.path.c) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) + if (count < sizeof (psf->rsrc.path) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; return SFE_NO_ERROR ; } ; @@ -164,9 +192,9 @@ psf_open_rsrc (SF_PRIVATE *psf) ** Now try for a resource fork stored in a separate file in the ** .AppleDouble/ directory. */ - count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ; + count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s.AppleDouble/%s", psf->file.dir, psf->file.name) ; psf->error = SFE_NO_ERROR ; - if (count < sizeof (psf->rsrc.path.c)) + if (count < sizeof (psf->rsrc.path)) { if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; return SFE_NO_ERROR ; @@ -477,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) @@ -572,9 +600,9 @@ psf_open_fd (PSF_FILE * pfile) } ; if (mode == 0) - fd = open (pfile->path.c, oflag) ; + fd = open (pfile->path, oflag) ; else - fd = open (pfile->path.c, oflag, mode) ; + fd = open (pfile->path, oflag, mode) ; return fd ; } /* psf_open_fd */ @@ -602,7 +630,7 @@ psf_fsync (SF_PRIVATE *psf) #endif } /* psf_fsync */ -#elif USE_WINDOWS_API +#else /* Win32 file i/o functions implemented using native Win32 API */ @@ -620,7 +648,7 @@ psf_fopen (SF_PRIVATE *psf) psf->error = 0 ; psf->file.handle = psf_open_handle (&psf->file) ; - if (psf->file.handle == NULL) + if (psf->file.handle == INVALID_HANDLE_VALUE) psf_log_syserr (psf, GetLastError ()) ; return psf->error ; @@ -634,14 +662,14 @@ psf_fclose (SF_PRIVATE *psf) return 0 ; if (psf->file.do_not_close_descriptor) - { psf->file.handle = NULL ; + { psf->file.handle = INVALID_HANDLE_VALUE ; return 0 ; } ; if ((retval = psf_close_handle (psf->file.handle)) == -1) psf_log_syserr (psf, GetLastError ()) ; - psf->file.handle = NULL ; + psf->file.handle = INVALID_HANDLE_VALUE ; return retval ; } /* psf_fclose */ @@ -649,13 +677,13 @@ psf_fclose (SF_PRIVATE *psf) /* USE_WINDOWS_API */ int psf_open_rsrc (SF_PRIVATE *psf) { - if (psf->rsrc.handle != NULL) + if (psf->rsrc.handle != INVALID_HANDLE_VALUE) return 0 ; /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ - snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/rsrc", psf->file.path.c) ; + snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s/rsrc", psf->file.path) ; psf->error = SFE_NO_ERROR ; - if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL) + if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE) { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ; return SFE_NO_ERROR ; } ; @@ -664,9 +692,9 @@ psf_open_rsrc (SF_PRIVATE *psf) ** Now try for a resource fork stored as a separate file in the same ** directory, but preceded with a dot underscore. */ - snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ; + snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s._%s", psf->file.dir, psf->file.name) ; psf->error = SFE_NO_ERROR ; - if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL) + if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE) { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ; return SFE_NO_ERROR ; } ; @@ -675,19 +703,17 @@ psf_open_rsrc (SF_PRIVATE *psf) ** Now try for a resource fork stored in a separate file in the ** .AppleDouble/ directory. */ - snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ; + snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s.AppleDouble/%s", psf->file.dir, psf->file.name) ; psf->error = SFE_NO_ERROR ; - if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL) + if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE) { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ; return SFE_NO_ERROR ; } ; /* No resource file found. */ - if (psf->rsrc.handle == NULL) + if (psf->rsrc.handle == INVALID_HANDLE_VALUE) psf_log_syserr (psf, GetLastError ()) ; - psf->rsrc.handle = NULL ; - return psf->error ; } /* psf_open_rsrc */ @@ -738,9 +764,9 @@ psf_get_filelen (SF_PRIVATE *psf) /* USE_WINDOWS_API */ void psf_init_files (SF_PRIVATE *psf) -{ psf->file.handle = NULL ; - psf->rsrc.handle = NULL ; - psf->file.hsaved = NULL ; +{ psf->file.handle = INVALID_HANDLE_VALUE ; + psf->rsrc.handle = INVALID_HANDLE_VALUE ; + psf->file.hsaved = INVALID_HANDLE_VALUE ; } /* psf_init_files */ /* USE_WINDOWS_API */ void @@ -764,6 +790,7 @@ psf_open_handle (PSF_FILE * pfile) DWORD dwShareMode ; DWORD dwCreationDistribution ; HANDLE handle ; + LPWSTR pwszPath = NULL ; switch (pfile->mode) { case SFM_READ : @@ -785,50 +812,40 @@ psf_open_handle (PSF_FILE * pfile) break ; default : - return NULL ; + return INVALID_HANDLE_VALUE ; + } ; + + int nResult = MultiByteToWideChar (CP_UTF8, 0, pfile->path, -1, NULL, 0) ; + pwszPath = malloc (nResult * sizeof (WCHAR)) ; + if (!pwszPath) + return INVALID_HANDLE_VALUE ; + + int nResult2 = MultiByteToWideChar (CP_UTF8, 0, pfile->path, -1, pwszPath, nResult) ; + if (nResult != nResult2) + { free (pwszPath) ; + return INVALID_HANDLE_VALUE ; } ; #if defined (WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - if (!pfile->use_wchar) - return NULL ; - CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ; cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ; cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ; - handle = CreateFile2 (pfile->path.wc, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ; - - if (handle == INVALID_HANDLE_VALUE) - return NULL ; - - return handle ; + handle = CreateFile2 (pwszPath, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ; #else - if (pfile->use_wchar) - handle = CreateFileW ( - pfile->path.wc, /* pointer to name of the file */ - dwDesiredAccess, /* access (read-write) mode */ - dwShareMode, /* share mode */ - 0, /* pointer to security attributes */ - dwCreationDistribution, /* how to create */ - FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ - NULL /* handle to file with attributes to copy */ - ) ; - else - handle = CreateFileA ( - pfile->path.c, /* pointer to name of the file */ - dwDesiredAccess, /* access (read-write) mode */ - dwShareMode, /* share mode */ - 0, /* pointer to security attributes */ - dwCreationDistribution, /* how to create */ - FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ - NULL /* handle to file with attributes to copy */ - ) ; - - if (handle == INVALID_HANDLE_VALUE) - return NULL ; + handle = CreateFileW ( + pwszPath, /* pointer to name of the file */ + dwDesiredAccess, /* access (read-write) mode */ + dwShareMode, /* share mode */ + 0, /* pointer to security attributes */ + dwCreationDistribution, /* how to create */ + FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ + NULL /* handle to file with attributes to copy */ + ) ; +#endif + free (pwszPath) ; return handle ; -#endif } /* psf_open_handle */ /* USE_WINDOWS_API */ static void @@ -860,14 +877,14 @@ psf_log_syserr (SF_PRIVATE *psf, int error) /* USE_WINDOWS_API */ int psf_close_rsrc (SF_PRIVATE *psf) { psf_close_handle (psf->rsrc.handle) ; - psf->rsrc.handle = NULL ; + psf->rsrc.handle = INVALID_HANDLE_VALUE ; return 0 ; } /* psf_close_rsrc */ /* USE_WINDOWS_API */ int psf_set_stdio (SF_PRIVATE *psf) -{ HANDLE handle = NULL ; +{ HANDLE handle = INVALID_HANDLE_VALUE ; int error = 0 ; switch (psf->file.mode) @@ -909,9 +926,7 @@ psf_set_file (SF_PRIVATE *psf, int fd) /* USE_WINDOWS_API */ int psf_file_valid (SF_PRIVATE *psf) -{ if (psf->file.handle == NULL) - return SF_FALSE ; - if (psf->file.handle == INVALID_HANDLE_VALUE) +{ if (psf->file.handle == INVALID_HANDLE_VALUE) return SF_FALSE ; return SF_TRUE ; } /* psf_set_file */ @@ -1073,7 +1088,7 @@ psf_ftell (SF_PRIVATE *psf) /* USE_WINDOWS_API */ static int psf_close_handle (HANDLE handle) -{ if (handle == NULL) +{ if (handle == INVALID_HANDLE_VALUE) return 0 ; if (CloseHandle (handle) == 0) @@ -1187,386 +1202,5 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) return retval ; } /* psf_ftruncate */ - -#else -/* Win32 file i/o functions implemented using Unix-style file i/o API */ - -/* Win32 has a 64 file offset seek function: -** -** __int64 _lseeki64 (int handle, __int64 offset, int origin) ; -** -** It also has a 64 bit fstat function: -** -** int fstati64 (int, struct _stati64) ; -** -** but the fscking thing doesn't work!!!!! The file size parameter returned -** by this function is only valid up until more data is written at the end of -** the file. That makes this function completely 100% useless. -*/ - -#include -#include - -/* Win32 */ int -psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) -{ int oflag, mode ; - - switch (open_mode) - { case SFM_READ : - oflag = O_RDONLY | O_BINARY ; - mode = 0 ; - break ; - - case SFM_WRITE : - oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; - mode = S_IRUSR | S_IWUSR | S_IRGRP ; - break ; - - case SFM_RDWR : - oflag = O_RDWR | O_CREAT | O_BINARY ; - mode = S_IRUSR | S_IWUSR | S_IRGRP ; - break ; - - default : - psf->error = SFE_BAD_OPEN_MODE ; - return -1 ; - break ; - } ; - - if (mode == 0) - psf->file.filedes = open (pathname, oflag) ; - else - psf->file.filedes = open (pathname, oflag, mode) ; - - if (psf->file.filedes == -1) - psf_log_syserr (psf, errno) ; - - return psf->file.filedes ; -} /* psf_fopen */ - -/* Win32 */ sf_count_t -psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) -{ sf_count_t new_position ; - - if (psf->virtual_io) - return psf->vio.seek (offset, whence, psf->vio_user_data) ; - - switch (whence) - { case SEEK_SET : - offset += psf->fileoffset ; - break ; - - case SEEK_END : - if (psf->file.mode == SFM_WRITE) - { new_position = _lseeki64 (psf->file.filedes, offset, whence) ; - - if (new_position < 0) - psf_log_syserr (psf, errno) ; - - return new_position - psf->fileoffset ; - } ; - - /* Transform SEEK_END into a SEEK_SET, ie find the file - ** length add the requested offset (should be <= 0) to - ** get the offset wrt the start of file. - */ - whence = SEEK_SET ; - offset = _lseeki64 (psf->file.filedes, 0, SEEK_END) + offset ; - break ; - - default : - /* No need to do anything about SEEK_CUR. */ - break ; - } ; - - /* - ** Bypass weird Win32-ism if necessary. - ** _lseeki64() returns an "invalid parameter" error if called with the - ** offset == 0 and whence == SEEK_CUR. - *** Use the _telli64() function instead. - */ - if (offset == 0 && whence == SEEK_CUR) - new_position = _telli64 (psf->file.filedes) ; - else - new_position = _lseeki64 (psf->file.filedes, offset, whence) ; - - if (new_position < 0) - psf_log_syserr (psf, errno) ; - - new_position -= psf->fileoffset ; - - return new_position ; -} /* psf_fseek */ - -/* Win32 */ sf_count_t -psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) -{ sf_count_t total = 0 ; - ssize_t count ; - - if (psf->virtual_io) - return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ; - - items *= bytes ; - - /* Do this check after the multiplication above. */ - if (items <= 0) - return 0 ; - - while (items > 0) - { /* Break the writes down to a sensible size. */ - count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; - - count = read (psf->file.filedes, ((char*) ptr) + total, (size_t) count) ; - - if (count == -1) - { if (errno == EINTR) - continue ; - - psf_log_syserr (psf, errno) ; - break ; - } ; - - if (count == 0) - break ; - - total += count ; - items -= count ; - } ; - - return total / bytes ; -} /* psf_fread */ - -/* Win32 */ sf_count_t -psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) -{ sf_count_t total = 0 ; - ssize_t count ; - - if (psf->virtual_io) - return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ; - - items *= bytes ; - - /* Do this check after the multiplication above. */ - if (items <= 0) - return 0 ; - - while (items > 0) - { /* Break the writes down to a sensible size. */ - count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; - - count = write (psf->file.filedes, ((const char*) ptr) + total, count) ; - - if (count == -1) - { if (errno == EINTR) - continue ; - - psf_log_syserr (psf, errno) ; - break ; - } ; - - if (count == 0) - break ; - - total += count ; - items -= count ; - } ; - - return total / bytes ; -} /* psf_fwrite */ - -/* Win32 */ sf_count_t -psf_ftell (SF_PRIVATE *psf) -{ sf_count_t pos ; - - if (psf->virtual_io) - return psf->vio.tell (psf->vio_user_data) ; - - pos = _telli64 (psf->file.filedes) ; - - if (pos == ((sf_count_t) -1)) - { psf_log_syserr (psf, errno) ; - return -1 ; - } ; - - return pos - psf->fileoffset ; -} /* psf_ftell */ - -/* Win32 */ int -psf_fclose (SF_PRIVATE *psf) -{ int retval ; - - while ((retval = close (psf->file.filedes)) == -1 && errno == EINTR) - /* Do nothing. */ ; - - if (retval == -1) - psf_log_syserr (psf, errno) ; - - psf->file.filedes = -1 ; - - return retval ; -} /* psf_fclose */ - -/* Win32 */ sf_count_t -psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) -{ sf_count_t k = 0 ; - sf_count_t count ; - - while (k < bufsize - 1) - { count = read (psf->file.filedes, &(buffer [k]), 1) ; - - if (count == -1) - { if (errno == EINTR) - continue ; - - psf_log_syserr (psf, errno) ; - break ; - } ; - - if (count == 0 || buffer [k++] == '\n') - break ; - } ; - - buffer [k] = 0 ; - - return k ; -} /* psf_fgets */ - -/* Win32 */ int -psf_is_pipe (SF_PRIVATE *psf) -{ struct stat statbuf ; - - if (psf->virtual_io) - return SF_FALSE ; - - /* Not sure if this works. */ - if (fstat (psf->file.filedes, &statbuf) == -1) - { psf_log_syserr (psf, errno) ; - /* Default to maximum safety. */ - return SF_TRUE ; - } ; - - /* These macros are defined in Win32/unistd.h. */ - if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) - return SF_TRUE ; - - return SF_FALSE ; -} /* psf_checkpipe */ - -/* Win32 */ sf_count_t -psf_get_filelen (SF_PRIVATE *psf) -{ -#if 0 - /* - ** Windoze is SOOOOO FUCKED!!!!!!! - ** This code should work but doesn't. Why? - ** Code below does work. - */ - struct _stati64 statbuf ; - - if (_fstati64 (psf->file.filedes, &statbuf)) - { psf_log_syserr (psf, errno) ; - return (sf_count_t) -1 ; - } ; - - return statbuf.st_size ; -#else - sf_count_t current, filelen ; - - if (psf->virtual_io) - return psf->vio.get_filelen (psf->vio_user_data) ; - - if ((current = _telli64 (psf->file.filedes)) < 0) - { psf_log_syserr (psf, errno) ; - return (sf_count_t) -1 ; - } ; - - /* - ** Lets face it, windoze if FUBAR!!! - ** - ** For some reason, I have to call _lseeki64() TWICE to get to the - ** end of the file. - ** - ** This might have been avoided if windows had implemented the POSIX - ** standard function fsync() but NO, that would have been too easy. - ** - ** I am VERY close to saying that windoze will no longer be supported - ** by libsndfile and changing the license to GPL at the same time. - */ - - _lseeki64 (psf->file.filedes, 0, SEEK_END) ; - - if ((filelen = _lseeki64 (psf->file.filedes, 0, SEEK_END)) < 0) - { psf_log_syserr (psf, errno) ; - return (sf_count_t) -1 ; - } ; - - if (filelen > current) - _lseeki64 (psf->file.filedes, current, SEEK_SET) ; - - switch (psf->file.mode) - { case SFM_WRITE : - filelen = filelen - psf->fileoffset ; - break ; - - case SFM_READ : - if (psf->fileoffset > 0 && psf->filelength > 0) - filelen = psf->filelength ; - break ; - - case SFM_RDWR : - /* - ** Cannot open embedded files SFM_RDWR so we don't need to - ** subtract psf->fileoffset. We already have the answer we - ** need. - */ - break ; - - default : - filelen = 0 ; - } ; - - return filelen ; -#endif -} /* psf_get_filelen */ - -/* Win32 */ int -psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) -{ int retval ; - - /* Returns 0 on success, non-zero on failure. */ - if (len < 0) - return 1 ; - - /* The global village idiots at micorsoft decided to implement - ** nearly all the required 64 bit file offset functions except - ** for one, truncate. The fscking morons! - ** - ** This is not 64 bit file offset clean. Somone needs to clean - ** this up. - */ - if (len > 0x7FFFFFFF) - return -1 ; - - retval = chsize (psf->file.filedes, len) ; - - if (retval == -1) - psf_log_syserr (psf, errno) ; - - return retval ; -} /* psf_ftruncate */ - - -static void -psf_log_syserr (SF_PRIVATE *psf, int error) -{ - /* Only log an error if no error has been set yet. */ - if (psf->error == 0) - { psf->error = SFE_SYSTEM ; - snprintf (psf->syserr, sizeof (psf->syserr), "System error : %s", strerror (error)) ; - } ; - - return ; -} /* psf_log_syserr */ - #endif diff --git a/src/flac.c b/src/flac.c index ea562f03..073ce553 100644 --- a/src/flac.c +++ b/src/flac.c @@ -43,6 +43,15 @@ #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, @@ -127,39 +136,39 @@ static FLAC__StreamEncoderWriteStatus sf_flac_enc_write_callback (const FLAC__St static void s2flac8_array (const short *src, int32_t *dest, int count) -{ while (--count >= 0) - dest [count] = src [count] >> 8 ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = src [i] >> 8 ; } /* s2flac8_array */ static void s2flac16_array (const short *src, int32_t *dest, int count) -{ while (--count >= 0) - dest [count] = src [count] ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = src [i] ; } /* s2flac16_array */ static void s2flac24_array (const short *src, int32_t *dest, int count) -{ while (--count >= 0) - dest [count] = src [count] << 8 ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = src [i] << 8 ; } /* s2flac24_array */ static void i2flac8_array (const int *src, int32_t *dest, int count) -{ while (--count >= 0) - dest [count] = src [count] >> 24 ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = src [i] >> 24 ; } /* i2flac8_array */ static void i2flac16_array (const int *src, int32_t *dest, int count) { - while (--count >= 0) - dest [count] = src [count] >> 16 ; + for (int i = 0 ; i < count ; i++) + dest [i] = src [i] >> 16 ; } /* i2flac16_array */ static void i2flac24_array (const int *src, int32_t *dest, int count) -{ while (--count >= 0) - dest [count] = src [count] >> 8 ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = src [i] >> 8 ; } /* i2flac24_array */ static sf_count_t @@ -952,7 +961,7 @@ flac_read_loop (SF_PRIVATE *psf, unsigned len) /* Current frame is busted, so NULL the pointer. */ pflac->frame = NULL ; break ; - }; + } ; state = FLAC__stream_decoder_get_state (pflac->fsd) ; if (state >= FLAC__STREAM_DECODER_END_OF_STREAM) { psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ; @@ -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) @@ -1180,17 +1189,17 @@ f2flac8_clip_array (const float *src, int32_t *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) - { dest [count] = 0x7F ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7F)) + { dest [i] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) - { dest [count] = -0x80 ; + if (scaled_value <= (-8.0 * 0x10)) + { dest [i] = -0x80 ; continue ; } ; - dest [count] = psf_lrintf (scaled_value) ; + dest [i] = psf_lrintf (scaled_value) ; } ; return ; @@ -1202,17 +1211,17 @@ f2flac16_clip_array (const float *src, int32_t *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x1000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) - { dest [count] = 0x7FFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFF)) + { dest [i] = 0x7FFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) - { dest [count] = -0x8000 ; + if (scaled_value <= (-8.0 * 0x1000)) + { dest [i] = -0x8000 ; continue ; } ; - dest [count] = psf_lrintf (scaled_value) ; + dest [i] = psf_lrintf (scaled_value) ; } ; } /* f2flac16_clip_array */ @@ -1222,18 +1231,18 @@ f2flac24_clip_array (const float *src, int32_t *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x100000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) - { dest [count] = 0x7FFFFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFF)) + { dest [i] = 0x7FFFFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) - { dest [count] = -0x800000 ; + if (scaled_value <= (-8.0 * 0x100000)) + { dest [i] = -0x800000 ; continue ; } - dest [count] = psf_lrintf (scaled_value) ; + dest [i] = psf_lrintf (scaled_value) ; } ; return ; @@ -1243,24 +1252,24 @@ static void f2flac8_array (const float *src, int32_t *dest, int count, int normalize) { float normfact = normalize ? (1.0 * 0x7F) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrintf (src [i] * normfact) ; } /* f2flac8_array */ static void f2flac16_array (const float *src, int32_t *dest, int count, int normalize) { float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrintf (src [i] * normfact) ; } /* f2flac16_array */ static void f2flac24_array (const float *src, int32_t *dest, int count, int normalize) { float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrintf (src [i] * normfact) ; } /* f2flac24_array */ static sf_count_t @@ -1311,17 +1320,17 @@ d2flac8_clip_array (const double *src, int32_t *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) - { dest [count] = 0x7F ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7F)) + { dest [i] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) - { dest [count] = -0x80 ; + if (scaled_value <= (-8.0 * 0x10)) + { dest [i] = -0x80 ; continue ; } ; - dest [count] = psf_lrint (scaled_value) ; + dest [i] = psf_lrint (scaled_value) ; } ; return ; @@ -1333,17 +1342,17 @@ d2flac16_clip_array (const double *src, int32_t *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x1000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) - { dest [count] = 0x7FFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFF)) + { dest [i] = 0x7FFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) - { dest [count] = -0x8000 ; + if (scaled_value <= (-8.0 * 0x1000)) + { dest [i] = -0x8000 ; continue ; } ; - dest [count] = psf_lrint (scaled_value) ; + dest [i] = psf_lrint (scaled_value) ; } ; return ; @@ -1355,17 +1364,17 @@ d2flac24_clip_array (const double *src, int32_t *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x100000) : 1.0 ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) - { dest [count] = 0x7FFFFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFF)) + { dest [i] = 0x7FFFFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) - { dest [count] = -0x800000 ; + if (scaled_value <= (-8.0 * 0x100000)) + { dest [i] = -0x800000 ; continue ; } ; - dest [count] = psf_lrint (scaled_value) ; + dest [i] = psf_lrint (scaled_value) ; } ; return ; @@ -1375,24 +1384,24 @@ static void d2flac8_array (const double *src, int32_t *dest, int count, int normalize) { double normfact = normalize ? (1.0 * 0x7F) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrint (src [i] * normfact) ; } /* d2flac8_array */ static void d2flac16_array (const double *src, int32_t *dest, int count, int normalize) { double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrint (src [i] * normfact) ; } /* d2flac16_array */ static void d2flac24_array (const double *src, int32_t *dest, int count, int normalize) { double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; - while (--count >= 0) - dest [count] = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + dest [i] = psf_lrint (src [i] * normfact) ; } /* d2flac24_array */ static sf_count_t diff --git a/src/float32.c b/src/float32.c index a63413d2..431e39bb 100644 --- a/src/float32.c +++ b/src/float32.c @@ -437,71 +437,71 @@ float32_get_capability (SF_PRIVATE *psf) static void f2s_array (const float *src, int count, short *dest, float scale) { - while (--count >= 0) - { dest [count] = psf_lrintf (scale * src [count]) ; + for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrintf (scale * src [i]) ; } ; } /* f2s_array */ static void f2s_clip_array (const float *src, int count, short *dest, float scale) -{ while (--count >= 0) - { float tmp = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { float tmp = scale * src [i] ; - if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) - dest [count] = SHRT_MAX ; - else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0) - dest [count] = SHRT_MIN ; + if (tmp > 32767.0) + dest [i] = SHRT_MAX ; + else if (tmp < -32768.0) + dest [i] = SHRT_MIN ; else - dest [count] = psf_lrintf (tmp) ; + dest [i] = psf_lrintf (tmp) ; } ; } /* f2s_clip_array */ static inline void f2i_array (const float *src, int count, int *dest, float scale) -{ while (--count >= 0) - { dest [count] = psf_lrintf (scale * src [count]) ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrintf (scale * src [i]) ; } ; } /* f2i_array */ static inline void f2i_clip_array (const float *src, int count, int *dest, float scale) -{ while (--count >= 0) - { float tmp = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { float tmp = scale * src [i] ; if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) - dest [count] = INT_MAX ; + dest [i] = INT_MAX ; else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) - dest [count] = INT_MIN ; + dest [i] = INT_MIN ; else - dest [count] = psf_lrintf (tmp) ; + dest [i] = psf_lrintf (tmp) ; } ; } /* f2i_clip_array */ static inline void f2d_array (const float *src, int count, double *dest) -{ while (--count >= 0) - { dest [count] = src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = src [i] ; } ; } /* f2d_array */ static inline void s2f_array (const short *src, float *dest, int count, float scale) -{ while (--count >= 0) - { dest [count] = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = scale * src [i] ; } ; } /* s2f_array */ static inline void i2f_array (const int *src, float *dest, int count, float scale) -{ while (--count >= 0) - { dest [count] = scale * src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = scale * src [i] ; } ; } /* i2f_array */ static inline void d2f_array (const double *src, float *dest, int count) -{ while (--count >= 0) - { dest [count] = src [count] ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = src [i] ; } ; } /* d2f_array */ @@ -523,7 +523,7 @@ host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; /* Fix me : Need lef2s_array */ if (psf->data_endswap == SF_TRUE) @@ -554,7 +554,7 @@ host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; @@ -583,7 +583,7 @@ host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; endswap_int_copy ((int*) (ptr + total), ubuf.ibuf, readcount) ; @@ -607,7 +607,7 @@ host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; @@ -645,7 +645,7 @@ host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -676,7 +676,7 @@ host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -706,7 +706,7 @@ host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) endswap_int_copy (ubuf.ibuf, (const int*) (ptr + total), bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -736,7 +736,7 @@ host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -762,7 +762,7 @@ replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; @@ -787,12 +787,12 @@ replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) float scale ; bufferlen = ARRAY_LEN (ubuf.fbuf) ; - scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; + scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ; while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; @@ -822,7 +822,7 @@ replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; @@ -851,7 +851,7 @@ replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; @@ -891,7 +891,7 @@ replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -924,7 +924,7 @@ replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -957,7 +957,7 @@ replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -988,7 +988,7 @@ replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) if (psf->data_endswap == SF_TRUE) endswap_int_array (ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1003,15 +1003,15 @@ replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) static void bf2f_array (float *buffer, int count) -{ while (--count >= 0) - { buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ; +{ for (int i = 0 ; i < count ; i++) + { buffer [i] = FLOAT32_READ ((unsigned char *) &buffer [i]) ; } ; } /* bf2f_array */ static void f2bf_array (float *buffer, int count) -{ while (--count >= 0) - { FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; +{ for (int i = 0 ; i < count ; i++) + { FLOAT32_WRITE (buffer [i], (unsigned char*) &buffer [i]) ; } ; } /* f2bf_array */ diff --git a/src/g72x.c b/src/g72x.c index 563a9092..62e40051 100644 --- a/src/g72x.c +++ b/src/g72x.c @@ -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) ; } @@ -264,7 +264,7 @@ g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = g72x_read_block (psf, pg72x, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) @@ -297,7 +297,7 @@ g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = g72x_read_block (psf, pg72x, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; @@ -329,7 +329,7 @@ g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = g72x_read_block (psf, pg72x, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (sptr [k]) ; @@ -505,7 +505,7 @@ g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = g72x_write_block (psf, pg72x, sptr, writecount) ; @@ -536,7 +536,7 @@ g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; count = g72x_write_block (psf, pg72x, sptr, writecount) ; @@ -568,7 +568,7 @@ g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrint (normfact * ptr [total + k]) ; count = g72x_write_block (psf, pg72x, sptr, writecount) ; diff --git a/src/gsm610.c b/src/gsm610.c index 06519bc2..933f03f0 100644 --- a/src/gsm610.c +++ b/src/gsm610.c @@ -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) ; @@ -198,7 +198,7 @@ gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) return 1 ; } ; - if ((k = psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) + if ((k = (int) psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ; if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) @@ -226,7 +226,7 @@ gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) return 1 ; } ; - if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) + if ((k = (int) psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ; if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) @@ -302,7 +302,7 @@ gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = arith_shift_left (sptr [k], 16) ; @@ -331,7 +331,7 @@ gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; @@ -360,7 +360,7 @@ gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; @@ -437,7 +437,7 @@ gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; /* Write the block to disk. */ - if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) + if ((k = (int) psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ; pgsm610->samplecount = 0 ; @@ -458,7 +458,7 @@ gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAVLIKE_GSM610_SAMPLES / 2, pgsm610->block+WAVLIKE_GSM610_BLOCKSIZE / 2) ; /* Write the block to disk. */ - if ((k = psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) + if ((k = (int) psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ; pgsm610->samplecount = 0 ; @@ -532,7 +532,7 @@ gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; @@ -561,7 +561,7 @@ gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; @@ -592,7 +592,7 @@ gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrint (normfact * ptr [total + k]) ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; diff --git a/src/id3.c b/src/id3.c index 2b82d0fa..1516ee31 100644 --- a/src/id3.c +++ b/src/id3.c @@ -26,34 +26,107 @@ #include "sndfile.h" #include "sfendian.h" #include "common.h" +#include "id3.h" + +#if HAVE_MPEG +#include + +struct id3v1_genre_handler_userdata +{ int number ; + const char *ret ; +} ; + +static void +id3v1_genre_handler (int number, const char *description, void *userdata) +{ struct id3v1_genre_handler_userdata *data = (struct id3v1_genre_handler_userdata *) userdata ; + if (data->number == number) + data->ret = description ; +} + +const char * +id3_lookup_v1_genre (int number) +{ struct id3v1_genre_handler_userdata data ; + + data.number = number ; + data.ret = NULL ; + id3tag_genre_list (id3v1_genre_handler, &data) ; + + return data.ret ; +} + +#else /* HAVE_MPEG */ + +const char * +id3_lookup_v1_genre (int UNUSED (number)) +{ return NULL ; + } + +#endif int id3_skip (SF_PRIVATE * psf) { unsigned char buf [10] ; + int offset ; memset (buf, 0, sizeof (buf)) ; psf_binheader_readf (psf, "pb", 0, buf, 10) ; if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3') - { int offset = buf [6] & 0x7f ; + { psf->id3_header.minor_version = buf [3] ; + offset = buf [6] & 0x7f ; offset = (offset << 7) | (buf [7] & 0x7f) ; offset = (offset << 7) | (buf [8] & 0x7f) ; offset = (offset << 7) | (buf [9] & 0x7f) ; - psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ; + /* + ** ID3 count field is how many bytes of ID3v2 header FOLLOW the ten + ** bytes of header magic and offset, NOT the total ID3v2 header len. + */ + psf->id3_header.len = offset + 10 ; + psf->id3_header.offset = psf->fileoffset ; + + psf_log_printf (psf, " ID3v2.%d header length : %d\n----------------------------------------\n", + psf->id3_header.minor_version, psf->id3_header.len) ; /* Never want to jump backwards in a file. */ if (offset < 0) return 0 ; - /* Calculate new file offset and position ourselves there. */ - offset += 10 ; - if (psf->fileoffset + offset < psf->filelength) - { psf_binheader_readf (psf, "p", offset) ; - psf->fileoffset += offset ; + /* Position ourselves at the new file offset. */ + if (psf->fileoffset + psf->id3_header.len < psf->filelength) + { psf_binheader_readf (psf, "p!", psf->id3_header.len) ; + psf->fileoffset += psf->id3_header.len ; return 1 ; } ; } ; return 0 ; } /* id3_skip */ + +const char * +id3_process_v2_genre (const char *genre) +{ int num = 0 ; + char c ; + const char *ptr ; + + if (!genre) + return NULL ; + + /* + ** Genre may require more processing. + ** + ** It is allowed to have numeric references to the genre table from ID3v1. + ** We'll just convert the simple case here, strings of the format "(nnn)". + */ + ptr = genre ; + if (ptr [0] == '(' && (c = *++ ptr) && isdigit (c)) + { num = c - '0' ; + while ((c == *++ ptr) && isdigit (c)) + num = num * 10 + (c - '0') ; + if (c == ')' && (c = *++ ptr) == '\0' && num < 256) + if ((ptr = id3_lookup_v1_genre (num))) + return ptr ; + } ; + + return genre ; +} /* id3_process_v2_genre */ diff --git a/src/id3.h b/src/id3.h new file mode 100644 index 00000000..4f54c4fc --- /dev/null +++ b/src/id3.h @@ -0,0 +1,29 @@ +/* +** Copyright (C) 2008-2019 Erik de Castro Lopo +** Copyright (C) 2019 Arthur Taylor +** +** This program is free software ; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation ; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY ; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef SF_SRC_ID3_H +#define SF_SRC_ID3_H + +int id3_skip (SF_PRIVATE * psf) ; + +const char *id3_lookup_v1_genre (int number) ; + +const char *id3_process_v2_genre (const char *genre) ; + +#endif /* SF_SRC_ID3_H */ diff --git a/src/ima_adpcm.c b/src/ima_adpcm.c index 8c9bbff3..bc61f4e5 100644 --- a/src/ima_adpcm.c +++ b/src/ima_adpcm.c @@ -182,7 +182,12 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) if (psf->file.mode != SFM_READ) return SFE_BAD_MODE_RW ; - pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ; + /* + ** Allocate enough space for 1 more than a multiple of 8 samples + ** to avoid having to branch when pulling apart the nibbles. + */ + count = ((samplesperblock - 2) | 7) + 2 ; + pimasize = sizeof (IMA_ADPCM_PRIVATE) + psf->sf.channels * (blockalign + samplesperblock + sizeof(short) * count) ; if (! (pima = calloc (1, pimasize))) return SFE_MALLOC_FAILED ; @@ -268,7 +273,7 @@ count ++ ; return 1 ; } ; - if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) + if ((k = (int) psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; /* Read and check the block header. */ @@ -373,7 +378,7 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) } ; /* Write the block to disk. */ - if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) + if ((k = (int) psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ; memset (pima->block, 0, pima->channels * pima->blocksize) ; @@ -386,7 +391,7 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) static int wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) { int chan, k, predictor, blockindx, indx, indxstart, diff ; - short step, bytecode, stepindx [2] ; + short step, bytecode, stepindx [2] = { 0 }; pima->blockcount ++ ; pima->samplecount = 0 ; @@ -396,7 +401,7 @@ wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) return 1 ; } ; - if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) + if ((k = (int) psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; /* Read and check the block header. */ @@ -552,7 +557,7 @@ wavlike_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) /* Write the block to disk. */ - if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) + if ((k = (int) psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ; memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ; diff --git a/src/mpc2k.c b/src/mpc2k.c index aef21ad9..733f1f4b 100644 --- a/src/mpc2k.c +++ b/src/mpc2k.c @@ -46,8 +46,6 @@ #define HEADER_LENGTH 42 /* Sum of above data fields. */ #define HEADER_NAME_LEN 17 /* Length of name string. */ -#define SFE_MPC_NO_MARKER 666 - /*------------------------------------------------------------------------------ ** Private static functions. */ @@ -131,7 +129,7 @@ mpc2k_write_header (SF_PRIVATE *psf, int calc_length) if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; - snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name.c) ; + snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name) ; psf_binheader_writef (psf, "e11b", BHW1 (1), BHW1 (4), BHWv (sample_name), BHWz (HEADER_NAME_LEN)) ; psf_binheader_writef (psf, "e111", BHW1 (100), BHW1 (0), BHW1 ((psf->sf.channels - 1) & 1)) ; diff --git a/src/mpeg.c b/src/mpeg.c new file mode 100644 index 00000000..44db0adf --- /dev/null +++ b/src/mpeg.c @@ -0,0 +1,165 @@ +/* +** Copyright (C) 2019 Erik de Castro Lopo +** Copyright (C) 2021 Arthur Taylor +** +** This program is free software ; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation ; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY ; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include "sndfile.h" +#include "common.h" + +#if HAVE_MPEG + +#include "mpeg.h" + +static int mpeg_write_header (SF_PRIVATE *psf, int calc_length) ; +static int mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; + +/*------------------------------------------------------------------------------ + * Private functions + */ + +static int +mpeg_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) +{ + if (psf->have_written) + return 0 ; + + return mpeg_l3_encoder_write_id3tag (psf) ; +} + +static int +mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize) +{ int bitrate_mode ; + + switch (command) + { case SFC_SET_COMPRESSION_LEVEL : + if (data == NULL || datasize != sizeof (double)) + { psf->error = SFE_BAD_COMMAND_PARAM ; + return SF_FALSE ; + } ; + if (psf->file.mode != SFM_WRITE) + { psf->error = SFE_NOT_WRITEMODE ; + return SF_FALSE ; + } ; + return mpeg_l3_encoder_set_quality (psf, *(double *) data) ; + + case SFC_SET_BITRATE_MODE : + if (psf->file.mode != SFM_WRITE) + { psf->error = SFE_NOT_WRITEMODE ; + return SF_FALSE ; + } ; + if (data == NULL || datasize != sizeof (int)) + { psf->error = SFE_BAD_COMMAND_PARAM ; + return SF_FALSE ; + } ; + bitrate_mode = *(int *) data ; + return mpeg_l3_encoder_set_bitrate_mode (psf, bitrate_mode) ; + + case SFC_GET_BITRATE_MODE : + if (psf->file.mode == SFM_READ) + return mpeg_decoder_get_bitrate_mode (psf) ; + else + return mpeg_l3_encoder_get_bitrate_mode (psf) ; + + default : + return SF_FALSE ; + } ; + + return SF_FALSE ; +} /* mpeg_command */ + +/*------------------------------------------------------------------------------ + * Public functions + */ + +int +mpeg_init (SF_PRIVATE *psf, int bitrate_mode, int write_metadata) +{ int error ; + + if (psf->file.mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if (psf->file.mode == SFM_WRITE) + { switch (SF_CODEC (psf->sf.format)) + { case SF_FORMAT_MPEG_LAYER_III : + if ((error = mpeg_l3_encoder_init (psf, write_metadata))) + return error ; + mpeg_l3_encoder_set_bitrate_mode (psf, bitrate_mode) ; + if (write_metadata) + { /* ID3 support */ + psf->strings.flags = SF_STR_ALLOW_START ; + psf->write_header = mpeg_write_header ; + } ; + break ; + + case SF_FORMAT_MPEG_LAYER_I : + case SF_FORMAT_MPEG_LAYER_II : + psf_log_printf (psf, "MPEG Layer I and II encoding is not yet supported.\n") ; + return SFE_UNIMPLEMENTED ; + + default: + psf_log_printf (psf, "%s: bad psf->sf.format 0x%x.\n", __func__, psf->sf.format) ; + return SFE_INTERNAL ; + } ; + } ; + + if (psf->file.mode == SFM_READ) + { if ((error = mpeg_decoder_init (psf))) + return error ; + } ; + + return 0 ; +} /* mpeg_init */ + +int +mpeg_open (SF_PRIVATE *psf) +{ int error ; + + /* Choose variable bitrate mode by default for standalone files.*/ + if ((error = mpeg_init (psf, SF_BITRATE_MODE_VARIABLE, SF_TRUE))) + return error ; + + psf->dataoffset = 0 ; + psf->command = mpeg_command ; + + if (psf->filelength != SF_COUNT_MAX) + psf->datalength = psf->filelength - psf->dataoffset ; + else + psf->datalength = SF_COUNT_MAX ; + + + return 0 ; +} /* mpeg_open */ + +#else /* HAVE_MPEG */ + +int +mpeg_init (SF_PRIVATE *psf, int UNUSED (bitrate_mode) , int UNUSED (write_metadata)) +{ + psf_log_printf (psf, "This version of libsndfile was compiled without MPEG support.\n") ; + return SFE_UNIMPLEMENTED ; +} /* mpeg_init */ + +int +mpeg_open (SF_PRIVATE *psf) +{ + psf_log_printf (psf, "This version of libsndfile was compiled without MP3 support.\n") ; + return SFE_UNIMPLEMENTED ; +} /* mpeg_open */ + +#endif diff --git a/src/mpeg.h b/src/mpeg.h new file mode 100644 index 00000000..f335745f --- /dev/null +++ b/src/mpeg.h @@ -0,0 +1,74 @@ +/* +** Copyright (C) 2019 Erik de Castro Lopo +** Copyright (C) 2019 Arthur Taylor +** +** This program is free software ; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation ; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY ; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef SNDFILE_MPEG_H +#define SNDFILE_MPEG_H + +#include "common.h" + +int mpeg_decoder_init (SF_PRIVATE *psf) ; + +/* +** Get the file bitrate mode, returning one of the SF_BITRATE_MODE_ enum +** values. Purely informative, 'Frankenstein' files and VBR files without an +** Xing/LAME/Info header may not be detected properly. +*/ +int mpeg_decoder_get_bitrate_mode (SF_PRIVATE *psf) ; + + +/* +** Initialize an encoder instance for writing. If parameter info_tag is +** SF_TRUE, a Xing/LAME/Info header is written at the beginning of the file, +** (unless the file cannot seek.) +*/ +int mpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag) ; + + +/* +** Write an ID3v2 header from the sndfile string metadata. Must be called +** before any audio data is written. Writing an ID3v2 header will also cause +** a ID3v1 trailer to be written on close automatically. +*/ +int mpeg_l3_encoder_write_id3tag (SF_PRIVATE *psf) ; + +/* +** Set the encoder quality setting. Argument to compression should be identical +** to that for SFC_SET_COMPRESSION_LEVEL; It should be in the range [0-1], +** with 0 being highest quality, least compression, and 1 being the opposite. +** Returns SF_TRUE on success, SF_FALSE otherwise. +*/ +int mpeg_l3_encoder_set_quality (SF_PRIVATE *psf, double compression) ; + +/* +** Set the encoder bitrate mode. Can only be called before any data has been +** written. Argument mode should be one of the SF_BITRATE_MODE_ enum values. +** Returns SF_TRUE on success, SF_FALSE otherwise. The SF_BITRATE_MODE_FILE +** enum value should not be passed here but rather intercepted at the container +** level and translated according to the container. +*/ +int mpeg_l3_encoder_set_bitrate_mode (SF_PRIVATE *psf, int mode) ; + +/* +** Get the encoder bitrate mode in use. Returns a SF_BITRATE_MODE_ enum value. +** Will not return SF_BITRATE_MODE_FILE. +*/ +int mpeg_l3_encoder_get_bitrate_mode (SF_PRIVATE *psf) ; + + +#endif /* SNDFILE_MPEG_H */ diff --git a/src/mpeg_decode.c b/src/mpeg_decode.c new file mode 100644 index 00000000..582c5e1a --- /dev/null +++ b/src/mpeg_decode.c @@ -0,0 +1,638 @@ +/* +** Copyright (C) 2019 - 2021 Arthur Taylor +** Copyright (C) 2019 Erik de Castro Lopo +** +** This program is free software ; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation ; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY ; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include + +#include "sndfile.h" +#include "common.h" +#include "mpeg.h" + +#if HAVE_MPEG + +#include "sfendian.h" +#include "id3.h" + +#include + +typedef struct +{ mpg123_handle *pmh ; + size_t header_remaining ; +} MPEG_DEC_PRIVATE ; + +static int mpeg_dec_close (SF_PRIVATE *psf) ; +static sf_count_t mpeg_dec_seek (SF_PRIVATE *psf, int whence, sf_count_t count) ; + +static ssize_t mpeg_dec_io_read (void *priv, void *buffer, size_t nbytes) ; +static off_t mpeg_dec_io_lseek (void *priv, off_t offset, int whence) ; + +static ssize_t +mpeg_dec_io_read (void *priv, void *buffer, size_t nbytes) +{ SF_PRIVATE *psf = (SF_PRIVATE *) priv ; + MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + + if (pmp3d->header_remaining) + { if (pmp3d->header_remaining < nbytes) + nbytes = pmp3d->header_remaining ; + psf_binheader_readf (psf, "b", buffer, nbytes) ; + pmp3d->header_remaining -= nbytes ; + return nbytes ; + } ; + + return psf_fread (buffer, 1, nbytes, psf) ; +} /* mpeg_dec_io_read */ + +static off_t +mpeg_dec_io_lseek (void *priv, off_t offset, int whence) +{ SF_PRIVATE *psf = (SF_PRIVATE *) priv ; + + return psf_fseek (psf, offset, whence) ; +} /* mpeg_dec_io_lseek */ + +static int +mpeg_dec_close (SF_PRIVATE *psf) +{ MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + + if (pmp3d) + { if (pmp3d->pmh) + { mpg123_close (pmp3d->pmh) ; + mpg123_delete (pmp3d->pmh) ; + pmp3d->pmh = NULL ; + } + free (psf->codec_data) ; + psf->codec_data = NULL ; + } ; + + return 0 ; +} /* mpeg_dec_close */ + +static sf_count_t +mpeg_dec_decode (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + size_t done ; + int error ; + + error = mpg123_read (pmp3d->pmh, (unsigned char *) ptr, len * sizeof (float), &done) ; + + if (error == MPG123_OK || error == MPG123_DONE) + return done / sizeof (float) ; + + if (error == MPG123_NEW_FORMAT) + { psf->error = SFE_MALFORMED_FILE ; + return -1 ; + } ; + + psf->error = SFE_INTERNAL ; + return -1 ; +} /* mpeg_dec_decode */ + +static sf_count_t +mpeg_dec_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + sf_count_t total, readlen ; + void (*convert) (const float *, short *, int, int) ; + const sf_count_t buflen = ARRAY_LEN (ubuf.fbuf) ; + + convert = (psf->add_clipping) ? psf_f2s_clip_array : psf_f2s_array ; + for (total = 0 ; total < len ; total += readlen) + { readlen = mpeg_dec_decode (psf, ubuf.fbuf, SF_MIN (buflen, len - total)) ; + if (readlen <= 0) + break ; + + convert (ubuf.fbuf, ptr + total, readlen, SF_TRUE) ; + } ; + + return total ; +} /*mpeg_dec_read_s */ + +static sf_count_t +mpeg_dec_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + sf_count_t total, readlen ; + void (*convert) (const float *, int *, int, int) ; + const sf_count_t buflen = ARRAY_LEN (ubuf.fbuf) ; + + convert = (psf->add_clipping) ? psf_f2i_clip_array : psf_f2i_array ; + for (total = 0 ; total < len ; total += readlen) + { readlen = mpeg_dec_decode (psf, ubuf.fbuf, SF_MIN (buflen, len - total)) ; + if (readlen <= 0) + break ; + + convert (ubuf.fbuf, ptr + total, readlen, SF_TRUE) ; + } ; + + return total ; +} /* mpeg_dec_read_i */ + +static sf_count_t +mpeg_dec_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ sf_count_t readlen ; + + readlen = mpeg_dec_decode (psf, ptr, len) ; + if (readlen <= 0) + return 0 ; + + if (psf->norm_float == SF_FALSE) + for (int i = 0 ; i < readlen ; i++) + { ptr [i] *= (1.0f * 0x8000) ; + } ; + + return readlen ; +} /* mpeg_dec_read_f */ + +static inline void +f2d_array (const float *src, int count, double *dest, double normfact) +{ for (int i = 0 ; i < count ; i++) + { dest [i] = src [i] * normfact ; + } +} /* f2d_array */ + +static sf_count_t +mpeg_dec_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + sf_count_t total, readlen ; + double normfact ; + const sf_count_t buflen = ARRAY_LEN (ubuf.fbuf) ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 : (1.0 * 0x8000) ; + + for (total = 0 ; total < len ; total += readlen) + { readlen = mpeg_dec_decode (psf, ubuf.fbuf, SF_MIN (buflen, len - total)) ; + if (readlen <= 0) + break ; + + f2d_array (ubuf.fbuf, readlen, ptr + total, normfact) ; + } ; + + return total ; +} /* mpeg_dec_read_d */ + +static sf_count_t +mpeg_dec_seek (SF_PRIVATE *psf, int mode, sf_count_t count) +{ MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + off_t ret ; + + if (mode != SFM_READ || psf->file.mode != SFM_READ) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + ret = mpg123_seek (pmp3d->pmh, count, SEEK_SET) ; + + if (ret < 0) + return PSF_SEEK_ERROR ; + + return (sf_count_t) ret ; +} /* mpeg_dec_seek */ + +static int +mpeg_dec_fill_sfinfo (mpg123_handle *mh, SF_INFO *info) +{ int error ; + int channels ; + int encoding ; + long rate ; + off_t length ; + + error = mpg123_getformat (mh, &rate, &channels, &encoding) ; + if (error != MPG123_OK) + return error ; + + info->samplerate = rate ; + info->channels = channels ; + + length = mpg123_length (mh) ; + if (length >= 0) + { info->frames = length ; + info->seekable = SF_TRUE ; + } + else + { info->frames = SF_COUNT_MAX ; + info->seekable = SF_FALSE ; + } + + /* Force 32-bit float samples. */ + if (encoding != MPG123_ENC_FLOAT_32) + { error = mpg123_format (mh, rate, channels, MPG123_ENC_FLOAT_32) ; + } ; + + return error ; +} /* mpeg_dec_fill_sfinfo */ + +static void +mpeg_dec_print_frameinfo (SF_PRIVATE *psf, const struct mpg123_frameinfo *fi) +{ psf_log_printf (psf, "MPEG-1/2 Audio\n----------------------------------------\n") ; + psf_log_printf (psf, " MPEG version : %s\n", + fi->version == MPG123_1_0 ? "MPEG 1.0" : + fi->version == MPG123_2_0 ? "MPEG 2.0" : + fi->version == MPG123_2_5 ? "MPEG 2.5" : "???") ; + psf_log_printf (psf, " layer : %d\n", fi->layer) ; + psf_log_printf (psf, " rate : %d\n", fi->rate) ; + psf_log_printf (psf, " mode : %s\n", + fi->mode == MPG123_M_STEREO ? "stereo" : + fi->mode == MPG123_M_JOINT ? "joint stereo" : + fi->mode == MPG123_M_DUAL ? "dual channel" : + fi->mode == MPG123_M_MONO ? "mono" : "???") ; + psf_log_printf (psf, " mode ext : %d\n", fi->mode_ext) ; + psf_log_printf (psf, " framesize : %d\n", fi->framesize) ; + psf_log_printf (psf, " crc : %d\n", !! (fi->flags & MPG123_CRC)) ; + psf_log_printf (psf, " copyright flag : %d\n", !! (fi->flags & MPG123_COPYRIGHT)) ; + psf_log_printf (psf, " private flag : %d\n", !! (fi->flags & MPG123_PRIVATE)) ; + psf_log_printf (psf, " original flag : %d\n", !! (fi->flags & MPG123_ORIGINAL)) ; + psf_log_printf (psf, " emphasis : %d\n", fi->emphasis) ; + psf_log_printf (psf, " bitrate mode : ") ; + switch (fi->vbr) + { case MPG123_CBR : + psf_log_printf (psf, "constant\n") ; + psf_log_printf (psf, " bitrate : %d kbps\n", fi->bitrate) ; + break ; + case MPG123_VBR : + psf_log_printf (psf, "variable\n") ; + break ; + + case MPG123_ABR : + psf_log_printf (psf, "average\n") ; + psf_log_printf (psf, " ABR target : %d\n", fi->abr_rate) ; + break ; + + default : + psf_log_printf (psf, "(%d) ???\n", fi->vbr) ; + break ; + } ; +} /* mpeg_dec_print_frameinfo */ + +/* + * Like strlcpy, except the size argument is the maximum size of the input, + * always null terminates the output string. Thus, up to size + 1 bytes may be + * written. + * + * Returns the length of the copied string. + */ +static int +strcpy_inbounded (char *dest, size_t size, const char *src) +{ char *c = memccpy (dest, src, '\0', size) ; + if (!c) + c = dest + size ; + *c = '\0' ; + return c - dest ; +} /* strcpy_inbounded */ + +static void +mpeg_decoder_read_strings_id3v1 (SF_PRIVATE *psf, mpg123_id3v1 *tags) +{ const char *genre ; + char buf [31] ; + + psf_log_printf (psf, "ID3v1 Tags\n") ; + + if (strcpy_inbounded (buf, ARRAY_LEN (tags->title), tags->title)) + { psf_log_printf (psf, " Title : %s\n", buf) ; + psf_store_string (psf, SF_STR_TITLE, buf) ; + } ; + + if (strcpy_inbounded (buf, ARRAY_LEN (tags->artist), tags->artist)) + { psf_log_printf (psf, " Artist : %s\n", buf) ; + psf_store_string (psf, SF_STR_ARTIST, buf) ; + } ; + + if (strcpy_inbounded (buf, ARRAY_LEN (tags->album), tags->album)) + { psf_log_printf (psf, " Album : %s\n", buf) ; + psf_store_string (psf, SF_STR_ALBUM, buf) ; + } ; + + if (strcpy_inbounded (buf, ARRAY_LEN (tags->year), tags->year)) + { psf_log_printf (psf, " Year : %s\n", buf) ; + psf_store_string (psf, SF_STR_DATE, buf) ; + } ; + + if (strcpy_inbounded (buf, ARRAY_LEN (tags->comment), tags->comment)) + { psf_log_printf (psf, " Comment : %s\n", buf) ; + psf_store_string (psf, SF_STR_COMMENT, buf) ; + } ; + + /* ID3v1.1 Tracknumber */ + if (tags->comment [28] == '\0' && tags->comment [29] != '\0') + { snprintf (buf, ARRAY_LEN (buf), "%hhu", (unsigned char) tags->comment [29]) ; + psf_log_printf (psf, " Tracknumber : %s\n", buf) ; + psf_store_string (psf, SF_STR_TRACKNUMBER, buf) ; + } ; + + if ((genre = id3_lookup_v1_genre (tags->genre)) != NULL) + { psf_log_printf (psf, " Genre : %s\n", genre) ; + psf_store_string (psf, SF_STR_GENRE, genre) ; + } ; +} /* mpeg_decoder_read_strings_id3v1 */ + +static void +mpeg_decoder_read_strings_id3v2 (SF_PRIVATE *psf, mpg123_id3v2 *tags) +{ mpg123_text *text_frame ; + size_t i ; + uint32_t marker ; + const char *title = NULL ; + const char *copyright = NULL ; + const char *software = NULL ; + const char *artist = NULL ; + const char *comment = NULL ; + const char *date = NULL ; + const char *album = NULL ; + const char *license = NULL ; + const char *tracknumber = NULL ; + const char *genre = NULL ; + const char *tlen = NULL ; + + psf_log_printf (psf, "ID3v2 Tags\n") ; + + // Read the parsed text tags + for (i = 0 ; i < tags->texts ; i++) + { text_frame = &tags->text [i] ; + psf_log_printf (psf, " %.4s : %s\n", text_frame->id, text_frame->text.p) ; + + // Thankfully mpg123 translates v2.2 3-byte frames to v2.3 4-byte for us. + marker = MAKE_MARKER (text_frame->id [0], text_frame->id [1], + text_frame->id [2], text_frame->id [3]) ; + + /* Use our own map of frame types to metadata for text frames */ + switch (marker) + { case MAKE_MARKER ('T', 'I', 'T', '2') : + title = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'C', 'O', 'P') : + copyright = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'E', 'N', 'C') : + case MAKE_MARKER ('T', 'S', 'S', 'E') : + software = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'P', 'E', '1') : + artist = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'A', 'L', 'B') : + album = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'R', 'C', 'K') : + tracknumber = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'Y', 'E', 'R') : + case MAKE_MARKER ('T', 'D', 'R', 'C') : + /* TODO (maybe) + case MAKE_MARKER ('T', 'D', 'A', 'T') : + case MAKE_MARKER ('T', 'I', 'M', 'E') : + case MAKE_MARKER ('T', 'D', 'R', 'A') : + */ + date = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'O', 'W', 'N') : + tracknumber = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'C', 'O', 'N') : + genre = text_frame->text.p ; + break ; + + case MAKE_MARKER ('T', 'L', 'E', 'N') : + tlen = text_frame->text.p ; + break ; + } ; + } ; + + /* Use mpg123's handling of comment headers, but print all the comment headers anyways. */ + if (tags->comment) + comment = tags->comment->p ; + for (i = 0 ; i < tags->comments ; i++) + { text_frame = &tags->comment_list [i] ; + psf_log_printf (psf, " %.4s : (%s)[%s] %s\n", text_frame->id, + text_frame->description. p, text_frame->lang, text_frame->text.p) ; + } ; + + /* Print extra headers */ + for (i = 0 ; i < tags->extras ; i++) + { text_frame = &tags->extra [i] ; + psf_log_printf (psf, " %.4s : (%s) %s\n", text_frame->id, + text_frame->description.p, text_frame->text.p) ; + } ; + + if (title != NULL) + psf_store_string (psf, SF_STR_TITLE, title) ; + if (copyright != NULL) + psf_store_string (psf, SF_STR_COPYRIGHT, copyright) ; + if (software != NULL) + psf_store_string (psf, SF_STR_SOFTWARE, software) ; + if (artist != NULL) + psf_store_string (psf, SF_STR_ARTIST, artist) ; + if (comment != NULL) + psf_store_string (psf, SF_STR_COMMENT, comment) ; + if (date != NULL) + psf_store_string (psf, SF_STR_DATE, date) ; + if (album != NULL) + psf_store_string (psf, SF_STR_ALBUM, album) ; + if (license != NULL) + psf_store_string (psf, SF_STR_LICENSE, license) ; + if (tracknumber != NULL) + psf_store_string (psf, SF_STR_TRACKNUMBER, tracknumber) ; + if (genre != NULL) + psf_store_string (psf, SF_STR_GENRE, id3_process_v2_genre (genre)) ; + if (tlen != NULL) + { /* If non-seekable, set framecount? Can we trust it? */ + } ; +} /* mpeg_decoder_read_strings_id3v2 */ + +static void +mpeg_decoder_read_strings (SF_PRIVATE *psf) +{ MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + mpg123_id3v1 *v1_tags ; + mpg123_id3v2 *v2_tags ; + + if (mpg123_id3 (pmp3d->pmh, &v1_tags, &v2_tags) != MPG123_OK) + return ; + + if (v1_tags != NULL) + mpeg_decoder_read_strings_id3v1 (psf, v1_tags) ; + + if (v2_tags != NULL) + mpeg_decoder_read_strings_id3v2 (psf, v2_tags) ; +} /* mpeg_decoder_read_strings */ + +static int +mpeg_dec_byterate (SF_PRIVATE *psf) +{ MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + struct mpg123_frameinfo fi ; + + if (mpg123_info (pmp3d->pmh, &fi) == MPG123_OK) + return (fi.bitrate + 7) / 8 ; + + return -1 ; + +} /* mpeg_dec_byterate */ + +/*============================================================================== +** exported functions +*/ + +int +mpeg_decoder_init (SF_PRIVATE *psf) +{ MPEG_DEC_PRIVATE *pmp3d ; + struct mpg123_frameinfo fi ; + int error ; + + if (! (psf->file.mode & SFM_READ)) + return SFE_INTERNAL ; + + /* + ** *** FIXME - Threading issues *** + ** + ** mpg123_init() is a global call that should only be called once, and + ** should be paried with mpg123_exit() when done. libsndfile does not + ** provide for these requirements. + ** + ** Currently this is a moot issue as mpg123_init() non-conditionally writes + ** static areas with calculated data, and mpg123_exit() is a NOP, but this + ** could change in a future version of it! + ** + ** From mpg123.h: + ** > This should be called once in a non-parallel context. It is not explicitly + ** > thread-safe, but repeated/concurrent calls still _should_ be safe as static + ** > tables are filled with the same values anyway. + ** + ** Note that calling mpg123_init() after it has already completed is a NOP. + ** + ** Update 2021-07-04 + ** mpg123 upstream has confirmed that mpg132_init() will become a NOP in future, + ** so this is moot. + */ + if (mpg123_init () != MPG123_OK) + return SFE_INTERNAL ; + + psf->codec_data = pmp3d = calloc (1, sizeof (MPEG_DEC_PRIVATE)) ; + if (!psf->codec_data) + return SFE_MALLOC_FAILED ; + + pmp3d->pmh = mpg123_new (NULL, &error) ; + if (!pmp3d->pmh) + { psf_log_printf (psf, "Could not obtain a mpg123 handle: %s\n", mpg123_plain_strerror (error)) ; + return SFE_INTERNAL ; + } ; + + psf->codec_close = mpeg_dec_close ; + + mpg123_replace_reader_handle (pmp3d->pmh, + mpeg_dec_io_read, mpeg_dec_io_lseek, NULL) ; + + mpg123_param (pmp3d->pmh, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 1.0) ; + mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT | MPG123_GAPLESS, 1.0) ; +#if MPG123_API_VERSION >= 45 + mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_NO_FRANKENSTEIN, 1.0) ; +#endif + + /* + ** Need to pass the first MPEG frame to libmpg123, but that frame was read + ** into psf->binheader in order that we could identify the stream. + */ + if (psf->is_pipe) + { /* + ** Can't seek, so setup our libmpg123 io callbacks to read the binheader + ** buffer first. + */ + psf_binheader_readf (psf, "p", psf->dataoffset) ; + pmp3d->header_remaining = psf_binheader_readf (psf, NULL) - psf->dataoffset ; + + /* Tell libmpg123 we can't seek the file. */ + mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_NO_PEEK_END, 1.0) ; + } + else + { /* + ** libmpg123 can parse the ID3v2 header. Undo the embedded file offset if the + ** enclosing file data is the ID3v2 header. + */ + if (psf->id3_header.len > 0 && psf->id3_header.len + psf->id3_header.offset == psf->fileoffset) + psf->fileoffset = psf->id3_header.offset ; + + psf_fseek (psf, 0, SEEK_SET) ; + } ; + + error = mpg123_open_handle (pmp3d->pmh, psf) ; + if (error != MPG123_OK) + { psf_log_printf (psf, "mpg123 could not open the file: %s\n", mpg123_plain_strerror (error)) ; + return SFE_BAD_FILE ; + } ; + + if (mpeg_dec_fill_sfinfo (pmp3d->pmh, &psf->sf) != MPG123_OK) + { psf_log_printf (psf, "Cannot get MPEG decoder configuration: %s\n", mpg123_plain_strerror (error)) ; + return SFE_BAD_FILE ; + } ; + + error = mpg123_info (pmp3d->pmh, &fi) ; + if (error != MPG123_OK) + { psf_log_printf (psf, "Cannot get MPEG frame info: %s\n", mpg123_plain_strerror (error)) ; + return SFE_INTERNAL ; + } + + switch (fi.layer) + { case 1 : psf->sf.format |= SF_FORMAT_MPEG_LAYER_I ; break ; + case 2 : psf->sf.format |= SF_FORMAT_MPEG_LAYER_II ; break ; + case 3 : psf->sf.format |= SF_FORMAT_MPEG_LAYER_III ; break ; + default : + return SFE_BAD_FILE ; + } ; + mpeg_dec_print_frameinfo (psf, &fi) ; + + psf->read_short = mpeg_dec_read_s ; + psf->read_int = mpeg_dec_read_i ; + psf->read_float = mpeg_dec_read_f ; + psf->read_double = mpeg_dec_read_d ; + psf->seek = mpeg_dec_seek ; + psf->byterate = mpeg_dec_byterate ; + + mpeg_decoder_read_strings (psf) ; + + return 0 ; +} /* mpeg_decoder_init */ + +int +mpeg_decoder_get_bitrate_mode (SF_PRIVATE *psf) +{ MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; + struct mpg123_frameinfo fi ; + + if (mpg123_info (pmp3d->pmh, &fi) == MPG123_OK) + { + switch (fi.vbr) + { case MPG123_CBR : return SF_BITRATE_MODE_CONSTANT ; + case MPG123_ABR : return SF_BITRATE_MODE_AVERAGE ; + case MPG123_VBR : return SF_BITRATE_MODE_VARIABLE ; + default : break ; + } ; + } ; + + psf_log_printf (psf, "Cannot determine MPEG bitrate mode.\n") ; + return -1 ; +} /* mpeg_decoder_get_bitrate_mode */ + +#else /* HAVE_MPEG */ + +int mpeg_decoder_init (SF_PRIVATE *psf) +{ psf_log_printf (psf, "This version of libsndfile was compiled without MPEG decode support.\n") ; + return SFE_UNIMPLEMENTED ; +} /* mpeg_decoder_init */ + +#endif /* HAVE_MPEG */ diff --git a/src/mpeg_l3_encode.c b/src/mpeg_l3_encode.c new file mode 100644 index 00000000..97324f79 --- /dev/null +++ b/src/mpeg_l3_encode.c @@ -0,0 +1,784 @@ +/* +** Copyright (C) 2020 Arthur Taylor +** Copyright (C) 2019 Erik de Castro Lopo +** +** This program is free software ; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation ; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY ; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" +#include "sndfile.h" +#include "common.h" +#include "mpeg.h" + + +#if HAVE_MPEG + +#include + +/* + * RANT RANT RANT + * + * Lame has 11 functions for inputing sample data of various types and + * configurations, but due to bad definitions, or missing combinations, they + * aren't really of much help to us. + * + */ + +typedef struct +{ lame_t lamef ; + unsigned char *block ; + size_t block_len ; + int frame_samples ; + double compression ; + int initialized ; +} MPEG_L3_ENC_PRIVATE ; + + +/*----------------------------------------------------------------------------------------------- +** Private function prototypes. +*/ + +static int mpeg_l3_encoder_close (SF_PRIVATE *psf) ; +static int mpeg_l3_encoder_construct (SF_PRIVATE *psf) ; +static int mpeg_l3_encoder_byterate (SF_PRIVATE *psf) ; + +static sf_count_t mpeg_l3_encode_write_short_stereo (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_short_mono (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_int_mono (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +/*----------------------------------------------------------------------------------------------- +** Exported functions. +*/ + +int +mpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag) +{ MPEG_L3_ENC_PRIVATE* pmpeg = NULL ; + + if (psf->file.mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if (psf->file.mode != SFM_WRITE) + return SFE_INTERNAL ; + + psf->codec_data = pmpeg = calloc (1, sizeof (MPEG_L3_ENC_PRIVATE)) ; + if (!pmpeg) + return SFE_MALLOC_FAILED ; + + if (psf->sf.channels < 1 || psf->sf.channels > 2) + return SFE_BAD_OPEN_FORMAT ; + + if (! (pmpeg->lamef = lame_init ())) + return SFE_MALLOC_FAILED ; + + pmpeg->compression = -1.0 ; /* Unset */ + + lame_set_in_samplerate (pmpeg->lamef, psf->sf.samplerate) ; + lame_set_num_channels (pmpeg->lamef, psf->sf.channels) ; + if (lame_set_out_samplerate (pmpeg->lamef, psf->sf.samplerate) < 0) + return SFE_MPEG_BAD_SAMPLERATE ; + + lame_set_write_id3tag_automatic (pmpeg->lamef, 0) ; + + if (!info_tag || psf->is_pipe) + { /* Can't seek back, so force disable Xing/Lame/Info header. */ + lame_set_bWriteVbrTag (pmpeg->lamef, 0) ; + } ; + + if (psf->sf.channels == 2) + { psf->write_short = mpeg_l3_encode_write_short_stereo ; + psf->write_int = mpeg_l3_encode_write_int_stereo ; + psf->write_float = mpeg_l3_encode_write_float_stereo ; + psf->write_double = mpeg_l3_encode_write_double_stereo ; + } + else + { psf->write_short = mpeg_l3_encode_write_short_mono ; + psf->write_int = mpeg_l3_encode_write_int_mono ; + psf->write_float = mpeg_l3_encode_write_float_mono ; + psf->write_double = mpeg_l3_encode_write_double_mono ; + } + + psf->sf.seekable = 0 ; + psf->codec_close = mpeg_l3_encoder_close ; + psf->byterate = mpeg_l3_encoder_byterate ; + psf->datalength = 0 ; + + return 0 ; +} /* mpeg_l3_encoder_init */ + +int +mpeg_l3_encoder_write_id3tag (SF_PRIVATE *psf) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + unsigned char *id3v2_buffer ; + int i, id3v2_size ; + + if (psf->have_written) + return 0 ; + + if ((i = mpeg_l3_encoder_construct (psf))) + return i ; + + if (psf_fseek (psf, 0, SEEK_SET) != 0) + return SFE_NOT_SEEKABLE ; + + /* Safe to call multiple times. */ + id3tag_init (pmpeg->lamef) ; + + for (i = 0 ; i < SF_MAX_STRINGS ; i++) + { switch (psf->strings.data [i].type) + { case SF_STR_TITLE : + id3tag_set_title (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + case SF_STR_ARTIST : + id3tag_set_artist (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + case SF_STR_ALBUM : + id3tag_set_album (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + case SF_STR_DATE : + id3tag_set_year (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + case SF_STR_COMMENT : + id3tag_set_comment (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + case SF_STR_GENRE : + id3tag_set_genre (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + case SF_STR_TRACKNUMBER : + id3tag_set_track (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; + break ; + + default: + break ; + } ; + } ; + + /* The header in this case is the ID3v2 tag header. */ + id3v2_size = lame_get_id3v2_tag (pmpeg->lamef, 0, 0) ; + if (id3v2_size > 0) + { psf_log_printf (psf, "Writing ID3v2 header.\n") ; + if (! (id3v2_buffer = malloc (id3v2_size))) + return SFE_MALLOC_FAILED ; + lame_get_id3v2_tag (pmpeg->lamef, id3v2_buffer, id3v2_size) ; + psf_fwrite (id3v2_buffer, 1, id3v2_size, psf) ; + psf->dataoffset = id3v2_size ; + free (id3v2_buffer) ; + } ; + + return 0 ; +} + +int +mpeg_l3_encoder_set_quality (SF_PRIVATE *psf, double compression) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + int bitrate_mode ; + int bitrate ; + int ret ; + + if (compression < 0.0 || compression > 1.0) + return SF_FALSE ; + + /* + ** Save the compression setting, as we may have to re-interpret it if + ** the bitrate mode changes. + */ + pmpeg->compression = compression ; + + bitrate_mode = mpeg_l3_encoder_get_bitrate_mode (psf) ; + if (bitrate_mode == SF_BITRATE_MODE_VARIABLE) + { ret = lame_set_VBR_quality (pmpeg->lamef, compression * 10.0) ; + } + else + { /* Choose a bitrate. */ + if (psf->sf.samplerate >= 32000) + { /* MPEG-1.0, bitrates are [32,320] kbps */ + bitrate = (320.0 - (compression * (320.0 - 32.0))) ; + } + else if (psf->sf.samplerate >= 16000) + { /* MPEG-2.0, bitrates are [8,160] */ + bitrate = (160.0 - (compression * (160.0 - 8.0))) ; + } + else + { /* MPEG-2.5, bitrates are [8,64] */ + bitrate = (64.0 - (compression * (64.0 - 8.0))) ; + } + + if (bitrate_mode == SF_BITRATE_MODE_AVERAGE) + ret = lame_set_VBR_mean_bitrate_kbps (pmpeg->lamef, bitrate) ; + else + ret = lame_set_brate (pmpeg->lamef, bitrate) ; + } ; + + if (ret == LAME_OKAY) + return SF_TRUE ; + + psf_log_printf (psf, "Failed to set lame encoder quality.\n") ; + return SF_FALSE ; +} /* mpeg_l3_encoder_set_quality */ + +int +mpeg_l3_encoder_set_bitrate_mode (SF_PRIVATE *psf, int mode) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + enum vbr_mode_e vbr_mode ; + + if (pmpeg->initialized) + { psf->error = SFE_CMD_HAS_DATA ; + return SF_FALSE ; + } ; + + switch (mode) + { case SF_BITRATE_MODE_CONSTANT : vbr_mode = vbr_off ; break ; + case SF_BITRATE_MODE_AVERAGE : vbr_mode = vbr_abr ; break ; + case SF_BITRATE_MODE_VARIABLE : vbr_mode = vbr_default ; break ; + default : + psf->error = SFE_BAD_COMMAND_PARAM ; + return SF_FALSE ; + } ; + + if (lame_set_VBR (pmpeg->lamef, vbr_mode) == LAME_OKAY) + { /* Re-evaluate the compression setting. */ + return mpeg_l3_encoder_set_quality (psf, pmpeg->compression) ; + } ; + + psf_log_printf (psf, "Failed to set LAME vbr mode to %d.\n", vbr_mode) ; + return SF_FALSE ; +} /* mpeg_l3_encoder_set_bitrate_mode */ + +int +mpeg_l3_encoder_get_bitrate_mode (SF_PRIVATE *psf) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + enum vbr_mode_e vbr_mode ; + + vbr_mode = lame_get_VBR (pmpeg->lamef) ; + + if (vbr_mode == vbr_off) + return SF_BITRATE_MODE_CONSTANT ; + if (vbr_mode == vbr_abr) + return SF_BITRATE_MODE_AVERAGE ; + if (vbr_mode == vbr_default || vbr_mode < vbr_max_indicator) + return SF_BITRATE_MODE_VARIABLE ; + + /* Something is wrong. */ + psf->error = SFE_INTERNAL ; + return -1 ; +} /* mpeg_l3_encoder_get_bitrate_mode */ + + +/*----------------------------------------------------------------------------------------------- +** Private functions. +*/ + +static int +mpeg_l3_encoder_close (SF_PRIVATE *psf) +{ MPEG_L3_ENC_PRIVATE* pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + int ret, len ; + sf_count_t pos ; + unsigned char *buffer ; + + /* Magic number 7200 comes from a comment in lame.h */ + len = 7200 ; + if (! (buffer = malloc (len))) + return SFE_MALLOC_FAILED ; + ret = lame_encode_flush (pmpeg->lamef, buffer, len) ; + if (ret > 0) + psf_fwrite (buffer, 1, ret, psf) ; + + /* + ** Write an IDv1 trailer. The whole tag structure is always 128 bytes, so is + ** guaranteed to fit in the buffer allocated above. + */ + ret = lame_get_id3v1_tag (pmpeg->lamef, buffer, len) ; + if (ret > 0) + { psf_log_printf (psf, " Writing ID3v1 trailer.\n") ; + psf_fwrite (buffer, 1, ret, psf) ; + } ; + + /* + ** If possible, seek back and write the LAME/XING/Info headers. This + ** contains information about the whole file and a seek table, and can + ** only be written after encoding. + ** + ** If enabled, Lame wrote an empty header at the beginning of the data + ** that we now fill in. + */ + ret = lame_get_lametag_frame (pmpeg->lamef, 0, 0) ; + if (ret > 0) + { if (ret > len) + { len = ret ; + free (buffer) ; + if (! (buffer = malloc (len))) + return SFE_MALLOC_FAILED ; + } ; + psf_log_printf (psf, " Writing LAME info header at offset %d, %d bytes.\n", + psf->dataoffset, len) ; + lame_get_lametag_frame (pmpeg->lamef, buffer, len) ; + pos = psf_ftell (psf) ; + if (psf_fseek (psf, psf->dataoffset, SEEK_SET) == psf->dataoffset) + { psf_fwrite (buffer, 1, ret, psf) ; + psf_fseek (psf, pos, SEEK_SET) ; + } ; + } ; + free (buffer) ; + + free (pmpeg->block) ; + pmpeg->block = NULL ; + + if (pmpeg->lamef) + { lame_close (pmpeg->lamef) ; + pmpeg->lamef = NULL ; + } ; + + return 0 ; +} /* mpeg_l3_encoder_close */ + +static void +mpeg_l3_encoder_log_config (SF_PRIVATE *psf, lame_t lamef) +{ const char *version ; + const char *chn_mode ; + + switch (lame_get_version (lamef)) + { case 0 : version = "2" ; break ; + case 1 : version = "1" ; break ; + case 2 : version = "2.5" ; break ; + default : version = "unknown!?" ; break ; + } ; + switch (lame_get_mode (lamef)) + { case STEREO : chn_mode = "stereo" ; break ; + case JOINT_STEREO : chn_mode = "joint-stereo" ; break ; + case MONO : chn_mode = "mono" ; break ; + default : chn_mode = "unknown!?" ; break ; + } ; + psf_log_printf (psf, " MPEG Version : %s\n", version) ; + psf_log_printf (psf, " Block samples : %d\n", lame_get_framesize (lamef)) ; + psf_log_printf (psf, " Channel mode : %s\n", chn_mode) ; + psf_log_printf (psf, " Samplerate : %d\n", lame_get_out_samplerate (lamef)) ; + psf_log_printf (psf, " Encoder mode : ") ; + switch (lame_get_VBR (lamef)) + { case vbr_off : + psf_log_printf (psf, "CBR\n") ; + psf_log_printf (psf, " Bitrate : %d kbps\n", lame_get_brate (lamef)) ; + break ; + case vbr_abr : + psf_log_printf (psf, "ABR\n") ; + psf_log_printf (psf, " Mean Bitrate : %d kbps\n", lame_get_VBR_mean_bitrate_kbps (lamef)) ; + break ; + + case vbr_mt : + case vbr_default : + psf_log_printf (psf, "VBR\n") ; + psf_log_printf (psf, " Quality : %d\n", lame_get_VBR_q (lamef)) ; + break ; + + default: + psf_log_printf (psf, "Unknown!? (%d)\n", lame_get_VBR (lamef)) ; + break ; + } ; + + psf_log_printf (psf, " Encoder delay : %d\n", lame_get_encoder_delay (lamef)) ; + psf_log_printf (psf, " Write INFO header : %d\n", lame_get_bWriteVbrTag (lamef)) ; +} /* mpeg_l3_encoder_log_config */ + +static int +mpeg_l3_encoder_construct (SF_PRIVATE *psf) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + int frame_samples_per_channel ; + + if (pmpeg->initialized == SF_FALSE) + { if (lame_init_params (pmpeg->lamef) < 0) + { psf_log_printf (psf, "Failed to initialize lame encoder!\n") ; + return SFE_INTERNAL ; + } ; + + psf_log_printf (psf, "Initialized LAME encoder.\n") ; + mpeg_l3_encoder_log_config (psf, pmpeg->lamef) ; + + frame_samples_per_channel = lame_get_framesize (pmpeg->lamef) ; + + /* + * Suggested output buffer size in bytes from lame.h comment is + * 1.25 * samples + 7200 + */ + pmpeg->block_len = (frame_samples_per_channel * 4) / 3 + 7200 ; + pmpeg->frame_samples = frame_samples_per_channel * psf->sf.channels ; + + pmpeg->block = malloc (pmpeg->block_len) ; + if (!pmpeg->block) + return SFE_MALLOC_FAILED ; + + pmpeg->initialized = SF_TRUE ; + } ; + + return 0 ; +} /* mpeg_l3_encoder_construct */ + +static int +mpeg_l3_encoder_byterate (SF_PRIVATE *psf) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; + int bitrate_mode ; + int byterate ; + float calculated_byterate ; + + bitrate_mode = mpeg_l3_encoder_get_bitrate_mode (psf) ; + byterate = (lame_get_brate (pmpeg->lamef) + 7) / 8 ; + + if (bitrate_mode == SF_BITRATE_MODE_VARIABLE) + { /* + ** For VBR, lame_get_brate returns the minimum bitrate, so calculate the + ** average byterate so far. + */ + calculated_byterate = psf_ftell (psf) - psf->dataoffset ; + calculated_byterate /= (float) psf->write_current ; + calculated_byterate *= (float) psf->sf.samplerate ; + + return SF_MIN (byterate, (int) calculated_byterate) ; + } + + return byterate ; +} /* mpeg_l3_encoder_byterate */ + +static sf_count_t +mpeg_l3_encode_write_short_mono (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + while (len) + { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; + + nbytes = lame_encode_buffer (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static sf_count_t +mpeg_l3_encode_write_short_stereo (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.sbuf), pmpeg->frame_samples) ; + while (len) + { writecount = SF_MIN (len, max_samples) ; + /* + * An oversight, but lame_encode_buffer_interleaved() lacks a const. + * As such, need another memcpy to not cause a warning. + */ + memcpy (ubuf.sbuf, ptr + total, writecount) ; + nbytes = lame_encode_buffer_interleaved (pmpeg->lamef, ubuf.sbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static sf_count_t +mpeg_l3_encode_write_int_mono (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + while (len) + { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; + + nbytes = lame_encode_buffer_int (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static sf_count_t +mpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + while (len) + { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; + + nbytes = lame_encode_buffer_interleaved_int (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static sf_count_t +mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + while (len) + { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; + + if (psf->norm_float) + nbytes = lame_encode_buffer_ieee_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; + else + nbytes = lame_encode_buffer_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static inline void +normalize_float (float *dest, const float *src, sf_count_t count, float norm_fact) +{ while (--count >= 0) + { dest [count] = src [count] * norm_fact ; + } ; +} + + +static sf_count_t +mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.fbuf), pmpeg->frame_samples) ; + while (len) + { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_float) + nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; + else + { /* Lame lacks a non-normalized interleaved float write. Bummer. */ + normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0 / (float) 0x8000) ; + nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ubuf.fbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; + } + + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static inline void +normalize_double (double *dest, const double *src, sf_count_t count, double norm_fact) +{ while (--count >= 0) + { dest [count] = src [count] * norm_fact ; + } ; +} + + +static sf_count_t +mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.dbuf), pmpeg->frame_samples) ; + while (len) + { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_double) + nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; + else + { /* Lame lacks non-normalized double writing */ + normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; + nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ubuf.dbuf, NULL, writecount, pmpeg->block, pmpeg->block_len) ; + } + + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + + +static sf_count_t +mpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ BUF_UNION ubuf ; + MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + + const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.dbuf), pmpeg->frame_samples) ; + while (len) + { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_double) + nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; + else + { /* Lame lacks interleaved non-normalized double writing */ + normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; + nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ubuf.dbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; + } + + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; + } ; + + if (nbytes) + { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; + if (writen != nbytes) + { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; + } ; + } ; + + total += writecount ; + len -= writecount ; + } ; + + return total ; +} + +#else /* HAVE_MPEG */ + +int +mpeg_l3_encoder_init (SF_PRIVATE *psf, int UNUSED (vbr)) +{ psf_log_printf (psf, "This version of libsndfile was compiled without MPEG Layer 3 encoding support.\n") ; + return SFE_UNIMPLEMENTED ; +} /* mpeg_l3_encoder_init */ + +#endif diff --git a/src/ms_adpcm.c b/src/ms_adpcm.c index 5e8f1a31..0e05181a 100644 --- a/src/ms_adpcm.c +++ b/src/ms_adpcm.c @@ -128,8 +128,14 @@ wavlike_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) if (psf->file.mode == SFM_WRITE) samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; - if (blockalign < 7 * psf->sf.channels) - { psf_log_printf (psf, "*** Error blockalign (%d) should be > %d.\n", blockalign, 7 * psf->sf.channels) ; + /* There's 7 samples per channel in the preamble of each block */ + if (samplesperblock < 7 * psf->sf.channels) + { psf_log_printf (psf, "*** Error samplesperblock (%d) should be >= %d.\n", samplesperblock, 7 * psf->sf.channels) ; + return SFE_INTERNAL ; + } ; + + if (2 * blockalign < samplesperblock * psf->sf.channels) + { psf_log_printf (psf, "*** Error blockalign (%d) should be >= %d.\n", blockalign, samplesperblock * psf->sf.channels / 2) ; return SFE_INTERNAL ; } ; @@ -224,7 +230,7 @@ msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) return 1 ; } ; - if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) + if ((k = (int) psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) { psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ; if (k <= 0) return 1 ; @@ -349,7 +355,7 @@ msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; - if ((count = msadpcm_read_block (psf, pms, ptr, readcount)) <= 0) + if ((count = (int) msadpcm_read_block (psf, pms, ptr, readcount)) <= 0) return -1 ; total += count ; @@ -376,9 +382,9 @@ msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; - if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) + if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) return -1 ; for (k = 0 ; k < readcount ; k++) @@ -408,9 +414,9 @@ msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; - if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) + if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) return -1 ; for (k = 0 ; k < readcount ; k++) @@ -440,9 +446,9 @@ msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; - if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) + if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) return -1 ; for (k = 0 ; k < readcount ; k++) @@ -627,7 +633,7 @@ msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) /* Write the block to disk. */ - if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) + if ((k = (int) psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ; memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ; @@ -673,7 +679,7 @@ msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) while (len > 0) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; - count = msadpcm_write_block (psf, pms, ptr, writecount) ; + count = (int) msadpcm_write_block (psf, pms, ptr, writecount) ; total += count ; len -= count ; @@ -699,10 +705,10 @@ msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; - count = msadpcm_write_block (psf, pms, sptr, writecount) ; + count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) @@ -729,10 +735,10 @@ msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; - count = msadpcm_write_block (psf, pms, sptr, writecount) ; + count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) @@ -759,10 +765,10 @@ msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrint (normfact * ptr [total + k]) ; - count = msadpcm_write_block (psf, pms, sptr, writecount) ; + count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) diff --git a/src/nms_adpcm.c b/src/nms_adpcm.c index 40f56f59..96d6ad26 100644 --- a/src/nms_adpcm.c +++ b/src/nms_adpcm.c @@ -702,7 +702,7 @@ static int psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms) { int k ; - if ((k = psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) + if ((k = (int) psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) { psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pnms->shortsperblock) ; memset (pnms->block + (k * sizeof (short)), 0, (pnms->shortsperblock - k) * sizeof (short)) ; } ; @@ -785,7 +785,7 @@ nms_adpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) @@ -818,7 +818,7 @@ nms_adpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; @@ -850,7 +850,7 @@ nms_adpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (sptr [k]) ; @@ -875,7 +875,7 @@ psf_nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms) endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ; /* Write the block to disk. */ - if ((k = psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) + if ((k = (int) psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pnms->shortsperblock) ; pnms->sample_curr = 0 ; @@ -945,7 +945,7 @@ nms_adpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; @@ -976,7 +976,7 @@ nms_adpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; @@ -1008,7 +1008,7 @@ nms_adpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) sptr = ubuf.sbuf ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = psf_lrint (normfact * ptr [total + k]) ; count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; diff --git a/src/ogg.c b/src/ogg.c index 7a4a167f..f3e92e14 100644 --- 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 ; } diff --git a/src/ogg.h b/src/ogg.h index 5c837a8e..8b2927a9 100644 --- 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 */ diff --git a/src/ogg_opus.c b/src/ogg_opus.c index 9be6e914..c9383624 100644 --- a/src/ogg_opus.c +++ b/src/ogg_opus.c @@ -171,16 +171,26 @@ #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, " stream mapping : [") ; + 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) ; - 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) ; + /* 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_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 ; } diff --git a/src/ogg_vorbis.c b/src/ogg_vorbis.c index 5f536516..f9428ed1 100644 --- a/src/ogg_vorbis.c +++ b/src/ogg_vorbis.c @@ -1,4 +1,5 @@ /* +** Copyright (C) 2018-2021 Arthur Taylor ** Copyright (C) 2002-2016 Erik de Castro Lopo ** Copyright (C) 2002-2005 Michael Smith ** Copyright (C) 2007 John ffitch @@ -19,7 +20,7 @@ */ /* -** Much of this code is based on the examples in libvorbis from the +** Much of this code is based on the examples in libvorbis from the ** XIPHOPHORUS Company http://www.xiph.org/ which has a BSD-style Licence ** Copyright (c) 2002, Xiph.org Foundation ** @@ -78,6 +79,9 @@ #include "ogg.h" +/* How many seconds in the future to not bother bisection searching for. */ +#define VORBIS_SEEK_THRESHOLD 2 + typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ; static int vorbis_read_header (SF_PRIVATE *psf) ; @@ -85,7 +89,9 @@ static int vorbis_write_header (SF_PRIVATE *psf, int calc_length) ; static int vorbis_close (SF_PRIVATE *psf) ; static int vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; static int vorbis_byterate (SF_PRIVATE *psf) ; -static sf_count_t vorbis_calculate_page_duration (SF_PRIVATE *psf) ; +static int vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) ; +static int vorbis_skip (SF_PRIVATE *psf, uint64_t target_gp) ; +static int vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) ; static sf_count_t vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static sf_count_t vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; @@ -115,26 +121,22 @@ static STR_PAIRS vorbis_metatypes [] = { SF_STR_ALBUM, "Album" }, { SF_STR_LICENSE, "License" }, { SF_STR_TRACKNUMBER, "Tracknumber" }, - { SF_STR_GENRE, "Genre" }, + { SF_STR_GENRE, "Genre" }, } ; typedef struct -{ /* Count current location */ - sf_count_t loc ; +{ /* Current granule position. */ + uint64_t gp ; /* Struct that stores all the static vorbis bitstream settings */ vorbis_info vinfo ; /* Struct that stores all the bitstream user comments */ vorbis_comment vcomment ; - /* Ventral working state for the packet->PCM decoder */ + /* Central working state for the packet->PCM decoder */ vorbis_dsp_state vdsp ; /* Local working space for packet->PCM decode */ vorbis_block vblock ; - /* Encoding quality in range [0.0, 1.0]. */ double quality ; - - /* Current granule position. */ - uint64_t pcm_current ; /* Offset of the first samples' granule position. */ uint64_t pcm_start ; /* Last valid samples' granule position. */ @@ -147,9 +149,10 @@ static int vorbis_read_header (SF_PRIVATE *psf) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; - sf_count_t duration ; int printed_metadata_msg = 0 ; - int i, k, nn ; + int i, nn ; + sf_count_t last_page ; + sf_count_t saved_offset ; /* ** The first page of the Ogg stream we are told to try and open as Vorbis @@ -184,8 +187,8 @@ vorbis_read_header (SF_PRIVATE *psf) ** Vorbis decoder. ** ** The next two packets in order are the comment and codebook headers. - ** They're likely large and may span multiple pages. Thus we reead - ** and submit data until we get our two pacakets, watching that no + ** They're likely large and may span multiple pages. Thus we read + ** and submit data until we get our two packets, watching that no ** pages are missing. If a page is missing, error out ; losing a ** header page is the only place where missing data is fatal. */ @@ -231,32 +234,23 @@ vorbis_read_header (SF_PRIVATE *psf) psf->dataoffset = ogg_sync_ftell (psf) ; /* - ** Caculate the granule position offset. The first page with a payload + ** Calculate the granule position offset. The first page with a payload ** packet shouldn't end in a continued packet. The difference between the ** page's granule position and the sum of frames on the page tells us the ** granule position offset. ** See https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-132000A.2 */ ogg_stream_unpack_page (psf, odata) ; - vdata->pcm_start = odata->pkt [odata->pkt_len - 1].granulepos ; - duration = vorbis_calculate_page_duration (psf) ; - - if (duration < (sf_count_t) vdata->pcm_start) - vdata->pcm_start -= duration ; - else - vdata->pcm_start = 0 ; + vorbis_calculate_granulepos (psf, &vdata->pcm_start) ; + vdata->gp = vdata->pcm_start ; /* ** Find the end of the stream, save it. Only works if the file is seekable. */ - vdata->loc = vdata->pcm_start ; vdata->pcm_end = (uint64_t) -1 ; psf->datalength = psf->filelength ; if (!psf->is_pipe) - { sf_count_t last_page ; - sf_count_t saved_offset ; - - saved_offset = ogg_sync_ftell (psf) ; + { saved_offset = ogg_sync_ftell (psf) ; last_page = ogg_sync_last_page_before (psf, odata, &vdata->pcm_end, psf->filelength, odata->ostream.serialno) ; if (last_page > 0) { if (!ogg_page_eos (&odata->opage)) @@ -270,17 +264,17 @@ 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") ; /* Throw the comments plus a few lines about the bitstream we're decoding. */ - for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++) + for (i = 0 ; i < ARRAY_LEN (vorbis_metatypes) ; i++) { char *dd ; - dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ; + dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [i].name, 0) ; if (dd == NULL) continue ; @@ -289,8 +283,8 @@ vorbis_read_header (SF_PRIVATE *psf) printed_metadata_msg = 1 ; } ; - psf_store_string (psf, vorbis_metatypes [k].id, dd) ; - psf_log_printf (psf, " %-10s : %s\n", vorbis_metatypes [k].name, dd) ; + psf_store_string (psf, vorbis_metatypes [i].id, dd) ; + psf_log_printf (psf, " %-10s : %s\n", vorbis_metatypes [i].name, dd) ; } ; psf_log_printf (psf, "End\n") ; @@ -306,7 +300,7 @@ vorbis_read_header (SF_PRIVATE *psf) /* Local state for most of the decode so multiple block decodes can ** proceed in parallel. We could init multiple vorbis_block structures - ** for vd here. */ + ** for vdsp here. */ vorbis_block_init (&vdata->vdsp, &vdata->vblock) ; return 0 ; @@ -334,7 +328,7 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) if (ret) return SFE_BAD_OPEN_FORMAT ; - vdata->loc = 0 ; + vdata->gp = 0 ; /* add a comment */ vorbis_comment_init (&vdata->vcomment) ; @@ -348,15 +342,15 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) switch (psf->strings.data [k].type) { case SF_STR_TITLE : name = "TITLE" ; break ; - case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ; + case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ; case SF_STR_SOFTWARE : name = "SOFTWARE" ; break ; case SF_STR_ARTIST : name = "ARTIST" ; break ; case SF_STR_COMMENT : name = "COMMENT" ; break ; case SF_STR_DATE : name = "DATE" ; break ; case SF_STR_ALBUM : name = "ALBUM" ; break ; case SF_STR_LICENSE : name = "LICENSE" ; break ; - case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ; - case SF_STR_GENRE : name = "Genre" ; break ; + case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ; + case SF_STR_GENRE : name = "Genre" ; break ; default : continue ; } ; @@ -517,7 +511,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 : @@ -535,6 +530,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 ; } ; @@ -636,9 +638,9 @@ vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *t len -= samples ; /* tell libvorbis how many samples we actually consumed */ vorbis_synthesis_read (&vdata->vdsp, samples) ; - vdata->loc += samples ; + vdata->gp += samples ; if (len == 0) - return i ; /* Is this necessary */ + return i ; } ; /* Out of samples, load the next packet. */ @@ -648,9 +650,9 @@ vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *t if (nn <= 0) return i ; if (nn == 2) - { /* Ran over a hole. loc is now out of date, need to recalculate. */ - vdata->loc = odata->pkt [odata->pkt_len - 1].granulepos ; - vdata->loc -= vorbis_calculate_page_duration (psf) ; + { /* Ran over a hole. gp is now out of date, need to recalculate. */ + vorbis_synthesis_restart (&vdata->vdsp) ; + vorbis_calculate_granulepos (psf, &vdata->gp) ; } } ; @@ -722,7 +724,7 @@ vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata } ; } ; - vdata->loc += in_frames ; + vdata->gp += in_frames ; } /* vorbis_write_data */ @@ -791,11 +793,131 @@ vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens) return lens ; } /* vorbis_write_d */ +static int +vorbis_skip (SF_PRIVATE *psf, uint64_t target) +{ OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; + VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; + ogg_packet *pkt ; + int thisblock, lastblock, nn ; + const int blocksize = vorbis_info_blocksize (&vdata->vinfo, 1) ; + + /* Read out any samples that may be in the decoder from a seek without a + ** search. */ + thisblock = vorbis_synthesis_pcmout (&vdata->vdsp, NULL) ; + if (thisblock > 0) + { if ((uint64_t) thisblock + vdata->gp >= target) + thisblock = SF_MIN (thisblock, (int) (target - vdata->gp)) ; + + vorbis_synthesis_read (&vdata->vdsp, thisblock) ; + vdata->gp += thisblock ; + if (vdata->gp == target) + return 0 ; + } ; + + /* Read through packets that are before our target */ + lastblock = 0 ; + for ( ; vdata->gp < target ; ) + { /* Ensure there are unpacked packets. */ + if (odata->pkt_indx == odata->pkt_len) + { /* Page out of packets, load and unpack the next page. */ + nn = ogg_stream_unpack_page (psf, odata) ; + if (nn < 0) + return nn ; + if (nn == 0) + break ; + if (nn == 2) + { /* Ran over a hole. gp is now out of date, need to recalculate. */ + vorbis_synthesis_restart (&vdata->vdsp) ; + vorbis_calculate_granulepos (psf, &vdata->gp) ; + if (target < vdata->gp) + { /* Our target is inside the hole :-( */ + return 0 ; + } ; + } ; + } ; + + pkt = &odata->pkt [odata->pkt_indx] ; + thisblock = vorbis_packet_blocksize (&vdata->vinfo, pkt) ; + if (thisblock < 0) + { /* Not an audio packet */ + odata->pkt_indx++ ; + continue ; + } ; + + if (lastblock) + { vdata->gp += ((lastblock + thisblock) / 4) ; + } ; + + /* Check to see if the block contains our target */ + if (vdata->gp + ((thisblock + blocksize) / 4) >= target) + break ; + + /* Block is before the target. Track for state, but don't decode. */ + odata->pkt_indx++ ; + vorbis_synthesis_trackonly (&vdata->vblock, pkt) ; + vorbis_synthesis_blockin (&vdata->vdsp, &vdata->vblock) ; + lastblock = thisblock ; + } ; + + /* We are at the correct block, but still need to consume samples to reach + ** our target. */ + vorbis_read_sample (psf, (void *) NULL, (target - vdata->gp) * psf->sf.channels, vorbis_rnull) ; + + return 0 ; +} /* vorbis_skip */ + +static int +vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) +{ OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; + VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; + uint64_t best_gp, search_target_gp ; + int ret ; + + /* Can't bisect a file we don't know the end of (cannot seek). */ + if (vdata->pcm_end == (uint64_t) -1) + return 0 ; + + /* If the target is for the near future, don't bother bisecting, just skip + ** to it. */ + if (target_gp >= vdata->gp && + target_gp - vdata->gp < ((unsigned) (VORBIS_SEEK_THRESHOLD) * psf->sf.samplerate)) + return 0 ; + + /* Search for a position a half large-block before our target. As Vorbis is + ** lapped, every sample position come from two blocks, the "left" half of + ** one block and the "right" half of the previous block. The granule + ** position of an Ogg page of a Vorbis stream is the sample offset of the + ** last finished sample in the stream that can be decoded from a page. A + ** page also contains another half-block of samples waiting to be lapped + ** with the first half-block of samples from the next page. + ** + ** Searching for a sample one half of a large block before our target + ** guarantees we always load a page containing the previous half block + ** required to decode the target. Downside is we can't use best_gp + ** parameter of the page seek function. */ + search_target_gp = vorbis_info_blocksize (&vdata->vinfo, 1) / 2 ; + 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->vinfo.rate) ; + if (ret < 0) + return ret ; + + ret = ogg_stream_unpack_page (psf, odata) ; + if (ret > 0) + { /* Reset the decoder, recalculate position */ + vorbis_synthesis_restart (&vdata->vdsp) ; + ret = vorbis_calculate_granulepos (psf, &vdata->gp) ; + } ; + + return ret ; +} /* vorbis_seek_trysearch */ + static sf_count_t vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; - sf_count_t target ; + uint64_t target_gp ; int ret ; if (odata == NULL || vdata == NULL) @@ -807,63 +929,30 @@ vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset) } ; if (psf->file.mode == SFM_READ) - { target = offset + vdata->pcm_start ; + { target_gp = (uint64_t) offset + vdata->pcm_start ; - /* - ** If the end of the file is know, and the seek isn't for the near - ** future, do a search of the file for a good place to start. - */ - ret = 0 ; - if ((vdata->pcm_end != (uint64_t) -1) && - (target < vdata->loc || target - vdata->loc > (2 * psf->sf.samplerate))) - { uint64_t best_gp ; + ret = vorbis_seek_trysearch (psf, target_gp) ; - best_gp = vdata->pcm_start ; - - ret = ogg_stream_seek_page_search (psf, odata, target, vdata->pcm_start, - vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page) ; - if (ret >= 0) - { ret = ogg_stream_unpack_page (psf, odata) ; - if (ret == 1) - { vdata->loc = best_gp ; - vorbis_synthesis_restart (&vdata->vdsp) ; - } ; - } ; - } ; - - if (ret >= 0 && offset + (sf_count_t) vdata->pcm_start >= vdata->loc) - target = offset + vdata->pcm_start - vdata->loc ; - else + if (ret < 0 || vdata->gp > target_gp) { /* Search failed (bad data?), reset to the beginning of the stream. */ + psf_log_printf (psf, "Vorbis: Seek search failed. Reading through stream from start.\n") ; ogg_stream_reset_serialno (&odata->ostream, odata->ostream.serialno) ; odata->pkt_len = 0 ; odata->pkt_indx = 0 ; ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ; - vdata->loc = 0 ; + vdata->gp = vdata->pcm_start ; vorbis_synthesis_restart (&vdata->vdsp) ; - target = offset ; } ; - while (target > 0) - { sf_count_t m = target > 4096 ? 4096 : target ; + vorbis_skip (psf, target_gp) ; - /* - ** Need to multiply by channels here because the seek is done in - ** terms of frames and the read function is done in terms of - ** samples. - */ - vorbis_read_sample (psf, (void *) NULL, m * psf->sf.channels, vorbis_rnull) ; - - target -= m ; - } ; - - return vdata->loc - vdata->pcm_start ; + return vdata->gp - vdata->pcm_start ; } ; - return 0 ; + psf->error = SFE_BAD_SEEK ; + return ((sf_count_t) -1) ; } /* vorbis_seek */ - static int vorbis_byterate (SF_PRIVATE *psf) { @@ -873,27 +962,88 @@ vorbis_byterate (SF_PRIVATE *psf) return -1 ; } /* vorbis_byterate */ -static sf_count_t -vorbis_calculate_page_duration (SF_PRIVATE *psf) +static int +vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; - long thisblock, lastblock ; - sf_count_t duration ; - int i ; + ogg_packet *pkt ; + uint64_t last_gp ; + int thisblock, lastblock, i ; + unsigned duration ; - lastblock = -1 ; - duration = 0 ; - for (i = 0 ; i < odata->pkt_len ; i++) - { thisblock = vorbis_packet_blocksize (&vdata->vinfo, &(odata->pkt [i])) ; - if (thisblock >= 0) - { if (lastblock != -1) - duration += (lastblock + thisblock) >> 2 ; - lastblock = thisblock ; + /* Calculate the granule position when dropped into the middle of a stream + ** with an un-primed decoder. + ** + ** Normally the last unpacked packet contains the granule position of the + ** last completed sample from decoding all the blocks in the page's + ** packets. By calculating how many samples we can decode from the blocks + ** in the page's packets and subtracting it from the final packet's granule + ** position we get the position of the first sample to be output from the + ** decoder after it primes. That is, the current granule position. + ** + ** However, there is an ambiguity if this is the last page of a stream. The + ** last page of a stream may have a granule position of fewer samples than + ** the page actually contains. The excess samples are padding leftovers + ** for and exact sample length file. */ + + if (odata->pkt_len > 0) + { /* Calculate how many samples can be decoded from blocks in this page, + ** accounting for the fact that blocks are 1/2 lapped. */ + lastblock = -1 ; + duration = 0 ; + pkt = odata->pkt ; + for (i = 0 ; i < odata->pkt_len ; i++) + { thisblock = vorbis_packet_blocksize (&vdata->vinfo, &pkt [i]) ; + if (thisblock >= 0) + { if (lastblock != -1) + duration += (lastblock + thisblock) >> 2 ; + lastblock = thisblock ; + } ; } ; + + pkt = &odata->pkt [odata->pkt_len - 1] ; + last_gp = pkt->granulepos ; + if (last_gp == (uint64_t) -1) + { psf_log_printf (psf, "Vorbis: Ogg page has no granule position, cannot calculate sample position!\n") ; + psf->error = SFE_MALFORMED_FILE ; + return -1 ; + } ; + + if (pkt->e_o_s) + { if (last_gp <= duration) + { /* Corner case: One page stream. Ogg/Vorbis spec dictates the + ** granule position offset MUST be zero, hence this first (and + ** only) page must start at 0. */ + *gp_out = 0 ; + return 1 ; + } ; + + /* Otherwise, we cannot know where we are without looking at the + ** blocks of the previous page. (The granule position of the + ** previous page is not enough, we need the block sizes.) + ** + ** We avoid this case by never allowing a bisection search to seek + ** beyond the second-to-last page, so the last page is always + ** approached with a known location and never dropped into. + ** + ** The only way we should be able to end up here is if there was a + ** hole in stream just before the last page, in which case all bets + ** are off anyways. */ + psf_log_printf (psf, "Vorbis: Cannot calculate ambiguous last page duration. Sample count may be wrong.\n") ; + } ; + + if (last_gp < duration) + { psf_log_printf (psf, "Vorbis: Granule position is nonsensical! (Missing end-of-stream marker?)\n") ; + psf->error = SFE_MALFORMED_FILE ; + return -1 ; + } ; + + *gp_out = last_gp - duration ; + return 1 ; } ; - return duration ; -} + return 0 ; +} /* vorbis_calculate_granulepos */ #else /* HAVE_EXTERNAL_XIPH_LIBS */ diff --git a/src/paf.c b/src/paf.c index 459bc469..871931c6 100644 --- a/src/paf.c +++ b/src/paf.c @@ -493,7 +493,7 @@ paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) } ; /* Read the block. */ - if ((k = psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) + if ((k = (int) psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ; /* Do endian swapping if necessary. */ @@ -549,7 +549,7 @@ paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = paf24_read (psf, ppaf24, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = iptr [k] >> 16 ; @@ -591,7 +591,7 @@ paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = paf24_read (psf, ppaf24, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; @@ -619,7 +619,7 @@ paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = paf24_read (psf, ppaf24, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; @@ -668,7 +668,7 @@ paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) } ; /* Write block to disk. */ - if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) + if ((k = (int) psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ; if (ppaf24->sample_count < ppaf24->write_block * PAF24_SAMPLES_PER_BLOCK + ppaf24->write_count) @@ -718,7 +718,7 @@ paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = ptr [total + k] << 16 ; count = paf24_write (psf, ppaf24, iptr, writecount) ; @@ -772,7 +772,7 @@ paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = psf_lrintf (normfact * ptr [total + k]) ; count = paf24_write (psf, ppaf24, iptr, writecount) ; @@ -803,7 +803,7 @@ paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = psf_lrint (normfact * ptr [total+k]) ; count = paf24_write (psf, ppaf24, iptr, writecount) ; diff --git a/src/pcm.c b/src/pcm.c index 3ea0d090..d7dc82c4 100644 --- a/src/pcm.c +++ b/src/pcm.c @@ -134,10 +134,11 @@ pcm_init (SF_PRIVATE *psf) else if ((SF_CODEC (psf->sf.format)) == SF_FORMAT_PCM_U8) chars = SF_CHARS_UNSIGNED ; - if (CPU_IS_BIG_ENDIAN) - psf->data_endswap = (psf->endian == SF_ENDIAN_BIG) ? SF_FALSE : SF_TRUE ; - else - psf->data_endswap = (psf->endian == SF_ENDIAN_LITTLE) ? SF_FALSE : SF_TRUE ; +#if CPU_IS_BIG_ENDIAN + psf->data_endswap = (psf->endian == SF_ENDIAN_BIG) ? SF_FALSE : SF_TRUE ; +#else + psf->data_endswap = (psf->endian == SF_ENDIAN_LITTLE) ? SF_FALSE : SF_TRUE ; +#endif if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR) { switch (psf->bytewidth * 0x10000 + psf->endian + chars) @@ -283,37 +284,37 @@ pcm_init (SF_PRIVATE *psf) static inline void sc2s_array (const signed char *src, int count, short *dest) -{ while (--count >= 0) - { dest [count] = ((uint16_t) src [count]) << 8 ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = ((uint16_t) src [i]) << 8 ; } ; } /* sc2s_array */ static inline void uc2s_array (const unsigned char *src, int count, short *dest) -{ while (--count >= 0) - { dest [count] = (((uint32_t) src [count]) - 0x80) << 8 ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = (((uint32_t) src [i]) - 0x80) << 8 ; } ; } /* uc2s_array */ static inline void let2s_array (const tribyte *src, int count, short *dest) -{ while (--count >= 0) - dest [count] = LET2H_16_PTR (src [count].bytes) ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = LET2H_16_PTR (src [i].bytes) ; } /* let2s_array */ static inline void bet2s_array (const tribyte *src, int count, short *dest) -{ while (--count >= 0) - dest [count] = BET2H_16_PTR (src [count].bytes) ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = BET2H_16_PTR (src [i].bytes) ; } /* bet2s_array */ static inline void lei2s_array (const int *src, int count, short *dest) { int value ; - while (--count >= 0) - { value = LE2H_32 (src [count]) ; - dest [count] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = LE2H_32 (src [i]) ; + dest [i] = value >> 16 ; } ; } /* lei2s_array */ @@ -321,9 +322,9 @@ static inline void bei2s_array (const int *src, int count, short *dest) { int value ; - while (--count >= 0) - { value = BE2H_32 (src [count]) ; - dest [count] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = BE2H_32 (src [i]) ; + dest [i] = value >> 16 ; } ; } /* bei2s_array */ @@ -332,15 +333,15 @@ bei2s_array (const int *src, int count, short *dest) static inline void sc2i_array (const signed char *src, int count, int *dest) -{ while (--count >= 0) - { dest [count] = arith_shift_left ((int) src [count], 24) ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = arith_shift_left ((int) src [i], 24) ; } ; } /* sc2i_array */ static inline void uc2i_array (const unsigned char *src, int count, int *dest) -{ while (--count >= 0) - { dest [count] = arith_shift_left (((int) src [count]) - 128, 24) ; +{ for (int i = 0 ; i < count ; i++) + { dest [i] = arith_shift_left (((int) src [i]) - 128, 24) ; } ; } /* uc2i_array */ @@ -348,9 +349,9 @@ static inline void bes2i_array (const short *src, int count, int *dest) { short value ; - while (--count >= 0) - { value = BE2H_16 (src [count]) ; - dest [count] = arith_shift_left (value, 16) ; + for (int i = 0 ; i < count ; i++) + { value = BE2H_16 (src [i]) ; + dest [i] = arith_shift_left (value, 16) ; } ; } /* bes2i_array */ @@ -358,22 +359,22 @@ static inline void les2i_array (const short *src, int count, int *dest) { short value ; - while (--count >= 0) - { value = LE2H_16 (src [count]) ; - dest [count] = arith_shift_left (value, 16) ; + for (int i = 0 ; i < count ; i++) + { value = LE2H_16 (src [i]) ; + dest [i] = arith_shift_left (value, 16) ; } ; } /* les2i_array */ static inline void bet2i_array (const tribyte *src, int count, int *dest) -{ while (--count >= 0) - dest [count] = psf_get_be24 (src [count].bytes, 0) ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = psf_get_be24 (src [i].bytes, 0) ; } /* bet2i_array */ static inline void let2i_array (const tribyte *src, int count, int *dest) -{ while (--count >= 0) - dest [count] = psf_get_le24 (src [count].bytes, 0) ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = psf_get_le24 (src [i].bytes, 0) ; } /* let2i_array */ /*-------------------------------------------------------------------------- @@ -381,24 +382,24 @@ let2i_array (const tribyte *src, int count, int *dest) static inline void sc2f_array (const signed char *src, int count, float *dest, float normfact) -{ while (--count >= 0) - dest [count] = ((float) src [count]) * normfact ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = ((float) src [i]) * normfact ; } /* sc2f_array */ static inline void uc2f_array (const unsigned char *src, int count, float *dest, float normfact) -{ while (--count >= 0) - dest [count] = (((int) src [count]) - 128) * normfact ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = (((int) src [i]) - 128) * normfact ; } /* uc2f_array */ static inline void les2f_array (const short *src, int count, float *dest, float normfact) { short value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = LE2H_16 (value) ; - dest [count] = ((float) value) * normfact ; + dest [i] = ((float) value) * normfact ; } ; } /* les2f_array */ @@ -406,10 +407,10 @@ static inline void bes2f_array (const short *src, int count, float *dest, float normfact) { short value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = BE2H_16 (value) ; - dest [count] = ((float) value) * normfact ; + dest [i] = ((float) value) * normfact ; } ; } /* bes2f_array */ @@ -417,9 +418,9 @@ static inline void let2f_array (const tribyte *src, int count, float *dest, float normfact) { int value ; - while (--count >= 0) - { value = psf_get_le24 (src [count].bytes, 0) ; - dest [count] = ((float) value) * normfact ; + for (int i = 0 ; i < count ; i++) + { value = psf_get_le24 (src [i].bytes, 0) ; + dest [i] = ((float) value) * normfact ; } ; } /* let2f_array */ @@ -427,9 +428,9 @@ static inline void bet2f_array (const tribyte *src, int count, float *dest, float normfact) { int value ; - while (--count >= 0) - { value = psf_get_be24 (src [count].bytes, 0) ; - dest [count] = ((float) value) * normfact ; + for (int i = 0 ; i < count ; i++) + { value = psf_get_be24 (src [i].bytes, 0) ; + dest [i] = ((float) value) * normfact ; } ; } /* bet2f_array */ @@ -437,10 +438,10 @@ static inline void lei2f_array (const int *src, int count, float *dest, float normfact) { int value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = LE2H_32 (value) ; - dest [count] = ((float) value) * normfact ; + dest [i] = ((float) value) * normfact ; } ; } /* lei2f_array */ @@ -448,10 +449,10 @@ static inline void bei2f_array (const int *src, int count, float *dest, float normfact) { int value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = BE2H_32 (value) ; - dest [count] = ((float) value) * normfact ; + dest [i] = ((float) value) * normfact ; } ; } /* bei2f_array */ @@ -460,24 +461,24 @@ bei2f_array (const int *src, int count, float *dest, float normfact) static inline void sc2d_array (const signed char *src, int count, double *dest, double normfact) -{ while (--count >= 0) - dest [count] = ((double) src [count]) * normfact ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = ((double) src [i]) * normfact ; } /* sc2d_array */ static inline void uc2d_array (const unsigned char *src, int count, double *dest, double normfact) -{ while (--count >= 0) - dest [count] = (((int) src [count]) - 128) * normfact ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = (((int) src [i]) - 128) * normfact ; } /* uc2d_array */ static inline void les2d_array (const short *src, int count, double *dest, double normfact) { short value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = LE2H_16 (value) ; - dest [count] = ((double) value) * normfact ; + dest [i] = ((double) value) * normfact ; } ; } /* les2d_array */ @@ -485,10 +486,10 @@ static inline void bes2d_array (const short *src, int count, double *dest, double normfact) { short value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = BE2H_16 (value) ; - dest [count] = ((double) value) * normfact ; + dest [i] = ((double) value) * normfact ; } ; } /* bes2d_array */ @@ -496,9 +497,9 @@ static inline void let2d_array (const tribyte *src, int count, double *dest, double normfact) { int value ; - while (--count >= 0) - { value = psf_get_le24 (src [count].bytes, 0) ; - dest [count] = ((double) value) * normfact ; + for (int i = 0 ; i < count ; i++) + { value = psf_get_le24 (src [i].bytes, 0) ; + dest [i] = ((double) value) * normfact ; } ; } /* let2d_array */ @@ -506,9 +507,9 @@ static inline void bet2d_array (const tribyte *src, int count, double *dest, double normfact) { int value ; - while (--count >= 0) - { value = psf_get_be24 (src [count].bytes, 0) ; - dest [count] = ((double) value) * normfact ; + for (int i = 0 ; i < count ; i++) + { value = psf_get_be24 (src [i].bytes, 0) ; + dest [i] = ((double) value) * normfact ; } ; } /* bet2d_array */ @@ -516,10 +517,10 @@ static inline void lei2d_array (const int *src, int count, double *dest, double normfact) { int value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = LE2H_32 (value) ; - dest [count] = ((double) value) * normfact ; + dest [i] = ((double) value) * normfact ; } ; } /* lei2d_array */ @@ -527,10 +528,10 @@ static inline void bei2d_array (const int *src, int count, double *dest, double normfact) { int value ; - while (--count >= 0) - { value = src [count] ; + for (int i = 0 ; i < count ; i++) + { value = src [i] ; value = BE2H_32 (value) ; - dest [count] = ((double) value) * normfact ; + dest [i] = ((double) value) * normfact ; } ; } /* bei2d_array */ @@ -539,31 +540,31 @@ bei2d_array (const int *src, int count, double *dest, double normfact) static inline void s2sc_array (const short *src, signed char *dest, int count) -{ while (--count >= 0) - dest [count] = src [count] >> 8 ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = src [i] >> 8 ; } /* s2sc_array */ static inline void s2uc_array (const short *src, unsigned char *dest, int count) -{ while (--count >= 0) - dest [count] = (src [count] >> 8) + 0x80 ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = (src [i] >> 8) + 0x80 ; } /* s2uc_array */ static inline void s2let_array (const short *src, tribyte *dest, int count) -{ while (--count >= 0) - { dest [count].bytes [0] = 0 ; - dest [count].bytes [1] = src [count] ; - dest [count].bytes [2] = src [count] >> 8 ; +{ for (int i = 0 ; i < count ; i++) + { dest [i].bytes [0] = 0 ; + dest [i].bytes [1] = src [i] ; + dest [i].bytes [2] = src [i] >> 8 ; } ; } /* s2let_array */ static inline void s2bet_array (const short *src, tribyte *dest, int count) -{ while (--count >= 0) - { dest [count].bytes [2] = 0 ; - dest [count].bytes [1] = src [count] ; - dest [count].bytes [0] = src [count] >> 8 ; +{ for (int i = 0 ; i < count ; i++) + { dest [i].bytes [2] = 0 ; + dest [i].bytes [1] = src [i] ; + dest [i].bytes [0] = src [i] >> 8 ; } ; } /* s2bet_array */ @@ -571,13 +572,12 @@ static inline void s2lei_array (const short *src, int *dest, int count) { unsigned char *ucptr ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; ucptr [0] = 0 ; ucptr [1] = 0 ; - ucptr [2] = src [count] ; - ucptr [3] = src [count] >> 8 ; + ucptr [2] = src [i] ; + ucptr [3] = src [i] >> 8 ; } ; } /* s2lei_array */ @@ -585,11 +585,10 @@ static inline void s2bei_array (const short *src, int *dest, int count) { unsigned char *ucptr ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - ucptr [0] = src [count] >> 8 ; - ucptr [1] = src [count] ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + ucptr [0] = src [i] >> 8 ; + ucptr [1] = src [i] ; ucptr [2] = 0 ; ucptr [3] = 0 ; } ; @@ -600,25 +599,24 @@ s2bei_array (const short *src, int *dest, int count) static inline void i2sc_array (const int *src, signed char *dest, int count) -{ while (--count >= 0) - dest [count] = (src [count] >> 24) ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = (src [i] >> 24) ; } /* i2sc_array */ static inline void i2uc_array (const int *src, unsigned char *dest, int count) -{ while (--count >= 0) - dest [count] = ((src [count] >> 24) + 128) ; +{ for (int i = 0 ; i < count ; i++) + dest [i] = ((src [i] >> 24) + 128) ; } /* i2uc_array */ static inline void i2bes_array (const int *src, short *dest, int count) { unsigned char *ucptr ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - ucptr [0] = src [count] >> 24 ; - ucptr [1] = src [count] >> 16 ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + ucptr [0] = src [i] >> 24 ; + ucptr [1] = src [i] >> 16 ; } ; } /* i2bes_array */ @@ -626,11 +624,10 @@ static inline void i2les_array (const int *src, short *dest, int count) { unsigned char *ucptr ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - ucptr [0] = src [count] >> 16 ; - ucptr [1] = src [count] >> 24 ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + ucptr [0] = src [i] >> 16 ; + ucptr [1] = src [i] >> 24 ; } ; } /* i2les_array */ @@ -638,11 +635,11 @@ static inline void i2let_array (const int *src, tribyte *dest, int count) { int value ; - while (--count >= 0) - { value = src [count] >> 8 ; - dest [count].bytes [0] = value ; - dest [count].bytes [1] = value >> 8 ; - dest [count].bytes [2] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = src [i] >> 8 ; + dest [i].bytes [0] = value ; + dest [i].bytes [1] = value >> 8 ; + dest [i].bytes [2] = value >> 16 ; } ; } /* i2let_array */ @@ -650,11 +647,11 @@ static inline void i2bet_array (const int *src, tribyte *dest, int count) { int value ; - while (--count >= 0) - { value = src [count] >> 8 ; - dest [count].bytes [2] = value ; - dest [count].bytes [1] = value >> 8 ; - dest [count].bytes [0] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = src [i] >> 8 ; + dest [i].bytes [2] = value ; + dest [i].bytes [1] = value >> 8 ; + dest [i].bytes [0] = value >> 16 ; } ; } /* i2bet_array */ @@ -672,7 +669,7 @@ pcm_read_sc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; sc2s_array (ubuf.scbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -694,7 +691,7 @@ pcm_read_uc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; uc2s_array (ubuf.ucbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -709,9 +706,10 @@ static sf_count_t pcm_read_bes2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int total ; - total = psf_fread (ptr, sizeof (short), len, psf) ; - if (CPU_IS_LITTLE_ENDIAN) - endswap_short_array (ptr, len) ; + total = (int) psf_fread (ptr, sizeof (short), len, psf) ; +#if CPU_IS_LITTLE_ENDIAN + endswap_short_array (ptr, len) ; +#endif return total ; } /* pcm_read_bes2s */ @@ -721,8 +719,9 @@ pcm_read_les2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (short), len, psf) ; - if (CPU_IS_BIG_ENDIAN) - endswap_short_array (ptr, len) ; +#if CPU_IS_BIG_ENDIAN + endswap_short_array (ptr, len) ; +#endif return total ; } /* pcm_read_les2s */ @@ -738,7 +737,7 @@ pcm_read_bet2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; bet2s_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -760,7 +759,7 @@ pcm_read_let2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; let2s_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -782,7 +781,7 @@ pcm_read_bei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; bei2s_array (ubuf.ibuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -804,7 +803,7 @@ pcm_read_lei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; lei2s_array (ubuf.ibuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -829,7 +828,7 @@ pcm_read_sc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; sc2i_array (ubuf.scbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -851,7 +850,7 @@ pcm_read_uc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; uc2i_array (ubuf.ucbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -873,7 +872,7 @@ pcm_read_bes2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; bes2i_array (ubuf.sbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -895,7 +894,7 @@ pcm_read_les2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; les2i_array (ubuf.sbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -917,7 +916,7 @@ pcm_read_bet2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; bet2i_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -939,7 +938,7 @@ pcm_read_let2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; let2i_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -955,8 +954,9 @@ pcm_read_bei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (int), len, psf) ; - if (CPU_IS_LITTLE_ENDIAN) - endswap_int_array (ptr, len) ; +#if CPU_IS_LITTLE_ENDIAN + endswap_int_array (ptr, len) ; +#endif return total ; } /* pcm_read_bei2i */ @@ -966,8 +966,9 @@ pcm_read_lei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (int), len, psf) ; - if (CPU_IS_BIG_ENDIAN) - endswap_int_array (ptr, len) ; +#if CPU_IS_BIG_ENDIAN + endswap_int_array (ptr, len) ; +#endif return total ; } /* pcm_read_lei2i */ @@ -989,7 +990,7 @@ pcm_read_sc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; sc2f_array (ubuf.scbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1014,7 +1015,7 @@ pcm_read_uc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; uc2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1039,7 +1040,7 @@ pcm_read_bes2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; bes2f_array (ubuf.sbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1064,7 +1065,7 @@ pcm_read_les2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; les2f_array (ubuf.sbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1090,7 +1091,7 @@ pcm_read_bet2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; bet2f_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1116,7 +1117,7 @@ pcm_read_let2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; let2f_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1141,7 +1142,7 @@ pcm_read_bei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; bei2f_array (ubuf.ibuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1166,7 +1167,7 @@ pcm_read_lei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; lei2f_array (ubuf.ibuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1194,7 +1195,7 @@ pcm_read_sc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; sc2d_array (ubuf.scbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1219,7 +1220,7 @@ pcm_read_uc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; uc2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1244,7 +1245,7 @@ pcm_read_bes2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; bes2d_array (ubuf.sbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1269,7 +1270,7 @@ pcm_read_les2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; les2d_array (ubuf.sbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1294,7 +1295,7 @@ pcm_read_bet2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; bet2d_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1320,7 +1321,7 @@ pcm_read_let2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; let2d_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1345,7 +1346,7 @@ pcm_read_bei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; bei2d_array (ubuf.ibuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1370,7 +1371,7 @@ pcm_read_lei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; lei2d_array (ubuf.ibuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -1398,7 +1399,7 @@ pcm_write_s2sc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2sc_array (ptr + total, ubuf.scbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1420,7 +1421,7 @@ pcm_write_s2uc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2uc_array (ptr + total, ubuf.ucbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1432,21 +1433,21 @@ pcm_write_s2uc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) static sf_count_t pcm_write_s2bes (SF_PRIVATE *psf, const short *ptr, sf_count_t len) -{ BUF_UNION ubuf ; +{ +#if CPU_IS_BIG_ENDIAN + return psf_fwrite (ptr, sizeof (short), len, psf) ; +#else + BUF_UNION ubuf ; int bufferlen, writecount ; sf_count_t total = 0 ; - if (CPU_IS_BIG_ENDIAN) - return psf_fwrite (ptr, sizeof (short), len, psf) ; - else - bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; endswap_short_copy (ubuf.sbuf, ptr + total, bufferlen) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1454,24 +1455,26 @@ pcm_write_s2bes (SF_PRIVATE *psf, const short *ptr, sf_count_t len) } ; return total ; +#endif } /* pcm_write_s2bes */ static sf_count_t pcm_write_s2les (SF_PRIVATE *psf, const short *ptr, sf_count_t len) -{ BUF_UNION ubuf ; +{ +#if CPU_IS_LITTLE_ENDIAN + return psf_fwrite (ptr, sizeof (short), len, psf) ; +#else + BUF_UNION ubuf ; int bufferlen, writecount ; sf_count_t total = 0 ; - if (CPU_IS_LITTLE_ENDIAN) - return psf_fwrite (ptr, sizeof (short), len, psf) ; - bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; endswap_short_copy (ubuf.sbuf, ptr + total, bufferlen) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1479,6 +1482,7 @@ pcm_write_s2les (SF_PRIVATE *psf, const short *ptr, sf_count_t len) } ; return total ; +#endif } /* pcm_write_s2les */ static sf_count_t @@ -1493,7 +1497,7 @@ pcm_write_s2bet (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2bet_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1515,7 +1519,7 @@ pcm_write_s2let (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2let_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1537,7 +1541,7 @@ pcm_write_s2bei (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2bei_array (ptr + total, ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1559,7 +1563,7 @@ pcm_write_s2lei (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2lei_array (ptr + total, ubuf.ibuf, bufferlen) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1584,7 +1588,7 @@ pcm_write_i2sc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2sc_array (ptr + total, ubuf.scbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1606,7 +1610,7 @@ pcm_write_i2uc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2uc_array (ptr + total, ubuf.ucbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.ucbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1628,7 +1632,7 @@ pcm_write_i2bes (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2bes_array (ptr + total, ubuf.sbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1650,7 +1654,7 @@ pcm_write_i2les (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2les_array (ptr + total, ubuf.sbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1672,7 +1676,7 @@ pcm_write_i2bet (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2bet_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1694,7 +1698,7 @@ pcm_write_i2let (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2let_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1706,20 +1710,21 @@ pcm_write_i2let (SF_PRIVATE *psf, const int *ptr, sf_count_t len) static sf_count_t pcm_write_i2bei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) -{ BUF_UNION ubuf ; +{ +#if CPU_IS_BIG_ENDIAN + return psf_fwrite (ptr, sizeof (int), len, psf) ; +#else + BUF_UNION ubuf ; int bufferlen, writecount ; sf_count_t total = 0 ; - if (CPU_IS_BIG_ENDIAN) - return psf_fwrite (ptr, sizeof (int), len, psf) ; - bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; endswap_int_copy (ubuf.ibuf, ptr + total, bufferlen) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1727,24 +1732,26 @@ pcm_write_i2bei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) } ; return total ; +#endif } /* pcm_write_i2bei */ static sf_count_t pcm_write_i2lei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) -{ BUF_UNION ubuf ; +{ +#if CPU_IS_LITTLE_ENDIAN + return psf_fwrite (ptr, sizeof (int), len, psf) ; +#else + BUF_UNION ubuf ; int bufferlen, writecount ; sf_count_t total = 0 ; - if (CPU_IS_LITTLE_ENDIAN) - return psf_fwrite (ptr, sizeof (int), len, psf) ; - bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; endswap_int_copy (ubuf.ibuf, ptr + total, bufferlen) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1752,6 +1759,7 @@ pcm_write_i2lei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) } ; return total ; +#endif } /* pcm_write_i2lei */ /*------------------------------------------------------------------------------ @@ -1765,8 +1773,8 @@ f2sc_array (const float *src, signed char *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7F) : 1.0 ; - while (--count >= 0) - { dest [count] = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrintf (src [i] * normfact) ; } ; } /* f2sc_array */ @@ -1776,18 +1784,18 @@ f2sc_clip_array (const float *src, signed char *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count] = 127 ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [i] = 127 ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count] = -128 ; + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i] = -128 ; continue ; } ; - dest [count] = psf_lrintf (scaled_value) >> 24 ; + dest [i] = psf_lrintf (scaled_value) >> 24 ; } ; } /* f2sc_clip_array */ @@ -1805,7 +1813,7 @@ pcm_write_f2sc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.scbuf, bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1824,8 +1832,8 @@ f2uc_array (const float *src, unsigned char *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7F) : 1.0 ; - while (--count >= 0) - { dest [count] = psf_lrintf (src [count] * normfact) + 128 ; + for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrintf (src [i] * normfact) + 128 ; } ; } /* f2uc_array */ @@ -1835,18 +1843,18 @@ f2uc_clip_array (const float *src, unsigned char *dest, int count, int normalize normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count] = 0xFF ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [i] = 0xFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count] = 0 ; + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i] = 0 ; continue ; } ; - dest [count] = (psf_lrintf (scaled_value) >> 24) + 128 ; + dest [i] = (psf_lrintf (scaled_value) >> 24) + 128 ; } ; } /* f2uc_clip_array */ @@ -1864,7 +1872,7 @@ pcm_write_f2uc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.ucbuf, bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1884,11 +1892,10 @@ f2bes_array (const float *src, short *dest, int count, int normalize) short value ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - value = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrintf (src [i] * normfact) ; ucptr [1] = value ; ucptr [0] = value >> 8 ; } ; @@ -1901,17 +1908,16 @@ f2bes_clip_array (const float *src, short *dest, int count, int normalize) int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; @@ -1937,7 +1943,7 @@ pcm_write_f2bes (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1957,11 +1963,10 @@ f2les_array (const float *src, short *dest, int count, int normalize) int value ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - value = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrintf (src [i] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; } ; @@ -1974,17 +1979,16 @@ f2les_clip_array (const float *src, short *dest, int count, int normalize) int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x80 ; continue ; @@ -2010,7 +2014,7 @@ pcm_write_f2les (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2030,11 +2034,11 @@ f2let_array (const float *src, tribyte *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; - while (--count >= 0) - { value = psf_lrintf (src [count] * normfact) ; - dest [count].bytes [0] = value ; - dest [count].bytes [1] = value >> 8 ; - dest [count].bytes [2] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = psf_lrintf (src [i] * normfact) ; + dest [i].bytes [0] = value ; + dest [i].bytes [1] = value >> 8 ; + dest [i].bytes [2] = value >> 16 ; } ; } /* f2let_array */ @@ -2045,25 +2049,29 @@ f2let_clip_array (const float *src, tribyte *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count].bytes [0] = 0xFF ; - dest [count].bytes [1] = 0xFF ; - dest [count].bytes [2] = 0x7F ; + 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].bytes [0] = 0xFF ; + dest [i].bytes [1] = 0xFF ; + dest [i].bytes [2] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count].bytes [0] = 0x00 ; - dest [count].bytes [1] = 0x00 ; - dest [count].bytes [2] = 0x80 ; +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i].bytes [0] = 0x00 ; + dest [i].bytes [1] = 0x00 ; + dest [i].bytes [2] = 0x80 ; continue ; } ; +#endif value = psf_lrintf (scaled_value) ; - dest [count].bytes [0] = value >> 8 ; - dest [count].bytes [1] = value >> 16 ; - dest [count].bytes [2] = value >> 24 ; + dest [i].bytes [0] = value >> 8 ; + dest [i].bytes [1] = value >> 16 ; + dest [i].bytes [2] = value >> 24 ; } ; } /* f2let_clip_array */ @@ -2081,7 +2089,7 @@ pcm_write_f2let (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2101,11 +2109,11 @@ f2bet_array (const float *src, tribyte *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; - while (--count >= 0) - { value = psf_lrintf (src [count] * normfact) ; - dest [count].bytes [0] = value >> 16 ; - dest [count].bytes [1] = value >> 8 ; - dest [count].bytes [2] = value ; + for (int i = 0 ; i < count ; i++) + { value = psf_lrintf (src [i] * normfact) ; + dest [i].bytes [0] = value >> 16 ; + dest [i].bytes [1] = value >> 8 ; + dest [i].bytes [2] = value ; } ; } /* f2bet_array */ @@ -2116,25 +2124,29 @@ f2bet_clip_array (const float *src, tribyte *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count].bytes [0] = 0x7F ; - dest [count].bytes [1] = 0xFF ; - dest [count].bytes [2] = 0xFF ; + 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].bytes [0] = 0x7F ; + dest [i].bytes [1] = 0xFF ; + dest [i].bytes [2] = 0xFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count].bytes [0] = 0x80 ; - dest [count].bytes [1] = 0x00 ; - dest [count].bytes [2] = 0x00 ; +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i].bytes [0] = 0x80 ; + dest [i].bytes [1] = 0x00 ; + dest [i].bytes [2] = 0x00 ; continue ; } ; +#endif value = psf_lrint (scaled_value) ; - dest [count].bytes [0] = value >> 24 ; - dest [count].bytes [1] = value >> 16 ; - dest [count].bytes [2] = value >> 8 ; + dest [i].bytes [0] = value >> 24 ; + dest [i].bytes [1] = value >> 16 ; + dest [i].bytes [2] = value >> 8 ; } ; } /* f2bet_clip_array */ @@ -2152,7 +2164,7 @@ pcm_write_f2bet (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2172,10 +2184,10 @@ f2bei_array (const float *src, int *dest, int count, int normalize) int value ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - value = psf_lrintf (src [count] * normfact) ; + + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrintf (src [i] * normfact) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; @@ -2190,25 +2202,28 @@ f2bei_clip_array (const float *src, int *dest, int count, int normalize) int value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= 1.0 * 0x7FFFFFFF) + 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] = 0x7F ; ucptr [1] = 0xFF ; ucptr [2] = 0xFF ; ucptr [3] = 0xFF ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x80 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; ucptr [3] = 0x00 ; continue ; } ; +#endif value = psf_lrintf (scaled_value) ; ucptr [0] = value >> 24 ; @@ -2232,7 +2247,7 @@ pcm_write_f2bei (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2252,11 +2267,10 @@ f2lei_array (const float *src, int *dest, int count, int normalize) int value ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - value = psf_lrintf (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrintf (src [i] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; @@ -2271,25 +2285,28 @@ f2lei_clip_array (const float *src, int *dest, int count, int normalize) int value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + 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] = 0xFF ; ucptr [2] = 0xFF ; ucptr [3] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; ucptr [3] = 0x80 ; continue ; } ; +#endif value = psf_lrintf (scaled_value) ; ucptr [0] = value ; @@ -2313,7 +2330,7 @@ pcm_write_f2lei (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_float) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2332,8 +2349,8 @@ d2sc_array (const double *src, signed char *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7F) : 1.0 ; - while (--count >= 0) - { dest [count] = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrint (src [i] * normfact) ; } ; } /* d2sc_array */ @@ -2343,18 +2360,18 @@ d2sc_clip_array (const double *src, signed char *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count] = 127 ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [i] = 127 ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count] = -128 ; + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i] = -128 ; continue ; } ; - dest [count] = psf_lrintf (scaled_value) >> 24 ; + dest [i] = psf_lrintf (scaled_value) >> 24 ; } ; } /* d2sc_clip_array */ @@ -2372,7 +2389,7 @@ pcm_write_d2sc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.scbuf, bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2391,8 +2408,8 @@ d2uc_array (const double *src, unsigned char *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7F) : 1.0 ; - while (--count >= 0) - { dest [count] = psf_lrint (src [count] * normfact) + 128 ; + for (int i = 0 ; i < count ; i++) + { dest [i] = psf_lrint (src [i] * normfact) + 128 ; } ; } /* d2uc_array */ @@ -2402,18 +2419,18 @@ d2uc_clip_array (const double *src, unsigned char *dest, int count, int normaliz normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count] = 255 ; + for (int i = 0 ; i < count ; i++) + { scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [i] = 255 ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count] = 0 ; + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i] = 0 ; continue ; } ; - dest [count] = (psf_lrint (src [count] * normfact) >> 24) + 128 ; + dest [i] = (psf_lrint (src [i] * normfact) >> 24) + 128 ; } ; } /* d2uc_clip_array */ @@ -2431,7 +2448,7 @@ pcm_write_d2uc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.ucbuf, bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2451,11 +2468,10 @@ d2bes_array (const double *src, short *dest, int count, int normalize) double normfact ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - value = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrint (src [i] * normfact) ; ucptr [1] = value ; ucptr [0] = value >> 8 ; } ; @@ -2468,17 +2484,16 @@ d2bes_clip_array (const double *src, short *dest, int count, int normalize) int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; @@ -2504,7 +2519,7 @@ pcm_write_d2bes (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2524,11 +2539,10 @@ d2les_array (const double *src, short *dest, int count, int normalize) double normfact ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - value = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrint (src [i] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; } ; @@ -2541,17 +2555,16 @@ d2les_clip_array (const double *src, short *dest, int count, int normalize) double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; - ucptr = ((unsigned char*) dest) + 2 * count ; - while (--count >= 0) - { ucptr -= 2 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + scaled_value = src [i] * normfact ; + if (scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x80 ; continue ; @@ -2577,7 +2590,7 @@ pcm_write_d2les (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2597,11 +2610,11 @@ d2let_array (const double *src, tribyte *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; - while (--count >= 0) - { value = psf_lrint (src [count] * normfact) ; - dest [count].bytes [0] = value ; - dest [count].bytes [1] = value >> 8 ; - dest [count].bytes [2] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = psf_lrint (src [i] * normfact) ; + dest [i].bytes [0] = value ; + dest [i].bytes [1] = value >> 8 ; + dest [i].bytes [2] = value >> 16 ; } ; } /* d2let_array */ @@ -2612,25 +2625,29 @@ d2let_clip_array (const double *src, tribyte *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count].bytes [0] = 0xFF ; - dest [count].bytes [1] = 0xFF ; - dest [count].bytes [2] = 0x7F ; + 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].bytes [0] = 0xFF ; + dest [i].bytes [1] = 0xFF ; + dest [i].bytes [2] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count].bytes [0] = 0x00 ; - dest [count].bytes [1] = 0x00 ; - dest [count].bytes [2] = 0x80 ; +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i].bytes [0] = 0x00 ; + dest [i].bytes [1] = 0x00 ; + dest [i].bytes [2] = 0x80 ; continue ; } ; +#endif value = psf_lrint (scaled_value) ; - dest [count].bytes [0] = value >> 8 ; - dest [count].bytes [1] = value >> 16 ; - dest [count].bytes [2] = value >> 24 ; + dest [i].bytes [0] = value >> 8 ; + dest [i].bytes [1] = value >> 16 ; + dest [i].bytes [2] = value >> 24 ; } ; } /* d2let_clip_array */ @@ -2648,7 +2665,7 @@ pcm_write_d2let (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2668,11 +2685,11 @@ d2bet_array (const double *src, tribyte *dest, int count, int normalize) normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; - while (--count >= 0) - { value = psf_lrint (src [count] * normfact) ; - dest [count].bytes [2] = value ; - dest [count].bytes [1] = value >> 8 ; - dest [count].bytes [0] = value >> 16 ; + for (int i = 0 ; i < count ; i++) + { value = psf_lrint (src [i] * normfact) ; + dest [i].bytes [2] = value ; + dest [i].bytes [1] = value >> 8 ; + dest [i].bytes [0] = value >> 16 ; } ; } /* d2bet_array */ @@ -2683,25 +2700,29 @@ d2bet_clip_array (const double *src, tribyte *dest, int count, int normalize) normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; - while (--count >= 0) - { scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) - { dest [count].bytes [2] = 0xFF ; - dest [count].bytes [1] = 0xFF ; - dest [count].bytes [0] = 0x7F ; + 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].bytes [2] = 0xFF ; + dest [i].bytes [1] = 0xFF ; + dest [i].bytes [0] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) - { dest [count].bytes [2] = 0x00 ; - dest [count].bytes [1] = 0x00 ; - dest [count].bytes [0] = 0x80 ; +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) + { dest [i].bytes [2] = 0x00 ; + dest [i].bytes [1] = 0x00 ; + dest [i].bytes [0] = 0x80 ; continue ; } ; +#endif value = psf_lrint (scaled_value) ; - dest [count].bytes [2] = value >> 8 ; - dest [count].bytes [1] = value >> 16 ; - dest [count].bytes [0] = value >> 24 ; + dest [i].bytes [2] = value >> 8 ; + dest [i].bytes [1] = value >> 16 ; + dest [i].bytes [0] = value >> 24 ; } ; } /* d2bet_clip_array */ @@ -2719,7 +2740,7 @@ pcm_write_d2bet (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2739,11 +2760,10 @@ d2bei_array (const double *src, int *dest, int count, int normalize) double normfact ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - value = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrint (src [i] * normfact) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; @@ -2758,25 +2778,28 @@ d2bei_clip_array (const double *src, int *dest, int count, int normalize) double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + 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 [3] = 0xFF ; ucptr [2] = 0xFF ; ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [3] = 0x00 ; ucptr [2] = 0x00 ; ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; } ; +#endif value = psf_lrint (scaled_value) ; ucptr [0] = value >> 24 ; @@ -2800,7 +2823,7 @@ pcm_write_d2bei (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -2820,11 +2843,10 @@ d2lei_array (const double *src, int *dest, int count, int normalize) double normfact ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - value = psf_lrint (src [count] * normfact) ; + for (int i = 0 ; i < count ; i++) + { ucptr = (unsigned char*) &dest [i] ; + value = psf_lrint (src [i] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; @@ -2839,25 +2861,28 @@ d2lei_clip_array (const double *src, int *dest, int count, int normalize) double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; - ucptr = ((unsigned char*) dest) + 4 * count ; - while (--count >= 0) - { ucptr -= 4 ; - scaled_value = src [count] * normfact ; - if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + 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] = 0xFF ; ucptr [2] = 0xFF ; ucptr [3] = 0x7F ; continue ; } ; - if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) +#endif +#if CPU_CLIPS_NEGATIVE == 0 + if (scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; ucptr [3] = 0x80 ; continue ; } ; +#endif value = psf_lrint (scaled_value) ; ucptr [0] = value ; @@ -2881,7 +2906,7 @@ pcm_write_d2lei (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_double) ; - writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; diff --git a/src/rf64.c b/src/rf64.c index 876cd451..123db445 100644 --- a/src/rf64.c +++ b/src/rf64.c @@ -197,7 +197,7 @@ rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) else psf_log_printf (psf, "%M : 0x%x (should be 0xFFFFFFFF)\n %M\n", RF64_MARKER, WAVE_MARKER) ; - while (NOT (done)) + while (!done) { marker = chunk_size = 0 ; psf_binheader_readf (psf, "em4", &marker, &chunk_size) ; @@ -328,7 +328,7 @@ rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) if (psf->datalength + psf->dataoffset < psf->filelength) psf->dataend = psf->datalength + psf->dataoffset ; - if (NOT (psf->sf.seekable) || psf->dataoffset < 0) + if (!psf->sf.seekable || psf->dataoffset < 0) break ; /* Seek past data and continue reading header. */ @@ -762,7 +762,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length) psf->dataoffset = psf->header.indx ; - if (NOT (has_data)) + if (!has_data) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; diff --git a/src/sd2.c b/src/sd2.c index dd3dbef6..f5ef9de2 100644 --- a/src/sd2.c +++ b/src/sd2.c @@ -240,7 +240,7 @@ sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length)) /* Very start of resource fork. */ psf_binheader_writef (psf, "E444", BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ; - psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name.c)) ; + psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name)) ; psf_binheader_writef (psf, "Eo2mm", BHWo (0x50), BHW2 (0), BHWm (Sd2f_MARKER), BHWm (lsf1_MARKER)) ; /* Very start of resource map. */ diff --git a/src/sds.c b/src/sds.c index 85c8c11f..6bc76171 100644 --- a/src/sds.c +++ b/src/sds.c @@ -281,7 +281,7 @@ sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++) { - bytesread += psf_fread (&marker, 1, 2, psf) ; + bytesread += (int) psf_fread (&marker, 1, 2, psf) ; if (marker == 0) break ; @@ -431,7 +431,7 @@ sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) return 1 ; } ; - if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; if (psds->read_data [0] != 0xF0) @@ -475,7 +475,7 @@ sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) return 1 ; } ; - if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; if (psds->read_data [0] != 0xF0) @@ -519,7 +519,7 @@ sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) return 1 ; } ; - if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; if (psds->read_data [0] != 0xF0) @@ -565,7 +565,7 @@ sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = sds_read (psf, psds, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = iptr [k] >> 16 ; @@ -611,7 +611,7 @@ sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = sds_read (psf, psds, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; @@ -643,7 +643,7 @@ sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { readcount = (len >= bufferlen) ? bufferlen : len ; + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = sds_read (psf, psds, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; @@ -794,7 +794,7 @@ sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; - if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; psds->write_block ++ ; @@ -836,7 +836,7 @@ sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; - if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; psds->write_block ++ ; @@ -879,7 +879,7 @@ sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; - if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; psds->write_block ++ ; @@ -908,7 +908,7 @@ sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = arith_shift_left (ptr [total + k], 16) ; count = sds_write (psf, psds, iptr, writecount) ; @@ -956,7 +956,7 @@ sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = normfact * ptr [total + k] ; count = sds_write (psf, psds, iptr, writecount) ; @@ -989,7 +989,7 @@ sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) iptr = ubuf.ibuf ; bufferlen = ARRAY_LEN (ubuf.ibuf) ; while (len > 0) - { writecount = (len >= bufferlen) ? bufferlen : len ; + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) iptr [k] = normfact * ptr [total + k] ; count = sds_write (psf, psds, iptr, writecount) ; diff --git a/src/sfendian.h b/src/sfendian.h index 9367a96d..ab02742b 100644 --- a/src/sfendian.h +++ b/src/sfendian.h @@ -24,6 +24,10 @@ #include #include +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + #if HAVE_BYTESWAP_H /* Linux, any CPU */ #include @@ -31,19 +35,11 @@ #define ENDSWAP_32(x) (bswap_32 (x)) #define ENDSWAP_64(x) (bswap_64 (x)) -#elif defined __has_builtin +#elif __has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64) -#if __has_builtin (__builtin_bswap16) #define ENDSWAP_16(x) ((int16_t) __builtin_bswap16 ((uint16_t) x)) -#endif - -#if __has_builtin (__builtin_bswap32) #define ENDSWAP_32(x) ((int32_t) __builtin_bswap32 ((uint32_t) x)) -#endif - -#if __has_builtin (__builtin_bswap64) #define ENDSWAP_64(x) ((int64_t) __builtin_bswap64 ((uint64_t) x)) -#endif #elif COMPILER_IS_GCC @@ -210,43 +206,39 @@ static inline int64_t psf_get_be64 (const uint8_t *ptr, int offset) { int64_t value ; - value = ((uint32_t) ptr [offset]) << 24 ; - value += ptr [offset + 1] << 16 ; - value += ptr [offset + 2] << 8 ; + value = (int64_t) ((uint64_t) ptr [offset] << 24) ; + value += (int64_t) ((uint64_t) ptr [offset + 1] << 16) ; + value += (int64_t) ((uint64_t) ptr [offset + 2] << 8) ; value += ptr [offset + 3] ; value = (int64_t) (((uint64_t) value) << 32) ; - value += ((uint32_t) ptr [offset + 4]) << 24 ; - value += ptr [offset + 5] << 16 ; - value += ptr [offset + 6] << 8 ; + value += (int64_t) ((uint64_t) ptr [offset + 4] << 24) ; + value += (int64_t) ((uint64_t) ptr [offset + 5] << 16) ; + value += (int64_t) ((uint64_t) ptr [offset + 6] << 8) ; value += ptr [offset + 7] ; return value ; } /* psf_get_be64 */ static inline int64_t psf_get_le64 (const uint8_t *ptr, int offset) -{ int64_t value ; - - value = ((uint32_t) ptr [offset + 7]) << 24 ; - value += ptr [offset + 6] << 16 ; - value += ptr [offset + 5] << 8 ; +{ int64_t value = (int64_t) ((uint64_t) ptr [offset + 7] << 24) ; + value += (int64_t) ((uint64_t) ptr [offset + 6] << 16) ; + value += (int64_t) ((uint64_t) ptr [offset + 5] << 8) ; value += ptr [offset + 4] ; value = (int64_t) (((uint64_t) value) << 32) ; - value += ((uint32_t) ptr [offset + 3]) << 24 ; - value += ptr [offset + 2] << 16 ; - value += ptr [offset + 1] << 8 ; + value += (int64_t) ((uint64_t) ptr [offset + 3] << 24) ; + value += (int64_t) ((uint64_t) ptr [offset + 2] << 16) ; + value += (int64_t) ((uint64_t) ptr [offset + 1] << 8) ; value += ptr [offset] ; return value ; } /* psf_get_le64 */ static inline int32_t psf_get_be32 (const uint8_t *ptr, int offset) -{ int32_t value ; - - value = ((uint32_t) ptr [offset]) << 24 ; +{ int32_t value = ((uint32_t) ptr [offset]) << 24 ; value += ptr [offset + 1] << 16 ; value += ptr [offset + 2] << 8 ; value += ptr [offset + 3] ; @@ -255,9 +247,7 @@ psf_get_be32 (const uint8_t *ptr, int offset) static inline int32_t psf_get_le32 (const uint8_t *ptr, int offset) -{ int32_t value ; - - value = ((uint32_t) ptr [offset + 3]) << 24 ; +{ int32_t value = ((uint32_t) ptr [offset + 3]) << 24 ; value += ptr [offset + 2] << 16 ; value += ptr [offset + 1] << 8 ; value += ptr [offset] ; @@ -266,9 +256,7 @@ psf_get_le32 (const uint8_t *ptr, int offset) static inline int32_t psf_get_be24 (const uint8_t *ptr, int offset) -{ int32_t value ; - - value = ((uint32_t) ptr [offset]) << 24 ; +{ int32_t value = ((uint32_t) ptr [offset]) << 24 ; value += ptr [offset + 1] << 16 ; value += ptr [offset + 2] << 8 ; return value ; @@ -276,9 +264,7 @@ psf_get_be24 (const uint8_t *ptr, int offset) static inline int32_t psf_get_le24 (const uint8_t *ptr, int offset) -{ int32_t value ; - - value = ((uint32_t) ptr [offset + 2]) << 24 ; +{ int32_t value = ((uint32_t) ptr [offset + 2]) << 24 ; value += ptr [offset + 1] << 16 ; value += ptr [offset] << 8 ; return value ; @@ -295,37 +281,35 @@ psf_get_be16 (const uint8_t *ptr, int offset) static inline void endswap_short_array (short *ptr, int len) -{ short temp ; - - while (--len >= 0) - { temp = ptr [len] ; - ptr [len] = ENDSWAP_16 (temp) ; +{ + for (int i = 0 ; i < len ; i++) + { short temp = ptr [i] ; + ptr [i] = ENDSWAP_16 (temp) ; } ; } /* endswap_short_array */ static inline void endswap_short_copy (short *dest, const short *src, int len) { - while (--len >= 0) - { dest [len] = ENDSWAP_16 (src [len]) ; + for (int i = 0 ; i < len ; i++) + { dest [i] = ENDSWAP_16 (src [i]) ; } ; } /* endswap_short_copy */ static inline void endswap_int_array (int *ptr, int len) -{ int temp ; - - while (--len >= 0) - { temp = ptr [len] ; - ptr [len] = ENDSWAP_32 (temp) ; +{ + for (int i = 0 ; i < len ; i++) + { int temp = ptr [i] ; + ptr [i] = ENDSWAP_32 (temp) ; } ; } /* endswap_int_array */ static inline void endswap_int_copy (int *dest, const int *src, int len) { - while (--len >= 0) - { dest [len] = ENDSWAP_32 (src [len]) ; + for (int i = 0 ; i < len ; i++) + { dest [i] = ENDSWAP_32 (src [i]) ; } ; } /* endswap_int_copy */ @@ -334,21 +318,19 @@ endswap_int_copy (int *dest, const int *src, int len) static inline void endswap_int64_t_array (int64_t *ptr, int len) -{ int64_t value ; - - while (--len >= 0) - { value = ptr [len] ; - ptr [len] = ENDSWAP_64 (value) ; +{ + for (int i = 0 ; i < len ; i++) + { int64_t value = ptr [i] ; + ptr [i] = ENDSWAP_64 (value) ; } ; } /* endswap_int64_t_array */ static inline void endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len) -{ int64_t value ; - - while (--len >= 0) - { value = src [len] ; - dest [len] = ENDSWAP_64 (value) ; +{ + for (int i = 0 ; i < len ; i++) + { int64_t value = src [i] ; + dest [i] = ENDSWAP_64 (value) ; } ; } /* endswap_int64_t_copy */ diff --git a/src/sndfile.c b/src/sndfile.c index 63beda8d..397740f0 100644 --- a/src/sndfile.c +++ b/src/sndfile.c @@ -33,6 +33,11 @@ #include #endif +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + #define SNDFILE_MAGICK 0x1234C0DE #ifdef __APPLE__ @@ -277,7 +282,18 @@ ErrorStruct SndfileErrors [] = { SFE_FILENAME_TOO_LONG , "Error : Supplied filename too long." }, { SFE_NEGATIVE_RW_LEN , "Error : Length parameter passed to read/write is negative." }, - { SFE_OPUS_BAD_SAMPLERATE , "Error : Opus only supports sample rates of 8000, 12000, 16000, 24000 and 48000." }, + { SFE_OPUS_BAD_SAMPLERATE , "Error : Opus only supports sample rates of 8000, 12000, 16000, 24000, and 48000." }, + + { SFE_MPEG_BAD_SAMPLERATE , "Error : MPEG-1/2/2.5 only supports sample rates of 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, and 48000." }, + + { SFE_CAF_NOT_CAF , "Error : Not a CAF file." }, + { SFE_CAF_NO_DESC , "Error : No 'desc' marker in CAF file." }, + { SFE_CAF_BAD_PEAK , "Error : Bad 'PEAK' chunk in CAF file." }, + + { SFE_AVR_NOT_AVR , "Error : Not an AVR file." }, + { SFE_AVR_BAD_REZ_SIGN , "Error : Bad rez/sign combination." }, + + { SFE_MPC_NO_MARKER , "Error : No marker in MPC2K file." }, { SFE_MAX_ERROR , "Maximum error number." }, { SFE_MAX_ERROR + 1 , NULL } @@ -291,7 +307,6 @@ static int guess_file_type (SF_PRIVATE *psf) ; static int validate_sfinfo (SF_INFO *sfinfo) ; static int validate_psf (SF_PRIVATE *psf) ; static void save_header_info (SF_PRIVATE *psf) ; -static int copy_filename (SF_PRIVATE *psf, const char *path) ; static int psf_close (SF_PRIVATE *psf) ; static int try_resource_fork (SF_PRIVATE * psf) ; @@ -332,6 +347,14 @@ static char sf_syserr [SF_SYSERR_LEN] = { 0 } ; SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) { SF_PRIVATE *psf ; + const char *utf8path_ptr ; +#ifdef _WIN32 + LPWSTR wpath ; + int nResult ; + int wpath_len ; + char utf8path [SF_FILENAME_LEN] ; + DWORD dwError ; +#endif /* Ultimate sanity check. */ assert (sizeof (sf_count_t) == 8) ; @@ -345,8 +368,62 @@ sf_open (const char *path, int mode, SF_INFO *sfinfo) psf_log_printf (psf, "File : %s\n", path) ; - if (copy_filename (psf, path) != 0) +#ifdef _WIN32 + nResult = MultiByteToWideChar (CP_ACP, 0, path, -1, NULL, 0) ; + if (nResult == 0) + { sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; + psf_close (psf) ; + return NULL ; + } ; + + wpath_len = nResult ; + wpath = malloc (wpath_len * sizeof (WCHAR)) ; + if (!wpath) + { sf_errno = SFE_MALLOC_FAILED ; + psf_close (psf) ; + return NULL ; + } ; + + nResult = MultiByteToWideChar (CP_ACP, 0, path, -1, wpath, wpath_len) ; + if (nResult == 0) + { sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; + free (wpath) ; + psf_close (psf) ; + return NULL ; + } ; + + nResult = WideCharToMultiByte (CP_UTF8, 0, wpath, wpath_len, NULL, 0, NULL, + NULL) ; + if (nResult == 0) + { sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; + free (wpath) ; + psf_close (psf) ; + return NULL ; + } ; + + nResult = WideCharToMultiByte (CP_UTF8, 0, wpath, wpath_len, utf8path, + SF_FILENAME_LEN, NULL, NULL) ; + + free (wpath) ; + + if (nResult == 0) + { dwError = GetLastError () ; + if (dwError == ERROR_INSUFFICIENT_BUFFER) + sf_errno = SFE_FILENAME_TOO_LONG ; + else + sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; + psf_close (psf) ; + return NULL ; + } ; + + utf8path_ptr = utf8path ; +#else + utf8path_ptr = path ; +#endif + + if (psf_copy_filename (psf, utf8path_ptr) != 0) { sf_errno = psf->error ; + psf_close (psf) ; return NULL ; } ; @@ -381,7 +458,7 @@ sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) } ; psf_init_files (psf) ; - copy_filename (psf, "") ; + psf_copy_filename (psf, "") ; psf->file.mode = mode ; psf_set_file (psf, fd) ; @@ -614,6 +691,8 @@ sf_format_check (const SF_INFO *info) if ((subformat == SF_FORMAT_NMS_ADPCM_16 || subformat == SF_FORMAT_NMS_ADPCM_24 || subformat == SF_FORMAT_NMS_ADPCM_32) && info->channels == 1) return 1 ; + if (subformat == SF_FORMAT_MPEG_LAYER_III && info->channels <= 2) + return 1 ; break ; case SF_FORMAT_WAVEX : @@ -884,6 +963,15 @@ sf_format_check (const SF_INFO *info) if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; break ; + + case SF_FORMAT_MPEG : + if (info->channels > 2) + return 0 ; + if (endian != SF_ENDIAN_FILE) + return 0 ; + if (subformat == SF_FORMAT_MPEG_LAYER_I || subformat == SF_FORMAT_MPEG_LAYER_II || subformat == SF_FORMAT_MPEG_LAYER_III) + return 1 ; + break ; default : break ; } ; @@ -1226,7 +1314,7 @@ sf_command (SNDFILE *sndfile, int command, void *data, int datasize) return SF_FALSE ; } ; - if (NOT (broadcast_var_set (psf, data, datasize))) + if (!broadcast_var_set (psf, data, datasize)) return SF_FALSE ; if (psf->write_header) @@ -1255,7 +1343,7 @@ sf_command (SNDFILE *sndfile, int command, void *data, int datasize) { psf->error = SFE_CMD_HAS_DATA ; return SF_FALSE ; } ; - if (NOT (cart_var_set (psf, data, datasize))) + if (!cart_var_set (psf, data, datasize)) return SF_FALSE ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; @@ -2612,7 +2700,7 @@ try_resource_fork (SF_PRIVATE * psf) } ; /* More checking here. */ - psf_log_printf (psf, "Resource fork : %s\n", psf->rsrc.path.c) ; + psf_log_printf (psf, "Resource fork : %s\n", psf->rsrc.path) ; return SF_FORMAT_SD2 ; } /* try_resource_fork */ @@ -2623,7 +2711,7 @@ format_from_extension (SF_PRIVATE *psf) char buffer [16] ; int format = 0 ; - if ((cptr = strrchr (psf->file.name.c, '.')) == NULL) + if ((cptr = strrchr (psf->file.name, '.')) == NULL) return 0 ; cptr ++ ; @@ -2668,6 +2756,13 @@ format_from_extension (SF_PRIVATE *psf) psf->sf.samplerate = 8000 ; format = SF_FORMAT_RAW | SF_FORMAT_GSM610 ; } + else if (strcmp (cptr, "mp3") == 0) + { /* + * MPEG streams are quite tollerate of crap. If we couldn't identify a + * MP3 stream, but it has a .mp3 extension, let libmpg123 have a try. + */ + format = SF_FORMAT_MPEG ; + } /* For RAW files, make sure the dataoffset if set correctly. */ if ((SF_CONTAINER (format)) == SF_FORMAT_RAW) @@ -2676,10 +2771,22 @@ format_from_extension (SF_PRIVATE *psf) return format ; } /* 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 ; +retry: if (psf_binheader_readf (psf, "b", &buffer, SIGNED_SIZEOF (buffer)) != SIGNED_SIZEOF (buffer)) { psf->error = SFE_BAD_FILE_READ ; return 0 ; @@ -2780,10 +2887,14 @@ guess_file_type (SF_PRIVATE *psf) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 4)) { psf_log_printf (psf, "Found 'ID3' marker.\n") ; if (id3_skip (psf)) - return guess_file_type (psf) ; + goto 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 ; @@ -2795,10 +2906,16 @@ guess_file_type (SF_PRIVATE *psf) 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 */ @@ -2809,7 +2926,7 @@ validate_sfinfo (SF_INFO *sfinfo) return 0 ; if (sfinfo->frames < 0) return 0 ; - if (sfinfo->channels < 1) + if ((sfinfo->channels < 1) || (sfinfo->channels > SF_MAX_CHANNELS)) return 0 ; if ((SF_CONTAINER (sfinfo->format)) == 0) return 0 ; @@ -2844,34 +2961,6 @@ save_header_info (SF_PRIVATE *psf) { snprintf (sf_parselog, sizeof (sf_parselog), "%s", psf->parselog.buf) ; } /* save_header_info */ -static int -copy_filename (SF_PRIVATE *psf, const char *path) -{ const char *ccptr ; - char *cptr ; - - if (strlen (path) > 1 && strlen (path) - 1 >= sizeof (psf->file.path.c)) - { psf->error = SFE_FILENAME_TOO_LONG ; - return psf->error ; - } ; - - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", path) ; - if ((ccptr = strrchr (path, '/')) || (ccptr = strrchr (path, '\\'))) - ccptr ++ ; - else - ccptr = path ; - - snprintf (psf->file.name.c, sizeof (psf->file.name.c), "%s", ccptr) ; - - /* Now grab the directory. */ - snprintf (psf->file.dir.c, sizeof (psf->file.dir.c), "%s", path) ; - if ((cptr = strrchr (psf->file.dir.c, '/')) || (cptr = strrchr (psf->file.dir.c, '\\'))) - cptr [1] = 0 ; - else - psf->file.dir.c [0] = 0 ; - - return 0 ; -} /* copy_filename */ - /*============================================================================== */ @@ -3185,6 +3274,10 @@ psf_open_file (SF_PRIVATE *psf, SF_INFO *sfinfo) error = mpc2k_open (psf) ; break ; + case SF_FORMAT_MPEG : + error = mpeg_open (psf) ; + break ; + /* Lite remove end */ default : @@ -3205,6 +3298,7 @@ psf_open_file (SF_PRIVATE *psf, SF_INFO *sfinfo) /* Actual embedded files. */ break ; + case SF_FORMAT_MPEG : case SF_FORMAT_FLAC : /* Flac with an ID3v2 header? */ break ; diff --git a/src/svx.c b/src/svx.c index 72d803f1..342b0062 100644 --- 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)) ; @@ -240,12 +240,12 @@ svx_read_header (SF_PRIVATE *psf) psf_log_printf (psf, " %M : %u\n", marker, chunk_size) ; - if (strlen (psf->file.name.c) != chunk_size) - { if (chunk_size > sizeof (psf->file.name.c) - 1) + if (strlen (psf->file.name) != chunk_size) + { if (chunk_size > sizeof (psf->file.name) - 1) return SFE_SVX_BAD_NAME_LENGTH ; - psf_binheader_readf (psf, "b", psf->file.name.c, chunk_size) ; - psf->file.name.c [chunk_size] = 0 ; + psf_binheader_readf (psf, "b", psf->file.name, chunk_size) ; + psf->file.name [chunk_size] = 0 ; } else psf_binheader_readf (psf, "j", chunk_size) ; @@ -307,7 +307,8 @@ svx_read_header (SF_PRIVATE *psf) if ((chunk_size = psf_ftell (psf)) & 0x03) { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", chunk_size - 4) ; - psf_binheader_readf (psf, "j", -3) ; + chunk_size = chunk_size & 3 ; + psf_binheader_readf (psf, "j", 4 - chunk_size) ; break ; } ; psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker, psf_ftell (psf) - 8) ; @@ -380,7 +381,7 @@ svx_write_header (SF_PRIVATE *psf, int calc_length) psf_binheader_writef (psf, "Em44", BHWm (CHAN_MARKER), BHW4 (4), BHW4 (6)) ; /* Filename and annotation strings. */ - psf_binheader_writef (psf, "Emsms", BHWm (NAME_MARKER), BHWs (psf->file.name.c), BHWm (ANNO_MARKER), BHWs (annotation)) ; + psf_binheader_writef (psf, "Emsms", BHWm (NAME_MARKER), BHWs (psf->file.name), BHWm (ANNO_MARKER), BHWs (annotation)) ; /* BODY marker and size. */ psf_binheader_writef (psf, "Etm8", BHWm (BODY_MARKER), BHW8 ((psf->datalength < 0) ? diff --git a/src/test_broadcast_var.c b/src/test_broadcast_var.c index dbea9431..5ae81fb1 100644 --- a/src/test_broadcast_var.c +++ b/src/test_broadcast_var.c @@ -89,7 +89,11 @@ test_broadcast_var_set (void) static void test_broadcast_var_zero (void) { SF_PRIVATE sf_private, *psf ; +#ifdef _MSC_VER SF_BROADCAST_INFO_VAR (0) bi ; +#else + SF_BROADCAST_INFO_VAR () bi ; +#endif psf = &sf_private ; memset (psf, 0, sizeof (sf_private)) ; diff --git a/src/test_conversions.c b/src/test_conversions.c index 329e2260..f717fa58 100644 --- a/src/test_conversions.c +++ b/src/test_conversions.c @@ -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 ; @@ -62,7 +62,7 @@ conversion_test (char endian) memset (psf, 0, sizeof (sf_private)) ; psf->file.mode = SFM_WRITE ; - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; + snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; if (psf_fopen (psf) != 0) { printf ("\n\nError : failed to open file '%s' for write.\n\n", filename) ; @@ -77,7 +77,7 @@ conversion_test (char endian) memset (psf, 0, sizeof (sf_private)) ; psf->file.mode = SFM_READ ; - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; + snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; if (psf_fopen (psf) != 0) { printf ("\n\nError : failed to open file '%s' for read.\n\n", filename) ; diff --git a/src/test_file_io.c b/src/test_file_io.c index 36a85b0c..1e5b0f56 100644 --- a/src/test_file_io.c +++ b/src/test_file_io.c @@ -73,7 +73,7 @@ file_open_test (const char *filename) } ; psf->file.mode = SFM_READ ; - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; + snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; /* Test that open for read fails if the file doesn't exist. */ error = psf_fopen (psf) ; @@ -91,7 +91,7 @@ file_open_test (const char *filename) test_close_or_die (psf, __LINE__) ; - unlink (psf->file.path.c) ; + unlink (psf->file.path) ; /* Test file open in read/write mode for a non-existant file. */ psf->file.mode = SFM_RDWR ; @@ -105,7 +105,7 @@ file_open_test (const char *filename) test_close_or_die (psf, __LINE__) ; - unlink (psf->file.path.c) ; + unlink (psf->file.path) ; puts ("ok") ; } /* file_open_test */ @@ -126,7 +126,7 @@ file_read_write_test (const char *filename) memset (&sf_data, 0, sizeof (sf_data)) ; psf = &sf_data ; - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; + snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; /* Test file open in write mode. */ psf->file.mode = SFM_WRITE ; @@ -282,7 +282,7 @@ file_truncate_test (const char *filename) memset (buffer, 0xEE, sizeof (buffer)) ; psf = &sf_data ; - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; + snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; /* ** Open the file write mode, write 0xEE data and then extend the file @@ -302,13 +302,13 @@ file_truncate_test (const char *filename) for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++) if (buffer [k] != 0xEE) - { printf ("\n\nLine %d : buffer [%d] = %d (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ; + { printf ("\n\nLine %d : buffer [%d] = %hhu (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ; exit (1) ; } ; for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++) if (buffer [k] != 0) - { printf ("\n\nLine %d : buffer [%d] = %d (should be 0)\n\n", __LINE__, k, buffer [k]) ; + { printf ("\n\nLine %d : buffer [%d] = %hhu (should be 0)\n\n", __LINE__, k, buffer [k]) ; exit (1) ; } ; @@ -339,7 +339,7 @@ file_seek_with_offset_test (const char *filename) memset (&sf_data, 0, sizeof (sf_data)) ; psf = &sf_data ; psf->file.mode = SFM_READ ; - snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; + snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; test_open_or_die (psf, __LINE__) ; /* Gather basic info before setting offset. */ diff --git a/src/test_log_printf.c b/src/test_log_printf.c index e1806a14..ada62377 100644 --- a/src/test_log_printf.c +++ b/src/test_log_printf.c @@ -113,6 +113,8 @@ test_log_printf (void) /* Test printing of strings. */ CMP_4_ARGS (__LINE__, errors, "B %s, %3s, %8s, %-8s", "str") ; + CMP_4_ARGS (__LINE__, errors, "B %.2s, %.8s, %-8.8s, %-4.2s", "str") ; + if (errors) { puts ("\nExiting due to errors.\n") ; exit (1) ; diff --git a/src/ulaw.c b/src/ulaw.c index 744e3541..ed2f8ff0 100644 --- a/src/ulaw.c +++ b/src/ulaw.c @@ -793,69 +793,69 @@ unsigned char ulaw_encode [8193] = static inline void ulaw2s_array (unsigned char *buffer, int count, short *ptr) -{ while (--count >= 0) - ptr [count] = ulaw_decode [(int) buffer [count]] ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = ulaw_decode [(int) buffer [i]] ; } /* ulaw2s_array */ static inline void ulaw2i_array (unsigned char *buffer, int count, int *ptr) -{ while (--count >= 0) - ptr [count] = ((uint32_t) ulaw_decode [buffer [count]]) << 16 ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = ((uint32_t) ulaw_decode [buffer [i]]) << 16 ; } /* ulaw2i_array */ static inline void ulaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) -{ while (--count >= 0) - ptr [count] = normfact * ulaw_decode [(int) buffer [count]] ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = normfact * ulaw_decode [(int) buffer [i]] ; } /* ulaw2f_array */ static inline void ulaw2d_array (const unsigned char *buffer, int count, double *ptr, double normfact) -{ while (--count >= 0) - ptr [count] = normfact * ulaw_decode [(int) buffer [count]] ; +{ for (int i = 0 ; i < count ; i++) + ptr [i] = normfact * ulaw_decode [(int) buffer [i]] ; } /* ulaw2d_array */ static inline void s2ulaw_array (const short *ptr, int count, unsigned char *buffer) -{ while (--count >= 0) - { if (ptr [count] >= 0) - buffer [count] = ulaw_encode [ptr [count] / 4] ; +{ for (int i = 0 ; i < count ; i++) + { if (ptr [i] >= 0) + buffer [i] = ulaw_encode [ptr [i] / 4] ; else - buffer [count] = 0x7F & ulaw_encode [ptr [count] / -4] ; + buffer [i] = 0x7F & ulaw_encode [ptr [i] / -4] ; } ; } /* s2ulaw_array */ static inline void i2ulaw_array (const int *ptr, int count, unsigned char *buffer) -{ while (--count >= 0) - { if (ptr [count] == INT_MIN) - buffer [count] = ulaw_encode [INT_MAX >> (16 + 2)] ; - else if (ptr [count] >= 0) - buffer [count] = ulaw_encode [ptr [count] >> (16 + 2)] ; +{ for (int i = 0 ; i < count ; i++) + { if (ptr [i] == INT_MIN) + buffer [i] = ulaw_encode [INT_MAX >> (16 + 2)] ; + else if (ptr [i] >= 0) + buffer [i] = ulaw_encode [ptr [i] >> (16 + 2)] ; else - buffer [count] = 0x7F & ulaw_encode [-ptr [count] >> (16 + 2)] ; + buffer [i] = 0x7F & ulaw_encode [-ptr [i] >> (16 + 2)] ; } ; } /* i2ulaw_array */ static inline void f2ulaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) -{ while (--count >= 0) - { if (ptr [count] >= 0) - buffer [count] = ulaw_encode [psf_lrintf (normfact * ptr [count])] ; +{ for (int i = 0 ; i < count ; i++) + { if (ptr [i] >= 0) + buffer [i] = ulaw_encode [psf_lrintf (normfact * ptr [i])] ; else - buffer [count] = 0x7F & ulaw_encode [- psf_lrintf (normfact * ptr [count])] ; + buffer [i] = 0x7F & ulaw_encode [- psf_lrintf (normfact * ptr [i])] ; } ; } /* f2ulaw_array */ static inline void d2ulaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) -{ while (--count >= 0) - { if (!isfinite (ptr [count])) - buffer [count] = 0 ; - else if (ptr [count] >= 0) - buffer [count] = ulaw_encode [psf_lrint (normfact * ptr [count])] ; +{ for (int i = 0 ; i < count ; i++) + { if (!isfinite (ptr [i])) + buffer [i] = 0 ; + else if (ptr [i] >= 0) + buffer [i] = ulaw_encode [psf_lrint (normfact * ptr [i])] ; else - buffer [count] = 0x7F & ulaw_encode [- psf_lrint (normfact * ptr [count])] ; + buffer [i] = 0x7F & ulaw_encode [- psf_lrint (normfact * ptr [i])] ; } ; } /* d2ulaw_array */ @@ -873,7 +873,7 @@ ulaw_read_ulaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; ulaw2s_array (ubuf.ucbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -895,7 +895,7 @@ ulaw_read_ulaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; ulaw2i_array (ubuf.ucbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -920,7 +920,7 @@ ulaw_read_ulaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; ulaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -944,7 +944,7 @@ ulaw_read_ulaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; ulaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -970,7 +970,7 @@ ulaw_write_s2ulaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -992,7 +992,7 @@ ulaw_write_i2ulaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1018,7 +1018,7 @@ ulaw_write_f2ulaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; f2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1044,7 +1044,7 @@ ulaw_write_d2ulaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; d2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; - writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; diff --git a/src/vox_adpcm.c b/src/vox_adpcm.c index 50c3d05d..e206675c 100644 --- a/src/vox_adpcm.c +++ b/src/vox_adpcm.c @@ -128,7 +128,7 @@ vox_read_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, short *ptr, int len) while (indx < len) { pvox->code_count = (len - indx > IMA_OKI_ADPCM_PCM_LEN) ? IMA_OKI_ADPCM_CODE_LEN : (len - indx + 1) / 2 ; - if ((k = psf_fread (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) + if ((k = (int) psf_fread (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) { if (psf_ftell (psf) != psf->filelength) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->code_count) ; if (k == 0) @@ -275,7 +275,7 @@ vox_write_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, const short *ptr, int len ima_oki_adpcm_encode_block (pvox) ; - if ((k = psf_fwrite (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) + if ((k = (int) psf_fwrite (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pvox->code_count) ; indx += pvox->pcm_count ; diff --git a/src/w64.c b/src/w64.c index 426480b6..14346cd2 100644 --- a/src/w64.c +++ b/src/w64.c @@ -241,7 +241,9 @@ w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) psf_binheader_readf (psf, "j", 8 - (psf->header.indx & 0x7)) ; /* Generate hash of 16 byte marker. */ - marker = chunk_size = 0 ; + marker = 0 ; + chunk_size = 0 ; + bytesread = psf_binheader_readf (psf, "eh8", &marker, &chunk_size) ; if (bytesread == 0) break ; diff --git a/src/wav.c b/src/wav.c index fd3e453f..80baf288 100644 --- a/src/wav.c +++ b/src/wav.c @@ -73,21 +73,24 @@ #define wvpk_MARKER (MAKE_MARKER ('w', 'v', 'p', 'k')) #define OggS_MARKER (MAKE_MARKER ('O', 'g', 'g', 'S')) +/* ID3v1 trailer which can show up at the end and erronerously look like a chunk. */ +#define TAG__MARKER (MAKE_MARKER ('T', 'A', 'G', 0)) +#define TAG__MARKER_MASK (MAKE_MARKER (0xff, 0xff, 0xff, 0)) + #define WAVLIKE_PEAK_CHUNK_SIZE(ch) (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int))) enum -{ HAVE_RIFF = 0x01, - HAVE_WAVE = 0x02, - HAVE_fmt = 0x04, - HAVE_fact = 0x08, - HAVE_PEAK = 0x10, - HAVE_data = 0x20, - HAVE_other = 0x80000000 +{ HAVE_RIFF = 1 << 0, + HAVE_WAVE = 1 << 1, + HAVE_fmt = 1 << 2, + HAVE_fact = 1 << 3, + HAVE_PEAK = 1 << 4, + HAVE_data = 1 << 5, + HAVE_other = 1 << 6 } ; - /* known WAVEFORMATEXTENSIBLE GUIDS */ static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } @@ -204,6 +207,14 @@ wav_open (SF_PRIVATE *psf) psf->sf.frames = 0 ; } ; +#if (ENABLE_EXPERIMENTAL_CODE == 0) + /* For now, don't support writing MPEGLAYER3 WAVs, as we can't guarentee that + ** such a file written by libsndfile would have the same length when opened again. + */ + if (subformat == SF_FORMAT_MPEG_LAYER_III) + return SFE_UNSUPPORTED_ENCODING ; +#endif + if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) { blockalign = wavlike_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = -1 ; /* Corrected later. */ @@ -274,6 +285,10 @@ wav_open (SF_PRIVATE *psf) error = gsm610_init (psf) ; break ; + case SF_FORMAT_MPEG_LAYER_III : + error = mpeg_init (psf, SF_BITRATE_MODE_CONSTANT, SF_FALSE) ; + break ; + default : return SFE_UNIMPLEMENTED ; } ; @@ -295,7 +310,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) @@ -605,6 +620,15 @@ wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) break ; } ; + if ((marker & TAG__MARKER_MASK) == TAG__MARKER && + psf_ftell (psf) - 8 + 128 == psf->filelength) + { psf_log_printf (psf, "*** Hit ID3v1 trailer. Exiting parser.\n") ; + chunk_size = 128 ; + done = SF_TRUE ; + parsestage |= HAVE_other ; + break ; + } ; + if (psf_isprint ((marker >> 24) & 0xFF) && psf_isprint ((marker >> 16) & 0xFF) && psf_isprint ((marker >> 8) & 0xFF) && psf_isprint (marker & 0xFF)) { psf_log_printf (psf, "*** %M : %u (unknown marker)\n", marker, chunk_size) ; @@ -683,8 +707,6 @@ wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) break ; case WAVE_FORMAT_NMS_VBXADPCM : - *blockalign = wav_fmt->min.blockalign ; - *framesperblock = 160 ; switch (wav_fmt->min.bitwidth) { case 2 : psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16 ; @@ -740,6 +762,12 @@ wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_G721_32 ; break ; + case WAVE_FORMAT_MPEGLAYER3 : + psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_MPEG_LAYER_III ; + if (parsestage & HAVE_fact) + psf->sf.frames = fact_chunk.frames ; + break ; + default : return SFE_UNIMPLEMENTED ; } ; @@ -924,6 +952,59 @@ wav_write_fmt_chunk (SF_PRIVATE *psf) add_fact_chunk = SF_TRUE ; break ; +#if (ENABLE_EXPERIMENTAL_CODE == 0) + case SF_FORMAT_MPEG_LAYER_III : + { int bytespersec, blockalign, flags, blocksize, samplesperblock, codecdelay ; + + /* Intended to be set as the average sample rate. + ** TODO: Maybe re-write this on close with final average + ** byterate? */ + bytespersec = psf->byterate (psf) ; + + /* Average block size. Info only I think. */ + blocksize = (1152 * bytespersec) / psf->sf.samplerate ; + + /* Can be set to block size IFF the block size is + ** constant, set to 1 otherwise. Constant sized + ** MPEG block streams are uncommon (CBR @ 32kHz and + ** 48kHz only. Meh. */ + blockalign = 1 ; + + /* TODO: Only flags defined are padding-type. I /think/ + ** Lame does ISO style padding by default, which has a + ** flag value of 0. + */ + flags = 0 ; + + /* Should only vary per MPEG 1.0/2.0 vs '2.5'. + ** TODO: Move this out to MPEG specific place? */ + samplesperblock = psf->sf.samplerate >= 32000 ? 1152 : 576 ; + + /* Set as 0 if unknown. + ** TODO: Plumb this cleanly from Lame. + */ + codecdelay = 0 ; + + /* fmt chunk. */ + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 2 + 2 + 2 ; + + /* fmt : size, WAV format type, channels. */ + psf_binheader_writef (psf, "422", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_MPEGLAYER3), BHW2 (psf->sf.channels)) ; + + /* fmt : samplerate, bytespersec. */ + psf_binheader_writef (psf, "44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ; + + /* fmt : blockalign, bitwidth, extrabytes, id. */ + psf_binheader_writef (psf, "2222", BHW2 (blockalign), BHW2 (0), BHW2 (12), BHW2 (1)) ; + + /* fmt : flags, blocksize, samplesperblock, codecdelay */ + psf_binheader_writef (psf, "4222", BHW4 (flags), BHW2 (blocksize), BHW2 (samplesperblock), BHW2 (codecdelay)) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; +#endif + default : return SFE_UNIMPLEMENTED ; } ; @@ -1325,8 +1406,9 @@ wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen) psf_log_printf (psf, " SMPTE Format : %u\n", dword) ; bytesread += psf_binheader_readf (psf, "4", &dword) ; - snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d %02d", - (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, (dword >> 8) & 0x7F, dword & 0x7F) ; + snprintf (buffer, sizeof (buffer), "%02"PRIu32 ":%02"PRIu32 ":%02"PRIu32 + " %02"PRIu32 "", (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, + (dword >> 8) & 0x7F, dword & 0x7F) ; psf_log_printf (psf, " SMPTE Offset : %s\n", buffer) ; bytesread += psf_binheader_readf (psf, "4", &loop_count) ; diff --git a/src/wavlike.c b/src/wavlike.c index b59c6847..7acdc80e 100644 --- a/src/wavlike.c +++ b/src/wavlike.c @@ -173,6 +173,7 @@ wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize) { switch (wav_fmt->format) { case WAVE_FORMAT_GSM610 : case WAVE_FORMAT_IPP_ITU_G_723_1 : + case WAVE_FORMAT_MPEGLAYER3 : psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; break ; default : @@ -183,7 +184,8 @@ wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize) { switch (wav_fmt->format) { case WAVE_FORMAT_GSM610 : case WAVE_FORMAT_IPP_ITU_G_723_1 : - psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; + case WAVE_FORMAT_MPEGLAYER3 : + psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; break ; default : psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; @@ -306,6 +308,23 @@ wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize) psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ; break ; + case WAVE_FORMAT_MPEGLAYER3 : + bytesread += psf_binheader_readf (psf, "24222", &(wav_fmt->mpeg3.extrabytes), + &(wav_fmt->mpeg3.id), &(wav_fmt->mpeg3.flags), &(wav_fmt->mpeg3.blocksize), + &(wav_fmt->mpeg3.samplesperblock), &(wav_fmt->mpeg3.codecdelay)) ; + + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->mpeg3.bytespersec) ; + psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->mpeg3.extrabytes) ; + if (wav_fmt->mpeg3.id != 1) + psf_log_printf (psf, " ID : %d (unknown, should be 1)\n", wav_fmt->mpeg3.id) ; + else + psf_log_printf (psf, " ID : MPEGLAYER3_ID_MPEG\n") ; + psf_log_printf (psf, " Flags : 0x%08x\n", wav_fmt->mpeg3.flags) ; + psf_log_printf (psf, " Block Size : %d\n", wav_fmt->mpeg3.blocksize) ; + psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->mpeg3.samplesperblock) ; + psf_log_printf (psf, " Codec Delay : %d samples\n", wav_fmt->mpeg3.codecdelay) ; + break ; + case WAVE_FORMAT_EXTENSIBLE : if (wav_fmt->ext.bytespersec != wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ; @@ -830,7 +849,11 @@ wavlike_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize) return 0 ; } ; - if (chunksize >= sizeof (SF_CART_INFO_16K)) + /* + ** SF_CART_INFO_16K has an extra field 'tag_text_size' that isn't part + ** of the chunk, so don't include it in the size check. + */ + if (chunksize >= sizeof (SF_CART_INFO_16K) - 4) { psf_log_printf (psf, "cart : %u too big to be handled\n", chunksize) ; psf_binheader_readf (psf, "j", chunksize) ; return 0 ; @@ -879,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 */ @@ -958,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 ; @@ -980,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 ; @@ -1006,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 ; } ; @@ -1022,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 ; } ; @@ -1053,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 ; } ; @@ -1064,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 ; } ; diff --git a/src/wavlike.h b/src/wavlike.h index 4cde1e93..686287d8 100644 --- a/src/wavlike.h +++ b/src/wavlike.h @@ -263,6 +263,21 @@ typedef struct unsigned short samplesperblock ; } GSM610_WAV_FMT ; +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short id ; + unsigned int flags ; + unsigned short blocksize ; + unsigned short samplesperblock ; + unsigned short codecdelay ; +} MPEGLAYER3_WAV_FMT ; + typedef struct { unsigned int esf_field1 ; unsigned short esf_field2 ; @@ -291,6 +306,7 @@ typedef union G72x_ADPCM_WAV_FMT g72x ; EXTENSIBLE_WAV_FMT ext ; GSM610_WAV_FMT gsm610 ; + MPEGLAYER3_WAV_FMT mpeg3 ; WAV_FMT_SIZE20 size20 ; char padding [512] ; } WAV_FMT ; diff --git a/src/windows.c b/src/windows.c index 2ef3002f..c11ed9b4 100644 --- a/src/windows.c +++ b/src/windows.c @@ -27,18 +27,16 @@ #if OS_IS_WIN32 #include -#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 #include "sndfile.h" #include "common.h" extern int sf_errno ; -static void copy_filename (SF_PRIVATE * psf, LPCWSTR wpath) ; - SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) { SF_PRIVATE *psf ; - char utf8name [512] ; + char utf8name [SF_BUFFER_LEN] ; + DWORD dwError ; if ((psf = psf_allocate ()) == NULL) { sf_errno = SFE_MALLOC_FAILED ; @@ -48,12 +46,20 @@ sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) psf_init_files (psf) ; if (WideCharToMultiByte (CP_UTF8, 0, wpath, -1, utf8name, sizeof (utf8name), NULL, NULL) == 0) - psf->file.path.wc [0] = 0 ; + { dwError = GetLastError () ; + if (dwError == ERROR_INSUFFICIENT_BUFFER) + sf_errno = SFE_FILENAME_TOO_LONG ; + else + sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; + + sf_close (psf) ; + + return NULL ; + } ; psf_log_printf (psf, "File : '%s' (utf-8 converted from ucs-2)\n", utf8name) ; - copy_filename (psf, wpath) ; - psf->file.use_wchar = SF_TRUE ; + psf_copy_filename (psf, utf8name) ; psf->file.mode = mode ; psf->error = psf_fopen (psf) ; @@ -61,32 +67,4 @@ sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) return psf_open_file (psf, sfinfo) ; } /* sf_wchar_open */ - -static void -copy_filename (SF_PRIVATE *psf, LPCWSTR wpath) -{ const wchar_t *cwcptr ; - wchar_t *wcptr ; - - wcsncpy (psf->file.path.wc, wpath, ARRAY_LEN (psf->file.path.wc)) ; - psf->file.path.wc [ARRAY_LEN (psf->file.path.wc) - 1] = 0 ; - if ((cwcptr = wcsrchr (wpath, '/')) || (cwcptr = wcsrchr (wpath, '\\'))) - cwcptr ++ ; - else - cwcptr = wpath ; - - wcsncpy (psf->file.name.wc, cwcptr, ARRAY_LEN (psf->file.name.wc)) ; - psf->file.name.wc [ARRAY_LEN (psf->file.name.wc) - 1] = 0 ; - - /* Now grab the directory. */ - wcsncpy (psf->file.dir.wc, wpath, ARRAY_LEN (psf->file.dir.wc)) ; - psf->file.dir.wc [ARRAY_LEN (psf->file.dir.wc) - 1] = 0 ; - - if ((wcptr = wcsrchr (psf->file.dir.wc, '/')) || (wcptr = wcsrchr (psf->file.dir.wc, '\\'))) - wcptr [1] = 0 ; - else - psf->file.dir.wc [0] = 0 ; - - return ; -} /* copy_filename */ - #endif diff --git a/src/xi.c b/src/xi.c index c102060f..e8169471 100644 --- a/src/xi.c +++ b/src/xi.c @@ -252,7 +252,7 @@ dpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (total > 0) { len = (total > bufferlen) ? bufferlen : total ; - total -= dpcm_read_dles2s (psf, ubuf.sbuf, len) ; + total -= (int) dpcm_read_dles2s (psf, ubuf.sbuf, len) ; } ; } else @@ -260,7 +260,7 @@ dpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) bufferlen = ARRAY_LEN (ubuf.sbuf) ; while (total > 0) { len = (total > bufferlen) ? bufferlen : total ; - total -= dpcm_read_dsc2s (psf, ubuf.sbuf, len) ; + total -= (int) dpcm_read_dsc2s (psf, ubuf.sbuf, len) ; } ; } ; @@ -312,10 +312,6 @@ xi_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) psf_binheader_writef (psf, "b", BHWv (pxi->sample_name), BHWz (sizeof (pxi->sample_name))) ; - - - - /* Header construction complete so write it out. */ psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; @@ -409,8 +405,6 @@ xi_read_header (SF_PRIVATE *psf) psf_log_printf (psf, " size : %d\n", sample_sizes [k]) ; - - psf_log_printf (psf, " loop\n begin : %d\n end : %d\n", loop_begin, loop_end) ; psf_log_printf (psf, " volume : %u\n f. tune : %d\n flags : 0x%02X ", @@ -522,7 +516,7 @@ dpcm_read_dsc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; dsc2s_array (pxi, ubuf.scbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -548,7 +542,7 @@ dpcm_read_dsc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; dsc2i_array (pxi, ubuf.scbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -577,7 +571,7 @@ dpcm_read_dsc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; dsc2f_array (pxi, ubuf.scbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -606,7 +600,7 @@ dpcm_read_dsc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; dsc2d_array (pxi, ubuf.scbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -635,7 +629,7 @@ dpcm_read_dles2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; dles2s_array (pxi, ubuf.sbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -661,7 +655,7 @@ dpcm_read_dles2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; dles2i_array (pxi, ubuf.sbuf, readcount, ptr + total) ; total += readcount ; if (readcount < bufferlen) @@ -690,7 +684,7 @@ dpcm_read_dles2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; dles2f_array (pxi, ubuf.sbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -719,7 +713,7 @@ dpcm_read_dles2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) while (len > 0) { if (len < bufferlen) bufferlen = (int) len ; - readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; dles2d_array (pxi, ubuf.sbuf, readcount, ptr + total, normfact) ; total += readcount ; if (readcount < bufferlen) @@ -760,7 +754,7 @@ dpcm_write_s2dsc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -786,7 +780,7 @@ dpcm_write_i2dsc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -815,7 +809,7 @@ dpcm_write_f2dsc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; f2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen, normfact) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -844,7 +838,7 @@ dpcm_write_d2dsc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; d2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen, normfact) ; - writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -871,7 +865,7 @@ dpcm_write_s2dles (SF_PRIVATE *psf, const short *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; s2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -897,7 +891,7 @@ dpcm_write_i2dles (SF_PRIVATE *psf, const int *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; i2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -926,7 +920,7 @@ dpcm_write_f2dles (SF_PRIVATE *psf, const float *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; f2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen, normfact) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -955,7 +949,7 @@ dpcm_write_d2dles (SF_PRIVATE *psf, const double *ptr, sf_count_t len) { if (len < bufferlen) bufferlen = (int) len ; d2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen, normfact) ; - writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; + writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; total += writecount ; if (writecount < bufferlen) break ; @@ -1227,4 +1221,3 @@ d2dles_array (XI_PRIVATE *pxi, const double *src, short *dest, int count, double pxi->last_16 = last_val ; } /* d2dles_array */ - diff --git a/tests/alaw_test.c b/tests/alaw_test.c index b928083c..01b3dc4f 100644 --- a/tests/alaw_test.c +++ b/tests/alaw_test.c @@ -49,7 +49,7 @@ main (void) print_test_name ("alaw_test", "encoder") ; - filename = "test.raw" ; + filename = "alaw_test.raw" ; sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ALAW, 44100, 1) ; diff --git a/tests/chunk_test.c b/tests/chunk_test.c index ed340643..0e358e81 100644 --- a/tests/chunk_test.c +++ b/tests/chunk_test.c @@ -38,8 +38,8 @@ #define LOG_BUFFER_SIZE 1024 static void chunk_test (const char *filename, int format) ; -static void wav_subchunk_test (size_t chunk_size) ; -static void large_free_test (const char *filename, int format, size_t chunk_size) ; +static void wav_subchunk_test (unsigned int chunk_size) ; +static void large_free_test (const char *filename, int format, unsigned int chunk_size) ; int main (int argc, char *argv []) @@ -133,7 +133,7 @@ chunk_test_helper (const char *filename, int format, const char * testdata) snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ; chunk_info.id_size = 4 ; chunk_info.data = strdup (testdata) ; - chunk_info.datalen = strlen (chunk_info.data) ; + chunk_info.datalen = (unsigned int) strlen (chunk_info.data) ; length_before = chunk_info.datalen ; @@ -224,7 +224,7 @@ multichunk_test_helper (const char *filename, int format, const char * testdata chunk_info.id_size = 4 ; chunk_info.data = strdup (testdata [i]) ; - chunk_info.datalen = strlen (chunk_info.data) ; + chunk_info.datalen = (unsigned int) strlen (chunk_info.data) ; length_before [i] = chunk_info.datalen ; @@ -316,7 +316,7 @@ chunk_test (const char *filename, int format) static void -wav_subchunk_test (size_t chunk_size) +wav_subchunk_test (unsigned int chunk_size) { SNDFILE * file ; SF_INFO sfinfo ; SF_CHUNK_INFO chunk_info ; @@ -325,7 +325,7 @@ wav_subchunk_test (size_t chunk_size) short audio [16] ; int err, value ; - snprintf (filename, sizeof (filename), "subchunk_%04d.wav", (int) chunk_size) ; + snprintf (filename, sizeof (filename), "subchunk_%04u.wav", chunk_size) ; print_test_name (__func__, filename) ; exit_if_true (sizeof (chunk_data) < chunk_size, "\n\nLine %d : sizeof (data) < chunk_size\n\n", __LINE__) ; @@ -353,7 +353,7 @@ wav_subchunk_test (size_t chunk_size) snprintf (chunk_info.id, sizeof (chunk_info.id), "LIST") ; chunk_info.id_size = 4 ; chunk_info.data = chunk_data ; - chunk_info.datalen = chunk_size ; + chunk_info.datalen = (unsigned int) chunk_size ; err = sf_set_chunk (file, &chunk_info) ; exit_if_true ( @@ -386,7 +386,7 @@ wav_subchunk_test (size_t chunk_size) } /* wav_subchunk_test */ static void -large_free_test (const char *filename, int format, size_t chunk_size) +large_free_test (const char *filename, int format, unsigned int chunk_size) { SNDFILE * file ; SF_INFO sfinfo ; SF_CHUNK_INFO chunk_info ; diff --git a/tests/command_test.c b/tests/command_test.c index 625d8e56..86cbcfb3 100644 --- a/tests/command_test.c +++ b/tests/command_test.c @@ -115,8 +115,8 @@ main (int argc, char *argv []) { /* Preliminary float/double normalisation tests. More testing ** is done in the program 'floating_point_test'. */ - float_norm_test ("float.wav") ; - double_norm_test ("double.wav") ; + float_norm_test ("cmd_float.wav") ; + double_norm_test ("cmd_double.wav") ; test_count ++ ; } ; @@ -239,9 +239,9 @@ float_norm_test (const char *filename) /* Create float_data with all values being less than 1.0. */ for (k = 0 ; k < BUFFER_LEN / 2 ; k++) - float_data [k] = (k + 5) / (2.0 * BUFFER_LEN) ; + float_data [k] = (k + 5) / (2.0f * BUFFER_LEN) ; for (k = BUFFER_LEN / 2 ; k < BUFFER_LEN ; k++) - float_data [k] = (k + 5) ; + float_data [k] = (float) (k + 5) ; if (! (file = sf_open (filename, SFM_WRITE, &sfinfo))) { printf ("Line %d: sf_open_write failed with error : ", __LINE__) ; @@ -252,7 +252,7 @@ float_norm_test (const char *filename) /* Normalisation is on by default so no need to do anything here. */ - if ((k = sf_write_float (file, float_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) + if ((k = (unsigned int) sf_write_float (file, float_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) { printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -260,7 +260,7 @@ float_norm_test (const char *filename) /* Turn normalisation off. */ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; - if ((k = sf_write_float (file, float_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) + if ((k = (unsigned int) sf_write_float (file, float_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) { printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -291,7 +291,7 @@ float_norm_test (const char *filename) } ; /* Read float_data and check that it is normalised (ie default). */ - if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) + if ((k = (unsigned int) sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -306,7 +306,7 @@ float_norm_test (const char *filename) sf_seek (file, 0, SEEK_SET) ; sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; - if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) + if ((k = (unsigned int) sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -321,7 +321,7 @@ float_norm_test (const char *filename) sf_seek (file, 0, SEEK_SET) ; sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_TRUE) ; - if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) + if ((k = (unsigned int) sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -369,7 +369,7 @@ double_norm_test (const char *filename) /* Normailsation is on by default so no need to do anything here. */ /*-sf_command (file, "set-norm-double", "true", 0) ;-*/ - if ((k = sf_write_double (file, double_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) + if ((k = (unsigned int) sf_write_double (file, double_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) { printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -377,7 +377,7 @@ double_norm_test (const char *filename) /* Turn normalisation off. */ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ; - if ((k = sf_write_double (file, double_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) + if ((k = (unsigned int) sf_write_double (file, double_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) { printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -407,7 +407,7 @@ double_norm_test (const char *filename) } ; /* Read double_data and check that it is normalised (ie default). */ - if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) + if ((k = (unsigned int) sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -422,7 +422,7 @@ double_norm_test (const char *filename) sf_seek (file, 0, SEEK_SET) ; sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ; - if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) + if ((k = (unsigned int) sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -437,7 +437,7 @@ double_norm_test (const char *filename) sf_seek (file, 0, SEEK_SET) ; sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ; - if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) + if ((k = (unsigned int) sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; exit (1) ; } ; @@ -532,7 +532,7 @@ format_tests (void) /* Now test subtype formats. */ sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ; - if (count < 0 || count > 30) + if (count < 0 || count > 33) { printf ("Line %d: Weird count.\n", __LINE__) ; exit (1) ; } ; @@ -1021,7 +1021,7 @@ cue_test_var (const char *filename, int filetype, int count) sfinfo.channels = 1 ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; - if (sf_command (file, SFC_SET_CUE, write_cue, cues_size) == SF_FALSE) + if (sf_command (file, SFC_SET_CUE, write_cue, (int) cues_size) == SF_FALSE) { printf ("\n\nLine %d : sf_command (SFC_SET_CUE) failed with %d cues, datasize %zu --> error: %s\n\n", __LINE__, count, cues_size, sf_strerror (file)) ; exit (1) ; } ; @@ -1032,7 +1032,7 @@ cue_test_var (const char *filename, int filetype, int count) file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; - if (sf_command (file, SFC_GET_CUE, read_cue, cues_size) == SF_FALSE) + if (sf_command (file, SFC_GET_CUE, read_cue, (int) cues_size) == SF_FALSE) { printf ("\n\nLine %d : sf_command (SFC_GET_CUE) failed with %d cues, datasize %zu --> error: %s\n\n", __LINE__, count, cues_size, sf_strerror (file)) ; exit (1) ; } ; @@ -1351,7 +1351,7 @@ broadcast_coding_history_test (const char *filename) exit (1) ; } ; - bc_write.coding_history_size = strlen (supplied_history) ; + bc_write.coding_history_size = (uint32_t) strlen (supplied_history) ; bc_write.coding_history_size = snprintf (bc_write.coding_history, sizeof (bc_write.coding_history), "%s", supplied_history) ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; @@ -1423,7 +1423,7 @@ broadcast_coding_history_size (const char *filename) for (k = 0 ; bc_write.coding_history_size < 512 ; k++) { snprintf (bc_write.coding_history + bc_write.coding_history_size, sizeof (bc_write.coding_history) - bc_write.coding_history_size, "line %4d\n", k) ; - bc_write.coding_history_size = strlen (bc_write.coding_history) ; + bc_write.coding_history_size = (uint32_t) strlen (bc_write.coding_history) ; } ; exit_if_true (bc_write.coding_history_size < 512, @@ -1493,7 +1493,7 @@ cart_test (const char *filename, int filetype) ca_write.level_reference = 42 ; snprintf (ca_write.url, sizeof (ca_write.url), "http://www.test.com/test_url") ; snprintf (ca_write.tag_text, sizeof (ca_write.tag_text), "tag text test! \r\n") ; // must be terminated \r\n to be valid - ca_write.tag_text_size = strlen (ca_write.tag_text) ; + ca_write.tag_text_size = (uint32_t) strlen (ca_write.tag_text) ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; if (sf_command (file, SFC_SET_CART_INFO, &ca_write, sizeof (ca_write)) == SF_FALSE) @@ -1652,7 +1652,7 @@ cart_rdwr_test (const char *filename, int filetype) cinfo.level_reference = 42 ; snprintf (cinfo.url, sizeof (cinfo.url), "http://www.test.com/test_url") ; snprintf (cinfo.tag_text, sizeof (cinfo.tag_text), "tag text test!\r\n") ; - cinfo.tag_text_size = strlen (cinfo.tag_text) ; + cinfo.tag_text_size = (uint32_t) strlen (cinfo.tag_text) ; file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ; frames = sfinfo.frames ; diff --git a/tests/compression_size_test.c b/tests/compression_size_test.c index c8f43c81..b7dae300 100644 --- a/tests/compression_size_test.c +++ b/tests/compression_size_test.c @@ -37,6 +37,8 @@ #define SAMPLE_RATE 16000 #define DATA_LENGTH (SAMPLE_RATE) +static const char CMP_TEST_PREFIX[] = "cmp" ; + static float data_out [DATA_LENGTH] ; static inline float @@ -53,6 +55,8 @@ vorbis_test (void) float max_abs = 0.0 ; unsigned k ; + get_unique_test_name (&filename, CMP_TEST_PREFIX) ; + print_test_name ("vorbis_test", filename) ; /* Generate float data. */ @@ -98,7 +102,7 @@ vorbis_test (void) sf_close (file) ; for (k = 0 ; k < ARRAY_LEN (float_data) ; k ++) - max_abs = max_float (max_abs, fabs (float_data [k])) ; + max_abs = max_float (max_abs, fabsf (float_data [k])) ; exit_if_true (max_abs > 1.023, "\n\nLine %d : max_abs %f should be < 1.023.\n\n", __LINE__, max_abs) ; @@ -123,6 +127,8 @@ compression_size_test (int format, const char * filename) double quality ; int k ; + get_unique_test_name (&filename, CMP_TEST_PREFIX) ; + snprintf (q3_fname, sizeof (q3_fname), "q3_%s", filename) ; snprintf (q6_fname, sizeof (q6_fname), "q6_%s", filename) ; @@ -154,8 +160,8 @@ compression_size_test (int format, const char * filename) sf_close (q3_file) ; sf_close (q6_file) ; - q3_size = file_length (q3_fname) ; - q6_size = file_length (q6_fname) ; + q3_size = (int) file_length (q3_fname) ; + q6_size = (int) file_length (q6_fname) ; exit_if_true (q3_size >= q6_size, "\n\nLine %d : q3 size (%d) >= q6 size (%d)\n\n", __LINE__, q3_size, q6_size) ; @@ -178,33 +184,50 @@ main (int argc, char *argv []) " vorbis - test Ogg/Vorbis\n" " flac - test FLAC\n" " opus - test Opus\n" + " mpeg - test mpeg\n" " all - perform all tests\n", argv [0]) ; exit (0) ; } ; - if (! HAVE_EXTERNAL_XIPH_LIBS) - { puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ; - return 0 ; - } ; - if (strcmp (argv [1], "all") == 0) all_tests = 1 ; if (all_tests || strcmp (argv [1], "vorbis") == 0) - { vorbis_test () ; - compression_size_test (SF_FORMAT_OGG | SF_FORMAT_VORBIS, "vorbis.oga") ; - tests ++ ; + { if (HAVE_EXTERNAL_XIPH_LIBS) + { vorbis_test () ; + compression_size_test (SF_FORMAT_OGG | SF_FORMAT_VORBIS, "vorbis.oga") ; + tests ++ ; + } + else + puts (" No Ogg Vorbis tests because support was not compiled in.") ; } ; if (all_tests || strcmp (argv [1], "flac") == 0) - { compression_size_test (SF_FORMAT_FLAC | SF_FORMAT_PCM_16, "pcm16.flac") ; - tests ++ ; + { if (HAVE_EXTERNAL_XIPH_LIBS) + { compression_size_test (SF_FORMAT_FLAC | SF_FORMAT_PCM_16, "pcm16.flac") ; + tests ++ ; + } + else + puts (" No FLAC tests because support was not compiled in.") ; } ; if (all_tests || strcmp (argv [1], "opus") == 0) - { compression_size_test (SF_FORMAT_OGG | SF_FORMAT_OPUS, "opus.opus") ; - tests ++ ; + { if (HAVE_EXTERNAL_XIPH_LIBS) + { compression_size_test (SF_FORMAT_OGG | SF_FORMAT_OPUS, "opus.opus") ; + tests ++ ; + } + else + puts (" No Opus tests because support was not compiled in.") ; + } ; + + if (all_tests || strcmp (argv [1], "mpeg") == 0) + { if (HAVE_MPEG) + { compression_size_test (SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, "mpeg.mp3") ; + tests ++ ; + } + else + puts (" No MPEG tests because support was not compiled in.") ; } ; return 0 ; diff --git a/tests/cpp_test.cc b/tests/cpp_test.cc index 6e39da6d..e05a7370 100644 --- a/tests/cpp_test.cc +++ b/tests/cpp_test.cc @@ -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) ; } ; diff --git a/tests/dwvw_test.c b/tests/dwvw_test.c index b2cae067..0c92f874 100644 --- a/tests/dwvw_test.c +++ b/tests/dwvw_test.c @@ -86,7 +86,7 @@ dwvw_test (const char *filename, int format, int bit_width) file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; - if ((k = sf_read_int (file, read_buf, BUFFER_SIZE)) != BUFFER_SIZE) + if ((k = (int) sf_read_int (file, read_buf, BUFFER_SIZE)) != BUFFER_SIZE) { printf ("Error (line %d) : Only read %d/%d.frames.\n", __LINE__, k, BUFFER_SIZE) ; exit (1) ; } diff --git a/tests/error_test.c b/tests/error_test.c index 2e348e47..9cdabf4e 100644 --- a/tests/error_test.c +++ b/tests/error_test.c @@ -29,10 +29,6 @@ #include "sf_unistd.h" #endif -#if OS_IS_WIN32 -#include -#endif - #include #include "utils.h" @@ -178,6 +174,45 @@ bad_wav_test (const char * filename) puts ("ok") ; } /* 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] ; @@ -213,19 +248,10 @@ error_close_test (void) if (sf_close (sndfile) == 0) { -#if OS_IS_WIN32 - OSVERSIONINFOEX osvi ; - - memset (&osvi, 0, sizeof (OSVERSIONINFOEX)) ; - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX) ; - - if (GetVersionEx ((OSVERSIONINFO *) &osvi)) - { printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ; - printf ("\nHowever, this is a known bug in version %d.%d of windows so we'll ignore it.\n\n", - (int) osvi.dwMajorVersion, (int) osvi.dwMinorVersion) ; - } ; -#else printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ; +#if OS_IS_WIN32 + printf ("\nHowever, this is a known bug on windows platform so we'll ignore it.\n\n") ; +#else exit (1) ; #endif } ; @@ -255,7 +281,7 @@ unrecognised_test (void) sndfile = sf_open (filename, SFM_READ, &sfinfo) ; exit_if_true (sndfile != NULL, - "\n\nLine %d : SNDFILE* pointer (%p) should ne NULL.\n", __LINE__, sndfile + "\n\nLine %d : SNDFILE* pointer (%p) should be NULL.\n", __LINE__, (void *) sndfile ) ; k = sf_error (sndfile) ; @@ -279,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 () ; diff --git a/tests/floating_point_test.tpl b/tests/floating_point_test.tpl index 7258fa23..9651391c 100644 --- a/tests/floating_point_test.tpl +++ b/tests/floating_point_test.tpl @@ -38,11 +38,13 @@ #define SAMPLE_RATE 16000 +static const char FPT_TEST_PREFIX[] = "fpt" ; + static void float_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ; static void double_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ; [+ FOR float_type +][+ FOR int_type +][+ FOR endian_type -+]static void [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename) ; ++]static void [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename, int replace_float) ; [+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type +] @@ -125,6 +127,10 @@ main (int argc, char *argv []) float_scaled_test ("opus.opus", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_OPUS, -32.0) ; #endif +#if HAVE_MPEG + float_scaled_test ("mpeg.mp3", allow_exit, SF_FALSE, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, -52.0) ; +#endif + float_scaled_test ("replace_float.raw", allow_exit, SF_TRUE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ; /*============================================================================== @@ -183,14 +189,18 @@ main (int argc, char *argv []) double_scaled_test ("opus.opus", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_OPUS, -32.0) ; #endif +#if HAVE_MPEG + double_scaled_test ("mpeg.mp3", allow_exit, SF_FALSE, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, -52.0) ; +#endif + double_scaled_test ("replace_double.raw", allow_exit, SF_TRUE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -201.0) ; putchar ('\n') ; /* Float int tests. */ -[+ FOR float_type +][+ FOR int_type +][+ FOR endian_type -+] [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +].au") ; -[+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type -+] +[+ FOR float_type +][+ FOR int_type +][+ FOR endian_type +] +[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +].au", SF_FALSE) ; +[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_replace.au", SF_TRUE) ; +[+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type +] return 0 ; } /* main */ @@ -206,6 +216,7 @@ float_scaled_test (const char *filename, int allow_exit, int replace_float, int double snr ; int byterate ; + get_unique_test_name (&filename, FPT_TEST_PREFIX) ; print_test_name ("float_scaled_test", filename) ; gen_windowed_sine_float (float_data, DFT_DATA_LENGTH, 0.9999) ; @@ -259,6 +270,7 @@ double_scaled_test (const char *filename, int allow_exit, int replace_float, int double snr ; int byterate ; + get_unique_test_name (&filename, FPT_TEST_PREFIX) ; print_test_name ("double_scaled_test", filename) ; gen_windowed_sine_double (double_data, DFT_DATA_LENGTH, 0.9999) ; @@ -311,12 +323,13 @@ double_scaled_test (const char *filename, int allow_exit, int replace_float, int [+ FOR float_type +][+ FOR int_type +][+ FOR endian_type +] static void -[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename) +[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename, int replace_float) { SNDFILE *file ; SF_INFO sfinfo ; int max ; unsigned k ; + get_unique_test_name (&filename, FPT_TEST_PREFIX) ; print_test_name ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test", filename) ; gen_windowed_sine_[+ (get "float_name") +] ([+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), 0.9999) ; @@ -328,10 +341,12 @@ static void sfinfo.format = [+ (get "end_type") +] | SF_FORMAT_AU | [+ (get "minor_type") +] ; file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; + sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ; test_write_[+ (get "float_name") +]_or_die (file, 0, [+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), __LINE__) ; sf_close (file) ; file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; + sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ; if (sfinfo.frames != ARRAY_LEN ([+ (get "float_name") +]_data)) { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%" PRId64 " should be %d)\n", __LINE__, sfinfo.frames, DFT_DATA_LENGTH) ; diff --git a/tests/format_check_test.c b/tests/format_check_test.c index 7ab71c9b..2e76679a 100644 --- a/tests/format_check_test.c +++ b/tests/format_check_test.c @@ -121,6 +121,16 @@ format_combo_test (void) __LINE__ ) ; + /* Only have decode, not encode support for MPEG Layer I and II */ + if (subtype_fmt_info.format == SF_FORMAT_MPEG_LAYER_I || + subtype_fmt_info.format == SF_FORMAT_MPEG_LAYER_II) + continue ; + + /* MPEG Layer III in WAV is decode only currently */ + if (subtype_fmt_info.format == SF_FORMAT_MPEG_LAYER_III && + major_fmt_info.format == SF_FORMAT_WAV) + continue ; + snprintf (filename, sizeof (filename), "format-check.%s", major_fmt_info.extension) ; sndfile = sf_open (filename, SFM_WRITE, &info) ; diff --git a/tests/generate.c b/tests/generate.c index 87efbb44..b49b2718 100644 --- a/tests/generate.c +++ b/tests/generate.c @@ -39,10 +39,10 @@ generate_file (const char * filename, int format, int len) output = calloc (len, sizeof (float)) ; - maxabs = crappy_snare (output, len, 0, 0.95, maxabs) ; - maxabs = crappy_snare (output, len, len / 4, 0.85, maxabs) ; - maxabs = crappy_snare (output, len, 2 * len / 4, 0.85, maxabs) ; - crappy_snare (output, len, 3 * len / 4, 0.85, maxabs) ; + maxabs = crappy_snare (output, len, 0, 0.95f, maxabs) ; + maxabs = crappy_snare (output, len, len / 4, 0.85f, maxabs) ; + maxabs = crappy_snare (output, len, 2 * len / 4, 0.85f, maxabs) ; + crappy_snare (output, len, 3 * len / 4, 0.85f, maxabs) ; write_mono_file (filename, format, 44100, output, len) ; @@ -51,24 +51,24 @@ generate_file (const char * filename, int format, int len) static inline float rand_float (void) -{ return rand () / (0.5 * RAND_MAX) - 1.0 ; +{ return rand () / (0.5f * (float) RAND_MAX) - 1.0f ; } /* rand_float */ static float crappy_snare (float *output, int len, int offset, float gain, float maxabs) { int k ; - float env = 0.0 ; + float env = 0.0f ; for (k = offset ; k < len && env < gain ; k++) - { env += 0.03 ; + { env += 0.03f ; output [k] += env * rand_float () ; - maxabs = SF_MAX (maxabs, fabs (output [k])) ; + maxabs = SF_MAX (maxabs, fabsf (output [k])) ; } ; for ( ; k < len && env > 1e-8 ; k++) - { env *= 0.995 ; + { env *= 0.995f ; output [k] += env * rand_float () ; - maxabs = SF_MAX (maxabs, fabs (output [k])) ; + maxabs = SF_MAX (maxabs, fabsf (output [k])) ; } ; return maxabs ; diff --git a/tests/header_test.tpl b/tests/header_test.tpl index f4dd5b5b..b02fbef8 100644 --- a/tests/header_test.tpl +++ b/tests/header_test.tpl @@ -106,7 +106,7 @@ main (int argc, char *argv []) update_seek_int_test ("header_int.aiff", SF_FORMAT_AIFF) ; update_seek_float_test ("header_float.aiff", SF_FORMAT_AIFF) ; update_seek_double_test ("header_double.aiff", SF_FORMAT_AIFF) ; - header_shrink_test ("header_shrink.wav", SF_FORMAT_AIFF) ; + header_shrink_test ("header_shrink.aiff", SF_FORMAT_AIFF) ; extra_header_test ("extra.aiff", SF_FORMAT_AIFF) ; test_count++ ; } ; diff --git a/tests/headerless_test.c b/tests/headerless_test.c index 059fa683..86aa6db9 100644 --- a/tests/headerless_test.c +++ b/tests/headerless_test.c @@ -44,11 +44,11 @@ main (void) { old_test () ; - headerless_test ("raw.vox", SF_FORMAT_VOX_ADPCM, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM) ; - headerless_test ("raw.gsm", SF_FORMAT_GSM610, SF_FORMAT_RAW | SF_FORMAT_GSM610) ; + headerless_test ("headerless.vox", SF_FORMAT_VOX_ADPCM, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM) ; + headerless_test ("headerless.gsm", SF_FORMAT_GSM610, SF_FORMAT_RAW | SF_FORMAT_GSM610) ; - headerless_test ("raw.snd", SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; - headerless_test ("raw.au" , SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; + headerless_test ("headerless.snd", SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; + headerless_test ("headerless.au" , SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; return 0 ; } /* main */ @@ -74,7 +74,7 @@ headerless_test (const char * filename, int format, int expected) file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; - if ((k = sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) + if ((k = (int) sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) { printf ("Line %d: sf_write_short failed with short write (%d => %d).\n", __LINE__, BUFFER_SIZE, k) ; fflush (stdout) ; puts (sf_strerror (file)) ; @@ -135,7 +135,7 @@ old_test (void) file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; - if ((k = sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) + if ((k = (int) sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) { printf ("Line %d: sf_write_short failed with short write (%d => %d).\n", __LINE__, BUFFER_SIZE, k) ; fflush (stdout) ; puts (sf_strerror (file)) ; @@ -168,7 +168,7 @@ old_test (void) check_log_buffer_or_die (file, __LINE__) ; - if ((k = sf_read_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) + if ((k = (int) sf_read_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) { printf ("Line %d: short read (%d).\n", __LINE__, k) ; exit (1) ; } ; diff --git a/tests/locale_test.c b/tests/locale_test.c index b2653016..932c72ef 100644 --- a/tests/locale_test.c +++ b/tests/locale_test.c @@ -34,7 +34,6 @@ #if OS_IS_WIN32 #include -#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 #endif #include "sndfile.h" diff --git a/tests/long_read_write_test.c b/tests/long_read_write_test.c index 48624687..0629caef 100644 --- a/tests/long_read_write_test.c +++ b/tests/long_read_write_test.c @@ -66,7 +66,7 @@ main (int argc, char *argv []) { int value = k / 32 ; int_data [k] = (value & 1 ? -1 : 1) * value ; short_data [k] = int_data [k] ; - float_data [k] = int_data [k] / 32000.0 ; + float_data [k] = int_data [k] / 32000.0f ; double_data [k] = int_data [k] / 32000.0 ; } diff --git a/tests/lossy_comp_test.c b/tests/lossy_comp_test.c index cca274cc..92803213 100644 --- a/tests/lossy_comp_test.c +++ b/tests/lossy_comp_test.c @@ -44,6 +44,8 @@ #define LCT_MAX(x, y) ((x) > (y) ? (x) : (y)) +static const char LCT_TEST_PREFIX[] = "lct" ; + static void lcomp_test_short (const char *filename, int filetype, int chan, double margin) ; static void lcomp_test_int (const char *filename, int filetype, int chan, double margin) ; static void lcomp_test_float (const char *filename, int filetype, int chan, double margin) ; @@ -651,6 +653,7 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi sf_count_t datalen ; short *orig, *data ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("lcomp_test_short", filename) ; datalen = BUFFER_SIZE / channels ; @@ -658,7 +661,7 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi data = data_buffer.s ; orig = orig_buffer.s ; - gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; for (k = 0 ; k < channels * datalen ; k++) orig [k] = (short) (orig_buffer.d [k]) ; @@ -709,7 +712,7 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi for (k = 0 ; k < datalen ; k++) { if (error_function (data [k], orig [k], margin)) { printf ("\n\nLine %d: Incorrect sample A (#%d : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ; - oct_save_short (orig, data, datalen) ; + oct_save_short (orig, data, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ; @@ -720,7 +723,7 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi exit (1) ; } ; - if ((k = sf_readf_short (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_readf_short (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, channels * sfinfo.frames - datalen, k) ; exit (1) ; @@ -744,7 +747,7 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi /* Now test sf_seek function. */ - if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -765,7 +768,7 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -777,23 +780,23 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_readf_short_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\n\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; - oct_save_short (orig, data, datalen) ; + oct_save_short (orig, data, (int) datalen) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_readf_short_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; @@ -803,13 +806,13 @@ lcomp_test_short (const char *filename, int filetype, int channels, double margi /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_readf_short (file, data, datalen)) != 0) + if ((k = (int) sf_readf_short (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_readf_short past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -838,6 +841,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) double scale, max_val ; int *orig, *data ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("lcomp_test_int", filename) ; datalen = BUFFER_SIZE / channels ; @@ -854,7 +858,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) data = data_buffer.i ; orig = orig_buffer.i ; - gen_signal_double (orig_buffer.d, max_val, channels, datalen) ; + gen_signal_double (orig_buffer.d, max_val, channels, (int) datalen) ; for (k = 0 ; k < channels * datalen ; k++) orig [k] = lrint (orig_buffer.d [k]) ; @@ -906,7 +910,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) for (k = 0 ; k < datalen ; k++) { if (error_function (data [k] / scale, orig [k] / scale, margin)) { printf ("\nLine %d: Incorrect sample (#%d : %f should be %f).\n", __LINE__, k, data [k] / scale, orig [k] / scale) ; - oct_save_int (orig, data, datalen) ; + oct_save_int (orig, data, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ; @@ -917,7 +921,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) exit (1) ; } ; - if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, channels * sfinfo.frames - datalen, k) ; exit (1) ; @@ -942,7 +946,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) /* Now test sf_seek function. */ - if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -963,7 +967,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %" PRId64 " failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -975,13 +979,13 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %" PRId64 ")\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_readf_int_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %" PRId64 ").\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; @@ -990,7 +994,7 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_readf_int_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %" PRId64 ").\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; @@ -1000,13 +1004,13 @@ lcomp_test_int (const char *filename, int filetype, int channels, double margin) /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_readf_int (file, data, datalen)) != 0) + if ((k = (int) sf_readf_int (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -1035,6 +1039,7 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi float *orig, *data ; double half_max_abs ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("lcomp_test_float", filename) ; datalen = BUFFER_SIZE / channels ; @@ -1042,9 +1047,9 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi data = data_buffer.f ; orig = orig_buffer.f ; - gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; for (k = 0 ; k < channels * datalen ; k++) - orig [k] = orig_buffer.d [k] ; + orig [k] = (float) orig_buffer.d [k] ; sfinfo.samplerate = SAMPLE_RATE ; sfinfo.frames = 123456789 ; /* Ridiculous value. */ @@ -1100,7 +1105,7 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi for (k = 0 ; k < datalen ; k++) { if (error_function (data [k], orig [k], margin)) { printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ; - oct_save_float (orig, data, datalen) ; + oct_save_float (orig, data, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, fabs (0.5 * data [k])) ; @@ -1111,7 +1116,7 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi exit (1) ; } ; - if ((k = sf_readf_float (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_readf_float (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, channels * sfinfo.frames - datalen, k) ; exit (1) ; @@ -1136,7 +1141,7 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi /* Now test sf_seek function. */ - if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -1157,7 +1162,7 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -1169,22 +1174,22 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_readf_float_or_die (file, 0, data, 1, __LINE__) ; if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_readf_float_or_die (file, 0, data, 1, __LINE__) ; if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; @@ -1194,13 +1199,13 @@ lcomp_test_float (const char *filename, int filetype, int channels, double margi /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_readf_float (file, data, datalen)) != 0) + if ((k = (int) sf_readf_float (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_readf_float past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -1229,6 +1234,7 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg double *orig, *data ; double half_max_abs ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("lcomp_test_double", filename) ; datalen = BUFFER_SIZE / channels ; @@ -1236,7 +1242,7 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg data = data_buffer.d ; orig = orig_buffer.d ; - gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; for (k = 0 ; k < channels * datalen ; k++) orig [k] = orig_buffer.d [k] ; @@ -1294,7 +1300,7 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg for (k = 0 ; k < datalen ; k++) { if (error_function (data [k], orig [k], margin)) { printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ; - oct_save_double (orig, data, datalen) ; + oct_save_double (orig, data, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k])) ; @@ -1305,7 +1311,7 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg exit (1) ; } ; - if ((k = sf_readf_double (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_readf_double (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, channels * sfinfo.frames - datalen, k) ; exit (1) ; @@ -1330,7 +1336,7 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg /* Now test sf_seek function. */ - if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -1351,7 +1357,7 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -1363,22 +1369,22 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_readf_double_or_die (file, 0, data, 1, __LINE__) ; if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_readf_double_or_die (file, 0, data, 1, __LINE__) ; if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; @@ -1388,13 +1394,13 @@ lcomp_test_double (const char *filename, int filetype, int channels, double marg /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_readf_double (file, data, datalen)) != 0) + if ((k = (int) sf_readf_double (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_readf_double past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -1424,6 +1430,8 @@ sdlcomp_test_short (const char *filename, int filetype, int channels, double mar short *orig, *data, *smooth ; channels = 1 ; + + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("sdlcomp_test_short", filename) ; datalen = BUFFER_SIZE ; @@ -1432,9 +1440,9 @@ channels = 1 ; data = data_buffer.s ; smooth = smooth_buffer.s ; - gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; for (k = 0 ; k < datalen ; k++) - orig [k] = lrint (orig_buffer.d [k]) ; + orig [k] = (short) lrint (orig_buffer.d [k]) ; sfinfo.samplerate = SAMPLE_RATE ; sfinfo.frames = 123456789 ; /* Ridiculous value. */ @@ -1470,6 +1478,7 @@ channels = 1 ; if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) { sf_close (file) ; + unlink (filename) ; return ; } ; @@ -1513,17 +1522,17 @@ channels = 1 ; test_readf_short_or_die (file, 0, data, datalen, __LINE__) ; memcpy (smooth, orig, datalen * sizeof (short)) ; - smoothed_diff_short (data, datalen) ; - smoothed_diff_short (smooth, datalen) ; + smoothed_diff_short (data, (unsigned int) datalen) ; + smoothed_diff_short (smooth, (unsigned int) datalen) ; - half_max_abs = 0.0 ; + half_max_abs = 0 ; for (k = 0 ; k < datalen ; k++) { if (error_function (1.0 * data [k], 1.0 * smooth [k], margin)) { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ; - oct_save_short (orig, smooth, datalen) ; + oct_save_short (orig, smooth, (int) datalen) ; exit (1) ; } ; - half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k])) ; + half_max_abs = (int) (LCT_MAX (half_max_abs, ABS (0.5 * data [k]))) ; } ; if (half_max_abs < 1) @@ -1531,7 +1540,7 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_read_short (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_read_short (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; exit (1) ; } ; @@ -1546,7 +1555,7 @@ channels = 1 ; /* Now test sf_seek function. */ if (sfinfo.seekable) - { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -1554,9 +1563,9 @@ channels = 1 ; for (m = 0 ; m < 3 ; m++) { test_readf_short_or_die (file, m, data, datalen / 7, __LINE__) ; - smoothed_diff_short (data, datalen / 7) ; + smoothed_diff_short (data, (unsigned int) (datalen / 7)) ; memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (short)) ; - smoothed_diff_short (smooth, datalen / 7) ; + smoothed_diff_short (smooth, (unsigned int) (datalen / 7)) ; for (k = 0 ; k < datalen / 7 ; k++) if (error_function (1.0 * data [k], 1.0 * smooth [k], margin)) @@ -1571,7 +1580,7 @@ channels = 1 ; seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -1582,22 +1591,22 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_readf_short_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_readf_short_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; @@ -1607,14 +1616,14 @@ channels = 1 ; /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_read_short (file, data, datalen)) != 0) + if ((k = (int) sf_read_short (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_read_short past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -1643,6 +1652,7 @@ sdlcomp_test_int (const char *filename, int filetype, int channels, double margi channels = 1 ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("sdlcomp_test_int", filename) ; datalen = BUFFER_SIZE ; @@ -1652,7 +1662,7 @@ channels = 1 ; data = data_buffer.i ; smooth = smooth_buffer.i ; - gen_signal_double (orig_buffer.d, 32000.0 * scale, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0 * scale, channels, (int) datalen) ; for (k = 0 ; k < datalen ; k++) orig [k] = lrint (orig_buffer.d [k]) ; @@ -1690,6 +1700,7 @@ channels = 1 ; if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) { sf_close (file) ; + unlink (filename) ; return ; } ; @@ -1729,14 +1740,14 @@ channels = 1 ; test_readf_int_or_die (file, 0, data, datalen, __LINE__) ; memcpy (smooth, orig, datalen * sizeof (int)) ; - smoothed_diff_int (data, datalen) ; - smoothed_diff_int (smooth, datalen) ; + smoothed_diff_int (data, (unsigned int) datalen) ; + smoothed_diff_int (smooth, (unsigned int) datalen) ; half_max_abs = abs (data [0] >> 16) ; for (k = 1 ; k < datalen ; k++) { if (error_function (data [k] / scale, smooth [k] / scale, margin)) { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ; - oct_save_int (orig, smooth, datalen) ; + oct_save_int (orig, smooth, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ; @@ -1747,7 +1758,7 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; exit (1) ; } ; @@ -1768,7 +1779,7 @@ channels = 1 ; /* Now test sf_seek function. */ if (sfinfo.seekable) - { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -1776,9 +1787,9 @@ channels = 1 ; for (m = 0 ; m < 3 ; m++) { test_readf_int_or_die (file, m, data, datalen / 7, __LINE__) ; - smoothed_diff_int (data, datalen / 7) ; + smoothed_diff_int (data, (unsigned int) (datalen / 7)) ; memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (int)) ; - smoothed_diff_int (smooth, datalen / 7) ; + smoothed_diff_int (smooth, (unsigned int) (datalen / 7)) ; for (k = 0 ; k < datalen / 7 ; k++) if (error_function (data [k] / scale, smooth [k] / scale, margin)) @@ -1793,7 +1804,7 @@ channels = 1 ; seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -1804,22 +1815,22 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_readf_int_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_readf_int_or_die (file, 0, data, 1, __LINE__) ; if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; @@ -1829,14 +1840,14 @@ channels = 1 ; /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_readf_int (file, data, datalen)) != 0) + if ((k = (int) sf_readf_int (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -1865,6 +1876,7 @@ sdlcomp_test_float (const char *filename, int filetype, int channels, double mar channels = 1 ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("sdlcomp_test_float", filename) ; switch ((filetype & SF_FORMAT_SUBMASK)) @@ -1896,9 +1908,9 @@ channels = 1 ; data = data_buffer.f ; smooth = smooth_buffer.f ; - gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, (int) datalen) ; for (k = 0 ; k < datalen ; k++) - orig [k] = orig_buffer.d [k] ; + orig [k] = (float) orig_buffer.d [k] ; sfinfo.samplerate = SAMPLE_RATE ; sfinfo.frames = 123456789 ; /* Ridiculous value. */ @@ -1935,6 +1947,7 @@ channels = 1 ; if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) { sf_close (file) ; + unlink (filename) ; return ; } ; @@ -1979,14 +1992,14 @@ channels = 1 ; test_read_float_or_die (file, 0, data, datalen, __LINE__) ; memcpy (smooth, orig, datalen * sizeof (float)) ; - smoothed_diff_float (data, datalen) ; - smoothed_diff_float (smooth, datalen) ; + smoothed_diff_float (data, (unsigned int) datalen) ; + smoothed_diff_float (smooth, (unsigned int) datalen) ; half_max_abs = fabs (data [0]) ; for (k = 1 ; k < datalen ; k++) { if (error_function (data [k] * scale, smooth [k] * scale, margin)) { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) (data [k] * scale), (int) (smooth [k] * scale)) ; - oct_save_float (orig, smooth, datalen) ; + oct_save_float (orig, smooth, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k] * scale)) ; @@ -1998,7 +2011,7 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_read_float (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_read_float (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; exit (1) ; } ; @@ -2013,7 +2026,7 @@ channels = 1 ; /* Now test sf_seek function. */ if (sfinfo.seekable) - { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -2021,9 +2034,9 @@ channels = 1 ; for (m = 0 ; m < 3 ; m++) { test_read_float_or_die (file, 0, data, datalen / 7, __LINE__) ; - smoothed_diff_float (data, datalen / 7) ; + smoothed_diff_float (data, (unsigned int) (datalen / 7)) ; memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (float)) ; - smoothed_diff_float (smooth, datalen / 7) ; + smoothed_diff_float (smooth, (unsigned int) (datalen / 7)) ; for (k = 0 ; k < datalen / 7 ; k++) if (error_function (data [k] * scale, smooth [k] * scale, margin)) @@ -2038,7 +2051,7 @@ channels = 1 ; seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -2049,22 +2062,22 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_read_float_or_die (file, 0, data, channels, __LINE__) ; if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_read_float_or_die (file, 0, data, channels, __LINE__) ; if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos) ; @@ -2074,14 +2087,14 @@ channels = 1 ; /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_read_float (file, data, datalen)) != 0) + if ((k = (int) sf_read_float (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_read_float past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -2108,6 +2121,8 @@ sdlcomp_test_double (const char *filename, int filetype, int channels, double ma double *orig, *data, *smooth, half_max_abs, scale ; channels = 1 ; + + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("sdlcomp_test_double", filename) ; switch ((filetype & SF_FORMAT_SUBMASK)) @@ -2139,7 +2154,7 @@ channels = 1 ; data = data_buffer.d ; smooth = smooth_buffer.d ; - gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, (int) datalen) ; sfinfo.samplerate = SAMPLE_RATE ; sfinfo.frames = 123456789 ; /* Ridiculous value. */ @@ -2175,6 +2190,7 @@ channels = 1 ; if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) { sf_close (file) ; + unlink (filename) ; return ; } ; @@ -2221,14 +2237,14 @@ channels = 1 ; test_read_double_or_die (file, 0, data, datalen, __LINE__) ; memcpy (smooth, orig, datalen * sizeof (double)) ; - smoothed_diff_double (data, datalen) ; - smoothed_diff_double (smooth, datalen) ; + smoothed_diff_double (data, (unsigned int) datalen) ; + smoothed_diff_double (smooth, (unsigned int) datalen) ; half_max_abs = 0.0 ; for (k = 0 ; k < datalen ; k++) { if (error_function (data [k] * scale, smooth [k] * scale, margin)) { printf ("\n\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) (data [k] * scale), (int) (smooth [k] * scale)) ; - oct_save_double (orig, smooth, datalen) ; + oct_save_double (orig, smooth, (int) datalen) ; exit (1) ; } ; half_max_abs = LCT_MAX (half_max_abs, 0.5 * fabs (data [k] * scale)) ; @@ -2239,7 +2255,7 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_read_double (file, data, datalen)) != sfinfo.frames - datalen) + if ((k = (int) sf_read_double (file, data, datalen)) != sfinfo.frames - datalen) { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; exit (1) ; } ; @@ -2254,7 +2270,7 @@ channels = 1 ; /* Now test sf_seek function. */ if (sfinfo.seekable) - { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) + { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; exit (1) ; } ; @@ -2262,9 +2278,9 @@ channels = 1 ; for (m = 0 ; m < 3 ; m++) { test_read_double_or_die (file, m, data, datalen / 7, __LINE__) ; - smoothed_diff_double (data, datalen / 7) ; + smoothed_diff_double (data, (unsigned int) (datalen / 7)) ; memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (double)) ; - smoothed_diff_double (smooth, datalen / 7) ; + smoothed_diff_double (smooth, (unsigned int) (datalen / 7)) ; for (k = 0 ; k < datalen / 7 ; k++) if (error_function (data [k] * scale, smooth [k] * scale, margin)) @@ -2279,7 +2295,7 @@ channels = 1 ; seekpos = BUFFER_SIZE / 10 ; /* Check seek from start of file. */ - if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) + if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; exit (1) ; } ; @@ -2290,22 +2306,22 @@ channels = 1 ; exit (1) ; } ; - if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) + if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; - k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; + k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; test_read_double_or_die (file, 0, data, channels, __LINE__) ; if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos + 1) ; exit (1) ; } ; - seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; + seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; /* Check seek backward from current position. */ - k = sf_seek (file, -20, SEEK_CUR) ; + k = (int) sf_seek (file, -20, SEEK_CUR) ; test_read_double_or_die (file, 0, data, channels, __LINE__) ; if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos) ; @@ -2315,14 +2331,14 @@ channels = 1 ; /* Check that read past end of file returns number of items. */ sf_seek (file, sfinfo.frames, SEEK_SET) ; - if ((k = sf_read_double (file, data, datalen)) != 0) + if ((k = (int) sf_read_double (file, data, datalen)) != 0) { printf ("\n\nLine %d: Return value from sf_read_double past end of file incorrect (%d).\n", __LINE__, k) ; exit (1) ; } ; /* Check seek backward from end. */ - if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) + if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; exit (1) ; } ; @@ -2348,6 +2364,7 @@ read_raw_test (const char *filename, int filetype, int channels) short *orig, *data ; int k ; + get_unique_test_name (&filename, LCT_TEST_PREFIX) ; print_test_name ("read_raw_test", filename) ; datalen = ARRAY_LEN (orig_buffer.s) / 2 ; @@ -2355,9 +2372,9 @@ read_raw_test (const char *filename, int filetype, int channels) orig = orig_buffer.s ; data = data_buffer.s ; - gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; + gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; for (k = 0 ; k < datalen ; k++) - orig [k] = lrint (orig_buffer.d [k]) ; + orig [k] = (short) lrint (orig_buffer.d [k]) ; sfinfo.samplerate = SAMPLE_RATE ; sfinfo.frames = 123456789 ; /* Ridiculous value. */ @@ -2516,7 +2533,7 @@ smoothed_diff_float (float *data, unsigned int datalen) /* Calculate the smoothed sample-to-sample difference. */ for (k = 0 ; k < datalen - 1 ; k++) - { memory = 0.7 * memory + (1 - 0.7) * (data [k+1] - data [k]) ; + { memory = (float) (0.7 * memory + (1 - 0.7) * (data [k+1] - data [k])) ; data [k] = memory ; } ; data [datalen-1] = data [datalen-2] ; diff --git a/tests/mpeg_test.c b/tests/mpeg_test.c new file mode 100644 index 00000000..fe7f53d1 --- /dev/null +++ b/tests/mpeg_test.c @@ -0,0 +1,348 @@ +/* +** Copyright (C) 2007-2019 Erik de Castro Lopo +** Copyright (C) 2019 John ffitch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#if HAVE_UNISTD_H +#include +#else +#include "sf_unistd.h" +#endif + +#include + +#include + +#include "utils.h" + +#define SAMPLE_RATE 44100 +#define DATA_LENGTH (SAMPLE_RATE / 8) + +typedef union +{ double d [DATA_LENGTH] ; + float f [DATA_LENGTH] ; + int i [DATA_LENGTH] ; + short s [DATA_LENGTH] ; +} BUFFER ; + +static BUFFER data_out ; +static BUFFER data_in ; + +static void +mpeg_short_test (void) +{ const char * filename = "mpeg_short.mp3" ; + + SNDFILE * file ; + SF_INFO sfinfo ; + short seek_data [10] ; + unsigned k ; + + print_test_name ("mpeg_short_test", filename) ; + + /* Generate float data. */ + gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7F00) ; + + /* Convert to shorteger. */ + for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++) + data_out.s [k] = lrintf (data_out.f [k]) ; + + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + /* Set up output file type. */ + sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; + sfinfo.channels = 1 ; + sfinfo.samplerate = SAMPLE_RATE ; + + /* Write the output file. */ + file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; + test_write_short_or_die (file, 0, data_out.s, ARRAY_LEN (data_out.s), __LINE__) ; + sf_close (file) ; + + /* Read the file in again. */ + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + test_read_short_or_die (file, 0, data_in.s, ARRAY_LEN (data_in.s), __LINE__) ; + sf_close (file) ; + + puts ("ok") ; + + /* Test seeking. */ + print_test_name ("mpeg_seek_test", filename) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + + test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; + test_read_short_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; + compare_short_or_die (seek_data, data_in.s + 10, ARRAY_LEN (seek_data), __LINE__) ; + + /* Test seek to end of file. */ + test_seek_or_die (file, 0, SEEK_END, sfinfo.frames, sfinfo.channels, __LINE__) ; + + sf_close (file) ; + + puts ("ok") ; + + unlink (filename) ; +} /* mpeg_short_test */ + +static void +mpeg_int_test (void) +{ const char * filename = "mpeg_int.mp3" ; + + SNDFILE * file ; + SF_INFO sfinfo ; + int seek_data [10] ; + unsigned k ; + + print_test_name ("mpeg_int_test", filename) ; + + /* Generate float data. */ + gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7FFF0000) ; + + /* Convert to integer. */ + for (k = 0 ; k < ARRAY_LEN (data_out.i) ; k++) + data_out.i [k] = lrintf (data_out.f [k]) ; + + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + /* Set up output file type. */ + sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; + sfinfo.channels = 1 ; + sfinfo.samplerate = SAMPLE_RATE ; + + /* Write the output file. */ + file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; + test_write_int_or_die (file, 0, data_out.i, ARRAY_LEN (data_out.i), __LINE__) ; + sf_close (file) ; + + /* Read the file in again. */ + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + test_read_int_or_die (file, 0, data_in.i, ARRAY_LEN (data_in.i), __LINE__) ; + sf_close (file) ; + + puts ("ok") ; + + /* Test seeking. */ + print_test_name ("mpeg_seek_test", filename) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + + test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; + test_read_int_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; + compare_int_or_die (seek_data, data_in.i + 10, ARRAY_LEN (seek_data), __LINE__) ; + + sf_close (file) ; + + puts ("ok") ; + + unlink (filename) ; +} /* mpeg_int_test */ + +static void +mpeg_float_test (void) +{ const char * filename = "mpeg_float.mp3" ; + + SNDFILE * file ; + SF_INFO sfinfo ; + float seek_data [10] ; + + print_test_name ("mpeg_float_test", filename) ; + + gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 0.95) ; + + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + /* Set up output file type. */ + sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; + sfinfo.channels = 1 ; + sfinfo.samplerate = SAMPLE_RATE ; + + /* Write the output file. */ + file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; + test_write_float_or_die (file, 0, data_out.f, ARRAY_LEN (data_out.f), __LINE__) ; + sf_close (file) ; + + /* Read the file in again. */ + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + test_read_float_or_die (file, 0, data_in.f, ARRAY_LEN (data_in.f), __LINE__) ; + sf_close (file) ; + + puts ("ok") ; + + /* Test seeking. */ + print_test_name ("mpeg_seek_test", filename) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + + test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; + test_read_float_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; + compare_float_or_die (seek_data, data_in.f + 10, ARRAY_LEN (seek_data), __LINE__) ; + + sf_close (file) ; + + puts ("ok") ; + + unlink (filename) ; +} /* mpeg_float_test */ + +static void +mpeg_double_test (void) +{ const char * filename = "mpeg_double.mp3" ; + + SNDFILE * file ; + SF_INFO sfinfo ; + double seek_data [10] ; + + print_test_name ("mpeg_double_test", filename) ; + + gen_windowed_sine_double (data_out.d, ARRAY_LEN (data_out.d), 0.95) ; + + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + /* Set up output file type. */ + sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; + sfinfo.channels = 1 ; + sfinfo.samplerate = SAMPLE_RATE ; + + /* Write the output file. */ + file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; + test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ; + sf_close (file) ; + + /* Read the file in again. */ + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + test_read_double_or_die (file, 0, data_in.d, ARRAY_LEN (data_in.d), __LINE__) ; + sf_close (file) ; + + puts ("ok") ; + + /* Test seeking. */ + print_test_name ("mpeg_seek_test", filename) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + + test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; + test_read_double_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; + compare_double_or_die (seek_data, data_in.d + 10, ARRAY_LEN (seek_data), __LINE__) ; + + sf_close (file) ; + + puts ("ok") ; + + unlink (filename) ; +} /* mpeg_double_test */ + + +static void +mpeg_stereo_seek_test (const char * filename, int format) +{ static float data [SAMPLE_RATE] ; + static float stereo_out [SAMPLE_RATE * 2] ; + + SNDFILE * file ; + SF_INFO sfinfo ; + sf_count_t pos ; + unsigned k ; + + print_test_name (__func__, filename) ; + + gen_windowed_sine_float (data, ARRAY_LEN (data), 0.95) ; + for (k = 0 ; k < ARRAY_LEN (data) ; k++) + { stereo_out [2 * k] = data [k] ; + stereo_out [2 * k + 1] = data [ARRAY_LEN (data) - k - 1] ; + } ; + + memset (&sfinfo, 0, sizeof (sfinfo)) ; + + /* Set up output file type. */ + sfinfo.format = format ; + sfinfo.channels = 2 ; + sfinfo.samplerate = SAMPLE_RATE ; + + /* Write the output file. */ + file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; + test_write_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ; + sf_close (file) ; + + /* Open file in again for reading. */ + memset (&sfinfo, 0, sizeof (sfinfo)) ; + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; + + /* Read in the whole file. */ + test_read_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ; + + /* Now hammer seeking code. */ + test_seek_or_die (file, 234, SEEK_SET, 234, sfinfo.channels, __LINE__) ; + test_readf_float_or_die (file, 0, data, 10, __LINE__) ; + compare_float_or_die (data, stereo_out + (234 * sfinfo.channels), 10, __LINE__) ; + + test_seek_or_die (file, 442, SEEK_SET, 442, sfinfo.channels, __LINE__) ; + test_readf_float_or_die (file, 0, data, 10, __LINE__) ; + compare_float_or_die (data, stereo_out + (442 * sfinfo.channels), 10, __LINE__) ; + + test_seek_or_die (file, 12, SEEK_CUR, 442 + 10 + 12, sfinfo.channels, __LINE__) ; + test_readf_float_or_die (file, 0, data, 10, __LINE__) ; + compare_float_or_die (data, stereo_out + ((442 + 10 + 12) * sfinfo.channels), 10, __LINE__) ; + + test_seek_or_die (file, 12, SEEK_CUR, 442 + 20 + 24, sfinfo.channels, __LINE__) ; + test_readf_float_or_die (file, 0, data, 10, __LINE__) ; + compare_float_or_die (data, stereo_out + ((442 + 20 + 24) * sfinfo.channels), 10, __LINE__) ; + + pos = 500 - sfinfo.frames ; + test_seek_or_die (file, pos, SEEK_END, 500, sfinfo.channels, __LINE__) ; + test_readf_float_or_die (file, 0, data, 10, __LINE__) ; + compare_float_or_die (data, stereo_out + (500 * sfinfo.channels), 10, __LINE__) ; + + pos = 10 - sfinfo.frames ; + test_seek_or_die (file, pos, SEEK_END, 10, sfinfo.channels, __LINE__) ; + test_readf_float_or_die (file, 0, data, 10, __LINE__) ; + compare_float_or_die (data, stereo_out + (10 * sfinfo.channels), 10, __LINE__) ; + + sf_close (file) ; + + puts ("ok") ; + unlink (filename) ; +} /* mpeg_stereo_seek_test */ + + +int +main (void) +{ + if (HAVE_MPEG) + { mpeg_short_test () ; + mpeg_int_test () ; + mpeg_float_test () ; + mpeg_double_test () ; + + mpeg_stereo_seek_test ("mpeg_seek.mp3", SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III) ; + } + else + puts (" No MPEG tests because mpg123/lame support was not compiled in.") ; + return 0 ; +} /* main */ + diff --git a/tests/multi_file_test.c b/tests/multi_file_test.c index 502d15a6..69069731 100644 --- a/tests/multi_file_test.c +++ b/tests/multi_file_test.c @@ -161,7 +161,7 @@ multi_file_test (const char *filename, int *formats, int format_count) printf ("This offset : %" PRId64 "\n", embed_info.offset + embed_info.length) ; } ; - if (lseek (fd, embed_info.offset + embed_info.length, SEEK_SET) < 0) + if (lseek (fd, (long) (embed_info.offset + embed_info.length), SEEK_SET) < 0) { printf ("\n\nLine %d: lseek failed : %s\n", __LINE__, strerror (errno)) ; exit (1) ; } ; diff --git a/tests/ogg_opus_test.c b/tests/ogg_opus_test.c index 37532bec..a850908c 100644 --- a/tests/ogg_opus_test.c +++ b/tests/ogg_opus_test.c @@ -62,7 +62,7 @@ ogg_opus_short_test (void) /* Convert to short. */ for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++) - data_out.s [k] = lrintf (data_out.f [k]) ; + data_out.s [k] = (short) lrintf (data_out.f [k]) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; diff --git a/tests/ogg_test.c b/tests/ogg_test.c index ba3d8992..dcc5ed19 100644 --- a/tests/ogg_test.c +++ b/tests/ogg_test.c @@ -62,7 +62,7 @@ ogg_short_test (void) /* Convert to shorteger. */ for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++) - data_out.s [k] = lrintf (data_out.f [k]) ; + data_out.s [k] = (short) lrintf (data_out.f [k]) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; diff --git a/tests/pedantic-header-test.sh.in b/tests/pedantic-header-test.sh.in index 283af645..561628dc 100644 --- a/tests/pedantic-header-test.sh.in +++ b/tests/pedantic-header-test.sh.in @@ -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 diff --git a/tests/stdin_test.c b/tests/stdin_test.c index 651614ae..1a9c67b8 100644 --- a/tests/stdin_test.c +++ b/tests/stdin_test.c @@ -185,7 +185,7 @@ stdin_test (int typemajor, int count) } ; total = 0 ; - while ((k = sf_read_short (file, data + total, BUFFER_LEN - total)) > 0) + while ((k = (int) sf_read_short (file, data + total, BUFFER_LEN - total)) > 0) total += k ; if (total != count) diff --git a/tests/stdout_test.c b/tests/stdout_test.c index a71ed643..e2cbe8d8 100644 --- a/tests/stdout_test.c +++ b/tests/stdout_test.c @@ -155,7 +155,7 @@ stdout_test (int typemajor, int count) while (total < count) { this_write = (count - total > 1024) ? 1024 : count - total ; - if ((k = sf_write_short (file, data + total, this_write)) != this_write) + if ((k = (int) sf_write_short (file, data + total, this_write)) != this_write) { fprintf (stderr, "sf_write_short # %d failed with short write (%d -> %d)\n", count, this_write, k) ; exit (1) ; } ; diff --git a/tests/string_test.c b/tests/string_test.c index 70a0dfbf..ab07df7c 100644 --- a/tests/string_test.c +++ b/tests/string_test.c @@ -37,6 +37,8 @@ #define BUFFER_LEN (1 << 10) #define LOG_BUFFER_SIZE 1024 +static const char STR_TEST_PREFIX[] = "str" ; + static void string_start_test (const char *filename, int typemajor) ; static void string_start_end_test (const char *filename, int typemajor) ; static void string_multi_set_test (const char *filename, int typemajor) ; @@ -113,6 +115,14 @@ main (int argc, char *argv []) test_count++ ; } ; + if (do_all || ! strcmp (argv [1], "mpeg")) + { if (HAVE_MPEG) + string_start_test ("mpeg.mp3", SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III) ; + else + puts (" No MP3 tests because MPEG support was not compiled in.") ; + test_count++ ; + } ; + if (do_all || ! strcmp (argv [1], "ogg")) { if (HAVE_EXTERNAL_XIPH_LIBS) string_start_test ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS) ; @@ -195,7 +205,9 @@ static const char long_title [] = "This is a very long and very boring title for this file", long_artist [] = "The artist who kept on changing its name", genre [] = "The genre", - trackno [] = "Track three" ; + trackno [] = "Track three", + id3v1_genre [] = "Rock", + year [] = "2001" ; static short data_out [BUFFER_LEN] ; @@ -207,6 +219,7 @@ string_start_end_test (const char *filename, int typemajor) SF_INFO sfinfo ; int errors = 0 ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name ("string_start_end_test", filename) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; @@ -356,6 +369,7 @@ string_start_test (const char *filename, int formattype) int errors = 0 ; int typemajor = SF_FORMAT_TYPEMASK & formattype ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name ("string_start_test", filename) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; @@ -370,6 +384,7 @@ string_start_test (const char *filename, int formattype) break ; case SF_FORMAT_OGG | SF_FORMAT_VORBIS : + case SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III : break ; default : @@ -386,9 +401,15 @@ string_start_test (const char *filename, int formattype) sf_set_string (file, SF_STR_ARTIST, artist) ; sf_set_string (file, SF_STR_COPYRIGHT, copyright) ; sf_set_string (file, SF_STR_COMMENT, comment) ; - sf_set_string (file, SF_STR_DATE, date) ; sf_set_string (file, SF_STR_ALBUM, album) ; sf_set_string (file, SF_STR_LICENSE, license) ; + if (typemajor == SF_FORMAT_MPEG) + { sf_set_string (file, SF_STR_GENRE, id3v1_genre) ; + sf_set_string (file, SF_STR_DATE, year) ; + } + else + { sf_set_string (file, SF_STR_DATE, date) ; + } ; /* Write data to file. */ test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ; @@ -411,24 +432,35 @@ string_start_test (const char *filename, int formattype) printf (" Bad filename : %s\n", cptr) ; } ; - cptr = sf_get_string (file, SF_STR_COPYRIGHT) ; - if (cptr == NULL || strcmp (copyright, cptr) != 0) - { if (errors++ == 0) - puts ("\n") ; - printf (" Bad copyright : %s\n", cptr) ; + if (typemajor != SF_FORMAT_MPEG) + { cptr = sf_get_string (file, SF_STR_COPYRIGHT) ; + if (cptr == NULL || strcmp (copyright, cptr) != 0) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad copyright : %s\n", cptr) ; + } ; + + cptr = sf_get_string (file, SF_STR_SOFTWARE) ; + if (cptr == NULL || strstr (cptr, software) != cptr) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad software : %s\n", cptr) ; + } ; + + if (cptr && str_count (cptr, "libsndfile") != 1) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad software : %s\n", cptr) ; + } ; } ; - cptr = sf_get_string (file, SF_STR_SOFTWARE) ; - if (cptr == NULL || strstr (cptr, software) != cptr) - { if (errors++ == 0) - puts ("\n") ; - printf (" Bad software : %s\n", cptr) ; - } ; - - if (cptr && str_count (cptr, "libsndfile") != 1) - { if (errors++ == 0) - puts ("\n") ; - printf (" Bad software : %s\n", cptr) ; + if (typemajor == SF_FORMAT_MPEG) + { cptr = sf_get_string (file, SF_STR_GENRE) ; + if (cptr == NULL || strcmp (id3v1_genre, cptr) != 0) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad genre : %s\n", cptr) ; + } ; } ; cptr = sf_get_string (file, SF_STR_ARTIST) ; @@ -445,13 +477,29 @@ string_start_test (const char *filename, int formattype) printf (" Bad comment : %s\n", cptr) ; } ; - if (typemajor != SF_FORMAT_AIFF) - { cptr = sf_get_string (file, SF_STR_DATE) ; - if (cptr == NULL || strcmp (date, cptr) != 0) - { if (errors++ == 0) - puts ("\n") ; - printf (" Bad date : %s\n", cptr) ; - } ; + switch (typemajor) + { case SF_FORMAT_AIFF : + /* not supported */ + break ; + + case SF_FORMAT_MPEG : + /* id3 only supports years */ + cptr = sf_get_string (file, SF_STR_DATE) ; + if (cptr == NULL || strcmp (year, cptr) != 0) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad date : %s\n", cptr) ; + } ; + break ; + + default : + cptr = sf_get_string (file, SF_STR_DATE) ; + if (cptr == NULL || strcmp (date, cptr) != 0) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad date : %s\n", cptr) ; + } ; + break ; } ; if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF) @@ -463,13 +511,21 @@ string_start_test (const char *filename, int formattype) } ; } ; - if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF && typemajor != SF_FORMAT_RF64) - { cptr = sf_get_string (file, SF_STR_LICENSE) ; - if (cptr == NULL || strcmp (license, cptr) != 0) - { if (errors++ == 0) - puts ("\n") ; - printf (" Bad license : %s\n", cptr) ; - } ; + switch (typemajor) + { case SF_FORMAT_WAV : + case SF_FORMAT_AIFF : + case SF_FORMAT_RF64 : + case SF_FORMAT_MPEG : + /* not supported */ + break ; + + default: + cptr = sf_get_string (file, SF_STR_LICENSE) ; + if (cptr == NULL || strcmp (license, cptr) != 0) + { if (errors++ == 0) + puts ("\n") ; + printf (" Bad license : %s\n", cptr) ; + } ; } ; if (errors > 0) @@ -497,6 +553,7 @@ string_multi_set_test (const char *filename, int typemajor) SF_INFO sfinfo ; int count ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name (__func__, filename) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; @@ -566,6 +623,7 @@ string_rdwr_test (const char *filename, int typemajor) sf_count_t frames ; const char * str ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name (__func__, filename) ; create_short_sndfile (filename, typemajor | SF_FORMAT_PCM_16, 2) ; @@ -618,6 +676,7 @@ string_short_rdwr_test (const char *filename, int typemajor) sf_count_t frames = BUFFER_LEN ; const char * str ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name (__func__, filename) ; memset (&sfinfo, 0, sizeof (sfinfo)) ; @@ -687,6 +746,7 @@ static void software_string_test (const char *filename) { size_t k ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name (__func__, filename) ; for (k = 0 ; k < 50 ; k++) @@ -727,6 +787,7 @@ string_rdwr_grow_test (const char *filename, int typemajor) sf_count_t frames ; const char * str ; + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name (__func__, filename) ; /* Create a file that contains some strings. Then open the file in RDWR mode and @@ -785,6 +846,7 @@ string_header_update (const char *filename, int typemajor) const char * str ; const int GROW_BUFFER_AMOUNT = 4 ; /* this should be less than half the size of the string header */ + get_unique_test_name (&filename, STR_TEST_PREFIX) ; print_test_name (__func__, filename) ; /* Create a short file. */ diff --git a/tests/test_wrapper.sh.in b/tests/test_wrapper.sh.in index b06a1788..ab92f7c4 100644 --- a/tests/test_wrapper.sh.in +++ b/tests/test_wrapper.sh.in @@ -352,6 +352,15 @@ echo "----------------------------------------------------------------------" echo " $sfversion passed tests on OPUS files." echo "----------------------------------------------------------------------" +# mpeg-tests +./tests/mpeg_test@EXEEXT@ +./tests/compression_size_test@EXEEXT@ mpeg +./tests/string_test@EXEEXT@ mpeg + +echo "----------------------------------------------------------------------" +echo " $sfversion passed tests on MPEG files." +echo "----------------------------------------------------------------------" + # io-tests ./tests/stdio_test@EXEEXT@ ./tests/pipe_test@EXEEXT@ diff --git a/tests/ulaw_test.c b/tests/ulaw_test.c index 9e0eba9b..cf2084bd 100644 --- a/tests/ulaw_test.c +++ b/tests/ulaw_test.c @@ -49,7 +49,7 @@ main (void) print_test_name ("ulaw_test", "encoder") ; - filename = "test.raw" ; + filename = "ulaw_test.raw" ; sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ULAW, 44100, 1) ; diff --git a/tests/utils.tpl b/tests/utils.tpl index 7be35fad..0d1cd8bb 100644 --- a/tests/utils.tpl +++ b/tests/utils.tpl @@ -104,6 +104,8 @@ void count_open_files (void) ; void increment_open_file_count (void) ; void check_open_file_count_or_die (int lineno) ; +void get_unique_test_name (const char ** filename, const char * test) ; + #ifdef SNDFILE_H static inline void @@ -191,6 +193,7 @@ sf_count_t file_length_fd (int fd) ; #include #include #include +#include #include #include @@ -213,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) @@ -750,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) ; } ; @@ -851,6 +876,15 @@ check_open_file_count_or_die (int lineno) #endif } /* check_open_file_count_or_die */ +void +get_unique_test_name (const char ** filename, const char * test) +{ static char buffer [1024] ; + + snprintf (buffer, sizeof (buffer), "%s_%s", test, *filename) ; + + *filename = buffer ; +} /* get_unique_test_name */ + void write_mono_file (const char * filename, int format, int srate, float * output, int len) { SNDFILE * file ; diff --git a/tests/virtual_io_test.c b/tests/virtual_io_test.c index 854bc302..b5f84ac2 100644 --- a/tests/virtual_io_test.c +++ b/tests/virtual_io_test.c @@ -216,7 +216,7 @@ vio_test (const char *fname, int format) fflush (stdout) ; puts (sf_strerror (NULL)) ; - dump_data_to_file (fname, vio_data.data, vio_data.length) ; + dump_data_to_file (fname, vio_data.data, (unsigned int) vio_data.length) ; exit (1) ; } ; diff --git a/tests/write_read_test.tpl b/tests/write_read_test.tpl index af87e12a..ed152f89 100644 --- a/tests/write_read_test.tpl +++ b/tests/write_read_test.tpl @@ -42,6 +42,8 @@ #define SILLY_WRITE_COUNT (234) +static const char WRT_TEST_PREFIX[] = "wrt" ; + [+ FOR data_type +]static void pcm_test_[+ (get "type_name") +] (const char *str, int format, int long_file_ok) ; [+ ENDFOR data_type @@ -446,6 +448,7 @@ pcm_test_[+ (get "type_name") +] (const char *filename, int format, int long_fil /* Sd2 files cannot be opened from an existing file descriptor. */ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ; + get_unique_test_name (&filename, WRT_TEST_PREFIX) ; print_test_name ("pcm_test_[+ (get "type_name") +]", filename) ; sfinfo.samplerate = 44100 ; @@ -1008,6 +1011,7 @@ empty_file_test (const char *filename, int format) /* Sd2 files cannot be opened from an existing file descriptor. */ allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ; + get_unique_test_name (&filename, WRT_TEST_PREFIX) ; print_test_name ("empty_file_test", filename) ; unlink (filename) ; diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 00000000..a37a18b4 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", + "name": "libsndfile", + "description": "A library for reading and writing audio files", + "version-semver": "1.1.0", + "default-features": [ + "external-libs", + "mpeg" + ], + "features": { + "external-libs": { + "description": "Enable FLAC, Vorbis, and Opus codecs", + "dependencies": [ + "libvorbis", + "libflac", + "opus" + ] + }, + "mpeg": { + "description": "Enable MPEG codecs", + "dependencies": [ + "mpg123", + "mp3lame" + ] + }, + "regtest": { + "description": "Build regtest", + "dependencies": [ + "sqlite3" + ] + }, + "experimental": { + "description": "Enable experimental code", + "dependencies": [ + "speex" + ] + } + } +}