Version upgrade! Merge branch 'dev'

Signed-off-by: huang-jianfei200 <huangjianfei4@huawei.com>
This commit is contained in:
huang-jianfei200 2023-11-15 20:02:12 +08:00
commit 297f533a38
150 changed files with 6693 additions and 4373 deletions

View File

@ -18,34 +18,38 @@ jobs:
ubuntu-clang-cmake-shared, ubuntu-clang-cmake-shared,
macos-cmake, macos-cmake,
macos-cmake-shared, macos-cmake-shared,
windows-vs2019-x64, windows-vs2022-x64,
windows-vs2019-x64-shared, windows-vs2022-x64-shared,
windows-vs2019-Win32, windows-vs2022-Win32,
windows-vs2019-Win32-shared windows-vs2022-Win32-shared
] ]
include: include:
- name: ubuntu-gcc-autotools - name: ubuntu-gcc-autotools
os: ubuntu-latest os: ubuntu-latest
cc: gcc cc: gcc
cxx: g++ cxx: g++
autotools-options: --enable-werror
build-system: autotools build-system: autotools
- name: ubuntu-clang-autotools - name: ubuntu-clang-autotools
os: ubuntu-latest os: ubuntu-latest
cc: clang cc: clang
cxx: clang++ cxx: clang++
autotools-options: --enable-werror
build-system: autotools build-system: autotools
- name: ubuntu-gcc-ossfuzz - name: ubuntu-gcc-ossfuzz
os: ubuntu-latest os: ubuntu-latest
cc: gcc cc: gcc
cxx: g++ cxx: g++
autotools-options: --enable-werror
build-system: ossfuzz build-system: ossfuzz
- name: macos-autotools - name: macos-autotools
os: macos-latest os: macos-latest
cc: clang cc: clang
cxx: clang++ cxx: clang++
autotools-options: --enable-werror
build-system: autotools build-system: autotools
- name: ubuntu-gcc-cmake - name: ubuntu-gcc-cmake
@ -117,22 +121,22 @@ jobs:
-DCMAKE_C_FLAGS="-Wall -Wextra" -DCMAKE_C_FLAGS="-Wall -Wextra"
-DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_VERBOSE_MAKEFILE=ON
- name: windows-vs2019-x64 - name: windows-vs2022-x64
os: windows-latest os: windows-latest
triplet: 'x64-windows-static' triplet: 'x64-windows-static'
build-system: cmake build-system: cmake
cmake-generator: 'Visual Studio 16 2019' cmake-generator: 'Visual Studio 17 2022'
cmake-options: >- cmake-options: >-
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug> -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
-DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=Release
-DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_TARGET_TRIPLET=x64-windows-static
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
- name: windows-vs2019-x64-shared - name: windows-vs2022-x64-shared
os: windows-latest os: windows-latest
triplet: 'x64-windows-static' triplet: 'x64-windows-static'
build-system: cmake build-system: cmake
cmake-generator: 'Visual Studio 16 2019' cmake-generator: 'Visual Studio 17 2022'
cmake-options: >- cmake-options: >-
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug> -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
-DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON
@ -143,11 +147,11 @@ jobs:
-DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_TARGET_TRIPLET=x64-windows-static
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
- name: windows-vs2019-Win32 - name: windows-vs2022-Win32
os: windows-latest os: windows-latest
triplet: 'x86-windows-static' triplet: 'x86-windows-static'
build-system: cmake build-system: cmake
cmake-generator: 'Visual Studio 16 2019' cmake-generator: 'Visual Studio 17 2022'
cmake-options: >- cmake-options: >-
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug> -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
-DCMAKE_GENERATOR_PLATFORM=Win32 -DCMAKE_GENERATOR_PLATFORM=Win32
@ -155,11 +159,11 @@ jobs:
-DVCPKG_TARGET_TRIPLET=x86-windows-static -DVCPKG_TARGET_TRIPLET=x86-windows-static
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
- name: windows-vs2019-Win32-shared - name: windows-vs2022-Win32-shared
os: windows-latest os: windows-latest
triplet: 'x86-windows-static' triplet: 'x86-windows-static'
build-system: cmake build-system: cmake
cmake-generator: 'Visual Studio 16 2019' cmake-generator: 'Visual Studio 17 2022'
cmake-options: >- cmake-options: >-
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug> -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
-DCMAKE_GENERATOR_PLATFORM=Win32 -DCMAKE_GENERATOR_PLATFORM=Win32
@ -179,16 +183,25 @@ jobs:
- name: Install MacOS dependencies - name: Install MacOS dependencies
if: startsWith(matrix.os,'macos') if: startsWith(matrix.os,'macos')
run: | 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') 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') if: startsWith(matrix.os,'windows')
run: | shell: 'bash'
vcpkg install libvorbis libflac opus sqlite3 speex --triplet ${{matrix.triplet}} 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 - name: Configure, build and test with Autotools
env: env:
@ -196,17 +209,18 @@ jobs:
CXX: ${{ matrix.cxx }} CXX: ${{ matrix.cxx }}
if: startsWith(matrix.build-system,'autotools') if: startsWith(matrix.build-system,'autotools')
run: | run: |
./autogen.sh autoreconf -vif
if [[ "${CC}" == "clang" ]]; then if [[ "${CC}" == "clang" ]]; then
./configure --enable-werror && make clean all check && make distcheck ./configure --enable-werror && make distcheck
else else
Scripts/asan-configure.sh --enable-werror && make clean all check && make distcheck Scripts/asan-configure.sh --enable-werror && make distcheck
fi fi
- name: Configure, build and test with CMake - name: Configure, build and test with CMake
env: env:
CC: ${{ matrix.cc }} CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }} CXX: ${{ matrix.cxx }}
VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite'
if: startsWith(matrix.build-system,'cmake') if: startsWith(matrix.build-system,'cmake')
run: | run: |
mkdir build mkdir build

26
.github/workflows/cifuzz.yml vendored Normal file
View File

@ -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

3
.gitignore vendored
View File

@ -48,6 +48,7 @@ build-test-tarball.mk
config.log config.log
config.status config.status
configure configure
configure~
doc/AUTHORS doc/AUTHORS
doc/ChangeLog doc/ChangeLog
doc/NEWS doc/NEWS
@ -62,7 +63,7 @@ examples/sndfile-loopify
examples/sndfile-to-text examples/sndfile-to-text
examples/sndfilehandle examples/sndfilehandle
include/sndfile.h include/sndfile.h
libsndfile-1.0.* libsndfile-*.tar.xz
libsndfile-testsuite-* libsndfile-testsuite-*
libsndfile.spec libsndfile.spec
libtool libtool

View File

@ -3,7 +3,7 @@
Assuming the Android Ndk is installed at location `/path/to/toolchain`, building Assuming the Android Ndk is installed at location `/path/to/toolchain`, building
libsndfile for Android (arm-linux-androideabi) should be as simple as: libsndfile for Android (arm-linux-androideabi) should be as simple as:
``` ```
./autogen.sh autoreconf -vif
export ANDROID_TOOLCHAIN_HOME=/path/to/android/toolchain export ANDROID_TOOLCHAIN_HOME=/path/to/android/toolchain
./Scripts/android-configure.sh ./Scripts/android-configure.sh
make 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 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 for this documentation and script to improve its utility for real Android
developers. 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 <number of parallel jobs>]
```
This will build libsndfile for android.

147
CHANGELOG.md Normal file
View File

@ -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 <windows.h>
#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
#including <sndfile.h>
```
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

View File

@ -15,7 +15,27 @@ if (POLICY CMP0091)
endif () endif ()
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 # Variables
@ -54,7 +74,6 @@ endif ()
option (BUILD_PROGRAMS "Build programs" ON) option (BUILD_PROGRAMS "Build programs" ON)
option (BUILD_EXAMPLES "Build examples" ON) option (BUILD_EXAMPLES "Build examples" ON)
option (ENABLE_CPACK "Enable CPack support" 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) option (ENABLE_BOW_DOCS "Enable black-on-white html docs" OFF)
if (MSVC AND (DEFINED ENABLE_STATIC_RUNTIME)) if (MSVC AND (DEFINED ENABLE_STATIC_RUNTIME))
option (ENABLE_STATIC_RUNTIME "Enable static runtime" ${ENABLE_STATIC_RUNTIME}) option (ENABLE_STATIC_RUNTIME "Enable static runtime" ${ENABLE_STATIC_RUNTIME})
@ -75,9 +94,16 @@ endif ()
include(SndFileChecks) 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) cmake_dependent_option (ENABLE_CPU_CLIP "Enable tricky cpu specific clipper" ON "CPU_CLIPS_POSITIVE;CPU_CLIPS_NEGATIVE" OFF)
if (NOT ENABLE_CPU_CLIP) if (NOT ENABLE_CPU_CLIP)
set (CPU_CLIPS_POSITIVE FALSE) set (CPU_CLIPS_POSITIVE FALSE)
@ -104,11 +130,12 @@ set (HAVE_ALSA_ASOUNDLIB_H ${ALSA_FOUND})
set (HAVE_SNDIO_H ${SNDIO_FOUND}) set (HAVE_SNDIO_H ${SNDIO_FOUND})
set (ENABLE_EXPERIMENTAL_CODE ${ENABLE_EXPERIMENTAL}) set (ENABLE_EXPERIMENTAL_CODE ${ENABLE_EXPERIMENTAL})
set (HAVE_MPEG ${ENABLE_MPEG})
set (HAVE_SPEEX ${ENABLE_EXPERIMENTAL}) 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 (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_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 (ENABLE_EXPERIMENTAL ENABLE_EXPERIMENTAL "enable experimental code")
add_feature_info (BUILD_TESTING BUILD_TESTING "build tests") add_feature_info (BUILD_TESTING BUILD_TESTING "build tests")
add_feature_info (BUILD_REGTEST BUILD_REGTEST "build regtest") add_feature_info (BUILD_REGTEST BUILD_REGTEST "build regtest")
@ -147,6 +174,18 @@ set_package_properties (FLAC PROPERTIES
DESCRIPTION "Free Lossless Audio Codec Library" DESCRIPTION "Free Lossless Audio Codec Library"
PURPOSE "Enables FLAC support" 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 set_package_properties(Opus PROPERTIES
TYPE RECOMMENDED TYPE RECOMMENDED
URL "www.opus-codec.org/" URL "www.opus-codec.org/"
@ -181,8 +220,6 @@ feature_summary (WHAT ALL)
configure_file (src/config.h.cmake src/config.h) configure_file (src/config.h.cmake src/config.h)
configure_file (include/sndfile.h.in include/sndfile.h)
if (INSTALL_PKGCONFIG_MODULE) if (INSTALL_PKGCONFIG_MODULE)
set (prefix ${CMAKE_INSTALL_PREFIX}) set (prefix ${CMAKE_INSTALL_PREFIX})
@ -196,6 +233,10 @@ if (INSTALL_PKGCONFIG_MODULE)
set (EXTERNAL_XIPH_REQUIRE "${EXTERNAL_XIPH_REQUIRE} speex") set (EXTERNAL_XIPH_REQUIRE "${EXTERNAL_XIPH_REQUIRE} speex")
endif () endif ()
endif () endif ()
if (ENABLE_MPEG)
set (EXTERNAL_MPEG_REQUIRE "libmpg123")
set (EXTERNAL_MPEG_LIBS "-lmp3lame")
endif ()
configure_file (sndfile.pc.in sndfile.pc @ONLY) configure_file (sndfile.pc.in sndfile.pc @ONLY)
@ -207,8 +248,8 @@ endif ()
# Public libsndfile headers # Public libsndfile headers
set (sndfile_HDRS set (sndfile_HDRS
include/sndfile.h
include/sndfile.hh include/sndfile.hh
${CMAKE_CURRENT_BINARY_DIR}/include/sndfile.h
) )
# #
@ -247,6 +288,7 @@ add_library (sndfile
src/ogg.c src/ogg.c
src/chanmap.h src/chanmap.h
src/chanmap.c src/chanmap.c
src/id3.h
src/id3.c src/id3.c
$<$<BOOL:${WIN32}>:src/windows.c> $<$<BOOL:${WIN32}>:src/windows.c>
src/sndfile.c src/sndfile.c
@ -284,8 +326,12 @@ add_library (sndfile
src/ogg_speex.c src/ogg_speex.c
src/ogg_pcm.c src/ogg_pcm.c
src/ogg_opus.c src/ogg_opus.c
src/ogg_vcomment.h
src/ogg_vcomment.c src/ogg_vcomment.c
src/nms_adpcm.c src/nms_adpcm.c
src/mpeg.c
src/mpeg_decode.c
src/mpeg_l3_encode.c
src/GSM610/config.h src/GSM610/config.h
src/GSM610/gsm.h src/GSM610/gsm.h
src/GSM610/gsm610_priv.h src/GSM610/gsm610_priv.h
@ -349,6 +395,8 @@ target_link_libraries (sndfile
$<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:FLAC::FLAC> $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:FLAC::FLAC>
$<$<AND:$<BOOL:${ENABLE_EXPERIMENTAL}>,$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>,$<BOOL:${HAVE_SPEEX}>>:Speex::Speex> $<$<AND:$<BOOL:${ENABLE_EXPERIMENTAL}>,$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>,$<BOOL:${HAVE_SPEEX}>>:Speex::Speex>
$<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Opus::opus> $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Opus::opus>
$<$<BOOL:${HAVE_MPEG}>:MPG123::libmpg123>
$<$<BOOL:${HAVE_MPEG}>:mp3lame::mp3lame>
) )
set_target_properties (sndfile PROPERTIES set_target_properties (sndfile PROPERTIES
PUBLIC_HEADER "${sndfile_HDRS}" PUBLIC_HEADER "${sndfile_HDRS}"
@ -368,6 +416,28 @@ endif ()
if (BUILD_SHARED_LIBS) 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) if (WIN32)
set (VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set (VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR})
set (GEN_TOOL cmake) set (GEN_TOOL cmake)
@ -380,11 +450,23 @@ if (BUILD_SHARED_LIBS)
target_sources (sndfile PRIVATE ${PROJECT_BINARY_DIR}/src/version-metadata.rc) target_sources (sndfile PRIVATE ${PROJECT_BINARY_DIR}/src/version-metadata.rc)
endif () endif ()
set_target_properties (sndfile PROPERTIES set_target_properties (sndfile PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR} SOVERSION ${SNDFILE_ABI_VERSION_MAJOR}
VERSION ${PROJECT_VERSION} 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 # Symbol files generation
if (WIN32) if (WIN32)
@ -404,7 +486,7 @@ if (BUILD_SHARED_LIBS)
if (DEFINED SYMBOL_OS) if (DEFINED SYMBOL_OS)
add_custom_command ( add_custom_command (
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} 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}..." COMMENT "Generating ${SYMBOL_FILENAME}..."
) )
@ -647,6 +729,11 @@ if (BUILD_EXAMPLES)
$<$<BOOL:${LIBM_REQUIRED}>:m> $<$<BOOL:${LIBM_REQUIRED}>:m>
) )
# generate
add_executable (generate examples/generate.c)
target_link_libraries (generate PRIVATE sndfile)
# sndfilehandle # sndfilehandle
add_executable (sndfilehandle examples/sndfilehandle.cc) add_executable (sndfilehandle examples/sndfilehandle.cc)
@ -658,6 +745,7 @@ if (BUILD_EXAMPLES)
make_sine make_sine
sfprocess sfprocess
list_formats list_formats
generate
sndfilehandle sndfilehandle
) )
@ -716,6 +804,8 @@ if (ENABLE_PACKAGE_CONFIG)
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
) )
export (EXPORT SndFileTargets NAMESPACE SndFile:: FILE ${PROJECT_BINARY_DIR}/SndFileTargets.cmake)
include (CMakePackageConfigHelpers) include (CMakePackageConfigHelpers)
if (ENABLE_EXTERNAL_LIBS) if (ENABLE_EXTERNAL_LIBS)
@ -724,8 +814,19 @@ if (ENABLE_PACKAGE_CONFIG)
set (SndFile_WITH_EXTERNAL_LIBS 0) set (SndFile_WITH_EXTERNAL_LIBS 0)
endif () endif ()
if(ENABLE_MPEG)
set (SndFile_WITH_MPEG 1)
else ()
set (SndFile_WITH_MPEG 0)
endif ()
set (INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) set (INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig.cmake 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} INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
PATH_VARS INCLUDE_INSTALL_DIR PATH_VARS INCLUDE_INSTALL_DIR
) )
@ -735,9 +836,13 @@ if (ENABLE_PACKAGE_CONFIG)
NAMESPACE SndFile:: NAMESPACE SndFile::
DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
) )
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig2.cmake
RENAME SndFileConfig.cmake
DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
)
install( install(
FILES FILES
${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/SndFileConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
) )
@ -1181,6 +1286,14 @@ if (BUILD_TESTING)
$<$<BOOL:${LIBM_REQUIRED}>:m> $<$<BOOL:${LIBM_REQUIRED}>:m>
) )
add_executable (mpeg_test tests/mpeg_test.c)
target_link_libraries (mpeg_test
PRIVATE
sndfile
test_utils
$<$<BOOL:${LIBM_REQUIRED}>:m>
)
add_executable (stdin_test tests/stdin_test.c) add_executable (stdin_test tests/stdin_test.c)
target_link_libraries (stdin_test target_link_libraries (stdin_test
PRIVATE PRIVATE
@ -1412,6 +1525,10 @@ if (BUILD_TESTING)
add_test (lossy_comp_test_ogg_opus lossy_comp_test ogg_opus) add_test (lossy_comp_test_ogg_opus lossy_comp_test ogg_opus)
add_test (string_test_opus string_test 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 ### io-tests
add_test (stdio_test stdio_test) add_test (stdio_test stdio_test)
add_test (pipe_test pipe_test) add_test (pipe_test pipe_test)
@ -1467,5 +1584,8 @@ if (BUILD_TESTING)
endif () endif ()
if (ENABLE_CPACK) if (ENABLE_CPACK)
if ((NOT CPACK_PACKAGE_VERSION) AND CPACK_PACKAGE_VERSION_STAGE)
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_FULL}")
endif ()
include (CPack) include (CPack)
endif () endif ()

View File

@ -18,6 +18,30 @@
* Patches should always be submitted via a either Github "pull request" or a * Patches should always be submitted via a either Github "pull request" or a
via emailed patches created using "git format-patch". via emailed patches created using "git format-patch".
* Patches for new features should include tests and documentation. * 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 * Patches to fix bugs should either pass all tests, or modify the tests in some
sane way. sane way.
* When a new feature is added for a particular file format and that feature * When a new feature is added for a particular file format and that feature

View File

@ -13,8 +13,8 @@ endif
endif endif
EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \ EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \
Scripts/linux-to-win-cross-configure.sh \ NEWS.OLD CHANGELOG.md Scripts/linux-to-win-cross-configure.sh \
CMakeLists.txt $(cmake_files) Win32 CMakeLists.txt $(cmake_files) Win32 SECURITY.md
cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \ cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \
cmake/CMakeAutoGen.cmake cmake/CMakeAutoGenScript.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/SndFileChecks.cmake cmake/TestInline.cmake \
cmake/TestLargeFiles.cmake cmake/TestInline.c.in \ cmake/TestLargeFiles.cmake cmake/TestInline.c.in \
cmake/FindOpus.cmake cmake/SndFileConfig.cmake.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 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 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 \ $(SYMBOL_FILES) src/create_symbols_file.py src/binheader_writef_check.py \
src/GSM610/README src/GSM610/COPYRIGHT src/GSM610/ChangeLog \ src/GSM610/README src/GSM610/COPYRIGHT src/GSM610/ChangeLog \
src/G72x/README src/G72x/README.original src/G72x/ChangeLog \ src/G72x/README src/G72x/README.original src/G72x/ChangeLog \
@ -60,28 +62,27 @@ endif
#=============================================================================== #===============================================================================
lib_LTLIBRARIES = src/libsndfile.la lib_LTLIBRARIES = src/libsndfile.la
include_HEADERS = include/sndfile.hh include_HEADERS = include/sndfile.h include/sndfile.hh
nodist_include_HEADERS = include/sndfile.h src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_CFLAGS)
src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS)
# MinGW requires -no-undefined if a DLL is to be built. # 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_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_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/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/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/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/ogg.h src/chanmap.h 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) 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_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) EXTRA_src_libsndfile_la_DEPENDENCIES = $(SYMBOL_FILES)
noinst_LTLIBRARIES = src/libcommon.la 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_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/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/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/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/nms_adpcm.c $(WIN_VERSION_FILE) 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 check_PROGRAMS = src/test_main
src_test_main_SOURCES = src/test_main.c src/test_main.h src/test_conversions.c src/test_float.c src/test_endswap.c \ src_test_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 SYMBOL_SCRIPT = $(top_srcdir)/src/create_symbols_file.py
src/Symbols.gnu-binutils: $(SYMBOL_SCRIPT) 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) 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) 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) 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) 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). # 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/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/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/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 += \ BUILT_SOURCES += \
tests/write_read_test.c \ 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_SOURCES = tests/checksum_test.c tests/utils.c tests/utils.h
tests_checksum_test_LDADD = src/libsndfile.la 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 # Lite remove start
tests_dwvw_test_SOURCES = tests/dwvw_test.c tests/utils.c tests/utils.h tests_dwvw_test_SOURCES = tests/dwvw_test.c tests/utils.c tests/utils.h
tests_dwvw_test_LDADD = src/libsndfile.la tests_dwvw_test_LDADD = src/libsndfile.la
@ -457,7 +462,8 @@ endif
if USE_OSSFUZZERS if USE_OSSFUZZERS
noinst_PROGRAMS += \ noinst_PROGRAMS += \
ossfuzz/sndfile_fuzzer ossfuzz/sndfile_fuzzer \
ossfuzz/sndfile_alt_fuzzer
noinst_LTLIBRARIES += \ noinst_LTLIBRARIES += \
ossfuzz/libstandaloneengine.la 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_LDFLAGS = $(AM_LDFLAGS) -static
ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD) 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_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h
ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS) ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS)

View File

2
README
View File

@ -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 libsndfile is a library of C routines for reading and writing
files containing sampled audio data. files containing sampled audio data.

View File

@ -18,7 +18,7 @@ for details.
## Hacking ## Hacking
The canonical source code repository for libsndfile is at The canonical source code repository for libsndfile is at
[http://libsndfile.github.io/libsndfile/][github]. <https://github.com/libsndfile/libsndfile>.
You can grab the source code using: 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: 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 \ 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 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. although the package install tools and package names may be slightly different.
Similarly on Mac OS X, assuming [brew] is already installed: 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 Once the build environment has been set up, building and testing libsndfile is
as simple as: as simple as:
./autogen.sh autoreconf -vif
./configure --enable-werror ./configure --enable-werror
make make
make check make check
@ -134,6 +135,8 @@ You can pass additional options with `/D<parameter>=<value>` when you run
`ON` by default. Setting `BUILD_SHARED_LIBS` to `ON` disables this option. `ON` by default. Setting `BUILD_SHARED_LIBS` to `ON` disables this option.
* `ENABLE_EXTERNAL_LIBS` - enable Ogg, Vorbis, FLAC and Opus support. This * `ENABLE_EXTERNAL_LIBS` - enable Ogg, Vorbis, FLAC and Opus support. This
option is available and set to `ON` if all dependency libraries were found. 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 * `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 `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 * `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 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, 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: 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 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 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, [Vcpkg](https://github.com/Microsoft/vcpkg).
libvorbis, libflac and libopus libraries:
vcpkg install libogg:x64-windows-static libvorbis:x64-windows-static Install Vcpkg and then add this parameter to cmake command line:
libflac:x64-windows-static opus:x64-windows-static libogg:x86-windows-static
libvorbis:x86-windows-static libflac:x86-windows-static opus:x86-windows-static
Then and add this parameter to cmake command line:
-DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake -DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/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 -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 **Note**: Use must use the same CRT library for external libraries and the
libsndfile library itself. For `*-static` triplets Vcpkg uses libsndfile library itself. For `*-static` triplets Vcpkg uses
[static CRT](https://vcpkg.readthedocs.io/en/latest/users/triplets/). [static CRT](https://vcpkg.readthedocs.io/en/latest/users/triplets/).

11
SECURITY.md Normal file
View File

@ -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.

View File

@ -95,7 +95,7 @@ Build/Stamp/build-ogg : Build/Stamp/sha256sum
ifeq ($(disable_ogg_crc), true) ifeq ($(disable_ogg_crc), true)
echo "Ogg/CRC enabled" echo "Ogg/CRC enabled"
(cd Build && git clone https://github.com/xiph/ogg $(ogg_version)) (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 else
echo "Ogg/CRC disabled" echo "Ogg/CRC disabled"
(cd Build && tar xf Tarballs/$(ogg_tarball)) (cd Build && tar xf Tarballs/$(ogg_tarball))
@ -110,7 +110,7 @@ Build/Stamp/install-libs : Build/Stamp/extract Build/Stamp/build-ogg
touch $@ touch $@
configure : configure.ac configure : configure.ac
./autogen.sh autoreconf -vif
Build/Stamp/configure : Build/Stamp/install-libs configure Build/Stamp/configure : Build/Stamp/install-libs configure
PKG_CONFIG_LIBDIR=Build/lib/pkgconfig ./configure PKG_CONFIG_LIBDIR=Build/lib/pkgconfig ./configure

View File

@ -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

64
cmake/FindMpg123.cmake Normal file
View File

@ -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)

67
cmake/Findmp3lame.cmake Normal file
View File

@ -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)

View File

@ -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)

View File

@ -16,13 +16,6 @@ if (LARGE_FILES_DEFINITIONS)
add_definitions(${LARGE_FILES_DEFINITIONS}) add_definitions(${LARGE_FILES_DEFINITIONS})
endif () 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") if (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
find_package (Sndio) find_package (Sndio)
elseif (NOT WIN32) elseif (NOT WIN32)
@ -56,6 +49,14 @@ else ()
set (HAVE_EXTERNAL_XIPH_LIBS 0) set (HAVE_EXTERNAL_XIPH_LIBS 0)
endif () 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 (Speex)
find_package (SQLite3) 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 (sys/types.h HAVE_SYS_TYPES_H)
check_include_file (unistd.h HAVE_UNISTD_H) check_include_file (unistd.h HAVE_UNISTD_H)
check_include_file (immintrin.h HAVE_IMMINTRIN_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_x86 (CPU_IS_X86)
check_cpu_arch_x64 (CPU_IS_X64) check_cpu_arch_x64 (CPU_IS_X64)
@ -112,28 +114,6 @@ if (ENABLE_TESTING)
check_type_size (void* SIZEOF_VOIDP) check_type_size (void* SIZEOF_VOIDP)
endif() 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) if (NOT WIN32)
check_library_exists (m floor "" LIBM_REQUIRED) check_library_exists (m floor "" LIBM_REQUIRED)
if (LIBM_REQUIRED) if (LIBM_REQUIRED)

View File

@ -4,6 +4,7 @@ set(SndFile_VERSION_MINOR @PROJECT_VERSION_MINOR@)
set(SndFile_VERSION_PATCH @PROJECT_VERSION_PATCH@) set(SndFile_VERSION_PATCH @PROJECT_VERSION_PATCH@)
set (SndFile_WITH_EXTERNAL_LIBS @SndFile_WITH_EXTERNAL_LIBS@) set (SndFile_WITH_EXTERNAL_LIBS @SndFile_WITH_EXTERNAL_LIBS@)
set (SndFile_WITH_MPEG @SndFile_WITH_MPEG@)
@PACKAGE_INIT@ @PACKAGE_INIT@
@ -16,6 +17,11 @@ if (SndFile_WITH_EXTERNAL_LIBS AND NOT @BUILD_SHARED_LIBS@)
find_dependency (Opus) find_dependency (Opus)
endif () endif ()
if (SndFile_WITH_MPEG AND NOT @BUILD_SHARED_LIBS@)
find_dependency (mp3lame)
find_dependency (MPG123)
endif ()
include (${CMAKE_CURRENT_LIST_DIR}/SndFileTargets.cmake) include (${CMAKE_CURRENT_LIST_DIR}/SndFileTargets.cmake)
set_and_check (SndFile_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check (SndFile_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")

View File

@ -1,9 +1,9 @@
dnl Copyright (C) 1999-2021 Erik de Castro Lopo <erikd@mega-nerd.com>. dnl Copyright (C) 1999-2022 Erik de Castro Lopo <erikd@mega-nerd.com>.
dnl Require autoconf version >= 2.69 dnl Require autoconf version >= 2.69
AC_PREREQ([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/]) [libsndfile],[http://libsndfile.github.io/libsndfile/])
dnl Check whether we want to set defaults for CFLAGS, CXXFLAGS, CPPFLAGS and LDFLAGS 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_MACRO_DIR([m4])
AC_CONFIG_HEADERS([src/config.h]) 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]) AM_SILENT_RULES([yes])
dnl ==================================================================================== dnl ====================================================================================
@ -57,7 +57,7 @@ AC_LANG_POP([C++])
AC_PROG_SED AC_PROG_SED
AM_PROG_AR AM_PROG_AR
LT_INIT([win32-dll]) LT_INIT([disable-static win32-dll])
LT_PROG_RC LT_PROG_RC
AC_PROG_INSTALL 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 age.
dnl 6. If any interfaces have been removed since the last public release, then set age dnl 6. If any interfaces have been removed since the last public release, then set age
dnl to 0. 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 ------------------------------------------------------------------------------------ dnl ------------------------------------------------------------------------------------
AC_HEADER_STDC
AC_CHECK_HEADERS([endian.h]) AC_CHECK_HEADERS([endian.h])
AC_CHECK_HEADERS([byteswap.h]) AC_CHECK_HEADERS([byteswap.h])
AC_CHECK_HEADERS([locale.h]) AC_CHECK_HEADERS([locale.h])
AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/time.h])
AC_CHECK_HEADERS([immintrin.h]) AC_CHECK_HEADERS([immintrin.h])
AC_CHECK_HEADERS([stdbool.h])
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
@ -129,9 +141,6 @@ AC_DEFINE_UNQUOTED([ENABLE_EXPERIMENTAL_CODE], [${EXPERIMENTAL_CODE}], [Set to 1
AC_ARG_ENABLE([werror], AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])]) [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], AC_ARG_ENABLE([cpu-clip],
[AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])]) [AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])])
@ -147,6 +156,9 @@ AC_ARG_ENABLE([alsa],
AC_ARG_ENABLE([external-libs], AC_ARG_ENABLE([external-libs],
[AS_HELP_STRING([--disable-external-libs], [disable use of FLAC, Ogg and Vorbis [[default=no]]])]) [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, AC_ARG_ENABLE(octave,
[AS_HELP_STRING([--enable-octave], [enable building of GNU Octave module])]) [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"]) AM_CONDITIONAL([ENABLE_TEST_COVERAGE], [test "x$enable_test_coverage" = "xyes"])
AC_ARG_ENABLE([ossfuzzers], AC_ARG_ENABLE([ossfuzzers],
[AS_HELP_STRING([--enable-ossfuzzers], [AS_HELP_STRING([--enable-ossfuzzers], [Whether to generate the fuzzers for OSS-Fuzz])])
[Whether to generate the fuzzers for OSS-Fuzz])], AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$enable_ossfuzzers" = "xyes"])
[have_ossfuzzers=yes], [have_ossfuzzers=no])
AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_ossfuzzers" = "xyes"])
AC_SUBST([LIB_FUZZING_ENGINE]) AC_SUBST([LIB_FUZZING_ENGINE])
AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"]) 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([int64_t], [8])
AC_CHECK_SIZEOF([long long], [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. dnl Check for common 64 bit file offset types.
AC_CHECK_SIZEOF([off_t], [1]) 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], AS_CASE([$host_os],
[mingw32*], [ [mingw32*], [
TYPEOF_SF_COUNT_T="__int64"
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
SIZEOF_SF_COUNT_T=8
AC_DEFINE([__USE_MINGW_ANSI_STDIO], [1], [Set to 1 to use C99 printf/snprintf in MinGW.]) AC_DEFINE([__USE_MINGW_ANSI_STDIO], [1], [Set to 1 to use C99 printf/snprintf in MinGW.])
], ],
[linux-android*], [
TYPEOF_SF_COUNT_T="int64_t"
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
SIZEOF_SF_COUNT_T=8
],
[ [
SIZEOF_SF_COUNT_T=0
AS_IF([test "x$ac_cv_sizeof_off_t" = "x8"], [ AS_IF([test "x$ac_cv_sizeof_off_t" = "x8"], [
dnl If sizeof (off_t) is 8, no further checking is needed. 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 Save the old sizeof (off_t) value and then unset it to see if it
dnl changes when Large File Support is enabled. dnl changes when Large File Support is enabled.
@ -234,43 +225,9 @@ AS_CASE([$host_os],
]) ])
AC_CHECK_SIZEOF(off_t,1) 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 AC_TYPE_SSIZE_T
dnl ==================================================================================== dnl ====================================================================================
@ -374,8 +331,8 @@ AS_IF([test -n "$PKG_CONFIG"], [
fi fi
], [ ], [
AS_ECHO([""]) AS_ECHO([""])
AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg and]]) AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg,]])
AC_MSG_WARN([[*** libvorbis) is either missing (possibly only the development]]) 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([[*** headers) or is of an unsupported version.]])
AC_MSG_WARN([[***]]) AC_MSG_WARN([[***]])
AC_MSG_WARN([[*** Unfortunately, for ease of maintenance, the external libs]]) 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.]) 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 ====================================================================================
dnl Check for libsqlite3 (only used in regtest). dnl Check for libsqlite3 (only used in regtest).
@ -574,18 +578,24 @@ AS_IF([test "x$enable_werror" = "xyes"], [
AC_LANG_POP([C++]) AC_LANG_POP([C++])
]) ])
common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self -Wno-format-truncation" common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self"
AX_APPEND_COMPILE_FLAGS([${common_flags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS]) 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++]) 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++]) 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"], [ AS_IF([test "x$enable_test_coverage" = "xyes"], [
AX_APPEND_COMPILE_FLAGS([-coverage], [CFLAGS]) 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" 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"], [ AS_IF([test "x$enable_static" = "xno"], [
@ -657,7 +667,8 @@ AC_SUBST(HTML_BGCOLOUR)
AC_SUBST(HTML_FGCOLOUR) AC_SUBST(HTML_FGCOLOUR)
AC_SUBST(SHLIB_VERSION_ARG) 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(CLEAN_VERSION)
AC_SUBST(VERSION_MAJOR) AC_SUBST(VERSION_MAJOR)
AC_SUBST(GEN_TOOL) AC_SUBST(GEN_TOOL)
@ -665,6 +676,7 @@ AC_SUBST(GEN_TOOL)
AC_SUBST(WIN_RC_VERSION) AC_SUBST(WIN_RC_VERSION)
AC_SUBST(HAVE_EXTERNAL_XIPH_LIBS) AC_SUBST(HAVE_EXTERNAL_XIPH_LIBS)
AC_SUBST(HAVE_MPEG)
AC_SUBST(OS_SPECIFIC_CFLAGS) AC_SUBST(OS_SPECIFIC_CFLAGS)
AC_SUBST(OS_SPECIFIC_LINKS) AC_SUBST(OS_SPECIFIC_LINKS)
AC_SUBST(SNDIO_LIBS) AC_SUBST(SNDIO_LIBS)
@ -672,12 +684,18 @@ AC_SUBST(SNDIO_LIBS)
AC_SUBST(EXTERNAL_XIPH_CFLAGS) AC_SUBST(EXTERNAL_XIPH_CFLAGS)
AC_SUBST(EXTERNAL_XIPH_LIBS) AC_SUBST(EXTERNAL_XIPH_LIBS)
AC_SUBST(EXTERNAL_XIPH_REQUIRE) 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(SRC_BINDIR)
AC_SUBST(TEST_BINDIR) AC_SUBST(TEST_BINDIR)
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Octave/Makefile Makefile Octave/Makefile
src/version-metadata.rc include/sndfile.h src/version-metadata.rc
tests/test_wrapper.sh tests/pedantic-header-test.sh tests/test_wrapper.sh tests/pedantic-header-test.sh
libsndfile.spec sndfile.pc libsndfile.spec sndfile.pc
Scripts/build-test-tarball.mk Scripts/build-test-tarball.mk
@ -717,6 +735,7 @@ AC_MSG_RESULT([
Experimental code : ................... ${enable_experimental:-no} Experimental code : ................... ${enable_experimental:-no}
Using ALSA in example programs : ...... ${enable_alsa:-no} Using ALSA in example programs : ...... ${enable_alsa:-no}
External FLAC/Ogg/Vorbis/Opus : ....... ${enable_external_libs:-no} External FLAC/Ogg/Vorbis/Opus : ....... ${enable_external_libs:-no}
External MPEG Lame/MPG123 : ........... ${enable_mpeg:-no}
Building Octave interface : ........... ${OCTAVE_BUILD} Building Octave interface : ........... ${OCTAVE_BUILD}
Tools : Tools :
@ -725,7 +744,6 @@ AC_MSG_RESULT([
CXX Compiler Vendor is : .............. ${ax_cv_cxx_compiler_vendor} (${ax_cv_cxx_compiler_version}) CXX Compiler Vendor is : .............. ${ax_cv_cxx_compiler_vendor} (${ax_cv_cxx_compiler_version})
Sanitizer enabled : ................... ${enable_sanitizer:-no} Sanitizer enabled : ................... ${enable_sanitizer:-no}
Stack smash protection : .............. ${enable_stack_smash_protection:-no}
Installation directories : Installation directories :

View File

@ -438,10 +438,12 @@ Use CMake project.
## Q20 : Why doesn't libsndfile support MP3? {#Q020} ## 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 patented. Those patents have now expired and there is an
[open ticket](https://github.com/libsndfile/libsndfile/issues/258) to implement [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} ## Q21 : How do I use libsndfile in a closed source or commercial program and comply with the license? {#Q021}

View File

@ -1,6 +1,6 @@
--- ---
author: "The libsndfile team" author: "The libsndfile team"
version: "1.0.31" version: "1.1.0"
markdown: kramdown markdown: kramdown
plugins: plugins:

View File

@ -12,7 +12,7 @@ title: libsndfile home page
<a href="#history">History</a> -+- <a href="#history">History</a> -+-
<a href="#features">Features</a> -+- <a href="#features">Features</a> -+-
<a href="#similar-or-related-projects">Similar or related projects</a> -+- <a href="#similar-or-related-projects">Similar or related projects</a> -+-
<a href="https://github.com/libsndfile/libsndfile/blob/master/NEWS">News</a> <a href="https://github.com/libsndfile/libsndfile/blob/master/CHANGELOG.md">News</a>
<br> <br>
<a href="development.html">Development</a> -+- <a href="development.html">Development</a> -+-
<a href="api.html">Programming interface</a> -+- <a href="api.html">Programming interface</a> -+-

View File

@ -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 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. 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 When opening a file for write, the caller must fill in structure members
**samplerate**, **channels**, and **format**. **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 also include bitmasks for separating major and minor file types. Not all
combinations of endian-ness and major and minor file types are valid. combinations of endian-ness and major and minor file types are valid.
| Name | Value | Description | | Name | Value | Description |
|:-----------------------|:-----------|:-------------------------------------------| |:-------------------------|:-----------|:-------------------------------------------|
| **Major formats.** | | **Major formats.** |
| SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). | | SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). |
| SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). | | SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). |
| SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). | | SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). |
| SF_FORMAT_RAW | 0x040000 | RAW PCM data. | | SF_FORMAT_RAW | 0x040000 | RAW PCM data. |
| SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. | | SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. |
| SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. | | SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. |
| SF_FORMAT_NIST | 0x070000 | Sphere NIST format. | | SF_FORMAT_NIST | 0x070000 | Sphere NIST format. |
| SF_FORMAT_VOC | 0x080000 | VOC files. | | SF_FORMAT_VOC | 0x080000 | VOC files. |
| SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL | | SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL |
| SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV | | 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_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 |
| SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 | | SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 |
| SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format | | SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format |
| SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument | | SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument |
| SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format | | SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format |
| SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard | | SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard |
| SF_FORMAT_AVR | 0x120000 | Audio Visual Research | | SF_FORMAT_AVR | 0x120000 | Audio Visual Research |
| SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX | | SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX |
| SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 | | SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 |
| SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format | | SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format |
| SF_FORMAT_CAF | 0x180000 | Core Audio File format | | SF_FORMAT_CAF | 0x180000 | Core Audio File format |
| SF_FORMAT_WVE | 0x190000 | Psion WVE format | | SF_FORMAT_WVE | 0x190000 | Psion WVE format |
| SF_FORMAT_OGG | 0x200000 | Xiph OGG container | | SF_FORMAT_OGG | 0x200000 | Xiph OGG container |
| SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler | | SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler |
| SF_FORMAT_RF64 | 0x220000 | RF64 WAV file | | SF_FORMAT_RF64 | 0x220000 | RF64 WAV file |
| **Subtypes.** | | SF_FORMAT_MPEG | 0x230000 | MPEG-1/2 audio stream |
| SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data | | **Subtypes.** |
| SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data | | SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data |
| SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data | | SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data |
| SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data | | SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data |
| SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) | | SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data |
| SF_FORMAT_FLOAT | 0x0006 | 32 bit float data | | SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) |
| SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data | | SF_FORMAT_FLOAT | 0x0006 | 32 bit float data |
| SF_FORMAT_ULAW | 0x0010 | U-Law encoded. | | SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data |
| SF_FORMAT_ALAW | 0x0011 | A-Law encoded. | | SF_FORMAT_ULAW | 0x0010 | U-Law encoded. |
| SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. | | SF_FORMAT_ALAW | 0x0011 | A-Law encoded. |
| SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. | | SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. |
| SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. | | SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. |
| SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM | | SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. |
| SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. | | SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM |
| SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. | | SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. |
| SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. | | SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. |
| SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. | | SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. |
| SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. | | SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. |
| SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. | | SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. |
| SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. | | SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. |
| SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. | | SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. |
| SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. | | SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. |
| SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. | | SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. |
| SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) | | SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. |
| SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) | | SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) |
| SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. | | SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) |
| SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. | | SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. |
| SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). | | SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. |
| SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). | | SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). |
| SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). | | SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). |
| SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). | | SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). |
| **Endian-ness options.** | | SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). |
| SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. | | SF_FORMAT_MPEG_LAYER_I | 0x0080 | MPEG-1 Audio Layer I. |
| SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. | | SF_FORMAT_MPEG_LAYER_II | 0x0081 | MPEG-1 Audio Layer II. |
| SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. | | SF_FORMAT_MPEG_LAYER_III | 0x0082 | MPEG-2 Audio Layer III. |
| SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. | | **Endian-ness options.** |
| SF_FORMAT_SUBMASK | 0x0000FFFF | | | SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. |
| SF_FORMAT_TYPEMASK | 0x0FFF0000 | | | SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. |
| SF_FORMAT_ENDMASK | 0x30000000 | | | 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 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**(). [**sf_close**()](#close) to free up memory allocated during the call to **sf_open**().

View File

@ -64,6 +64,7 @@ The available commands are as follows:
| [SFC_WAVEX_SET_AMBISONIC](#sfc_wavex_set_ambisonic) | Modify a WAVEX header for Ambisonic format. | | [SFC_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_VBR_ENCODING_QUALITY](#sfc_set_vbr_encoding_quality) | Set the Variable Bit Rate encoding quality. |
| [SFC_SET_OGG_PAGE_LATENCY_MS](#sfc_set_ogg_page_latency_ms) | Set Ogg page latency for Opus file. | | [SFC_SET_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_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_RAW_DATA_NEEDS_ENDSWAP](#sfc_raw_data_needs_endswap) | Determine if raw data needs endswapping. |
| [SFC_GET_BROADCAST_INFO](#sfc_get_broadcast_info) | Get the Broadcast Chunk info. | | [SFC_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_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_GET_ORIGINAL_SAMPLERATE](#sfc_get_original_samplerate) | Get original samplerate metadata. |
| [SFC_SET_ORIGINAL_SAMPLERATE](#sfc_set_original_samplerate) | Set 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. 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 ## SFC_SET_COMPRESSION_LEVEL
Set the compression level. The compression level should be between 0.0 (minimum 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, 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 [SFC_GET_CURRENT_SF_INFO](#sfc_get_current_sf_info) should be called to
determine the new frames count and samplerate 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.

View File

@ -9,7 +9,7 @@ interested in helping can raise an issue on Github.
The main repository can be found on Github: The main repository can be found on Github:
<http://libsndfile.github.io/libsndfile/"> <https://github.com/libsndfile/libsndfile/>
and includes [instuctions](https://github.com/libsndfile/libsndfile/blob/master/README.md) and includes [instuctions](https://github.com/libsndfile/libsndfile/blob/master/README.md)
on how to build libsndfile from the Git repo. on how to build libsndfile from the Git repo.

View File

@ -40,11 +40,12 @@ From version 1.0.18, libsndfile also reads and writes
From version 1.0.29, libsndfile can read and write From version 1.0.29, libsndfile can read and write
[Ogg/Opus](https://opus-codec.org/). [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: Some of the file formats I am also interested in adding are:
- Kurzweil K2000 sampler files. - Kurzweil K2000 sampler files.
- Ogg Speex. - Ogg Speex.
- MPEG Layer 3 (commonly known as MP3)
Other file formats may also be added on request. Other file formats may also be added on request.

View File

@ -142,6 +142,8 @@ Here is the release history for libsndfile:
problems, delete old generated sndfile.h from $(top_builddir)/src. problems, delete old generated sndfile.h from $(top_builddir)/src.
* Version 1.0.31 (January 24 2021) Bugfix release. Fix multiple memory leaks * 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. 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 ## 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 Check latest version on
[GitHub Releases page](https://github.com/libsndfile/libsndfile/releases/). [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: @SoapGentoo. You can verify signatures with his public GPG key:
``` ```

View File

@ -55,7 +55,7 @@ to disable gcc optimisations and make debugging with gdb/ddd easier.
Add a unique identifier for the new file type. 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 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 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 way to do this is to find the largest value in the list, add 0x10000 to it and

View File

@ -118,7 +118,7 @@ encode_file (const char *infilename, const char *outfilename, int filetype)
exit (1) ; 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_write_float (outfile, buffer, readcount) ;
sf_close (infile) ; sf_close (infile) ;

View File

@ -74,12 +74,12 @@ main (void)
if (sfinfo.channels == 1) if (sfinfo.channels == 1)
{ for (k = 0 ; k < SAMPLE_COUNT ; k++) { 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) else if (sfinfo.channels == 2)
{ for (k = 0 ; k < SAMPLE_COUNT ; k++) { for (k = 0 ; k < SAMPLE_COUNT ; k++)
{ buffer [2 * k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ; { buffer [2 * k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ;
buffer [2 * k + 1] = AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI) ; buffer [2 * k + 1] = (int) (AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI)) ;
} ; } ;
} }
else else

View File

@ -98,19 +98,21 @@ main (void)
if (sfinfo.channels > MAX_CHANNELS) if (sfinfo.channels > MAX_CHANNELS)
{ printf ("Not able to process more than %d channels\n", MAX_CHANNELS) ; { printf ("Not able to process more than %d channels\n", MAX_CHANNELS) ;
sf_close (infile) ;
return 1 ; return 1 ;
} ; } ;
/* Open the output file. */ /* Open the output file. */
if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo))) if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo)))
{ printf ("Not able to open output file %s.\n", outfilename) ; { printf ("Not able to open output file %s.\n", outfilename) ;
puts (sf_strerror (NULL)) ; puts (sf_strerror (NULL)) ;
sf_close (infile) ;
return 1 ; return 1 ;
} ; } ;
/* While there are.frames in the input file, read them, process /* While there are.frames in the input file, read them, process
** them and write them to the output file. ** 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) ; { process_data (data, readcount, sfinfo.channels) ;
sf_write_double (outfile, data, readcount) ; sf_write_double (outfile, data, readcount) ;
} ; } ;

View File

@ -46,12 +46,6 @@
#define BUFFER_LEN (1 << 14) #define BUFFER_LEN (1 << 14)
typedef struct
{ char *infilename, *outfilename ;
SF_INFO infileinfo, outfileinfo ;
} OptionData ;
const char * program_name (const char * argv0) ; const char * program_name (const char * argv0) ;
static void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ; static void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ;
static void add_instrument_data (SNDFILE *outfile, const SF_INFO * in_info) ; 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. */ /* Open the output file. */
if ((outfile = sf_open (outfilename, SFM_WRITE, &out_sfinfo)) == NULL) if ((outfile = sf_open (outfilename, SFM_WRITE, &out_sfinfo)) == NULL)
{ printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ; { printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ;
sf_close (infile) ;
return 1 ; return 1 ;
} ; } ;
@ -143,7 +138,7 @@ sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels)
readcount = frames ; readcount = frames ;
while (readcount > 0) while (readcount > 0)
{ readcount = sf_readf_int (infile, data, frames) ; { readcount = (int) sf_readf_int (infile, data, frames) ;
sf_writef_int (outfile, data, readcount) ; sf_writef_int (outfile, data, readcount) ;
} ; } ;

View File

@ -60,15 +60,21 @@ print_usage (char *progname)
} /* print_usage */ } /* print_usage */
static void static int
convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precision) convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precision)
{ float buf [BLOCK_SIZE] ; { float *buf ;
sf_count_t frames ; sf_count_t frames ;
int k, m, readcount ; 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 ; 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 (k = 0 ; k < readcount ; k++)
{ for (m = 0 ; m < channels ; m++) { for (m = 0 ; m < channels ; m++)
if (full_precision) 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 */ } /* convert_to_text */
int int
@ -89,6 +97,7 @@ main (int argc, char * argv [])
FILE *outfile = NULL ; FILE *outfile = NULL ;
SF_INFO sfinfo ; SF_INFO sfinfo ;
int full_precision = 0 ; int full_precision = 0 ;
int ret = 1 ;
progname = strrchr (argv [0], '/') ; progname = strrchr (argv [0], '/') ;
progname = progname ? progname + 1 : argv [0] ; progname = progname ? progname + 1 : argv [0] ;
@ -97,7 +106,7 @@ main (int argc, char * argv [])
{ case 4 : { case 4 :
if (!strcmp ("--full-precision", argv [3])) if (!strcmp ("--full-precision", argv [3]))
{ print_usage (progname) ; { print_usage (progname) ;
return 1 ; goto cleanup ;
} ; } ;
full_precision = 1 ; full_precision = 1 ;
argv++ ; argv++ ;
@ -105,7 +114,7 @@ main (int argc, char * argv [])
break ; break ;
default: default:
print_usage (progname) ; print_usage (progname) ;
return 1 ; goto cleanup ;
} ; } ;
infilename = argv [1] ; infilename = argv [1] ;
@ -114,19 +123,19 @@ main (int argc, char * argv [])
if (strcmp (infilename, outfilename) == 0) if (strcmp (infilename, outfilename) == 0)
{ printf ("Error : Input and output filenames are the same.\n\n") ; { printf ("Error : Input and output filenames are the same.\n\n") ;
print_usage (progname) ; print_usage (progname) ;
return 1 ; goto cleanup ;
} ; } ;
if (infilename [0] == '-') if (infilename [0] == '-')
{ printf ("Error : Input filename (%s) looks like an option.\n\n", infilename) ; { printf ("Error : Input filename (%s) looks like an option.\n\n", infilename) ;
print_usage (progname) ; print_usage (progname) ;
return 1 ; goto cleanup ;
} ; } ;
if (outfilename [0] == '-') if (outfilename [0] == '-')
{ printf ("Error : Output filename (%s) looks like an option.\n\n", outfilename) ; { printf ("Error : Output filename (%s) looks like an option.\n\n", outfilename) ;
print_usage (progname) ; print_usage (progname) ;
return 1 ; goto cleanup ;
} ; } ;
memset (&sfinfo, 0, sizeof (sfinfo)) ; memset (&sfinfo, 0, sizeof (sfinfo)) ;
@ -134,23 +143,26 @@ main (int argc, char * argv [])
if ((infile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL) if ((infile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL)
{ printf ("Not able to open input file %s.\n", infilename) ; { printf ("Not able to open input file %s.\n", infilename) ;
puts (sf_strerror (NULL)) ; puts (sf_strerror (NULL)) ;
return 1 ; goto cleanup ;
} ; } ;
/* Open the output file. */ /* Open the output file. */
if ((outfile = fopen (outfilename, "w")) == NULL) if ((outfile = fopen (outfilename, "w")) == NULL)
{ printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (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, "# Converted from file %s.\n", infilename) ;
fprintf (outfile, "# Channels %d, Sample rate %d\n", sfinfo.channels, sfinfo.samplerate) ; 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) ; sf_close (infile) ;
fclose (outfile) ; if (outfile != NULL)
fclose (outfile) ;
return 0 ; return ret ;
} /* main */ } /* main */

File diff suppressed because it is too large Load Diff

View File

@ -1,872 +0,0 @@
/*
** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** 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 <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#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 <windows.h>
** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
** #including <sndfile.h>
*/
#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 */

View File

@ -47,6 +47,8 @@
** **
** API documentation is in the doc/ directory of the source code tarball ** API documentation is in the doc/ directory of the source code tarball
** and at http://libsndfile.github.io/libsndfile/api.html. ** and at http://libsndfile.github.io/libsndfile/api.html.
**
** This file is intended to compile with C++98 and newer.
*/ */
#ifndef SNDFILE_HH #ifndef SNDFILE_HH
@ -57,10 +59,10 @@
#include <string> #include <string>
#include <new> // for std::nothrow #include <new> // for std::nothrow
#if __cplusplus < 201100 #if ((defined (_MSC_VER) && (_MSC_VER >= 1600)) || (__cplusplus >= 201100L))
#ifndef nullptr #define SF_NULL nullptr
#define nullptr NULL #else
#endif #define SF_NULL NULL
#endif #endif
class SndfileHandle class SndfileHandle
@ -78,7 +80,7 @@ class SndfileHandle
public : public :
/* Default constructor */ /* Default constructor */
SndfileHandle (void) : p (nullptr) {} ; SndfileHandle (void) : p (SF_NULL) {} ;
SndfileHandle (const char *path, int mode = SFM_READ, SndfileHandle (const char *path, int mode = SFM_READ,
int format = 0, int channels = 0, int samplerate = 0) ; int format = 0, int channels = 0, int samplerate = 0) ;
SndfileHandle (std::string const & path, int mode = SFM_READ, 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, SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ,
int format = 0, int channels = 0, int samplerate = 0) ; int format = 0, int channels = 0, int samplerate = 0) ;
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES #ifdef _WIN32
SndfileHandle (LPCWSTR wpath, int mode = SFM_READ, SndfileHandle (const wchar_t *wpath, int mode = SFM_READ,
int format = 0, int channels = 0, int samplerate = 0) ; int format = 0, int channels = 0, int samplerate = 0) ;
#endif #endif
@ -99,9 +101,9 @@ class SndfileHandle
SndfileHandle & operator = (const SndfileHandle &rhs) ; SndfileHandle & operator = (const SndfileHandle &rhs) ;
/* Mainly for debugging/testing. */ /* 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) ; } bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
@ -161,20 +163,20 @@ class SndfileHandle
inline inline
SndfileHandle::SNDFILE_ref::SNDFILE_ref (void) SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
: sf (nullptr), sfinfo (), ref (1) : sf (SF_NULL), sfinfo (), ref (1)
{} {}
inline inline
SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void) SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
{ if (sf != nullptr) sf_close (sf) ; } { if (sf != SF_NULL) sf_close (sf) ; }
inline inline
SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate) SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
: p (nullptr) : p (SF_NULL)
{ {
p = new (std::nothrow) SNDFILE_ref () ; p = new (std::nothrow) SNDFILE_ref () ;
if (p != nullptr) if (p != SF_NULL)
{ p->ref = 1 ; { p->ref = 1 ;
p->sfinfo.frames = 0 ; p->sfinfo.frames = 0 ;
@ -192,11 +194,11 @@ SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, in
inline inline
SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate) 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 () ; p = new (std::nothrow) SNDFILE_ref () ;
if (p != nullptr) if (p != SF_NULL)
{ p->ref = 1 ; { p->ref = 1 ;
p->sfinfo.frames = 0 ; p->sfinfo.frames = 0 ;
@ -214,14 +216,14 @@ SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int c
inline inline
SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate) SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
: p (nullptr) : p (SF_NULL)
{ {
if (fd < 0) if (fd < 0)
return ; return ;
p = new (std::nothrow) SNDFILE_ref () ; p = new (std::nothrow) SNDFILE_ref () ;
if (p != nullptr) if (p != SF_NULL)
{ p->ref = 1 ; { p->ref = 1 ;
p->sfinfo.frames = 0 ; p->sfinfo.frames = 0 ;
@ -239,11 +241,11 @@ SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int ch
inline inline
SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate) 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 () ; p = new (std::nothrow) SNDFILE_ref () ;
if (p != nullptr) if (p != SF_NULL)
{ p->ref = 1 ; { p->ref = 1 ;
p->sfinfo.frames = 0 ; p->sfinfo.frames = 0 ;
@ -261,7 +263,7 @@ SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mod
inline inline
SndfileHandle::~SndfileHandle (void) SndfileHandle::~SndfileHandle (void)
{ if (p != nullptr && -- p->ref == 0) { if (p != SF_NULL && -- p->ref == 0)
delete p ; delete p ;
} /* SndfileHandle destructor */ } /* SndfileHandle destructor */
@ -269,7 +271,7 @@ SndfileHandle::~SndfileHandle (void)
inline inline
SndfileHandle::SndfileHandle (const SndfileHandle &orig) SndfileHandle::SndfileHandle (const SndfileHandle &orig)
: p (orig.p) : p (orig.p)
{ if (p != nullptr) { if (p != SF_NULL)
++ p->ref ; ++ p->ref ;
} /* SndfileHandle copy constructor */ } /* SndfileHandle copy constructor */
@ -278,11 +280,11 @@ SndfileHandle::operator = (const SndfileHandle &rhs)
{ {
if (&rhs == this) if (&rhs == this)
return *this ; return *this ;
if (p != nullptr && -- p->ref == 0) if (p != SF_NULL && -- p->ref == 0)
delete p ; delete p ;
p = rhs.p ; p = rhs.p ;
if (p != nullptr) if (p != SF_NULL)
++ p->ref ; ++ p->ref ;
return *this ; return *this ;
@ -407,30 +409,30 @@ SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
inline SNDFILE * inline SNDFILE *
SndfileHandle::rawHandle (void) SndfileHandle::rawHandle (void)
{ return (p ? p->sf : nullptr) ; } { return (p ? p->sf : SF_NULL) ; }
inline SNDFILE * inline SNDFILE *
SndfileHandle::takeOwnership (void) SndfileHandle::takeOwnership (void)
{ {
if (p == nullptr || (p->ref != 1)) if (p == SF_NULL || (p->ref != 1))
return nullptr ; return SF_NULL ;
SNDFILE * sf = p->sf ; SNDFILE * sf = p->sf ;
p->sf = nullptr ; p->sf = SF_NULL ;
delete p ; delete p ;
p = nullptr ; p = SF_NULL ;
return sf ; return sf ;
} }
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES #ifdef _WIN32
inline inline
SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate) SndfileHandle::SndfileHandle (const wchar_t *wpath, int mode, int fmt, int chans, int srate)
: p (nullptr) : p (SF_NULL)
{ {
p = new (std::nothrow) SNDFILE_ref () ; p = new (std::nothrow) SNDFILE_ref () ;
if (p != nullptr) if (p != SF_NULL)
{ p->ref = 1 ; { p->ref = 1 ;
p->sfinfo.frames = 0 ; p->sfinfo.frames = 0 ;

View File

@ -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 # SYNOPSIS
@ -9,9 +9,9 @@
# DESCRIPTION # DESCRIPTION
# #
# Check whether -D_FORTIFY_SOURCE=2 can be added to CPPFLAGS without macro # Check whether -D_FORTIFY_SOURCE=2 can be added to CPPFLAGS without macro
# redefinition warnings. Some distributions (such as Gentoo Linux) enable # redefinition warnings, other cpp warnings or linker. Some distributions
# _FORTIFY_SOURCE globally in their compilers, leading to unnecessary # (such as Gentoo Linux) enable _FORTIFY_SOURCE globally in their
# warnings in the form of # compilers, leading to unnecessary warnings in the form of
# #
# <command-line>:0:0: error: "_FORTIFY_SOURCE" redefined [-Werror] # <command-line>:0:0: error: "_FORTIFY_SOURCE" redefined [-Werror]
# <built-in>: note: this is the location of the previous definition # <built-in>: 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 # _FORTIFY_SOURCE is already defined, and if not, adds -D_FORTIFY_SOURCE=2
# to CPPFLAGS. # 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 # LICENSE
# #
# Copyright (c) 2017 David Seifert <soap@gentoo.org> # Copyright (c) 2017 David Seifert <soap@gentoo.org>
# Copyright (c) 2019 Reini Urban <rurban@cpan.org>
# #
# Copying and distribution of this file, with or without modification, are # Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice # permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any # and this notice are preserved. This file is offered as-is, without any
# warranty. # warranty.
#serial 1 #serial 4
AC_DEFUN([AX_ADD_FORTIFY_SOURCE],[ 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_MSG_CHECKING([whether to add -D_FORTIFY_SOURCE=2 to CPPFLAGS])
AC_LINK_IFELSE([ AC_LINK_IFELSE([
AC_LANG_SOURCE( AC_LANG_PROGRAM([],
[[ [[
int main() {
#ifndef _FORTIFY_SOURCE #ifndef _FORTIFY_SOURCE
return 0; return 0;
#else #else
this_is_an_error; this_is_an_error;
#endif #endif
}
]] ]]
)], [ )],
AC_MSG_RESULT([yes]) AC_LINK_IFELSE([
CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" AC_LANG_SOURCE([[
], [ #define _FORTIFY_SOURCE 2
AC_MSG_RESULT([no]) #include <string.h>
]) 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
])
]) ])

View File

@ -55,10 +55,10 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [puts ("")])], pkg_link=
CFLAGS=$pkg_link_saved_CFLAGS CFLAGS=$pkg_link_saved_CFLAGS
LIBS=$pkg_link_saved_LIBS LIBS=$pkg_link_saved_LIBS
if test $pkg_link = no ; then AS_IF([test x$pkg_link = xno], [
$as_echo_n "link failed ... " AS_ECHO_N(["link failed ... "])
pkg_failed=yes pkg_failed=yes
fi ])
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
and $1[]_LIBS to avoid the need to call pkg-config. and $1[]_LIBS to avoid the need to call pkg-config.

View File

@ -16,7 +16,7 @@ AC_DEFUN([OCTAVE_MKOCTFILE_VERSION],
AC_ARG_WITH(mkoctfile, 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 ]) [ with_mkoctfile=$withval ])
test -z "$with_mkoctfile" && with_mkoctfile=mkoctfile test -z "$with_mkoctfile" && with_mkoctfile=mkoctfile

View File

@ -29,7 +29,7 @@ AC_DEFUN([AC_OCTAVE_VERSION],
[ [
AC_ARG_WITH(octave, 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 ]) [ with_octave=$withval ])
test -z "$with_octave" && with_octave=octave test -z "$with_octave" && with_octave=octave
@ -63,7 +63,7 @@ AC_DEFUN([AC_OCTAVE_CONFIG_VERSION],
[ [
AC_ARG_WITH(octave-config, 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 ]) [ with_octave_config=$withval ])
test -z "$with_octave_config" && with_octave_config=octave-config test -z "$with_octave_config" && with_octave_config=octave-config

View File

@ -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 <stdio.h>
],
[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 <cstdio>
],
[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

View File

@ -1,4 +1,4 @@
.Dd November 2, 2014 .Dd September 10, 2021
.Dt SNDFILE-PLAY 1 .Dt SNDFILE-PLAY 1
.Os .Os
.Sh NAME .Sh NAME
@ -19,6 +19,8 @@ ALSA or OSS
sndio sndio
.It FreeBSD .It FreeBSD
/dev/dsp (OSS) /dev/dsp (OSS)
.It NetBSD
/dev/audio
.It Solaris .It Solaris
/dev/audio /dev/audio
.It MacOSX 10.6 .It MacOSX 10.6

View File

@ -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 # libasound2-dev libflac-dev libogg-dev libopus-dev libvorbis-dev
# Compile the fuzzer. # Compile the fuzzer.
./autogen.sh autoreconf -vif
./configure --disable-shared --enable-ossfuzzers ./configure --disable-shared --enable-ossfuzzers
make V=1 make V=1
# Copy the fuzzer to the output directory. # Copy the fuzzer to the output directory.
cp -v ossfuzz/sndfile_fuzzer $OUT/ cp -v ossfuzz/sndfile_fuzzer $OUT/
cp -v ossfuzz/sndfile_alt_fuzzer $OUT/

View File

@ -0,0 +1,79 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sndfile.h>
#include <inttypes.h>
#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 ;
}

View File

@ -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

View File

@ -5,151 +5,35 @@
#include <sndfile.h> #include <sndfile.h>
#include <inttypes.h> #include <inttypes.h>
typedef struct #include "sndfile_fuzz_header.h"
{
sf_count_t offset;
sf_count_t length;
const unsigned char *data;
} VIO_DATA;
static sf_count_t vfget_filelen (void *user_data)
{
VIO_DATA *vf = (VIO_DATA *)user_data;
return vf->length;
}
static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
{
VIO_DATA *vf = (VIO_DATA *)user_data;
sf_count_t new_offset;
switch (whence)
{
case SEEK_SET:
new_offset = offset;
break ;
case SEEK_CUR:
new_offset = vf->offset + offset;
break ;
case SEEK_END:
new_offset = vf->length + offset;
break;
default:
break;
}
/* Ensure you can't seek outside the data */
if (new_offset > vf->length)
{
/* Trying to seek past the end of the data */
printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");"
" whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n",
new_offset, vf->length, whence, vf->offset, offset);
new_offset = vf->length;
}
else if (new_offset < 0)
{
/* Trying to seek before the start of the data */
printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset"
"(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n",
new_offset, whence, vf->offset, vf->length, offset);
new_offset = 0;
}
vf->offset = new_offset;
return vf->offset;
}
static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
{
VIO_DATA *vf = (VIO_DATA *)user_data;
if (vf->offset + count > vf->length)
{
count = vf->length - vf->offset;
}
memcpy(ptr, vf->data + vf->offset, count);
vf->offset += count;
return count;
}
static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
{
(void)ptr;
(void)count;
(void)user_data;
// Cannot write to this virtual file.
return 0;
}
static sf_count_t vftell (void *user_data)
{ VIO_DATA *vf = (VIO_DATA *)user_data;
return vf->offset;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ { VIO_DATA vio_data ;
VIO_DATA vio_data; SF_VIRTUAL_IO vio ;
SF_VIRTUAL_IO vio; SF_INFO sndfile_info ;
SF_INFO sndfile_info; SNDFILE *sndfile = NULL ;
SNDFILE *sndfile = NULL; float* read_buffer = NULL ;
float* read_buffer = NULL;
// Initialize the virtual IO structure. int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ;
vio.get_filelen = vfget_filelen; if (err)
vio.seek = vfseek; goto EXIT_LABEL ;
vio.read = vfread;
vio.write = vfwrite;
vio.tell = vftell;
// Initialize the VIO user data. // Just the right number of channels. Create some buffer space for reading.
vio_data.data = data; read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
vio_data.length = size; if (read_buffer == NULL)
vio_data.offset = 0; abort() ;
memset(&sndfile_info, 0, sizeof(SF_INFO)); while (sf_readf_float(sndfile, read_buffer, 1))
{
// Try and open the virtual file. // Do nothing with the data.
sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data); }
if (sndfile_info.channels == 0)
{
// No sound channels in file.
goto EXIT_LABEL;
}
else if (sndfile_info.channels > 1024 * 1024)
{
// Too many channels to handle.
goto EXIT_LABEL;
}
// Just the right number of channels. Create some buffer space for reading.
read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
if (read_buffer == NULL)
{
abort();
}
while (sf_readf_float(sndfile, read_buffer, 1))
{
// Do nothing with the data.
}
EXIT_LABEL: EXIT_LABEL:
if (sndfile != NULL) if (sndfile != NULL)
{ sf_close(sndfile) ;
sf_close(sndfile);
}
free(read_buffer); free(read_buffer) ;
return 0; return 0 ;
} }

View File

@ -73,7 +73,7 @@ sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize
{ data [k] /= max ; { data [k] /= max ;
if (!isfinite (data [k])) /* infinite or NaN */ if (!isfinite (data [k])) /* infinite or NaN */
return 1; return 1 ;
} }
sf_writef_double (outfile, data, readcount) ; sf_writef_double (outfile, data, readcount) ;
} ; } ;
@ -91,7 +91,7 @@ sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels)
readcount = frames ; readcount = frames ;
while (readcount > 0) while (readcount > 0)
{ readcount = sf_readf_int (infile, data, frames) ; { readcount = (int) sf_readf_int (infile, data, frames) ;
sf_writef_int (outfile, data, readcount) ; 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_16 :
case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_32 : case SF_FORMAT_PCM_32 :
case SF_FORMAT_MPEG_LAYER_III :
break ; break ;
default : 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. */ /* Special case for coding_history because we may want to append. */
if (info->coding_history != NULL) if (info->coding_history != NULL)
{ if (info->coding_hist_append) { 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])) while (slen > 1 && isspace (binfo.coding_history [slen - 1]))
slen -- ; 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)) ; memset (binfo.coding_history, 0, sizeof (binfo.coding_history)) ;
memcpy (binfo.coding_history, info->coding_history, slen) ; 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 }, { "caf", 0, SF_FORMAT_CAF },
{ "wve", 0, SF_FORMAT_WVE }, { "wve", 0, SF_FORMAT_WVE },
{ "prc", 0, SF_FORMAT_WVE }, { "prc", 0, SF_FORMAT_WVE },
{ "ogg", 0, SF_FORMAT_OGG },
{ "oga", 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 }, { "opus", 0, SF_FORMAT_OGG | SF_FORMAT_OPUS },
{ "mpc", 0, SF_FORMAT_MPC2K }, { "mpc", 0, SF_FORMAT_MPC2K },
{ "rf64", 0, SF_FORMAT_RF64 }, { "rf64", 0, SF_FORMAT_RF64 },
{ "mp3", 0, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III },
} ; /* format_map */ } ; /* format_map */
int int
@ -453,6 +455,7 @@ sfe_container_name (int format)
case SF_FORMAT_OGG : return "OGG" ; case SF_FORMAT_OGG : return "OGG" ;
case SF_FORMAT_MPC2K : return "MPC2K" ; case SF_FORMAT_MPC2K : return "MPC2K" ;
case SF_FORMAT_RF64 : return "RF64" ; case SF_FORMAT_RF64 : return "RF64" ;
case SF_FORMAT_MPEG : return "MPEG" ;
default : break ; default : break ;
} ; } ;
@ -491,6 +494,9 @@ sfe_codec_name (int format)
case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ; case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ;
case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ; case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ;
case SF_FORMAT_OPUS : return "Opus" ; 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 ; default : break ;
} ; } ;
return "unknown" ; return "unknown" ;

View File

@ -143,7 +143,7 @@ concat_data_fp (SNDFILE *wfile, SNDFILE *rofile, int channels)
sf_seek (wfile, 0, SEEK_END) ; sf_seek (wfile, 0, SEEK_END) ;
while (readcount > 0) while (readcount > 0)
{ readcount = sf_readf_double (rofile, data, frames) ; { readcount = (int) sf_readf_double (rofile, data, frames) ;
sf_writef_double (wfile, data, readcount) ; 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) ; sf_seek (wfile, 0, SEEK_END) ;
while (readcount > 0) while (readcount > 0)
{ readcount = sf_readf_int (rofile, data, frames) ; { readcount = (int) sf_readf_int (rofile, data, frames) ;
sf_writef_int (wfile, data, readcount) ; sf_writef_int (wfile, data, readcount) ;
} ; } ;

View File

@ -281,7 +281,7 @@ main (int argc, char * argv [])
continue ; 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) ; exit (1) ;
} ; } ;
@ -354,7 +354,10 @@ main (int argc, char * argv [])
|| (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT) || (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT)
|| (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT) || (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT)
|| (infileminor == SF_FORMAT_OPUS) || (outfileminor == SF_FORMAT_OPUS) || (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) { if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0)
{ printf ("Error : Not able to decode input file %s.\n", infilename) ; { printf ("Error : Not able to decode input file %s.\n", infilename) ;
return 1 ; return 1 ;
@ -388,7 +391,7 @@ copy_metadata (SNDFILE *outfile, SNDFILE *infile, int channels)
memset (&binfo, 0, sizeof (binfo)) ; memset (&binfo, 0, sizeof (binfo)) ;
if (channels < ARRAY_LEN (chanmap)) 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) if (sf_command (infile, SFC_GET_CHANNEL_MAP_INFO, chanmap, size) == SF_TRUE)
sf_command (outfile, SFC_SET_CHANNEL_MAP_INFO, chanmap, size) ; sf_command (outfile, SFC_SET_CHANNEL_MAP_INFO, chanmap, size) ;

View File

@ -65,43 +65,48 @@ static void deinterleave_double (STATE * state) ;
int int
main (int argc, char **argv) main (int argc, char **argv)
{ STATE state ; { STATE *state = NULL ;
SF_INFO sfinfo ; SF_INFO sfinfo ;
char pathname [512], ext [32], *cptr ; char pathname [512], ext [32], *cptr ;
int ch, double_split ; int ch, double_split, ret = 1 ;
if (argc != 2) if (argc != 2)
{ if (argc != 1) { if (argc != 1)
puts ("\nError : need a single input file.\n") ; puts ("\nError : need a single input file.\n") ;
usage_exit () ; 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)) ; 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)) ; { 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) if (sfinfo.channels < 2)
{ printf ("\nError : Input file '%s' only has one channel.\n", argv [1]) ; { printf ("\nError : Input file '%s' only has one channel.\n", argv [1]) ;
exit (1) ; goto cleanup ;
} ; } ;
if (sfinfo.channels > MAX_CHANNELS) if (sfinfo.channels > MAX_CHANNELS)
{ printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n", { printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n",
argv [1], sfinfo.channels, MAX_CHANNELS) ; argv [1], sfinfo.channels, MAX_CHANNELS) ;
exit (1) ; goto cleanup ;
} ; } ;
state.channels = sfinfo.channels ; state->channels = sfinfo.channels ;
sfinfo.channels = 1 ; sfinfo.channels = 1 ;
if (snprintf (pathname, sizeof (pathname), "%s", argv [1]) > (int) sizeof (pathname)) 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)) ; { 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) if ((cptr = strrchr (pathname, '.')) == NULL)
@ -114,7 +119,7 @@ main (int argc, char **argv)
printf ("Input file : %s\n", pathname) ; printf ("Input file : %s\n", pathname) ;
puts ("Output files :") ; puts ("Output files :") ;
for (ch = 0 ; ch < state.channels ; ch++) for (ch = 0 ; ch < state->channels ; ch++)
{ char filename [520] ; { char filename [520] ;
size_t count ; size_t count ;
@ -124,9 +129,9 @@ main (int argc, char **argv)
{ printf ("File name truncated to %s\n", filename) ; { 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)) ; { printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ;
exit (1) ; goto cleanup ;
} ; } ;
printf (" %s\n", filename) ; printf (" %s\n", filename) ;
@ -145,16 +150,24 @@ main (int argc, char **argv)
} ; } ;
if (double_split) if (double_split)
deinterleave_double (&state) ; deinterleave_double (state) ;
else else
deinterleave_int (&state) ; deinterleave_int (state) ;
sf_close (state.infile) ; ret = 0 ;
for (ch = 0 ; ch < MAX_CHANNELS ; ch++)
if (state.outfile [ch] != NULL)
sf_close (state.outfile [ch]) ;
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 */ } /* main */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -170,7 +183,6 @@ usage_exit (void)
"a_00.wav, a_01.wav and so on.\n" "a_00.wav, a_01.wav and so on.\n"
) ; ) ;
printf ("Using %s.\n\n", sf_version_string ()) ; printf ("Using %s.\n\n", sf_version_string ()) ;
exit (1) ;
} /* usage_exit */ } /* usage_exit */
static void static void
@ -179,7 +191,7 @@ deinterleave_int (STATE * state)
int ch, k ; int ch, k ;
do 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 (ch = 0 ; ch < state->channels ; ch ++)
{ for (k = 0 ; k < read_len ; k++) { for (k = 0 ; k < read_len ; k++)
@ -197,7 +209,7 @@ deinterleave_double (STATE * state)
int ch, k ; int ch, k ;
do 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 (ch = 0 ; ch < state->channels ; ch ++)
{ for (k = 0 ; k < read_len ; k++) { for (k = 0 ; k < read_len ; k++)

View File

@ -110,8 +110,6 @@ main (int argc, char *argv [])
** Print version and usage. ** Print version and usage.
*/ */
static double data [BUFFER_LEN] ;
static void static void
usage_exit (const char *progname) usage_exit (const char *progname)
{ printf ("Usage :\n %s <file> ...\n", progname) ; { printf ("Usage :\n %s <file> ...\n", progname) ;
@ -167,6 +165,8 @@ calc_decibels (SF_INFO * sfinfo, double max)
case SF_FORMAT_FLOAT : case SF_FORMAT_FLOAT :
case SF_FORMAT_DOUBLE : case SF_FORMAT_DOUBLE :
case SF_FORMAT_VORBIS :
case SF_FORMAT_OPUS :
decibels = max / 1.0 ; decibels = max / 1.0 ;
break ; break ;
@ -313,7 +313,9 @@ instrument_dump (const char *filename)
printf (" Loop points : %d\n", inst.loop_count) ; printf (" Loop points : %d\n", inst.loop_count) ;
for (k = 0 ; k < inst.loop_count ; k++) 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') ; putchar ('\n') ;
return 0 ; return 0 ;

View File

@ -60,46 +60,54 @@ typedef struct
} STATE ; } STATE ;
static void usage_exit (void) ; static void print_usage (void) ;
static void interleave_int (STATE * state) ; static void interleave_int (STATE * state) ;
static void interleave_double (STATE * state) ; static void interleave_double (STATE * state) ;
int int
main (int argc, char **argv) main (int argc, char **argv)
{ STATE state ; { STATE *state = NULL ;
SF_INFO sfinfo ; SF_INFO sfinfo ;
int k, double_merge = 0 ; int k, double_merge = 0 ;
int ret = 1 ;
if (argc < 5) if (argc < 5)
{ if (argc > 1) { if (argc > 1)
puts ("\nError : need at least 2 input files.") ; puts ("\nError : need at least 2 input files.") ;
usage_exit () ; print_usage () ;
goto cleanup ;
} ; } ;
if (strcmp (argv [argc - 2], "-o") != 0) if (strcmp (argv [argc - 2], "-o") != 0)
{ puts ("\nError : second last command line parameter should be '-o'.\n") ; { puts ("\nError : second last command line parameter should be '-o'.\n") ;
usage_exit () ; print_usage () ;
goto cleanup ;
} ; } ;
if (argc - 3 > MAX_INPUTS) if (argc - 3 > MAX_INPUTS)
{ printf ("\nError : Cannot handle more than %d input channels.\n\n", 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)) ; memset (&sfinfo, 0, sizeof (sfinfo)) ;
for (k = 1 ; k < argc - 2 ; k++) 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)) ; { 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) if (sfinfo.channels != 1)
{ printf ("\bError : Input file '%s' should be mono (has %d channels).\n", argv [k], sfinfo.channels) ; { 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) switch (sfinfo.format & SF_FORMAT_SUBMASK)
@ -113,28 +121,36 @@ main (int argc, char **argv)
break ; 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) ; 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)) ; { printf ("Not able to open output file '%s'\n%s\n", argv [argc - 1], sf_strerror (NULL)) ;
exit (1) ; goto cleanup ;
} ; } ;
if (double_merge) if (double_merge)
interleave_double (&state) ; interleave_double (state) ;
else else
interleave_int (&state) ; interleave_int (state) ;
for (k = 0 ; k < MAX_INPUTS ; k++) ret = 0 ;
if (state.infile [k] != NULL)
sf_close (state.infile [k]) ;
sf_close (state.outfile) ;
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 */ } /* main */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -142,12 +158,11 @@ main (int argc, char **argv)
static void static void
usage_exit (void) print_usage (void)
{ puts ("\nUsage : sndfile-interleave <input 1> <input 2> ... -o <output file>\n") ; { puts ("\nUsage : sndfile-interleave <input 1> <input 2> ... -o <output file>\n") ;
puts ("Merge two or more mono files into a single multi-channel file.\n") ; puts ("Merge two or more mono files into a single multi-channel file.\n") ;
printf ("Using %s.\n\n", sf_version_string ()) ; printf ("Using %s.\n\n", sf_version_string ()) ;
exit (1) ; } /* print_usage */
} /* usage_exit */
static void static void
@ -159,7 +174,7 @@ interleave_int (STATE * state)
{ max_read_len = 0 ; { max_read_len = 0 ;
for (ch = 0 ; ch < state->channels ; ch ++) 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) if (read_len < BUFFER_LEN)
memset (state->din.i + read_len, 0, sizeof (state->din.i [0]) * (BUFFER_LEN - read_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 ; { max_read_len = 0 ;
for (ch = 0 ; ch < state->channels ; ch ++) 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) if (read_len < BUFFER_LEN)
memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ; memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ;

View File

@ -64,7 +64,7 @@
#elif HAVE_SNDIO_H #elif HAVE_SNDIO_H
#include <sndio.h> #include <sndio.h>
#elif (defined (sun) && defined (unix)) #elif (defined (sun) && defined (unix)) || defined(__NetBSD__)
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/audioio.h> #include <sys/audioio.h>
@ -328,10 +328,12 @@ alsa_write_float (snd_pcm_t *alsa_dev, float *data, int frames, int channels)
return 0 ; return 0 ;
break ; break ;
#if defined ESTRPIPE && ESTRPIPE != EPIPE
case -ESTRPIPE : case -ESTRPIPE :
fprintf (stderr, "alsa_write_float: Suspend event.n") ; fprintf (stderr, "alsa_write_float: Suspend event.n") ;
return 0 ; return 0 ;
break ; break ;
#endif
case -EIO : case -EIO :
puts ("alsa_write_float: EIO") ; puts ("alsa_write_float: EIO") ;
@ -727,7 +729,7 @@ sndio_play (int argc, char *argv [])
** Solaris. ** Solaris.
*/ */
#if (defined (sun) && defined (unix)) /* ie Solaris */ #if (defined (sun) && defined (unix)) || defined(__NetBSD__)
static void static void
solaris_play (int argc, char *argv []) 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.channels = sfinfo.channels ;
audio_info.play.precision = 16 ; audio_info.play.precision = 16 ;
audio_info.play.encoding = AUDIO_ENCODING_LINEAR ; 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))) if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info)))
{ perror ("ioctl (AUDIO_SETINFO) failed") ; { perror ("ioctl (AUDIO_SETINFO) failed") ;
@ -807,7 +807,7 @@ solaris_play (int argc, char *argv [])
return ; return ;
} /* solaris_play */ } /* solaris_play */
#endif /* Solaris */ #endif /* Solaris or NetBSD */
/*============================================================================== /*==============================================================================
** Main function. ** Main function.
@ -845,7 +845,7 @@ main (int argc, char *argv [])
opensoundsys_play (argc, argv) ; opensoundsys_play (argc, argv) ;
#elif HAVE_SNDIO_H #elif HAVE_SNDIO_H
sndio_play (argc, argv) ; sndio_play (argc, argv) ;
#elif (defined (sun) && defined (unix)) #elif (defined (sun) && defined (unix)) || defined(__NetBSD__)
solaris_play (argc, argv) ; solaris_play (argc, argv) ;
#elif (OS_IS_WIN32 == 1) #elif (OS_IS_WIN32 == 1)
win32_play (argc, argv) ; win32_play (argc, argv) ;

View File

@ -56,6 +56,12 @@
#define NOT(x) (! (x)) #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 usage_exit (const char *progname) ;
static void salvage_file (const char * broken_wav, const char * fixed_w64) ; 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 void lseek_or_die (int fd, sf_off_t offset, int whence) ;
static sf_count_t get_file_length (int fd, const char * name) ; static sf_off_t get_file_length (int fd, const char * name) ;
static sf_count_t find_data_offset (int fd, int format) ; static sf_count_t find_data_offset (int fd, int format) ;
static void copy_data (int fd, SNDFILE * sndfile, int readsize) ; 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 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) if (lseek (fd, offset, whence) < 0)
#else
if (_lseeki64 (fd, offset, whence) < 0)
#endif
{ printf ("lseek failed : %s\n", strerror (errno)) ; { printf ("lseek failed : %s\n", strerror (errno)) ;
exit (1) ; exit (1) ;
} ; } ;
@ -191,9 +201,14 @@ lseek_or_die (int fd, off_t offset, int whence)
} /* lseek_or_die */ } /* lseek_or_die */
static sf_count_t static sf_off_t
get_file_length (int fd, const char * name) 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) if (sizeof (sbuf.st_size) != 8)
{ puts ("Error : sizeof (sbuf.st_size) != 8. Was program compiled with\n" { 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) ; exit (1) ;
} ; } ;
#ifndef _WIN32
if (fstat (fd, &sbuf) != 0) if (fstat (fd, &sbuf) != 0)
#else
if (_fstat64 (fd, &sbuf) != 0)
#endif
{ printf ("Error : fstat ('%s') failed : %s\n", name, strerror (errno)) ; { printf ("Error : fstat ('%s') failed : %s\n", name, strerror (errno)) ;
exit (1) ; exit (1) ;
} ; } ;
@ -233,7 +252,7 @@ find_data_offset (int fd, int format)
exit (1) ; exit (1) ;
} ; } ;
slen = strlen (target) ; slen = (int) strlen (target) ;
lseek_or_die (fd, 0, SEEK_SET) ; lseek_or_die (fd, 0, SEEK_SET) ;

View File

@ -267,14 +267,14 @@ db_check_all (REG_DB * db_handle)
int int
db_list_all (REG_DB * db_handle) db_list_all (REG_DB * db_handle)
{ {
printf ("%s : %p\n", __func__, db_handle) ; printf ("%s : %p\n", __func__, (void *) db_handle) ;
return 0 ; return 0 ;
} /* db_list_all */ } /* db_list_all */
int int
db_del_entry (REG_DB * db_handle, const char * entry) 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 ; return 0 ;
} /* db_del_entry */ } /* db_del_entry */
@ -428,7 +428,7 @@ static void
get_filename_pathname (REGTEST_DB * db, const char *filepath) get_filename_pathname (REGTEST_DB * db, const char *filepath)
{ {
const char * basename = db_basename (filepath) ; const char * basename = db_basename (filepath) ;
int slen ; size_t slen ;
/* Test for a relative path /* Test for a relative path
*/ */

View File

@ -6,7 +6,8 @@ includedir=@includedir@
Name: sndfile Name: sndfile
Description: A library for reading and writing audio files Description: A library for reading and writing audio files
Requires: Requires:
Requires.private: @EXTERNAL_XIPH_REQUIRE@ Requires.private: @EXTERNAL_XIPH_REQUIRE@ @EXTERNAL_MPEG_REQUIRE@
Version: @VERSION@ Version: @VERSION@
Libs: -L${libdir} -lsndfile Libs: -L${libdir} -lsndfile
Libs.private: @EXTERNAL_MPEG_LIBS@
Cflags: -I${includedir} Cflags: -I${includedir}

View File

@ -42,6 +42,8 @@
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -44,6 +44,8 @@
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -48,7 +48,7 @@ typedef struct alac_decoder_s
{ {
int32_t mPredictor [ALAC_FRAME_LENGTH] ; int32_t mPredictor [ALAC_FRAME_LENGTH] ;
uint16_t mShiftBuffer [ALAC_FRAME_LENGTH] ; uint16_t mShiftBuffer [ALAC_FRAME_LENGTH] ;
} ; } u ;
uint32_t mNumChannels ; uint32_t mNumChannels ;
} ALAC_DECODER ; } ALAC_DECODER ;

View File

@ -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.compatibleVersion <= kALACVersion, return kALAC_IncompatibleVersion ;) ;
RequireAction ((p->mConfig.bitDepth >= 8 && p->mConfig.bitDepth <= 32), return kALAC_BadBitWidth ;) ; 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 ;) ; status = kALAC_MemFullError ; goto Exit ;) ;
} }
else else
@ -247,18 +247,18 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
// decompress // decompress
set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; 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 ;) ; RequireNoErr (status, goto Exit ;) ;
if (modeU == 0) 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 else
{ {
// the special "numActive == 31" mode can be done in-place // the special "numActive == 31" mode can be done in-place
unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 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 else
@ -300,7 +300,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
//Assert (shift <= 16) ; //Assert (shift <= 16) ;
for (i = 0 ; i < numSamples ; i++) 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 // 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: case 24:
out32 = sampleBuffer + channelIndex ; out32 = sampleBuffer + channelIndex ;
if (bytesShifted != 0) if (bytesShifted != 0)
copyPredictorTo24Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; copyPredictorTo24Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
else else
copyPredictorTo24 (p->mMixBufferU, out32, numChannels, numSamples) ; copyPredictorTo24 (p->mMixBufferU, out32, numChannels, numSamples) ;
break ; break ;
case 32: case 32:
out32 = sampleBuffer + channelIndex ; out32 = sampleBuffer + channelIndex ;
if (bytesShifted != 0) if (bytesShifted != 0)
copyPredictorTo32Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; copyPredictorTo32Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
else else
copyPredictorTo32 (p->mMixBufferU, out32, numChannels, numSamples) ; copyPredictorTo32 (p->mMixBufferU, out32, numChannels, numSamples) ;
break ; break ;
@ -408,34 +408,34 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
// decompress and run predictor for "left" channel // 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) ; 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 ;) ; RequireNoErr (status, goto Exit ;) ;
if (modeU == 0) 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 else
{ {
// the special "numActive == 31" mode can be done in-place // the special "numActive == 31" mode can be done in-place
unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 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) ;
} }
// decompress and run predictor for "right" channel // 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) ; 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 ;) ; RequireNoErr (status, goto Exit ;) ;
if (modeV == 0) 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 else
{ {
// the special "numActive == 31" mode can be done in-place // the special "numActive == 31" mode can be done in-place
unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 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 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) for (i = 0 ; i < (numSamples * 2) ; i += 2)
{ {
p->mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; p->u.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 + 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: case 24:
out32 = sampleBuffer + channelIndex ; out32 = sampleBuffer + channelIndex ;
unmix24 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, unmix24 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
mixBits, mixRes, p->mShiftBuffer, bytesShifted) ; mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ;
break ; break ;
case 32: case 32:
out32 = sampleBuffer + channelIndex ; out32 = sampleBuffer + channelIndex ;
unmix32 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, unmix32 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
mixBits, mixRes, p->mShiftBuffer, bytesShifted) ; mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ;
break ; 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) // 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 // - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits
if (channelIndex >= numChannels) if (channelIndex >= numChannels)

View File

@ -34,6 +34,8 @@
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -33,6 +33,8 @@
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -18,6 +18,8 @@
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -108,6 +108,8 @@ void private_init_state (G72x_STATE *state_ptr) ;
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -294,6 +294,8 @@ extern int16_t gsm_FAC [8] ;
#if __GNUC__ #if __GNUC__
#define ALWAYS_INLINE __attribute__ ((always_inline)) #define ALWAYS_INLINE __attribute__ ((always_inline))
#elif defined _MSC_VER
#define ALWAYS_INLINE __forceinline
#else #else
#define ALWAYS_INLINE #define ALWAYS_INLINE
#endif #endif

View File

@ -234,7 +234,7 @@ static int aiff_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * itera
int int
aiff_open (SF_PRIVATE *psf) aiff_open (SF_PRIVATE *psf)
{ COMM_CHUNK comm_fmt ; { COMM_CHUNK comm_fmt ;
int error, subformat ; int error = 0, subformat ;
memset (&comm_fmt, 0, sizeof (comm_fmt)) ; memset (&comm_fmt, 0, sizeof (comm_fmt)) ;
@ -404,7 +404,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
char *cptr ; char *cptr ;
int instr_found = 0, mark_found = 0 ; 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") ; psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
if ((paiff = psf->container_data) == NULL) 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) if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
return SFE_MALLOC_FAILED ; 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)) ; psf_binheader_readf (psf, "E44", &(psf->peak_info->version), &(psf->peak_info->timestamp)) ;
if (psf->peak_info->version != 1) 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 ; ubuf.scbuf [0] = 0 ;
/* The COMM chunk has an int aligned to an odd word boundary. Some /* 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. ** to take special care.
*/ */

View File

@ -51,12 +51,12 @@ typedef struct
/* Can't have a decoder and an encoder at the same time so stick /* 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 union
{ ALAC_DECODER decoder ; { ALAC_DECODER decoder ;
ALAC_ENCODER encoder ; ALAC_ENCODER encoder ;
} ; } u ;
char enctmpname [512] ; char enctmpname [512] ;
FILE *enctmp ; FILE *enctmp ;
@ -169,7 +169,7 @@ alac_close (SF_PRIVATE *psf)
plac = psf->codec_data ; plac = psf->codec_data ;
if (psf->file.mode == SFM_WRITE) if (psf->file.mode == SFM_WRITE)
{ ALAC_ENCODER *penc = &plac->encoder ; { ALAC_ENCODER *penc = &plac->u.encoder ;
SF_CHUNK_INFO chunk_info ; SF_CHUNK_INFO chunk_info ;
sf_count_t readcount ; sf_count_t readcount ;
uint8_t kuki_data [1024] ; 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. */ /* 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)) ; 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)) ; { psf_log_printf (psf, "*** alac_decoder_init() returned %s. ***\n", alac_error_string (error)) ;
return SFE_INTERNAL ; return SFE_INTERNAL ;
} ; } ;
if (plac->decoder.mNumChannels != (unsigned) 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->decoder.mNumChannels, 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 ; return SFE_INTERNAL ;
} ; } ;
@ -357,7 +357,7 @@ alac_writer_init (SF_PRIVATE *psf)
return SFE_ALAC_FAIL_TMPFILE ; 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 ; return 0 ;
} /* alac_writer_init */ } /* alac_writer_init */
@ -402,7 +402,7 @@ alac_reader_calc_frames (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
static int static int
alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac) alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
{ ALAC_DECODER *pdec = &plac->decoder ; { ALAC_DECODER *pdec = &plac->u.decoder ;
uint32_t packet_size ; uint32_t packet_size ;
BitBuffer bit_buffer ; BitBuffer bit_buffer ;
@ -437,7 +437,7 @@ alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
static int static int
alac_encode_block (ALAC_PRIVATE *plac) alac_encode_block (ALAC_PRIVATE *plac)
{ ALAC_ENCODER *penc = &plac->encoder ; { ALAC_ENCODER *penc = &plac->u.encoder ;
uint32_t num_bytes = 0 ; uint32_t num_bytes = 0 ;
alac_encode (penc, plac->partial_block_frames, plac->buffer, plac->byte_buffer, &num_bytes) ; 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 ; break ;
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; 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 ; 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 ; break ;
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; 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 ; 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 ; break ;
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; 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 ; 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 ; break ;
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; 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 ; 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) while (len > 0)
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; { 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 ; 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) while (len > 0)
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; { 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 ; 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) while (len > 0)
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; { 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 ; 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) while (len > 0)
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; { 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 ; 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 ; pakt_size = chunk_info.datalen ;
chunk_info.data = pakt_data = malloc (pakt_size + 5) ; 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) if ((bcount = psf->get_chunk_data (psf, chunk_iterator, &chunk_info)) != SF_ERR_NO_ERROR)
{ while (chunk_iterator) { while (chunk_iterator)
@ -850,7 +852,7 @@ alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t UNUSED (pakt_offset))
count ++ ; count ++ ;
if (count > 5 || bcount + count > pakt_size) 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 ; value = 0 ;
break ; break ;
} ; } ;

View File

@ -292,69 +292,69 @@ unsigned char alaw_encode [2048 + 1] =
static inline void static inline void
alaw2s_array (unsigned char *buffer, int count, short *ptr) alaw2s_array (unsigned char *buffer, int count, short *ptr)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
ptr [count] = alaw_decode [(int) buffer [count]] ; ptr [i] = alaw_decode [(int) buffer [i]] ;
} /* alaw2s_array */ } /* alaw2s_array */
static inline void static inline void
alaw2i_array (unsigned char *buffer, int count, int *ptr) alaw2i_array (unsigned char *buffer, int count, int *ptr)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
ptr [count] = ((uint32_t) alaw_decode [(int) buffer [count]]) << 16 ; ptr [i] = ((uint32_t) alaw_decode [(int) buffer [i]]) << 16 ;
} /* alaw2i_array */ } /* alaw2i_array */
static inline void static inline void
alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; ptr [i] = normfact * alaw_decode [(int) buffer [i]] ;
} /* alaw2f_array */ } /* alaw2f_array */
static inline void static inline void
alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; ptr [i] = normfact * alaw_decode [(int) buffer [i]] ;
} /* alaw2d_array */ } /* alaw2d_array */
static inline void static inline void
s2alaw_array (const short *ptr, int count, unsigned char *buffer) s2alaw_array (const short *ptr, int count, unsigned char *buffer)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ if (ptr [count] >= 0) { if (ptr [i] >= 0)
buffer [count] = alaw_encode [ptr [count] / 16] ; buffer [i] = alaw_encode [ptr [i] / 16] ;
else else
buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ; buffer [i] = 0x7F & alaw_encode [ptr [i] / -16] ;
} ; } ;
} /* s2alaw_array */ } /* s2alaw_array */
static inline void static inline void
i2alaw_array (const int *ptr, int count, unsigned char *buffer) i2alaw_array (const int *ptr, int count, unsigned char *buffer)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ if (ptr [count] == INT_MIN) { if (ptr [i] == INT_MIN)
buffer [count] = alaw_encode [INT_MAX >> (16 + 4)] ; buffer [i] = alaw_encode [INT_MAX >> (16 + 4)] ;
else if (ptr [count] >= 0) else if (ptr [i] >= 0)
buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ; buffer [i] = alaw_encode [ptr [i] >> (16 + 4)] ;
else else
buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ; buffer [i] = 0x7F & alaw_encode [- ptr [i] >> (16 + 4)] ;
} ; } ;
} /* i2alaw_array */ } /* i2alaw_array */
static inline void static inline void
f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ if (ptr [count] >= 0) { if (ptr [i] >= 0)
buffer [count] = alaw_encode [psf_lrintf (normfact * ptr [count])] ; buffer [i] = alaw_encode [psf_lrintf (normfact * ptr [i])] ;
else else
buffer [count] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [count])] ; buffer [i] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [i])] ;
} ; } ;
} /* f2alaw_array */ } /* f2alaw_array */
static inline void static inline void
d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ if (!isfinite (ptr [count])) { if (!isfinite (ptr [i]))
buffer [count] = 0 ; buffer [i] = 0 ;
else if (ptr [count] >= 0) else if (ptr [i] >= 0)
buffer [count] = alaw_encode [psf_lrint (normfact * ptr [count])] ; buffer [i] = alaw_encode [psf_lrint (normfact * ptr [i])] ;
else else
buffer [count] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [count])] ; buffer [i] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [i])] ;
} ; } ;
} /* d2alaw_array */ } /* d2alaw_array */
@ -372,7 +372,7 @@ alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) ; alaw2s_array (ubuf.ucbuf, readcount, ptr + total) ;
total += readcount ; total += readcount ;
if (readcount < bufferlen) if (readcount < bufferlen)
@ -394,7 +394,7 @@ alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) ; alaw2i_array (ubuf.ucbuf, readcount, ptr + total) ;
total += readcount ; total += readcount ;
if (readcount < bufferlen) if (readcount < bufferlen)
@ -419,7 +419,7 @@ alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) ; alaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ;
total += readcount ; total += readcount ;
if (readcount < bufferlen) if (readcount < bufferlen)
@ -443,7 +443,7 @@ alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) ; alaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ;
total += readcount ; total += readcount ;
if (readcount < bufferlen) if (readcount < bufferlen)
@ -469,7 +469,7 @@ alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; bufferlen = (int) len ;
s2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -491,7 +491,7 @@ alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; bufferlen = (int) len ;
i2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -516,7 +516,7 @@ alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; bufferlen = (int) len ;
f2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -541,7 +541,7 @@ alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; bufferlen = (int) len ;
d2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;

View File

@ -28,8 +28,6 @@
#define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T')) #define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T'))
#define AVR_HDR_SIZE 128 #define AVR_HDR_SIZE 128
#define SFE_AVR_X 666
/* /*
** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu) ** 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) ; psf_log_printf (psf, "%M\n", hdr.marker) ;
if (hdr.marker != TWOBIT_MARKER) if (hdr.marker != TWOBIT_MARKER)
return SFE_AVR_X ; return SFE_AVR_NOT_AVR ;
psf_log_printf (psf, " Name : %s\n", hdr.name) ; psf_log_printf (psf, " Name : %s\n", hdr.name) ;
@ -145,7 +143,7 @@ avr_read_header (SF_PRIVATE *psf)
default : default :
psf_log_printf (psf, "Error : bad rez/sign combination.\n") ; 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) ; psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ;

View File

@ -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. */ /* Force coding_history_size to be even. */
len = strlen (psf->broadcast_16k->coding_history) ; len = strlen (psf->broadcast_16k->coding_history) ;
len += (len & 1) ? 1 : 0 ; 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. */ /* Currently writing this version. */
psf->broadcast_16k->version = 2 ; psf->broadcast_16k->version = 2 ;
@ -146,7 +146,7 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
break ; break ;
default : default :
snprintf (chnstr, sizeof (chnstr), "%uchn", psfinfo->channels) ; snprintf (chnstr, sizeof (chnstr), "%dchn", psfinfo->channels) ;
break ; 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, 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) ; psfinfo->samplerate, width, chnstr, PACKAGE_NAME, PACKAGE_VERSION) ;
if (count >= added_history_max) if (count >= added_history_max)

View File

@ -66,10 +66,6 @@
#define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8))) #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. ** Typedefs.
*/ */
@ -411,11 +407,16 @@ caf_read_header (SF_PRIVATE *psf)
{ case peak_MARKER : { case peak_MARKER :
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) 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)) ; 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 ; 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) if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
return SFE_MALLOC_FAILED ; return SFE_MALLOC_FAILED ;
@ -442,7 +443,7 @@ caf_read_header (SF_PRIVATE *psf)
case chan_MARKER : case chan_MARKER :
if (chunk_size < 12) if (chunk_size < 12)
{ psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; { 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 ; break ;
} }
@ -454,7 +455,7 @@ caf_read_header (SF_PRIVATE *psf)
case free_MARKER : case free_MARKER :
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; 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 ; break ;
case data_MARKER : case data_MARKER :
@ -479,14 +480,14 @@ caf_read_header (SF_PRIVATE *psf)
if (psf->datalength + psf->dataoffset < psf->filelength) if (psf->datalength + psf->dataoffset < psf->filelength)
psf->dataend = psf->datalength + psf->dataoffset ; 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 ; have_data = 1 ;
break ; break ;
case kuki_MARKER : case kuki_MARKER :
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ; 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 ; break ;
case pakt_MARKER : case pakt_MARKER :
@ -518,7 +519,7 @@ caf_read_header (SF_PRIVATE *psf)
psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ; psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ;
pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ; 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 ; break ;
case info_MARKER : case info_MARKER :
@ -537,7 +538,7 @@ caf_read_header (SF_PRIVATE *psf)
default : default :
psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ; 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 ; break ;
} ; } ;
@ -845,7 +846,7 @@ caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size)
if ((buf = malloc (chunk_size + 1)) == NULL) if ((buf = malloc (chunk_size + 1)) == NULL)
return (psf->error = SFE_MALLOC_FAILED) ; 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) ; psf_log_printf (psf, " count: %u\n", count) ;
/* Force terminate `buf` to make sure. */ /* Force terminate `buf` to make sure. */

View File

@ -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 = strlen (psf->cart_16k->tag_text) ;
len += (len & 1) ? 1 : 2 ; len += (len & 1) ? 1 : 2 ;
psf->cart_16k->tag_text_size = len ; psf->cart_16k->tag_text_size = (uint32_t) len ;
return SF_TRUE ; return SF_TRUE ;
} /* cart_var_set */ } /* cart_var_set */

View File

@ -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 ; hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ;
memcpy (psf->iterator->id, marker_str, marker_len) ; 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 ; psf->iterator->hash = hash ;
} }
@ -112,6 +112,9 @@ psf_store_read_chunk (READ_CHUNKS * pchk, const READ_CHUNK * rchunk)
{ pchk->used = 0 ; { pchk->used = 0 ;
pchk->count = 20 ; pchk->count = 20 ;
pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ; pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ;
if (!pchk->chunks)
{ return SFE_MALLOC_FAILED ;
} ;
} }
else if (pchk->used > pchk->count) else if (pchk->used > pchk->count)
return SFE_INTERNAL ; 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.offset = offset ;
rchunk.len = len ; 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) ; memcpy (rchunk.id, marker_str, rchunk.id_size) ;
return psf_store_read_chunk (pchk, &rchunk) ; 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->used = 0 ;
pchk->count = 20 ; pchk->count = 20 ;
pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ; pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ;
if (!pchk->chunks)
{ return SFE_MALLOC_FAILED ;
} ;
} }
else if (pchk->used >= pchk->count) else if (pchk->used >= pchk->count)
{ WRITE_CHUNK * old_ptr = pchk->chunks ; { WRITE_CHUNK * old_ptr = pchk->chunks ;

View File

@ -61,6 +61,12 @@ static SF_FORMAT_INFO const simple_formats [] =
}, },
#endif #endif
#if HAVE_MPEG
{ SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III,
"MPEG Layer 3", "mp3"
},
#endif
{ SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, { SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM,
"OKI Dialogic VOX ADPCM", "vox" "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_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" },
{ SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" }, { SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" },
{ SF_FORMAT_MPC2K, "MPC (Akai MPC 2k)", "mpc" }, { 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 #if HAVE_EXTERNAL_XIPH_LIBS
{ SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" }, { SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" },
#endif #endif
@ -215,6 +224,12 @@ static SF_FORMAT_INFO subtype_formats [] =
{ SF_FORMAT_OPUS, "Opus", NULL }, { SF_FORMAT_OPUS, "Opus", NULL },
#endif #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_16, "16 bit ALAC", NULL },
{ SF_FORMAT_ALAC_20, "20 bit ALAC", NULL }, { SF_FORMAT_ALAC_20, "20 bit ALAC", NULL },
{ SF_FORMAT_ALAC_24, "24 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) ; len = ARRAY_LEN (ubuf.dbuf) - (ARRAY_LEN (ubuf.dbuf) % psf->sf.channels) ;
for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */) 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++) for (k = 0 ; k < readcount ; k++)
{ temp = fabs (data [k]) ; { temp = fabs (data [k]) ;
max_val = temp > max_val ? temp : max_val ; 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 ; chan = 0 ;
readcount = len ; readcount = len ;
while (readcount > 0) 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++) for (k = 0 ; k < readcount ; k++)
{ temp = fabs (data [k]) ; { temp = fabs (data [k]) ;
peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ; peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ;

View File

@ -103,8 +103,8 @@ log_putchar (SF_PRIVATE *psf, char ch)
void void
psf_log_printf (SF_PRIVATE *psf, const char *format, ...) psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
{ va_list ap ; { va_list ap ;
uint32_t u ; uint32_t u, tens ;
int d, tens, shift, width, width_specifier, left_align, slen ; int d, shift, width, width_specifier, left_align, slen, precision ;
char c, *strptr, istr [5], lead_char, sign_char ; char c, *strptr, istr [5], lead_char, sign_char ;
va_start (ap, format) ; va_start (ap, format) ;
@ -153,6 +153,12 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
while ((c = *format++) && isdigit (c)) while ((c = *format++) && isdigit (c))
width_specifier = width_specifier * 10 + (c - '0') ; width_specifier = width_specifier * 10 + (c - '0') ;
precision = 0 ;
if (c == '.')
{ while ((c = *format++) && isdigit (c))
precision = precision * 10 + (c - '0') ;
} ;
switch (c) switch (c)
{ case 0 : /* NULL character. */ { case 0 : /* NULL character. */
va_end (ap) ; va_end (ap) ;
@ -162,12 +168,15 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
strptr = va_arg (ap, char *) ; strptr = va_arg (ap, char *) ;
if (strptr == NULL) if (strptr == NULL)
break ; break ;
slen = strlen (strptr) ; if (precision > 0)
slen = strnlen (strptr, precision) ;
else
slen = strlen (strptr) ;
width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ; width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ;
if (left_align == SF_FALSE) if (left_align == SF_FALSE)
while (width_specifier -- > 0) while (width_specifier -- > 0)
log_putchar (psf, ' ') ; log_putchar (psf, ' ') ;
while (*strptr) while (slen--)
log_putchar (psf, *strptr++) ; log_putchar (psf, *strptr++) ;
while (width_specifier -- > 0) while (width_specifier -- > 0)
log_putchar (psf, ' ') ; log_putchar (psf, ' ') ;
@ -177,15 +186,19 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
d = va_arg (ap, int) ; d = va_arg (ap, int) ;
if (d < 0) if (d < 0)
{ d = -d ; { sign_char = '-' ;
sign_char = '-' ;
if (lead_char != '0' && left_align == SF_FALSE) if (lead_char != '0' && left_align == SF_FALSE)
width_specifier -- ; width_specifier -- ;
} ;
u = - ((unsigned) d) ;
}
else
{ u = (unsigned) d ;
}
tens = 1 ; tens = 1 ;
width = 1 ; width = 1 ;
while (d / tens >= 10) while (u / tens >= 10)
{ tens *= 10 ; { tens *= 10 ;
width ++ ; width ++ ;
} ; } ;
@ -215,8 +228,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
log_putchar (psf, lead_char) ; log_putchar (psf, lead_char) ;
while (tens > 0) while (tens > 0)
{ log_putchar (psf, '0' + d / tens) ; { log_putchar (psf, '0' + u / tens) ;
d %= tens ; u %= tens ;
tens /= 10 ; tens /= 10 ;
} ; } ;
@ -225,7 +238,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
break ; break ;
case 'D': /* sf_count_t */ 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) ; D = va_arg (ap, sf_count_t) ;
@ -235,13 +249,19 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
log_putchar (psf, '0') ; log_putchar (psf, '0') ;
break ; break ;
} }
if (D < 0) else
{ log_putchar (psf, '-') ; { if (D < 0)
D = -D ; { log_putchar (psf, '-') ;
} ; U = -((uint64_t) D) ;
}
else
{ U = (uint64_t) D;
}
}
Tens = 1 ; Tens = 1 ;
width = 1 ; width = 1 ;
while (D / Tens >= 10) while (U / Tens >= 10)
{ Tens *= 10 ; { Tens *= 10 ;
width ++ ; width ++ ;
} ; } ;
@ -252,8 +272,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
} ; } ;
while (Tens > 0) while (Tens > 0)
{ log_putchar (psf, '0' + D / Tens) ; { log_putchar (psf, '0' + U / Tens) ;
D %= Tens ; U %= Tens ;
Tens /= 10 ; Tens /= 10 ;
} ; } ;
} ; } ;
@ -355,7 +375,7 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
strptr = istr ; strptr = istr ;
while (*strptr) while (*strptr)
{ c = *strptr++ ; { c = *strptr++ ;
log_putchar (psf, c) ; log_putchar (psf, psf_isprint (c) ? c : '.') ;
} ; } ;
break ; break ;
@ -520,36 +540,30 @@ header_put_le_int (SF_PRIVATE *psf, int x)
psf->header.ptr [psf->header.indx++] = (x >> 24) ; psf->header.ptr [psf->header.indx++] = (x >> 24) ;
} /* header_put_le_int */ } /* header_put_le_int */
#if (SIZEOF_SF_COUNT_T == 8)
static inline void static inline void
header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x) 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 >> 56) ;
psf->header.ptr [psf->header.indx++] = (x >> 48) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ;
psf->header.ptr [psf->header.indx++] = (x >> 40) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ;
psf->header.ptr [psf->header.indx++] = (x >> 32) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ;
psf->header.ptr [psf->header.indx++] = (x >> 24) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ;
psf->header.ptr [psf->header.indx++] = (x >> 16) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ;
psf->header.ptr [psf->header.indx++] = (x >> 8) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ;
psf->header.ptr [psf->header.indx++] = x ; psf->header.ptr [psf->header.indx++] = (unsigned char) x ;
} /* header_put_be_8byte */ } /* header_put_be_8byte */
static inline void static inline void
header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x) header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
{ psf->header.ptr [psf->header.indx++] = x ; { psf->header.ptr [psf->header.indx++] = (unsigned char) x ;
psf->header.ptr [psf->header.indx++] = (x >> 8) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ;
psf->header.ptr [psf->header.indx++] = (x >> 16) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ;
psf->header.ptr [psf->header.indx++] = (x >> 24) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ;
psf->header.ptr [psf->header.indx++] = (x >> 32) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ;
psf->header.ptr [psf->header.indx++] = (x >> 40) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ;
psf->header.ptr [psf->header.indx++] = (x >> 48) ; psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ;
psf->header.ptr [psf->header.indx++] = (x >> 56) ; psf->header.ptr [psf->header.indx++] = (x >> 56) ;
} /* header_put_le_8byte */ } /* header_put_le_8byte */
#else
#error "SIZEOF_SF_COUNT_T != 8"
#endif
int int
psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
{ va_list argptr ; { va_list argptr ;
@ -571,7 +585,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
while ((c = *format++)) while ((c = *format++))
{ {
if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16)) if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
return count ; break ;
switch (c) switch (c)
{ case ' ' : /* Do nothing. Just used to space out format string. */ { 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 ; 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))) 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) if (psf->rwf_endian == SF_ENDIAN_BIG)
header_put_be_int (psf, size + (size & 1)) ; 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 *) ; strptr = va_arg (argptr, char *) ;
size = strlen (strptr) ; 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))) 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) if (psf->rwf_endian == SF_ENDIAN_BIG)
header_put_be_int (psf, size) ; header_put_be_int (psf, size) ;
else else
@ -728,7 +742,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
size = (size > 254) ? 254 : size ; size = (size > 254) ? 254 : size ;
if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + 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) ; header_put_byte (psf, size) ;
memcpy (&(psf->header.ptr [psf->header.indx]), strptr, 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) ; size = va_arg (argptr, size_t) ;
if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) 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) ; memcpy (&(psf->header.ptr [psf->header.indx]), bindata, size) ;
psf->header.indx += size ; psf->header.indx += size ;
@ -752,7 +766,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
size = va_arg (argptr, size_t) ; size = va_arg (argptr, size_t) ;
if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
return count ; break ;
count += size ; count += size ;
while (size) while (size)
@ -773,7 +787,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
size = va_arg (argptr, size_t) ; size = va_arg (argptr, size_t) ;
if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
return count ; break ;
psf->header.indx += size ; psf->header.indx += size ;
count += size ; count += size ;
@ -783,7 +797,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
size = va_arg (argptr, size_t) ; size = va_arg (argptr, size_t) ;
if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size)) if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size))
return count ; break ;
psf->header.indx = size ; psf->header.indx = size ;
break ; break ;
@ -877,7 +891,7 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
psf_bump_header_allocation (psf, position) ; psf_bump_header_allocation (psf, position) ;
if (position > psf->header.len) if (position > psf->header.len)
{ /* Too much header to cache so just seek instead. */ { /* 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) ; psf_fseek (psf, position, whence) ;
return ; return ;
} ; } ;
@ -905,8 +919,22 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
if (psf->header.indx + position > psf->header.len) if (psf->header.indx + position > psf->header.len)
{ /* Need to jump this without caching it. */ { /* Need to jump this without caching it. */
position -= (psf->header.end - psf->header.indx) ;
psf->header.indx = psf->header.end ; 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 ; break ;
} ; } ;
@ -954,7 +982,7 @@ int
psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
{ va_list argptr ; { va_list argptr ;
sf_count_t *countptr, countdata ; sf_count_t *countptr, countdata ;
unsigned char *ucptr, sixteen_bytes [16] ; unsigned char *ucptr, sixteen_bytes [16] = { 0 } ;
unsigned int *intptr, intdata ; unsigned int *intptr, intdata ;
unsigned short *shortptr ; unsigned short *shortptr ;
char *charptr ; char *charptr ;
@ -971,7 +999,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
while ((c = *format++)) while ((c = *format++))
{ {
if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16)) if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
return count ; break ;
switch (c) switch (c)
{ case 'e' : /* All conversions are now from LE to host. */ { 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) ; memset (charptr, 0, count) ;
if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, 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) ; byte_count += header_gets (psf, charptr, count) ;
break ; break ;
@ -1127,6 +1155,10 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
byte_count += count ; byte_count += count ;
break ; break ;
case '!' : /* Clear buffer, forcing re-read. */
psf->header.end = psf->header.indx = 0 ;
break ;
default : default :
psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
psf->error = SFE_INTERNAL ; 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* void*
psf_memset (void *s, int c, sf_count_t len) psf_memset (void *s, int c, sf_count_t len)
{ char *ptr ; { char *ptr ;
@ -1246,7 +1309,11 @@ psf_memset (void *s, int c, sf_count_t len)
** bodgy something up instead. ** bodgy something up instead.
*/ */
#ifdef _MSC_VER
typedef SF_CUES_VAR (0) SF_CUES_0 ; 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 */ /* 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)) #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 * SF_CUES *
psf_cues_alloc (uint32_t cue_count) psf_cues_alloc (uint32_t cue_count)
{ SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ; { SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ;
if (pcues)
pcues->cue_count = cue_count ; { pcues->cue_count = cue_count ;
} ;
return pcues ; return pcues ;
} /* psf_cues_alloc */ } /* psf_cues_alloc */
@ -1527,6 +1595,7 @@ str_of_major_format (int format)
CASE_NAME (SF_FORMAT_CAF) ; CASE_NAME (SF_FORMAT_CAF) ;
CASE_NAME (SF_FORMAT_WVE) ; CASE_NAME (SF_FORMAT_WVE) ;
CASE_NAME (SF_FORMAT_OGG) ; CASE_NAME (SF_FORMAT_OGG) ;
CASE_NAME (SF_FORMAT_MPEG) ;
default : default :
break ; break ;
} ; } ;
@ -1563,6 +1632,9 @@ str_of_minor_format (int format)
CASE_NAME (SF_FORMAT_DPCM_8) ; CASE_NAME (SF_FORMAT_DPCM_8) ;
CASE_NAME (SF_FORMAT_DPCM_16) ; CASE_NAME (SF_FORMAT_DPCM_16) ;
CASE_NAME (SF_FORMAT_VORBIS) ; 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 : default :
break ; break ;
} ; } ;
@ -1606,8 +1678,8 @@ psf_f2s_array (const float *src, short *dest, int count, int normalize)
{ float normfact ; { float normfact ;
normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrintf (src [count] * normfact) ; dest [i] = psf_lrintf (src [i] * normfact) ;
return ; return ;
} /* psf_f2s_array */ } /* 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 ; normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) if (scaled_value >= (1.0 * 0x7FFF))
{ dest [count] = 0x7FFF ; { dest [i] = 0x7FFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) if (scaled_value <= (-8.0 * 0x1000))
{ dest [count] = 0x8000 ; { dest [i] = -0x7FFF - 1 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrintf (scaled_value) ; dest [i] = psf_lrintf (scaled_value) ;
} ; } ;
return ; return ;
@ -1640,8 +1712,8 @@ psf_d2s_array (const double *src, short *dest, int count, int normalize)
{ double normfact ; { double normfact ;
normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrint (src [count] * normfact) ; dest [i] = psf_lrint (src [i] * normfact) ;
return ; return ;
} /* psf_f2s_array */ } /* 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 ; normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) if (scaled_value >= (1.0 * 0x7FFF))
{ dest [count] = 0x7FFF ; { dest [i] = 0x7FFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) if (scaled_value <= (-8.0 * 0x1000))
{ dest [count] = 0x8000 ; { dest [i] = -0x7FFF - 1 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrint (scaled_value) ; dest [i] = psf_lrint (scaled_value) ;
} ; } ;
return ; return ;
@ -1675,8 +1747,8 @@ psf_f2i_array (const float *src, int *dest, int count, int normalize)
{ float normfact ; { float normfact ;
normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrintf (src [count] * normfact) ; dest [i] = psf_lrintf (src [i] * normfact) ;
return ; return ;
} /* psf_f2i_array */ } /* 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 ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) #if CPU_CLIPS_POSITIVE == 0
{ dest [count] = 0x7FFFFFFF ; if (scaled_value >= (1.0 * 0x7FFFFFFF))
{ dest [i] = 0x7FFFFFFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) #endif
{ dest [count] = 0x80000000 ; #if CPU_CLIPS_NEGATIVE == 0
if (scaled_value <= (-8.0 * 0x10000000))
{ dest [i] = 0x80000000 ;
continue ; continue ;
} ; } ;
#endif
dest [count] = psf_lrintf (scaled_value) ; dest [i] = psf_lrintf (scaled_value) ;
} ; } ;
return ; return ;
@ -1709,8 +1785,8 @@ psf_d2i_array (const double *src, int *dest, int count, int normalize)
{ double normfact ; { double normfact ;
normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrint (src [count] * normfact) ; dest [i] = psf_lrint (src [i] * normfact) ;
return ; return ;
} /* psf_f2i_array */ } /* 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 ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) #if CPU_CLIPS_POSITIVE == 0
{ dest [count] = 0x7FFFFFFF ; if (scaled_value >= (1.0 * 0x7FFFFFFF))
{ dest [i] = 0x7FFFFFFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) #endif
{ dest [count] = 0x80000000 ; #if CPU_CLIPS_NEGATIVE == 0
if (scaled_value <= (-8.0 * 0x10000000))
{ dest [i] = 0x80000000 ;
continue ; continue ;
} ; } ;
#endif
dest [count] = psf_lrint (scaled_value) ; dest [i] = psf_lrint (scaled_value) ;
} ; } ;
return ; return ;

View File

@ -23,6 +23,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#if HAVE_STDBOOL_H
#include <stdbool.h>
#endif
#if HAVE_INTTYPES_H #if HAVE_INTTYPES_H
#include <inttypes.h> #include <inttypes.h>
@ -47,20 +50,6 @@
#error "This code is not designed to be compiled with a C++ compiler." #error "This code is not designed to be compiled with a C++ compiler."
#endif #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 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_MAX(a, b) ((a) > (b) ? (a) : (b))
#define SF_MIN(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) ; })) #define COMPILE_TIME_ASSERT(e) (sizeof (struct { int : - !! (e) ; }))
@ -124,7 +97,6 @@
#define SF_MAX_CHANNELS 1024 #define SF_MAX_CHANNELS 1024
/* /*
* Macros for spliting the format file of SF_INFO into container type, * Macros for spliting the format file of SF_INFO into container type,
** codec type and endian-ness. ** 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 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 #if SIZEOF_WCHAR_T == 2
typedef wchar_t sfwchar_t ; typedef wchar_t sfwchar_t ;
#else #else
@ -314,20 +292,13 @@ typedef int16_t sfwchar_t ;
#endif #endif
static inline void * void *psf_memdup (const void *src, size_t n) ;
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 */
/* /*
** This version of isprint specifically ignores any locale info. Its used for ** This version of isprint specifically ignores any locale info. Its used for
** determining which characters can be printed in things like hexdumps. ** determining which characters can be printed in things like hexdumps.
*/ */
static inline int int psf_isprint (int ch) ;
psf_isprint (int ch)
{ return (ch >= ' ' && ch <= '~') ;
} /* psf_isprint */
/*======================================================================================= /*=======================================================================================
** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the ** 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 typedef struct
{ {
union char path [SF_FILENAME_LEN] ;
{ char c [SF_FILENAME_LEN] ; char dir [SF_FILENAME_LEN] ;
sfwchar_t wc [SF_FILENAME_LEN] ; char name [SF_FILENAME_LEN / 4] ;
} 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 ;
#if USE_WINDOWS_API #if USE_WINDOWS_API
/* /*
** These fields can only be used in src/file_io.c. ** These fields can only be used in src/file_io.c.
** They are basically the same as a windows file HANDLE. ** They are basically the same as a windows file HANDLE.
*/ */
void *handle, *hsaved ; void *handle, *hsaved ;
int use_wchar ;
#else #else
/* These fields can only be used in src/file_io.c. */ /* These fields can only be used in src/file_io.c. */
int filedes, savedes ; int filedes, savedes ;
#endif #endif
int do_not_close_descriptor ; int do_not_close_descriptor ;
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
} PSF_FILE ; } PSF_FILE ;
@ -390,13 +348,6 @@ typedef union
typedef struct sf_private_tag 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 ; PSF_FILE file, rsrc ;
char syserr [SF_SYSERR_LEN] ; 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 (*get_chunk_data) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
int cpu_flags ; int cpu_flags ;
ID3V2_HEADER_INFO id3_header ;
} SF_PRIVATE ; } SF_PRIVATE ;
@ -768,6 +721,17 @@ enum
SFE_OPUS_BAD_SAMPLERATE, 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. */ 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_open_rsrc (SF_PRIVATE *psf) ;
int psf_close_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) ; void psf_fclearerr (SF_PRIVATE *psf) ;
int psf_ferror (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_opus_open (SF_PRIVATE *psf) ;
int ogg_open (SF_PRIVATE *psf) ; int ogg_open (SF_PRIVATE *psf) ;
int mpeg_open (SF_PRIVATE *psf) ;
/* In progress. Do not currently work. */ /* In progress. Do not currently work. */
int mpeg_open (SF_PRIVATE *psf) ;
int rx2_open (SF_PRIVATE *psf) ; int rx2_open (SF_PRIVATE *psf) ;
int txw_open (SF_PRIVATE *psf) ; int txw_open (SF_PRIVATE *psf) ;
int wve_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 flac_init (SF_PRIVATE *psf) ;
int g72x_init (SF_PRIVATE * psf) ; int g72x_init (SF_PRIVATE * psf) ;
int alac_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ; 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) ; 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) ; 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. ** 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. ** compiler errors if code is carelessly converted from one to the other.
*/ */
static inline void void psf_strlcat (char *dest, size_t n, const char *src) ;
psf_strlcat (char *dest, size_t n, const char *src) void psf_strlcpy (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 */
/*------------------------------------------------------------------------------------ /*------------------------------------------------------------------------------------
** SIMD optimized math functions. ** 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 audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ;
int id3_skip (SF_PRIVATE * psf) ; 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) ; void alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet) ;

View File

@ -43,6 +43,9 @@
/* Will be set to 1 if flac, ogg and vorbis are available. */ /* Will be set to 1 if flac, ogg and vorbis are available. */
#cmakedefine01 HAVE_EXTERNAL_XIPH_LIBS #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. */ /* Define to 1 if you have the `floor' function. */
#cmakedefine01 HAVE_FLOOR #cmakedefine01 HAVE_FLOOR
@ -175,6 +178,9 @@
/* Define to 1 if you have the <immintrin.h> header file. */ /* Define to 1 if you have the <immintrin.h> header file. */
#cmakedefine01 HAVE_IMMINTRIN_H #cmakedefine01 HAVE_IMMINTRIN_H
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine01 HAVE_STDBOOL_H
/* Define to 1 if you have the `vsnprintf' function. */ /* Define to 1 if you have the `vsnprintf' function. */
#cmakedefine01 HAVE_VSNPRINTF #cmakedefine01 HAVE_VSNPRINTF
@ -217,9 +223,6 @@
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "@CPACK_PACKAGE_VERSION_FULL@" #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. */ /* The size of `double', as computed by sizeof. */
@SIZEOF_DOUBLE_CODE@ @SIZEOF_DOUBLE_CODE@
@ -247,9 +250,6 @@
/* The size of `off_t', as computed by sizeof. */ /* The size of `off_t', as computed by sizeof. */
@SIZEOF_OFF_T_CODE@ @SIZEOF_OFF_T_CODE@
/* Set to sizeof (long) if unknown. */
@SIZEOF_SF_COUNT_T_CODE@
/* The size of `short', as computed by sizeof. */ /* The size of `short', as computed by sizeof. */
@SIZEOF_SHORT_CODE@ @SIZEOF_SHORT_CODE@
@ -265,9 +265,6 @@
/* The size of `wchar_t', as computed by sizeof. */ /* The size of `wchar_t', as computed by sizeof. */
@SIZEOF_WCHAR_T_CODE@ @SIZEOF_WCHAR_T_CODE@
/* Set to long if unknown. */
#define TYPEOF_SF_COUNT_T @TYPEOF_SF_COUNT_T@
/* Enable extensions on AIX 3, Interix. */ /* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE #ifndef _ALL_SOURCE
# undef _ALL_SOURCE # undef _ALL_SOURCE

View File

@ -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) ; 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 ; total += thiswrite ;
len -= thiswrite ; len -= thiswrite ;
if (thiswrite < writecount) 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) ; 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 ; total += thiswrite ;
len -= thiswrite ; len -= thiswrite ;
if (thiswrite < writecount) 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)) ; bufferlen = sizeof (pdither->buffer) / (sizeof (float)) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (float) len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
writecount /= psf->sf.channels ; writecount /= psf->sf.channels ;
writecount *= psf->sf.channels ; writecount *= psf->sf.channels ;
dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, 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 ; total += thiswrite ;
len -= thiswrite ; len -= thiswrite ;
if (thiswrite < writecount) 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) ; bufferlen = sizeof (pdither->buffer) / sizeof (double) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (double) len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
writecount /= psf->sf.channels ; writecount /= psf->sf.channels ;
writecount *= psf->sf.channels ; writecount *= psf->sf.channels ;
dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, 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 ; total += thiswrite ;
len -= thiswrite ; len -= thiswrite ;
if (thiswrite < writecount) if (thiswrite < writecount)

View File

@ -486,71 +486,71 @@ double64_get_capability (SF_PRIVATE *psf)
static void static void
d2s_array (const double *src, int count, short *dest, double scale) d2s_array (const double *src, int count, short *dest, double scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = psf_lrint (scale * src [count]) ; { dest [i] = psf_lrint (scale * src [i]) ;
} ; } ;
} /* d2s_array */ } /* d2s_array */
static void static void
d2s_clip_array (const double *src, int count, short *dest, double scale) d2s_clip_array (const double *src, int count, short *dest, double scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ double tmp = scale * src [count] ; { double tmp = scale * src [i] ;
if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) if (tmp > 32767.0)
dest [count] = SHRT_MAX ; dest [i] = SHRT_MAX ;
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0) else if (tmp < -32768.0)
dest [count] = SHRT_MIN ; dest [i] = SHRT_MIN ;
else else
dest [count] = psf_lrint (tmp) ; dest [i] = psf_lrint (tmp) ;
} ; } ;
} /* d2s_clip_array */ } /* d2s_clip_array */
static void static void
d2i_array (const double *src, int count, int *dest, double scale) d2i_array (const double *src, int count, int *dest, double scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = psf_lrint (scale * src [count]) ; { dest [i] = psf_lrint (scale * src [i]) ;
} ; } ;
} /* d2i_array */ } /* d2i_array */
static void static void
d2i_clip_array (const double *src, int count, int *dest, double scale) d2i_clip_array (const double *src, int count, int *dest, double scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ float tmp = scale * src [count] ; { float tmp = scale * src [i] ;
if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) 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)) else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
dest [count] = INT_MIN ; dest [i] = INT_MIN ;
else else
dest [count] = psf_lrint (tmp) ; dest [i] = psf_lrint (tmp) ;
} ; } ;
} /* d2i_clip_array */ } /* d2i_clip_array */
static inline void static inline void
d2f_array (const double *src, int count, float *dest) d2f_array (const double *src, int count, float *dest)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = src [count] ; { dest [i] = src [i] ;
} ; } ;
} /* d2f_array */ } /* d2f_array */
static inline void static inline void
s2d_array (const short *src, double *dest, int count, double scale) s2d_array (const short *src, double *dest, int count, double scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = scale * src [count] ; { dest [i] = scale * src [i] ;
} ; } ;
} /* s2d_array */ } /* s2d_array */
static inline void static inline void
i2d_array (const int *src, double *dest, int count, double scale) i2d_array (const int *src, double *dest, int count, double scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = scale * src [count] ; { dest [i] = scale * src [i] ;
} ; } ;
} /* i2d_array */ } /* i2d_array */
static inline void static inline void
f2d_array (const float *src, double *dest, int count) f2d_array (const float *src, double *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = src [count] ; { dest [i] = src [i] ;
} ; } ;
} /* f2d_array */ } /* f2d_array */
@ -572,7 +572,7 @@ host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, readcount) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, readcount) ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -726,7 +726,7 @@ host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -755,7 +755,7 @@ host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; 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) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -811,7 +811,7 @@ replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, readcount) ; 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) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -973,7 +973,7 @@ replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -1001,7 +1001,7 @@ replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -1034,7 +1034,7 @@ replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -1049,15 +1049,15 @@ replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
static void static void
d2bd_read (double *buffer, int count) d2bd_read (double *buffer, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ; { buffer [i] = DOUBLE64_READ ((unsigned char *) &buffer [i]) ;
} ; } ;
} /* d2bd_read */ } /* d2bd_read */
static void static void
bd2d_write (double *buffer, int count) bd2d_write (double *buffer, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; { DOUBLE64_WRITE (buffer [i], (unsigned char*) &buffer [i]) ;
} ; } ;
} /* bd2d_write */ } /* bd2d_write */

View File

@ -115,9 +115,9 @@ dwd_close (SF_PRIVATE * UNUSED (psf))
** No assumptions are made about the packing of this struct. ** No assumptions are made about the packing of this struct.
*/ */
typedef struct typedef struct
{ unsigned char major, minor, compression, channels, bitwidth ; { uint8_t major, minor, compression, channels, bitwidth ;
unsigned short srate, maxval ; uint16_t srate, maxval ;
unsigned int id, datalen, frames, offset ; uint32_t id, datalen, frames, offset ;
} DWD_HEADER ; } DWD_HEADER ;
static int static int
@ -173,7 +173,7 @@ dwd_read_header (SF_PRIVATE *psf)
if (psf->filelength != dwdh.offset + dwdh.datalen) if (psf->filelength != dwdh.offset + dwdh.datalen)
{ psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; { 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 else
psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ;

View File

@ -198,7 +198,7 @@ dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
iptr = ubuf.ibuf ; iptr = ubuf.ibuf ;
bufferlen = ARRAY_LEN (ubuf.ibuf) ; bufferlen = ARRAY_LEN (ubuf.ibuf) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = iptr [k] >> 16 ; 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 ; iptr = ubuf.ibuf ;
bufferlen = ARRAY_LEN (ubuf.ibuf) ; bufferlen = ARRAY_LEN (ubuf.ibuf) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (float) (iptr [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 ; iptr = ubuf.ibuf ;
bufferlen = ARRAY_LEN (ubuf.ibuf) ; bufferlen = ARRAY_LEN (ubuf.ibuf) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (iptr [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. */ /* Load bits in bit reseviour. */
while (pdwvw->bit_count < bit_count) while (pdwvw->bit_count < bit_count)
{ if (pdwvw->b.index >= pdwvw->b.end) { 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 ; pdwvw->b.index = 0 ;
} ; } ;
@ -569,7 +569,7 @@ dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
iptr = ubuf.ibuf ; iptr = ubuf.ibuf ;
bufferlen = ARRAY_LEN (ubuf.ibuf) ; bufferlen = ARRAY_LEN (ubuf.ibuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
iptr [k] = arith_shift_left (ptr [total + k], 16) ; iptr [k] = arith_shift_left (ptr [total + k], 16) ;
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; 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 ; iptr = ubuf.ibuf ;
bufferlen = ARRAY_LEN (ubuf.ibuf) ; bufferlen = ARRAY_LEN (ubuf.ibuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
iptr [k] = psf_lrintf (normfact * ptr [total + k]) ; iptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; 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 ; iptr = ubuf.ibuf ;
bufferlen = ARRAY_LEN (ubuf.ibuf) ; bufferlen = ARRAY_LEN (ubuf.ibuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
iptr [k] = psf_lrint (normfact * ptr [total + k]) ; iptr [k] = psf_lrint (normfact * ptr [total + k]) ;
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;

View File

@ -76,6 +76,34 @@
static void psf_log_syserr (SF_PRIVATE *psf, int error) ; 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) #if (USE_WINDOWS_API == 0)
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -132,9 +160,9 @@ psf_open_rsrc (SF_PRIVATE *psf)
return 0 ; return 0 ;
/* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ /* 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 ; 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) { if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE)) 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 ** Now try for a resource fork stored as a separate file in the same
** directory, but preceded with a dot underscore. ** 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 ; 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) ; { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
return SFE_NO_ERROR ; 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 ** Now try for a resource fork stored in a separate file in the
** .AppleDouble/ directory. ** .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 ; 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) { if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
return SFE_NO_ERROR ; return SFE_NO_ERROR ;
@ -477,7 +505,7 @@ psf_is_pipe (SF_PRIVATE *psf)
static sf_count_t static sf_count_t
psf_get_filelen_fd (int fd) 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 ; struct stat64 statbuf ;
if (fstat64 (fd, &statbuf) == -1) if (fstat64 (fd, &statbuf) == -1)
@ -572,9 +600,9 @@ psf_open_fd (PSF_FILE * pfile)
} ; } ;
if (mode == 0) if (mode == 0)
fd = open (pfile->path.c, oflag) ; fd = open (pfile->path, oflag) ;
else else
fd = open (pfile->path.c, oflag, mode) ; fd = open (pfile->path, oflag, mode) ;
return fd ; return fd ;
} /* psf_open_fd */ } /* psf_open_fd */
@ -602,7 +630,7 @@ psf_fsync (SF_PRIVATE *psf)
#endif #endif
} /* psf_fsync */ } /* psf_fsync */
#elif USE_WINDOWS_API #else
/* Win32 file i/o functions implemented using native Win32 API */ /* Win32 file i/o functions implemented using native Win32 API */
@ -620,7 +648,7 @@ psf_fopen (SF_PRIVATE *psf)
psf->error = 0 ; psf->error = 0 ;
psf->file.handle = psf_open_handle (&psf->file) ; 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 ()) ; psf_log_syserr (psf, GetLastError ()) ;
return psf->error ; return psf->error ;
@ -634,14 +662,14 @@ psf_fclose (SF_PRIVATE *psf)
return 0 ; return 0 ;
if (psf->file.do_not_close_descriptor) if (psf->file.do_not_close_descriptor)
{ psf->file.handle = NULL ; { psf->file.handle = INVALID_HANDLE_VALUE ;
return 0 ; return 0 ;
} ; } ;
if ((retval = psf_close_handle (psf->file.handle)) == -1) if ((retval = psf_close_handle (psf->file.handle)) == -1)
psf_log_syserr (psf, GetLastError ()) ; psf_log_syserr (psf, GetLastError ()) ;
psf->file.handle = NULL ; psf->file.handle = INVALID_HANDLE_VALUE ;
return retval ; return retval ;
} /* psf_fclose */ } /* psf_fclose */
@ -649,13 +677,13 @@ psf_fclose (SF_PRIVATE *psf)
/* USE_WINDOWS_API */ int /* USE_WINDOWS_API */ int
psf_open_rsrc (SF_PRIVATE *psf) psf_open_rsrc (SF_PRIVATE *psf)
{ {
if (psf->rsrc.handle != NULL) if (psf->rsrc.handle != INVALID_HANDLE_VALUE)
return 0 ; return 0 ;
/* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ /* 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 ; 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) ; { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
return SFE_NO_ERROR ; 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 ** Now try for a resource fork stored as a separate file in the same
** directory, but preceded with a dot underscore. ** 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 ; 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) ; { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
return SFE_NO_ERROR ; 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 ** Now try for a resource fork stored in a separate file in the
** .AppleDouble/ directory. ** .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 ; 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) ; { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
return SFE_NO_ERROR ; return SFE_NO_ERROR ;
} ; } ;
/* No resource file found. */ /* No resource file found. */
if (psf->rsrc.handle == NULL) if (psf->rsrc.handle == INVALID_HANDLE_VALUE)
psf_log_syserr (psf, GetLastError ()) ; psf_log_syserr (psf, GetLastError ()) ;
psf->rsrc.handle = NULL ;
return psf->error ; return psf->error ;
} /* psf_open_rsrc */ } /* psf_open_rsrc */
@ -738,9 +764,9 @@ psf_get_filelen (SF_PRIVATE *psf)
/* USE_WINDOWS_API */ void /* USE_WINDOWS_API */ void
psf_init_files (SF_PRIVATE *psf) psf_init_files (SF_PRIVATE *psf)
{ psf->file.handle = NULL ; { psf->file.handle = INVALID_HANDLE_VALUE ;
psf->rsrc.handle = NULL ; psf->rsrc.handle = INVALID_HANDLE_VALUE ;
psf->file.hsaved = NULL ; psf->file.hsaved = INVALID_HANDLE_VALUE ;
} /* psf_init_files */ } /* psf_init_files */
/* USE_WINDOWS_API */ void /* USE_WINDOWS_API */ void
@ -764,6 +790,7 @@ psf_open_handle (PSF_FILE * pfile)
DWORD dwShareMode ; DWORD dwShareMode ;
DWORD dwCreationDistribution ; DWORD dwCreationDistribution ;
HANDLE handle ; HANDLE handle ;
LPWSTR pwszPath = NULL ;
switch (pfile->mode) switch (pfile->mode)
{ case SFM_READ : { case SFM_READ :
@ -785,50 +812,40 @@ psf_open_handle (PSF_FILE * pfile)
break ; break ;
default : 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 defined (WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
if (!pfile->use_wchar)
return NULL ;
CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ; CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ;
cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ; cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ;
cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ; cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ;
handle = CreateFile2 (pfile->path.wc, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ; handle = CreateFile2 (pwszPath, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ;
if (handle == INVALID_HANDLE_VALUE)
return NULL ;
return handle ;
#else #else
if (pfile->use_wchar) handle = CreateFileW (
handle = CreateFileW ( pwszPath, /* pointer to name of the file */
pfile->path.wc, /* pointer to name of the file */ dwDesiredAccess, /* access (read-write) mode */
dwDesiredAccess, /* access (read-write) mode */ dwShareMode, /* share mode */
dwShareMode, /* share mode */ 0, /* pointer to security attributes */
0, /* pointer to security attributes */ dwCreationDistribution, /* how to create */
dwCreationDistribution, /* how to create */ FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ NULL /* handle to file with attributes to copy */
NULL /* handle to file with attributes to copy */ ) ;
) ; #endif
else free (pwszPath) ;
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 ;
return handle ; return handle ;
#endif
} /* psf_open_handle */ } /* psf_open_handle */
/* USE_WINDOWS_API */ static void /* USE_WINDOWS_API */ static void
@ -860,14 +877,14 @@ psf_log_syserr (SF_PRIVATE *psf, int error)
/* USE_WINDOWS_API */ int /* USE_WINDOWS_API */ int
psf_close_rsrc (SF_PRIVATE *psf) psf_close_rsrc (SF_PRIVATE *psf)
{ psf_close_handle (psf->rsrc.handle) ; { psf_close_handle (psf->rsrc.handle) ;
psf->rsrc.handle = NULL ; psf->rsrc.handle = INVALID_HANDLE_VALUE ;
return 0 ; return 0 ;
} /* psf_close_rsrc */ } /* psf_close_rsrc */
/* USE_WINDOWS_API */ int /* USE_WINDOWS_API */ int
psf_set_stdio (SF_PRIVATE *psf) psf_set_stdio (SF_PRIVATE *psf)
{ HANDLE handle = NULL ; { HANDLE handle = INVALID_HANDLE_VALUE ;
int error = 0 ; int error = 0 ;
switch (psf->file.mode) switch (psf->file.mode)
@ -909,9 +926,7 @@ psf_set_file (SF_PRIVATE *psf, int fd)
/* USE_WINDOWS_API */ int /* USE_WINDOWS_API */ int
psf_file_valid (SF_PRIVATE *psf) psf_file_valid (SF_PRIVATE *psf)
{ if (psf->file.handle == NULL) { if (psf->file.handle == INVALID_HANDLE_VALUE)
return SF_FALSE ;
if (psf->file.handle == INVALID_HANDLE_VALUE)
return SF_FALSE ; return SF_FALSE ;
return SF_TRUE ; return SF_TRUE ;
} /* psf_set_file */ } /* psf_set_file */
@ -1073,7 +1088,7 @@ psf_ftell (SF_PRIVATE *psf)
/* USE_WINDOWS_API */ static int /* USE_WINDOWS_API */ static int
psf_close_handle (HANDLE handle) psf_close_handle (HANDLE handle)
{ if (handle == NULL) { if (handle == INVALID_HANDLE_VALUE)
return 0 ; return 0 ;
if (CloseHandle (handle) == 0) if (CloseHandle (handle) == 0)
@ -1187,386 +1202,5 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
return retval ; return retval ;
} /* psf_ftruncate */ } /* 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 <io.h>
#include <direct.h>
/* 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 #endif

View File

@ -43,6 +43,15 @@
#define ENC_BUFFER_SIZE 8192 #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 typedef enum
{ PFLAC_PCM_SHORT = 50, { PFLAC_PCM_SHORT = 50,
PFLAC_PCM_INT = 51, PFLAC_PCM_INT = 51,
@ -127,39 +136,39 @@ static FLAC__StreamEncoderWriteStatus sf_flac_enc_write_callback (const FLAC__St
static void static void
s2flac8_array (const short *src, int32_t *dest, int count) s2flac8_array (const short *src, int32_t *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
dest [count] = src [count] >> 8 ; dest [i] = src [i] >> 8 ;
} /* s2flac8_array */ } /* s2flac8_array */
static void static void
s2flac16_array (const short *src, int32_t *dest, int count) s2flac16_array (const short *src, int32_t *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
dest [count] = src [count] ; dest [i] = src [i] ;
} /* s2flac16_array */ } /* s2flac16_array */
static void static void
s2flac24_array (const short *src, int32_t *dest, int count) s2flac24_array (const short *src, int32_t *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
dest [count] = src [count] << 8 ; dest [i] = src [i] << 8 ;
} /* s2flac24_array */ } /* s2flac24_array */
static void static void
i2flac8_array (const int *src, int32_t *dest, int count) i2flac8_array (const int *src, int32_t *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
dest [count] = src [count] >> 24 ; dest [i] = src [i] >> 24 ;
} /* i2flac8_array */ } /* i2flac8_array */
static void static void
i2flac16_array (const int *src, int32_t *dest, int count) i2flac16_array (const int *src, int32_t *dest, int count)
{ {
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = src [count] >> 16 ; dest [i] = src [i] >> 16 ;
} /* i2flac16_array */ } /* i2flac16_array */
static void static void
i2flac24_array (const int *src, int32_t *dest, int count) i2flac24_array (const int *src, int32_t *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
dest [count] = src [count] >> 8 ; dest [i] = src [i] >> 8 ;
} /* i2flac24_array */ } /* i2flac24_array */
static sf_count_t static sf_count_t
@ -952,7 +961,7 @@ flac_read_loop (SF_PRIVATE *psf, unsigned len)
/* Current frame is busted, so NULL the pointer. */ /* Current frame is busted, so NULL the pointer. */
pflac->frame = NULL ; pflac->frame = NULL ;
break ; break ;
}; } ;
state = FLAC__stream_decoder_get_state (pflac->fsd) ; state = FLAC__stream_decoder_get_state (pflac->fsd) ;
if (state >= FLAC__STREAM_DECODER_END_OF_STREAM) if (state >= FLAC__STREAM_DECODER_END_OF_STREAM)
{ psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ; { 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) while (total < len)
{ pflac->ptr = ptr + total ; { 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) ; current = flac_read_loop (psf, readlen) ;
if (current == 0) if (current == 0)
break ; break ;
@ -997,7 +1006,7 @@ flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
while (total < len) while (total < len)
{ pflac->ptr = ptr + total ; { 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) ; current = flac_read_loop (psf, readlen) ;
if (current == 0) if (current == 0)
break ; break ;
@ -1017,7 +1026,7 @@ flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
while (total < len) while (total < len)
{ pflac->ptr = ptr + total ; { 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) ; current = flac_read_loop (psf, readlen) ;
if (current == 0) if (current == 0)
break ; break ;
@ -1037,7 +1046,7 @@ flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
while (total < len) while (total < len)
{ pflac->ptr = ptr + total ; { 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) ; current = flac_read_loop (psf, readlen) ;
if (current == 0) 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 ; normfact = normalize ? (8.0 * 0x10) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) if (scaled_value >= (1.0 * 0x7F))
{ dest [count] = 0x7F ; { dest [i] = 0x7F ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) if (scaled_value <= (-8.0 * 0x10))
{ dest [count] = -0x80 ; { dest [i] = -0x80 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrintf (scaled_value) ; dest [i] = psf_lrintf (scaled_value) ;
} ; } ;
return ; 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 ; normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) if (scaled_value >= (1.0 * 0x7FFF))
{ dest [count] = 0x7FFF ; { dest [i] = 0x7FFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) if (scaled_value <= (-8.0 * 0x1000))
{ dest [count] = -0x8000 ; { dest [i] = -0x8000 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrintf (scaled_value) ; dest [i] = psf_lrintf (scaled_value) ;
} ; } ;
} /* f2flac16_clip_array */ } /* 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 ; normfact = normalize ? (8.0 * 0x100000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) if (scaled_value >= (1.0 * 0x7FFFFF))
{ dest [count] = 0x7FFFFF ; { dest [i] = 0x7FFFFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) if (scaled_value <= (-8.0 * 0x100000))
{ dest [count] = -0x800000 ; { dest [i] = -0x800000 ;
continue ; continue ;
} }
dest [count] = psf_lrintf (scaled_value) ; dest [i] = psf_lrintf (scaled_value) ;
} ; } ;
return ; return ;
@ -1243,24 +1252,24 @@ static void
f2flac8_array (const float *src, int32_t *dest, int count, int normalize) f2flac8_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact = normalize ? (1.0 * 0x7F) : 1.0 ; { float normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrintf (src [count] * normfact) ; dest [i] = psf_lrintf (src [i] * normfact) ;
} /* f2flac8_array */ } /* f2flac8_array */
static void static void
f2flac16_array (const float *src, int32_t *dest, int count, int normalize) f2flac16_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; { float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrintf (src [count] * normfact) ; dest [i] = psf_lrintf (src [i] * normfact) ;
} /* f2flac16_array */ } /* f2flac16_array */
static void static void
f2flac24_array (const float *src, int32_t *dest, int count, int normalize) f2flac24_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; { float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrintf (src [count] * normfact) ; dest [i] = psf_lrintf (src [i] * normfact) ;
} /* f2flac24_array */ } /* f2flac24_array */
static sf_count_t 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 ; normfact = normalize ? (8.0 * 0x10) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) if (scaled_value >= (1.0 * 0x7F))
{ dest [count] = 0x7F ; { dest [i] = 0x7F ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) if (scaled_value <= (-8.0 * 0x10))
{ dest [count] = -0x80 ; { dest [i] = -0x80 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrint (scaled_value) ; dest [i] = psf_lrint (scaled_value) ;
} ; } ;
return ; 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 ; normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) if (scaled_value >= (1.0 * 0x7FFF))
{ dest [count] = 0x7FFF ; { dest [i] = 0x7FFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) if (scaled_value <= (-8.0 * 0x1000))
{ dest [count] = -0x8000 ; { dest [i] = -0x8000 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrint (scaled_value) ; dest [i] = psf_lrint (scaled_value) ;
} ; } ;
return ; 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 ; normfact = normalize ? (8.0 * 0x100000) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ scaled_value = src [count] * normfact ; { scaled_value = src [i] * normfact ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) if (scaled_value >= (1.0 * 0x7FFFFF))
{ dest [count] = 0x7FFFFF ; { dest [i] = 0x7FFFFF ;
continue ; continue ;
} ; } ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) if (scaled_value <= (-8.0 * 0x100000))
{ dest [count] = -0x800000 ; { dest [i] = -0x800000 ;
continue ; continue ;
} ; } ;
dest [count] = psf_lrint (scaled_value) ; dest [i] = psf_lrint (scaled_value) ;
} ; } ;
return ; return ;
@ -1375,24 +1384,24 @@ static void
d2flac8_array (const double *src, int32_t *dest, int count, int normalize) d2flac8_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact = normalize ? (1.0 * 0x7F) : 1.0 ; { double normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrint (src [count] * normfact) ; dest [i] = psf_lrint (src [i] * normfact) ;
} /* d2flac8_array */ } /* d2flac8_array */
static void static void
d2flac16_array (const double *src, int32_t *dest, int count, int normalize) d2flac16_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; { double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrint (src [count] * normfact) ; dest [i] = psf_lrint (src [i] * normfact) ;
} /* d2flac16_array */ } /* d2flac16_array */
static void static void
d2flac24_array (const double *src, int32_t *dest, int count, int normalize) d2flac24_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; { double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
while (--count >= 0) for (int i = 0 ; i < count ; i++)
dest [count] = psf_lrint (src [count] * normfact) ; dest [i] = psf_lrint (src [i] * normfact) ;
} /* d2flac24_array */ } /* d2flac24_array */
static sf_count_t static sf_count_t

View File

@ -437,71 +437,71 @@ float32_get_capability (SF_PRIVATE *psf)
static void static void
f2s_array (const float *src, int count, short *dest, float scale) f2s_array (const float *src, int count, short *dest, float scale)
{ {
while (--count >= 0) for (int i = 0 ; i < count ; i++)
{ dest [count] = psf_lrintf (scale * src [count]) ; { dest [i] = psf_lrintf (scale * src [i]) ;
} ; } ;
} /* f2s_array */ } /* f2s_array */
static void static void
f2s_clip_array (const float *src, int count, short *dest, float scale) f2s_clip_array (const float *src, int count, short *dest, float scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ float tmp = scale * src [count] ; { float tmp = scale * src [i] ;
if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) if (tmp > 32767.0)
dest [count] = SHRT_MAX ; dest [i] = SHRT_MAX ;
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0) else if (tmp < -32768.0)
dest [count] = SHRT_MIN ; dest [i] = SHRT_MIN ;
else else
dest [count] = psf_lrintf (tmp) ; dest [i] = psf_lrintf (tmp) ;
} ; } ;
} /* f2s_clip_array */ } /* f2s_clip_array */
static inline void static inline void
f2i_array (const float *src, int count, int *dest, float scale) f2i_array (const float *src, int count, int *dest, float scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = psf_lrintf (scale * src [count]) ; { dest [i] = psf_lrintf (scale * src [i]) ;
} ; } ;
} /* f2i_array */ } /* f2i_array */
static inline void static inline void
f2i_clip_array (const float *src, int count, int *dest, float scale) f2i_clip_array (const float *src, int count, int *dest, float scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ float tmp = scale * src [count] ; { float tmp = scale * src [i] ;
if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) 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)) else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
dest [count] = INT_MIN ; dest [i] = INT_MIN ;
else else
dest [count] = psf_lrintf (tmp) ; dest [i] = psf_lrintf (tmp) ;
} ; } ;
} /* f2i_clip_array */ } /* f2i_clip_array */
static inline void static inline void
f2d_array (const float *src, int count, double *dest) f2d_array (const float *src, int count, double *dest)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = src [count] ; { dest [i] = src [i] ;
} ; } ;
} /* f2d_array */ } /* f2d_array */
static inline void static inline void
s2f_array (const short *src, float *dest, int count, float scale) s2f_array (const short *src, float *dest, int count, float scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = scale * src [count] ; { dest [i] = scale * src [i] ;
} ; } ;
} /* s2f_array */ } /* s2f_array */
static inline void static inline void
i2f_array (const int *src, float *dest, int count, float scale) i2f_array (const int *src, float *dest, int count, float scale)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = scale * src [count] ; { dest [i] = scale * src [i] ;
} ; } ;
} /* i2f_array */ } /* i2f_array */
static inline void static inline void
d2f_array (const double *src, float *dest, int count) d2f_array (const double *src, float *dest, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ dest [count] = src [count] ; { dest [i] = src [i] ;
} ; } ;
} /* d2f_array */ } /* d2f_array */
@ -523,7 +523,7 @@ host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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 */ /* Fix me : Need lef2s_array */
if (psf->data_endswap == SF_TRUE) 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -676,7 +676,7 @@ host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; 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) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -736,7 +736,7 @@ host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -762,7 +762,7 @@ replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; endswap_int_array (ubuf.ibuf, bufferlen) ;
@ -787,12 +787,12 @@ replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
float scale ; float scale ;
bufferlen = ARRAY_LEN (ubuf.fbuf) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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) while (len > 0)
{ if (len < bufferlen) { if (len < bufferlen)
bufferlen = (int) len ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -924,7 +924,7 @@ replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -957,7 +957,7 @@ replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -988,7 +988,7 @@ replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
if (psf->data_endswap == SF_TRUE) if (psf->data_endswap == SF_TRUE)
endswap_int_array (ubuf.ibuf, bufferlen) ; 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 ; total += writecount ;
if (writecount < bufferlen) if (writecount < bufferlen)
break ; break ;
@ -1003,15 +1003,15 @@ replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
static void static void
bf2f_array (float *buffer, int count) bf2f_array (float *buffer, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ; { buffer [i] = FLOAT32_READ ((unsigned char *) &buffer [i]) ;
} ; } ;
} /* bf2f_array */ } /* bf2f_array */
static void static void
f2bf_array (float *buffer, int count) f2bf_array (float *buffer, int count)
{ while (--count >= 0) { for (int i = 0 ; i < count ; i++)
{ FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; { FLOAT32_WRITE (buffer [i], (unsigned char*) &buffer [i]) ;
} ; } ;
} /* f2bf_array */ } /* f2bf_array */

View File

@ -141,7 +141,7 @@ g72x_init (SF_PRIVATE * psf)
else else
pg72x->blocks_total = psf->datalength / pg72x->blocksize ; 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) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = g72x_read_block (psf, pg72x, sptr, readcount) ; count = g72x_read_block (psf, pg72x, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = g72x_read_block (psf, pg72x, sptr, readcount) ; count = g72x_read_block (psf, pg72x, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = g72x_read_block (psf, pg72x, sptr, readcount) ; count = g72x_read_block (psf, pg72x, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (sptr [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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ; sptr [k] = ptr [total + k] >> 16 ;
count = g72x_write_block (psf, pg72x, sptr, writecount) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
count = g72x_write_block (psf, pg72x, sptr, writecount) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrint (normfact * ptr [total + k]) ; sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
count = g72x_write_block (psf, pg72x, sptr, writecount) ; count = g72x_write_block (psf, pg72x, sptr, writecount) ;

View File

@ -150,7 +150,7 @@ Need separate gsm_data structs for encode and decode.
pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ; 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) ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
@ -198,7 +198,7 @@ gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
return 1 ; 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) ; 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) 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 ; 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) ; psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) 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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = arith_shift_left (sptr [k], 16) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [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) ; gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
/* Write the block to disk. */ /* 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) ; psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
pgsm610->samplecount = 0 ; 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) ; gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAVLIKE_GSM610_SAMPLES / 2, pgsm610->block+WAVLIKE_GSM610_BLOCKSIZE / 2) ;
/* Write the block to disk. */ /* 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) ; psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ;
pgsm610->samplecount = 0 ; pgsm610->samplecount = 0 ;
@ -532,7 +532,7 @@ gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
sptr = ubuf.sbuf ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ; sptr [k] = ptr [total + k] >> 16 ;
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrint (normfact * ptr [total + k]) ; sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;

View File

@ -26,34 +26,107 @@
#include "sndfile.h" #include "sndfile.h"
#include "sfendian.h" #include "sfendian.h"
#include "common.h" #include "common.h"
#include "id3.h"
#if HAVE_MPEG
#include <lame/lame.h>
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 int
id3_skip (SF_PRIVATE * psf) id3_skip (SF_PRIVATE * psf)
{ unsigned char buf [10] ; { unsigned char buf [10] ;
int offset ;
memset (buf, 0, sizeof (buf)) ; memset (buf, 0, sizeof (buf)) ;
psf_binheader_readf (psf, "pb", 0, buf, 10) ; psf_binheader_readf (psf, "pb", 0, buf, 10) ;
if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3') 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 [7] & 0x7f) ;
offset = (offset << 7) | (buf [8] & 0x7f) ; offset = (offset << 7) | (buf [8] & 0x7f) ;
offset = (offset << 7) | (buf [9] & 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. */ /* Never want to jump backwards in a file. */
if (offset < 0) if (offset < 0)
return 0 ; return 0 ;
/* Calculate new file offset and position ourselves there. */ /* Position ourselves at the new file offset. */
offset += 10 ; if (psf->fileoffset + psf->id3_header.len < psf->filelength)
if (psf->fileoffset + offset < psf->filelength) { psf_binheader_readf (psf, "p!", psf->id3_header.len) ;
{ psf_binheader_readf (psf, "p", offset) ; psf->fileoffset += psf->id3_header.len ;
psf->fileoffset += offset ;
return 1 ; return 1 ;
} ; } ;
} ; } ;
return 0 ; return 0 ;
} /* id3_skip */ } /* 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 */

29
src/id3.h Normal file
View File

@ -0,0 +1,29 @@
/*
** Copyright (C) 2008-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2019 Arthur Taylor <art@ified.ca>
**
** This program is free software ; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation ; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY ; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program ; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SF_SRC_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 */

View File

@ -182,7 +182,12 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
if (psf->file.mode != SFM_READ) if (psf->file.mode != SFM_READ)
return SFE_BAD_MODE_RW ; 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))) if (! (pima = calloc (1, pimasize)))
return SFE_MALLOC_FAILED ; return SFE_MALLOC_FAILED ;
@ -268,7 +273,7 @@ count ++ ;
return 1 ; 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) ; psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
/* Read and check the block header. */ /* 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. */ /* 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) ; psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ;
memset (pima->block, 0, 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 static int
wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
{ int chan, k, predictor, blockindx, indx, indxstart, diff ; { int chan, k, predictor, blockindx, indx, indxstart, diff ;
short step, bytecode, stepindx [2] ; short step, bytecode, stepindx [2] = { 0 };
pima->blockcount ++ ; pima->blockcount ++ ;
pima->samplecount = 0 ; pima->samplecount = 0 ;
@ -396,7 +401,7 @@ wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
return 1 ; 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) ; psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
/* Read and check the block header. */ /* 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. */ /* 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) ; psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ;
memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ; memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ;

View File

@ -46,8 +46,6 @@
#define HEADER_LENGTH 42 /* Sum of above data fields. */ #define HEADER_LENGTH 42 /* Sum of above data fields. */
#define HEADER_NAME_LEN 17 /* Length of name string. */ #define HEADER_NAME_LEN 17 /* Length of name string. */
#define SFE_MPC_NO_MARKER 666
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
** Private static functions. ** Private static functions.
*/ */
@ -131,7 +129,7 @@ mpc2k_write_header (SF_PRIVATE *psf, int calc_length)
if (psf->is_pipe == SF_FALSE) if (psf->is_pipe == SF_FALSE)
psf_fseek (psf, 0, SEEK_SET) ; 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, "e11b", BHW1 (1), BHW1 (4), BHWv (sample_name), BHWz (HEADER_NAME_LEN)) ;
psf_binheader_writef (psf, "e111", BHW1 (100), BHW1 (0), BHW1 ((psf->sf.channels - 1) & 1)) ; psf_binheader_writef (psf, "e111", BHW1 (100), BHW1 (0), BHW1 ((psf->sf.channels - 1) & 1)) ;

165
src/mpeg.c Normal file
View File

@ -0,0 +1,165 @@
/*
** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2021 Arthur Taylor <art@ified.ca>
**
** This program is free software ; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation ; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY ; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program ; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include "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

74
src/mpeg.h Normal file
View File

@ -0,0 +1,74 @@
/*
** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2019 Arthur Taylor <art@ified.ca>
**
** This program is free software ; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation ; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY ; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program ; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef 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 */

638
src/mpeg_decode.c Normal file
View File

@ -0,0 +1,638 @@
/*
** Copyright (C) 2019 - 2021 Arthur Taylor <art@ified.ca>
** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software ; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** 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 <math.h>
#include "sndfile.h"
#include "common.h"
#include "mpeg.h"
#if HAVE_MPEG
#include "sfendian.h"
#include "id3.h"
#include <mpg123.h>
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 */

784
src/mpeg_l3_encode.c Normal file
View File

@ -0,0 +1,784 @@
/*
** Copyright (C) 2020 Arthur Taylor <art@ified.ca>
** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software ; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** 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 <lame/lame.h>
/*
* 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

View File

@ -128,8 +128,14 @@ wavlike_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
if (psf->file.mode == SFM_WRITE) if (psf->file.mode == SFM_WRITE)
samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
if (blockalign < 7 * psf->sf.channels) /* There's 7 samples per channel in the preamble of each block */
{ psf_log_printf (psf, "*** Error blockalign (%d) should be > %d.\n", blockalign, 7 * psf->sf.channels) ; 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 ; return SFE_INTERNAL ;
} ; } ;
@ -224,7 +230,7 @@ msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
return 1 ; 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) ; { psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ;
if (k <= 0) if (k <= 0)
return 1 ; return 1 ;
@ -349,7 +355,7 @@ msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
while (len > 0) while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; { 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 ; return -1 ;
total += count ; total += count ;
@ -376,9 +382,9 @@ msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
sptr = ubuf.sbuf ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) 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 ; return -1 ;
for (k = 0 ; k < readcount ; k++) 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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) 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 ; return -1 ;
for (k = 0 ; k < readcount ; k++) 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 ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) 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 ; return -1 ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
@ -627,7 +633,7 @@ msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
/* Write the block to disk. */ /* 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) ; psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ;
memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ; 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) while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; { 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 ; total += count ;
len -= count ; len -= count ;
@ -699,10 +705,10 @@ msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
sptr = ubuf.sbuf ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ; 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 ; total += count ;
len -= writecount ; len -= writecount ;
if (count != writecount) if (count != writecount)
@ -729,10 +735,10 @@ msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
sptr = ubuf.sbuf ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrintf (normfact * ptr [total + 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 ; total += count ;
len -= writecount ; len -= writecount ;
if (count != writecount) if (count != writecount)
@ -759,10 +765,10 @@ msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
sptr = ubuf.sbuf ; sptr = ubuf.sbuf ;
bufferlen = ARRAY_LEN (ubuf.sbuf) ; bufferlen = ARRAY_LEN (ubuf.sbuf) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrint (normfact * ptr [total + 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 ; total += count ;
len -= writecount ; len -= writecount ;
if (count != writecount) if (count != writecount)

View File

@ -702,7 +702,7 @@ static int
psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms) psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms)
{ int k ; { 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) ; { 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)) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ; { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++) for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (sptr [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) ; endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ;
/* Write the block to disk. */ /* 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) ; psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pnms->shortsperblock) ;
pnms->sample_curr = 0 ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ; sptr [k] = ptr [total + k] >> 16 ;
count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; 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 ; sptr = ubuf.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ; bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0) while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ; { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++) for (k = 0 ; k < writecount ; k++)
sptr [k] = psf_lrint (normfact * ptr [total + k]) ; sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;

View File

@ -165,6 +165,8 @@ ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
return SFE_NOT_SEEKABLE ; return SFE_NOT_SEEKABLE ;
buffer = ogg_sync_buffer (&odata->osync, psf->header.indx) ; buffer = ogg_sync_buffer (&odata->osync, psf->header.indx) ;
if (buffer == NULL)
return SFE_MALLOC_FAILED ;
memcpy (buffer, psf->header.ptr, psf->header.indx) ; memcpy (buffer, psf->header.ptr, psf->header.indx) ;
ogg_sync_wrote (&odata->osync, 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 else
nb_read = OGG_SYNC_READ_SIZE ; nb_read = OGG_SYNC_READ_SIZE ;
buffer = (unsigned char *) ogg_sync_buffer (&odata->osync, nb_read) ; 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) ; read_ret = psf_fread (buffer, 1, nb_read, psf) ;
if (read_ret == 0) if (read_ret == 0)
return psf->error ? -1 : 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 */ } /* ogg_sync_last_page_before */
int 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 ; { ogg_page page ;
uint64_t gp ; uint64_t gp ;
sf_count_t d0, d1, d2 ; 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) if (buffering)
ogg_stream_reset (&odata->ostream) ; ogg_stream_reset (&odata->ostream) ;
/* Check to see if the last packet continues. */ /* 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) ; { ogg_page_search_continued_data (odata, &page) ;
/* /*
** If we have a continued packet, remember the offset of ** 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. ** remember the end of the page.
*/ */
best_start = page_offset ; best_start = page_offset ;
} ; /*
/* ** Then force buffering on, so that if a packet starts (but
** Then force buffering on, so that if a packet starts (but ** does not end) on the next page, we still avoid the extra
** does not end) on the next page, we still avoid the extra ** seek back.
** seek back. */
*/ buffering = SF_TRUE ;
buffering = SF_TRUE ; } ;
*best_gp = pcm_start = gp ; *best_gp = pcm_start = gp ;
if (target_gp - gp > 48000) if (target_gp - gp > gp_rate)
{ /* Out by over a second. Try another bisection. */ { /* Out by over a second. Try another bisection. */
break ; break ;
} }

View File

@ -57,7 +57,36 @@ typedef struct
((buf [base + 2] <<16) & 0xff0000) | \ ((buf [base + 2] <<16) & 0xff0000) | \
((buf [base + 1] << 8) & 0xff00) | \ ((buf [base + 1] << 8) & 0xff00) | \
(buf [base] & 0xff)) (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 *) ; 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 ** Preforms a bisection search. If not found exactly, the best result is
** returned in *best_gp. Found page is loaded into the virtual bitstream, ** 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 ** 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, 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 target_gp,
uint64_t *best_gp, sf_count_t begin, sf_count_t end) ; 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 */ #endif /* SF_SRC_OGG_H */

View File

@ -171,16 +171,26 @@
#define OGG_OPUS_COMMENT_PAD (512) /* Same as oggenc default */ #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 ** default for non-realtime of 20ms. While longer packets reduce the overhead
** data somewhat, it also decreases the quality. ** data somewhat, it also decreases the quality.
*/ */
#define OGG_OPUS_ENCODE_PACKET_LEN(samplerate) ((20 * (samplerate)) / 1000) #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 typedef struct
{ uint8_t version ; { uint8_t version ;
@ -215,10 +225,12 @@ typedef struct
{ uint32_t serialno ; { uint32_t serialno ;
OpusHeader header ; 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 ; 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 ; uint64_t pg_pos ;
/* integer coefficient of (current sample rate) / 48000Hz */ /* 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_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 (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_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 sf_count_t ogg_opus_page_seek_manual (SF_PRIVATE *psf, uint64_t target_gp) ;
static int ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp) ; static int ogg_opus_page_seek_search (SF_PRIVATE *psf, uint64_t target_gp) ;
static int ogg_opus_analyze_file (SF_PRIVATE *psf) ; static int ogg_opus_analyze_file (SF_PRIVATE *psf) ;
static int ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; static int ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
@ -409,27 +421,27 @@ ogg_opus_close (SF_PRIVATE *psf)
static void static void
opus_print_header (SF_PRIVATE *psf, OpusHeader *h) opus_print_header (SF_PRIVATE *psf, OpusHeader *h)
{ psf_log_printf (psf, "Opus Header Metadata\n") ; { psf_log_printf (psf, "Opus Header Metadata\n") ;
psf_log_printf (psf, " OggOpus version : %d\n", h->version) ; psf_log_printf (psf, " OggOpus version : %d\n", (int) h->version) ;
psf_log_printf (psf, " Channels : %d\n", h->channels) ; psf_log_printf (psf, " Channels : %d\n", (int) h->channels) ;
psf_log_printf (psf, " Preskip : %d samples @48kHz\n", h->preskip) ; psf_log_printf (psf, " Preskip : %d samples @48kHz\n", (int) h->preskip) ;
psf_log_printf (psf, " Input Samplerate : %d Hz\n", h->input_samplerate) ; psf_log_printf (psf, " Input Samplerate : %d Hz\n", (int) 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, " Gain : %d.%d\n", (int) arith_shift_right (h->gain & 0xF0, 8), h->gain & 0x0F) ;
psf_log_printf (psf, " Channel Mapping : ") ; psf_log_printf (psf, " Channel Mapping : ") ;
switch (h->channel_mapping) switch (h->channel_mapping)
{ case 0 : psf_log_printf (psf, "0 (mono or stereo)\n") ; break ; { 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 1 : psf_log_printf (psf, "1 (surround, AC3 channel order)\n") ; break ;
case 255 : psf_log_printf (psf, "255 (no 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) if (h->channel_mapping > 0)
{ int i ; { int i ;
psf_log_printf (psf, " streams total : %d\n", h->nb_streams) ; psf_log_printf (psf, " streams total : %d\n", (int) h->nb_streams) ;
psf_log_printf (psf, " streams coupled : %d\n", h->nb_coupled) ; psf_log_printf (psf, " streams coupled : %d\n", (int) h->nb_coupled) ;
psf_log_printf (psf, " stream mapping : [") ; psf_log_printf (psf, " stream mapping : [") ;
for (i = 0 ; i < h->channels - 1 ; i++) for (i = 0 ; i < h->channels - 1 ; i++)
psf_log_printf (psf, "%d,", h->stream_map [i]) ; psf_log_printf (psf, "%d,", (int) (h->stream_map [i])) ;
psf_log_printf (psf, "%d]\n", h->stream_map [i]) ; psf_log_printf (psf, "%d]\n", (int) (h->stream_map [i])) ;
} ; } ;
} /* opus_print_header */ } /* 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) ; count = psf_binheader_readf (psf, "ep1", 8, &h->version) ;
if (! (h->version == 1 || h->version == 0)) 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 ; 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 ; oopus->pg_pos = odata->pkt [odata->pkt_len - 1].granulepos ;
gp = ogg_opus_calculate_page_duration (odata) ; gp = ogg_opus_calculate_page_duration (odata) ;
oopus->pkt_pos = oopus->pg_pos - gp ; oopus->pkt_pos = oopus->pg_pos - gp ;
psf_log_printf (psf, "Opus : Hole found appears to be of length %d samples.\n", psf_log_printf (psf, "Opus : Hole found appears to be of length %D samples.\n",
(oopus->pkt_pos - last_page) / oopus->sr_factor) ; (oopus->pkt_pos - last_page) / (uint64_t) oopus->sr_factor) ;
/* /*
** Could save the hole size here, and have ogg_opus_read_refill() ** Could save the hole size here, and have ogg_opus_read_refill()
** do packet loss concealment until the hole is gone, but libopus does ** 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 ** MAY defer this action until it decodes the last packet
** completed on that page. ** 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 ; psf->error = SFE_MALFORMED_FILE ;
return -1 ; return -1 ;
} ; } ;
@ -1118,11 +1130,7 @@ ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
else else
nbytes = ogg_stream_pageout_fill (&odata->ostream, &odata->opage, 255 * 255) ; nbytes = ogg_stream_pageout_fill (&odata->ostream, &odata->opage, 255 * 255) ;
if (nbytes > 0) if (nbytes > 0)
{ /* { oopus->u.encode.last_segments -= ogg_page_segments (&odata->opage) ;
** LibOgg documentation is noted as being bad by it's author. Ogg
** page header byte 26 is the segment count.
*/
oopus->u.encode.last_segments -= odata->opage.header [26] ;
oopus->pg_pos = oopus->pkt_pos ; oopus->pg_pos = oopus->pkt_pos ;
ogg_write_page (psf, &odata->opage) ; 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 { psf->sf.frames = (oopus->u.decode.gp_end - oopus->u.decode.gp_start
- oopus->header.preskip) / oopus->sr_factor ; - 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. */ /* Go back to where we left off. */
ogg_sync_fseek (psf, saved_offset, SEEK_SET) ; 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_analyze_file */
/* /*
** ogg_opus_seek_null_read ** ogg_opus_null_read
** **
** Decode samples, doing nothing with them, until the desired granule position ** Decode samples, doing nothing with them, until the desired granule position
** is reached. ** is reached.
*/ */
static sf_count_t 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 ; { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ; OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
sf_count_t total ; 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 ; ) 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) { if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
return total ; return total ;
/* /*
@ -1500,22 +1515,18 @@ ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset)
*/ */
oopus->loc = 0 ; oopus->loc = 0 ;
} ; } ;
readlen = SF_MIN ((int) (offset - total), (oopus->len - oopus->loc)) ;
if (readlen > 0)
{ total += readlen ;
oopus->loc += readlen ;
} ;
} ; } ;
return total ; 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 ** Search within the file for the page with the highest granule position at or
** before our target. ** before our target.
*/ */
static int 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 ; { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ; OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
uint64_t pcm_start ; uint64_t pcm_start ;
@ -1523,49 +1534,48 @@ ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp)
uint64_t best_gp ; uint64_t best_gp ;
sf_count_t begin ; sf_count_t begin ;
sf_count_t end ; sf_count_t end ;
sf_count_t old_pos ;
int ret ; int ret ;
best_gp = pcm_start = oopus->u.decode.gp_start ; best_gp = pcm_start = oopus->u.decode.gp_start ;
pcm_end = oopus->u.decode.gp_end ; pcm_end = oopus->u.decode.gp_end ;
begin = psf->dataoffset ; begin = psf->dataoffset ;
end = oopus->u.decode.last_offset ;
/* Adjust the target to give time to converge. */ /* Search the Ogg stream for such a page */
if (target_gp >= OGG_OPUS_PREROLL) old_pos = ogg_sync_ftell (psf) ;
target_gp -= OGG_OPUS_PREROLL ; ret = ogg_stream_seek_page_search (psf, odata, target_gp, pcm_start, pcm_end, &best_gp, begin, end, 48000) ;
if (target_gp < pcm_start) if (ret != 0)
target_gp = pcm_start ; { ogg_sync_fseek (psf, old_pos, SEEK_SET) ;
return ret ;
/* 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) ;
/* Load the page that contains our pre-roll target */
oopus->loc = 0 ; oopus->loc = 0 ;
oopus->len = 0 ; oopus->len = 0 ;
if ((ret = ogg_opus_unpack_next_page (psf, odata, oopus)) != 1) if ((ret = ogg_opus_unpack_next_page (psf, odata, oopus)) != 1)
return ret ; return ret ;
oopus->pkt_pos = best_gp ; oopus->pkt_pos = best_gp ;
/* Reset the decoder (gain settings survive the reset) */
opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_RESET_STATE) ; opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_RESET_STATE) ;
/* Gain decoder settings survive resets. */
return 0 ; 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 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 ; { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ; OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
sf_count_t pos ; sf_count_t pos ;
int nn ; 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) if (oopus->pg_pos > target_gp)
{ ogg_stream_reset (&odata->ostream) ; { ogg_stream_reset (&odata->ostream) ;
pos = ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ; 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 ; return 1 ;
} /* ogg_opus_seek_manual */ } /* ogg_opus_page_seek_manual */
static sf_count_t static sf_count_t
ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ; { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
uint64_t target_gp ; OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
uint64_t current ; uint64_t target_gp, current_gp ;
int ret ; int ret ;
/* Only support seeking in read mode. */ /* 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 ; return PSF_SEEK_ERROR ;
} ; } ;
current = oopus->pkt_pos + oopus->loc * oopus->sr_factor ; /* 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
** Remember, there are preskip granulepos worth of samples at the front of * but before the current locaiton. */
** the stream which are bunk. Also, granule positions can be offset. oopus->loc = 0 ;
*/ current_gp = oopus->pkt_pos - (uint64_t) (oopus->len * oopus->sr_factor) ;
target_gp = offset * oopus->sr_factor + oopus->u.decode.gp_start + oopus->header.preskip ;
if (oopus->u.decode.gp_end == (uint64_t) -1) /* Calculate the target granule pos. This includes the decoder delay and
{ /* * the file granule position offset. */
** Don't know the end of the file. Could be a chained file we don't yet target_gp = offset * oopus->sr_factor ;
** support. Oh well, just do it manually. target_gp += oopus->u.decode.gp_start ;
*/ target_gp += oopus->header.preskip ;
ogg_opus_seek_manual (psf, target_gp) ;
} /* Check if we need to do a page seek. */
else if (target_gp < current_gp || target_gp - current_gp > OGG_OPUS_PREROLL)
{ /* { uint64_t preroll_gp ;
** 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- /* For a page seek, use an earlier target granule pos, giving the
** roll plus 10ms. * decoder samples to converge before the actual target. */
*/ if (target_gp >= OGG_OPUS_PREROLL + oopus->u.decode.gp_start + (uint64_t) oopus->header.preskip)
if (target_gp < current || target_gp - current > OGG_OPUS_PREROLL + 10 * 48) { preroll_gp = target_gp - OGG_OPUS_PREROLL ;
{ ret = ogg_opus_seek_page_search (psf, target_gp) ; }
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) if (ret < 0)
{ /* { /*
** Page seek failed, what to do? Could be bad data. We can ** 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 ** from the beginning has the advantage of finding where the
** file goes bad. ** file goes bad.
*/ */
ret = ogg_opus_seek_manual (psf, target_gp) ; ret = ogg_opus_page_seek_manual (psf, preroll_gp) ;
if (ret < 0) if (ret < 0)
{ /* { /*
** If were here, and there is no error, we can be pretty ** 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, ** We've seeked or skipped through pages until just before our target,
** now decode until we hit it. ** 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) ; return offset - ((oopus->header.preskip + oopus->u.decode.gp_start) / oopus->sr_factor) ;
} /* ogg_opus_seek */ } /* 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 ; *((int *) data) = oopus->header.input_samplerate ;
return SF_TRUE ; 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 : default :
break ; break ;
} }

Some files were not shown because too many files have changed in this diff Show More