mirror of
https://gitee.com/openharmony/third_party_libsnd
synced 2024-11-23 01:49:53 +00:00
Version upgrade! Merge branch 'dev'
Signed-off-by: huang-jianfei200 <huangjianfei4@huawei.com>
This commit is contained in:
commit
297f533a38
56
.github/workflows/action.yml
vendored
56
.github/workflows/action.yml
vendored
@ -18,34 +18,38 @@ jobs:
|
||||
ubuntu-clang-cmake-shared,
|
||||
macos-cmake,
|
||||
macos-cmake-shared,
|
||||
windows-vs2019-x64,
|
||||
windows-vs2019-x64-shared,
|
||||
windows-vs2019-Win32,
|
||||
windows-vs2019-Win32-shared
|
||||
windows-vs2022-x64,
|
||||
windows-vs2022-x64-shared,
|
||||
windows-vs2022-Win32,
|
||||
windows-vs2022-Win32-shared
|
||||
]
|
||||
include:
|
||||
- name: ubuntu-gcc-autotools
|
||||
os: ubuntu-latest
|
||||
cc: gcc
|
||||
cxx: g++
|
||||
autotools-options: --enable-werror
|
||||
build-system: autotools
|
||||
|
||||
- name: ubuntu-clang-autotools
|
||||
os: ubuntu-latest
|
||||
cc: clang
|
||||
cxx: clang++
|
||||
autotools-options: --enable-werror
|
||||
build-system: autotools
|
||||
|
||||
- name: ubuntu-gcc-ossfuzz
|
||||
os: ubuntu-latest
|
||||
cc: gcc
|
||||
cxx: g++
|
||||
autotools-options: --enable-werror
|
||||
build-system: ossfuzz
|
||||
|
||||
- name: macos-autotools
|
||||
os: macos-latest
|
||||
cc: clang
|
||||
cxx: clang++
|
||||
autotools-options: --enable-werror
|
||||
build-system: autotools
|
||||
|
||||
- name: ubuntu-gcc-cmake
|
||||
@ -117,22 +121,22 @@ jobs:
|
||||
-DCMAKE_C_FLAGS="-Wall -Wextra"
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON
|
||||
|
||||
- name: windows-vs2019-x64
|
||||
- name: windows-vs2022-x64
|
||||
os: windows-latest
|
||||
triplet: 'x64-windows-static'
|
||||
build-system: cmake
|
||||
cmake-generator: 'Visual Studio 16 2019'
|
||||
cmake-generator: 'Visual Studio 17 2022'
|
||||
cmake-options: >-
|
||||
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DVCPKG_TARGET_TRIPLET=x64-windows-static
|
||||
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
|
||||
- name: windows-vs2019-x64-shared
|
||||
- name: windows-vs2022-x64-shared
|
||||
os: windows-latest
|
||||
triplet: 'x64-windows-static'
|
||||
build-system: cmake
|
||||
cmake-generator: 'Visual Studio 16 2019'
|
||||
cmake-generator: 'Visual Studio 17 2022'
|
||||
cmake-options: >-
|
||||
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
|
||||
-DBUILD_SHARED_LIBS=ON
|
||||
@ -143,11 +147,11 @@ jobs:
|
||||
-DVCPKG_TARGET_TRIPLET=x64-windows-static
|
||||
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
|
||||
- name: windows-vs2019-Win32
|
||||
- name: windows-vs2022-Win32
|
||||
os: windows-latest
|
||||
triplet: 'x86-windows-static'
|
||||
build-system: cmake
|
||||
cmake-generator: 'Visual Studio 16 2019'
|
||||
cmake-generator: 'Visual Studio 17 2022'
|
||||
cmake-options: >-
|
||||
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
|
||||
-DCMAKE_GENERATOR_PLATFORM=Win32
|
||||
@ -155,11 +159,11 @@ jobs:
|
||||
-DVCPKG_TARGET_TRIPLET=x86-windows-static
|
||||
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
|
||||
- name: windows-vs2019-Win32-shared
|
||||
- name: windows-vs2022-Win32-shared
|
||||
os: windows-latest
|
||||
triplet: 'x86-windows-static'
|
||||
build-system: cmake
|
||||
cmake-generator: 'Visual Studio 16 2019'
|
||||
cmake-generator: 'Visual Studio 17 2022'
|
||||
cmake-options: >-
|
||||
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
|
||||
-DCMAKE_GENERATOR_PLATFORM=Win32
|
||||
@ -179,16 +183,25 @@ jobs:
|
||||
- name: Install MacOS dependencies
|
||||
if: startsWith(matrix.os,'macos')
|
||||
run: |
|
||||
brew install automake autogen speex
|
||||
brew install automake autogen speex mpg123
|
||||
|
||||
- name: Install Lunux dependencies
|
||||
- name: Install Linux dependencies
|
||||
if: startsWith(matrix.os,'ubuntu')
|
||||
run: sudo apt-get install -y autogen ninja-build libogg-dev libvorbis-dev libflac-dev libopus-dev libasound2-dev libsqlite3-dev libspeex-dev
|
||||
run: sudo apt-get update -y && sudo apt-get install -y autogen ninja-build libogg-dev libvorbis-dev libflac-dev libopus-dev libasound2-dev libsqlite3-dev libspeex-dev libmp3lame-dev libmpg123-dev
|
||||
|
||||
- name: Install Windows dependencies
|
||||
- name: Setup NuGet Credentials
|
||||
env:
|
||||
VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite'
|
||||
if: startsWith(matrix.os,'windows')
|
||||
run: |
|
||||
vcpkg install libvorbis libflac opus sqlite3 speex --triplet ${{matrix.triplet}}
|
||||
shell: 'bash'
|
||||
run: >
|
||||
`vcpkg fetch nuget | tail -n 1`
|
||||
sources add
|
||||
-source "https://nuget.pkg.github.com/libsndfile/index.json"
|
||||
-storepasswordincleartext
|
||||
-name "GitHub"
|
||||
-username "evpobr"
|
||||
-password "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- name: Configure, build and test with Autotools
|
||||
env:
|
||||
@ -196,17 +209,18 @@ jobs:
|
||||
CXX: ${{ matrix.cxx }}
|
||||
if: startsWith(matrix.build-system,'autotools')
|
||||
run: |
|
||||
./autogen.sh
|
||||
autoreconf -vif
|
||||
if [[ "${CC}" == "clang" ]]; then
|
||||
./configure --enable-werror && make clean all check && make distcheck
|
||||
./configure --enable-werror && make distcheck
|
||||
else
|
||||
Scripts/asan-configure.sh --enable-werror && make clean all check && make distcheck
|
||||
Scripts/asan-configure.sh --enable-werror && make distcheck
|
||||
fi
|
||||
|
||||
- name: Configure, build and test with CMake
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
CXX: ${{ matrix.cxx }}
|
||||
VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite'
|
||||
if: startsWith(matrix.build-system,'cmake')
|
||||
run: |
|
||||
mkdir build
|
||||
|
26
.github/workflows/cifuzz.yml
vendored
Normal file
26
.github/workflows/cifuzz.yml
vendored
Normal 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
3
.gitignore
vendored
@ -48,6 +48,7 @@ build-test-tarball.mk
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
configure~
|
||||
doc/AUTHORS
|
||||
doc/ChangeLog
|
||||
doc/NEWS
|
||||
@ -62,7 +63,7 @@ examples/sndfile-loopify
|
||||
examples/sndfile-to-text
|
||||
examples/sndfilehandle
|
||||
include/sndfile.h
|
||||
libsndfile-1.0.*
|
||||
libsndfile-*.tar.xz
|
||||
libsndfile-testsuite-*
|
||||
libsndfile.spec
|
||||
libtool
|
||||
|
@ -3,7 +3,7 @@
|
||||
Assuming the Android Ndk is installed at location `/path/to/toolchain`, building
|
||||
libsndfile for Android (arm-linux-androideabi) should be as simple as:
|
||||
```
|
||||
./autogen.sh
|
||||
autoreconf -vif
|
||||
export ANDROID_TOOLCHAIN_HOME=/path/to/android/toolchain
|
||||
./Scripts/android-configure.sh
|
||||
make
|
||||
@ -15,3 +15,32 @@ by setting them before the script is run.
|
||||
Since I (erikd), do almost zero Android development, I am happy accept patches
|
||||
for this documentation and script to improve its utility for real Android
|
||||
developers.
|
||||
|
||||
---
|
||||
|
||||
## Using CMake
|
||||
|
||||
(Tested on Linux)
|
||||
|
||||
For convenience, export the following variables:
|
||||
|
||||
```
|
||||
export ANDROID_ABI=arm64-v8a
|
||||
export ANDROID_PLATFORM_API_LEVEL=29
|
||||
export NDK_ROOT=/path/to/android/ndk
|
||||
```
|
||||
|
||||
Set `ANDROID_ABI`, `ANDROID_PLATFORM_API_LEVEL` according to your target system. Now cd into the libsndfile root directory, and run
|
||||
|
||||
```
|
||||
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ANDROID_ABI -DANDROID_PLATFORM=$ANDROID_PLATFORM_API_LEVEL
|
||||
```
|
||||
|
||||
cd into `build` and run make
|
||||
|
||||
```
|
||||
cd build
|
||||
make [-j <number of parallel jobs>]
|
||||
```
|
||||
|
||||
This will build libsndfile for android.
|
||||
|
147
CHANGELOG.md
Normal file
147
CHANGELOG.md
Normal 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
|
144
CMakeLists.txt
144
CMakeLists.txt
@ -15,7 +15,27 @@ if (POLICY CMP0091)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
project(libsndfile VERSION 1.0.31)
|
||||
option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON)
|
||||
if (ENABLE_EXTERNAL_LIBS)
|
||||
list (APPEND VCPKG_MANIFEST_FEATURES "external-libs")
|
||||
endif ()
|
||||
|
||||
option (ENABLE_MPEG "Enable MPEG codecs" ON)
|
||||
if (ENABLE_MPEG)
|
||||
list (APPEND VCPKG_MANIFEST_FEATURES "mpeg")
|
||||
endif ()
|
||||
|
||||
option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF)
|
||||
if (ENABLE_EXPERIMENTAL)
|
||||
list (APPEND VCPKG_MANIFEST_FEATURES "speex")
|
||||
endif ()
|
||||
|
||||
option (BUILD_REGTEST "Build regtest" OFF)
|
||||
if (BUILD_REGTEST)
|
||||
list (APPEND VCPKG_MANIFEST_FEATURES "regtest")
|
||||
endif ()
|
||||
|
||||
project(libsndfile VERSION 1.2.0)
|
||||
|
||||
#
|
||||
# Variables
|
||||
@ -54,7 +74,6 @@ endif ()
|
||||
option (BUILD_PROGRAMS "Build programs" ON)
|
||||
option (BUILD_EXAMPLES "Build examples" ON)
|
||||
option (ENABLE_CPACK "Enable CPack support" ON)
|
||||
option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF)
|
||||
option (ENABLE_BOW_DOCS "Enable black-on-white html docs" OFF)
|
||||
if (MSVC AND (DEFINED ENABLE_STATIC_RUNTIME))
|
||||
option (ENABLE_STATIC_RUNTIME "Enable static runtime" ${ENABLE_STATIC_RUNTIME})
|
||||
@ -75,9 +94,16 @@ endif ()
|
||||
|
||||
include(SndFileChecks)
|
||||
|
||||
if (ENABLE_EXTERNAL_LIBS AND NOT (Vorbis_FOUND OR FLAC_FOUND OR OPUS_FOUND))
|
||||
set (ENABLE_EXTERNAL_LIBS OFF)
|
||||
endif()
|
||||
if(ENABLE_MPEG AND (NOT HAVE_MPEG_LIBS))
|
||||
set (ENABLE_MPEG OFF)
|
||||
endif()
|
||||
if (BUILD_REGTEST AND (NOT SQLITE3_FOUND))
|
||||
set (BUILD_REGTEST OFF)
|
||||
endif()
|
||||
|
||||
cmake_dependent_option (BUILD_REGTEST "Build regtest" ON "SQLITE3_FOUND" OFF)
|
||||
cmake_dependent_option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON "Vorbis_FOUND;FLAC_FOUND;OPUS_FOUND" OFF)
|
||||
cmake_dependent_option (ENABLE_CPU_CLIP "Enable tricky cpu specific clipper" ON "CPU_CLIPS_POSITIVE;CPU_CLIPS_NEGATIVE" OFF)
|
||||
if (NOT ENABLE_CPU_CLIP)
|
||||
set (CPU_CLIPS_POSITIVE FALSE)
|
||||
@ -104,11 +130,12 @@ set (HAVE_ALSA_ASOUNDLIB_H ${ALSA_FOUND})
|
||||
set (HAVE_SNDIO_H ${SNDIO_FOUND})
|
||||
|
||||
set (ENABLE_EXPERIMENTAL_CODE ${ENABLE_EXPERIMENTAL})
|
||||
set (HAVE_MPEG ${ENABLE_MPEG})
|
||||
set (HAVE_SPEEX ${ENABLE_EXPERIMENTAL})
|
||||
set (HAVE_OPUS ${ENABLE_EXPERIMENTAL})
|
||||
|
||||
add_feature_info (BUILD_SHARED_LIBS BUILD_SHARED_LIBS "build shared libraries")
|
||||
add_feature_info (ENABLE_EXTERNAL_LIBS ENABLE_EXTERNAL_LIBS "enable FLAC, Vorbis, and Opus codecs")
|
||||
add_feature_info (ENABLE_MPEG ENABLE_MPEG "enable MPEG audio (including mp3) codecs")
|
||||
add_feature_info (ENABLE_EXPERIMENTAL ENABLE_EXPERIMENTAL "enable experimental code")
|
||||
add_feature_info (BUILD_TESTING BUILD_TESTING "build tests")
|
||||
add_feature_info (BUILD_REGTEST BUILD_REGTEST "build regtest")
|
||||
@ -147,6 +174,18 @@ set_package_properties (FLAC PROPERTIES
|
||||
DESCRIPTION "Free Lossless Audio Codec Library"
|
||||
PURPOSE "Enables FLAC support"
|
||||
)
|
||||
set_package_properties (mp3lame PROPERTIES
|
||||
TYPE RECOMMENDED
|
||||
URL "https://lame.sourceforge.io/"
|
||||
DESCRIPTION "High quality MPEG Audio Layer III (MP3) encoder"
|
||||
PURPOSE "Enables MPEG layer III (MP3) writing support"
|
||||
)
|
||||
set_package_properties (MPG123 PROPERTIES
|
||||
TYPE RECOMMENDED
|
||||
URL "https://www.mpg123.de/"
|
||||
DESCRIPTION "MPEG Audio Layer I/II/III decoder"
|
||||
PURPOSE "Enables MPEG Audio reading support"
|
||||
)
|
||||
set_package_properties(Opus PROPERTIES
|
||||
TYPE RECOMMENDED
|
||||
URL "www.opus-codec.org/"
|
||||
@ -181,8 +220,6 @@ feature_summary (WHAT ALL)
|
||||
|
||||
configure_file (src/config.h.cmake src/config.h)
|
||||
|
||||
configure_file (include/sndfile.h.in include/sndfile.h)
|
||||
|
||||
if (INSTALL_PKGCONFIG_MODULE)
|
||||
|
||||
set (prefix ${CMAKE_INSTALL_PREFIX})
|
||||
@ -196,6 +233,10 @@ if (INSTALL_PKGCONFIG_MODULE)
|
||||
set (EXTERNAL_XIPH_REQUIRE "${EXTERNAL_XIPH_REQUIRE} speex")
|
||||
endif ()
|
||||
endif ()
|
||||
if (ENABLE_MPEG)
|
||||
set (EXTERNAL_MPEG_REQUIRE "libmpg123")
|
||||
set (EXTERNAL_MPEG_LIBS "-lmp3lame")
|
||||
endif ()
|
||||
|
||||
configure_file (sndfile.pc.in sndfile.pc @ONLY)
|
||||
|
||||
@ -207,8 +248,8 @@ endif ()
|
||||
|
||||
# Public libsndfile headers
|
||||
set (sndfile_HDRS
|
||||
include/sndfile.h
|
||||
include/sndfile.hh
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/sndfile.h
|
||||
)
|
||||
|
||||
#
|
||||
@ -247,6 +288,7 @@ add_library (sndfile
|
||||
src/ogg.c
|
||||
src/chanmap.h
|
||||
src/chanmap.c
|
||||
src/id3.h
|
||||
src/id3.c
|
||||
$<$<BOOL:${WIN32}>:src/windows.c>
|
||||
src/sndfile.c
|
||||
@ -284,8 +326,12 @@ add_library (sndfile
|
||||
src/ogg_speex.c
|
||||
src/ogg_pcm.c
|
||||
src/ogg_opus.c
|
||||
src/ogg_vcomment.h
|
||||
src/ogg_vcomment.c
|
||||
src/nms_adpcm.c
|
||||
src/mpeg.c
|
||||
src/mpeg_decode.c
|
||||
src/mpeg_l3_encode.c
|
||||
src/GSM610/config.h
|
||||
src/GSM610/gsm.h
|
||||
src/GSM610/gsm610_priv.h
|
||||
@ -349,6 +395,8 @@ target_link_libraries (sndfile
|
||||
$<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:FLAC::FLAC>
|
||||
$<$<AND:$<BOOL:${ENABLE_EXPERIMENTAL}>,$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>,$<BOOL:${HAVE_SPEEX}>>:Speex::Speex>
|
||||
$<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Opus::opus>
|
||||
$<$<BOOL:${HAVE_MPEG}>:MPG123::libmpg123>
|
||||
$<$<BOOL:${HAVE_MPEG}>:mp3lame::mp3lame>
|
||||
)
|
||||
set_target_properties (sndfile PROPERTIES
|
||||
PUBLIC_HEADER "${sndfile_HDRS}"
|
||||
@ -368,6 +416,28 @@ endif ()
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
|
||||
#
|
||||
# ABI version of library.
|
||||
#
|
||||
|
||||
#
|
||||
# Read libtool version from `configure.ac` and set libsndfile ABI version:
|
||||
#
|
||||
# SNDFILE_ABI_VERSION_MAJOR
|
||||
# SNDFILE_ABI_VERSION_MINOR
|
||||
# SNDFILE_ABI_VERSION_PATCH
|
||||
# SNDFILE_ABI_VERSION
|
||||
#
|
||||
# and Mach-O current and compatibility versions:
|
||||
#
|
||||
# SNDFILE_MACHO_CURRENT_VERSION
|
||||
# SNDFILE_MACHO_COMPATIBILITY_VERSION
|
||||
#
|
||||
|
||||
include (SetupABIVersions)
|
||||
|
||||
setup_abi_versions()
|
||||
|
||||
if (WIN32)
|
||||
set (VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR})
|
||||
set (GEN_TOOL cmake)
|
||||
@ -380,11 +450,23 @@ if (BUILD_SHARED_LIBS)
|
||||
target_sources (sndfile PRIVATE ${PROJECT_BINARY_DIR}/src/version-metadata.rc)
|
||||
endif ()
|
||||
|
||||
|
||||
set_target_properties (sndfile PROPERTIES
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${SNDFILE_ABI_VERSION_MAJOR}
|
||||
VERSION ${SNDFILE_ABI_VERSION}
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
if (NOT (CMAKE_VERSION VERSION_LESS 3.17))
|
||||
set_target_properties (sndfile PROPERTIES
|
||||
MACHO_CURRENT_VERSION ${SNDFILE_MACHO_CURRENT_VERSION}
|
||||
MACHO_COMPATIBILITY_VERSION ${SNDFILE_MACHO_COMPATIBILITY_VERSION}
|
||||
)
|
||||
else ()
|
||||
message (FATAL_ERROR "Apple platform requires cmake >= 3.17 to build dylib.")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Symbol files generation
|
||||
|
||||
if (WIN32)
|
||||
@ -404,7 +486,7 @@ if (BUILD_SHARED_LIBS)
|
||||
if (DEFINED SYMBOL_OS)
|
||||
add_custom_command (
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${PROJECT_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${SNDFILE_ABI_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME}
|
||||
COMMENT "Generating ${SYMBOL_FILENAME}..."
|
||||
)
|
||||
|
||||
@ -647,6 +729,11 @@ if (BUILD_EXAMPLES)
|
||||
$<$<BOOL:${LIBM_REQUIRED}>:m>
|
||||
)
|
||||
|
||||
# generate
|
||||
|
||||
add_executable (generate examples/generate.c)
|
||||
target_link_libraries (generate PRIVATE sndfile)
|
||||
|
||||
# sndfilehandle
|
||||
|
||||
add_executable (sndfilehandle examples/sndfilehandle.cc)
|
||||
@ -658,6 +745,7 @@ if (BUILD_EXAMPLES)
|
||||
make_sine
|
||||
sfprocess
|
||||
list_formats
|
||||
generate
|
||||
sndfilehandle
|
||||
)
|
||||
|
||||
@ -716,6 +804,8 @@ if (ENABLE_PACKAGE_CONFIG)
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
export (EXPORT SndFileTargets NAMESPACE SndFile:: FILE ${PROJECT_BINARY_DIR}/SndFileTargets.cmake)
|
||||
|
||||
include (CMakePackageConfigHelpers)
|
||||
|
||||
if (ENABLE_EXTERNAL_LIBS)
|
||||
@ -724,8 +814,19 @@ if (ENABLE_PACKAGE_CONFIG)
|
||||
set (SndFile_WITH_EXTERNAL_LIBS 0)
|
||||
endif ()
|
||||
|
||||
if(ENABLE_MPEG)
|
||||
set (SndFile_WITH_MPEG 1)
|
||||
else ()
|
||||
set (SndFile_WITH_MPEG 0)
|
||||
endif ()
|
||||
|
||||
set (INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig.cmake
|
||||
INSTALL_DESTINATION ${PROJECT_BINARY_DIR}
|
||||
INSTALL_PREFIX ${PROJECT_BINARY_DIR}
|
||||
PATH_VARS INCLUDE_INSTALL_DIR
|
||||
)
|
||||
configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig2.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
|
||||
PATH_VARS INCLUDE_INSTALL_DIR
|
||||
)
|
||||
@ -735,9 +836,13 @@ if (ENABLE_PACKAGE_CONFIG)
|
||||
NAMESPACE SndFile::
|
||||
DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
|
||||
)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig2.cmake
|
||||
RENAME SndFileConfig.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SndFileConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_PACKAGEDIR}
|
||||
)
|
||||
@ -1181,6 +1286,14 @@ if (BUILD_TESTING)
|
||||
$<$<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)
|
||||
target_link_libraries (stdin_test
|
||||
PRIVATE
|
||||
@ -1412,6 +1525,10 @@ if (BUILD_TESTING)
|
||||
add_test (lossy_comp_test_ogg_opus lossy_comp_test ogg_opus)
|
||||
add_test (string_test_opus string_test opus)
|
||||
|
||||
### mpeg-tests ###
|
||||
add_test (mpeg_test mpeg_test)
|
||||
add_test (compression_size_test_mpeg compression_size_test mpeg)
|
||||
|
||||
### io-tests
|
||||
add_test (stdio_test stdio_test)
|
||||
add_test (pipe_test pipe_test)
|
||||
@ -1467,5 +1584,8 @@ if (BUILD_TESTING)
|
||||
endif ()
|
||||
|
||||
if (ENABLE_CPACK)
|
||||
if ((NOT CPACK_PACKAGE_VERSION) AND CPACK_PACKAGE_VERSION_STAGE)
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_FULL}")
|
||||
endif ()
|
||||
include (CPack)
|
||||
endif ()
|
||||
|
@ -18,6 +18,30 @@
|
||||
* Patches should always be submitted via a either Github "pull request" or a
|
||||
via emailed patches created using "git format-patch".
|
||||
* Patches for new features should include tests and documentation.
|
||||
* Commit messages should follow the ["How to Write a Git Commit Message"](https://chris.beams.io/posts/git-commit/) guide:
|
||||
1. Separate subject from body with a blank line
|
||||
2. Limit the subject line to 50 characters
|
||||
3. Capitalize the subject line
|
||||
4. Do not end the subject line with a period
|
||||
5. Use the imperative mood in the subject line
|
||||
6. Wrap the body at 72 characters
|
||||
7. Use the body to explain what and why vs. how
|
||||
|
||||
Additional rule: the commit message may contain a prefix. The prefix must
|
||||
contain the name of the feature or source file related to the commit and must
|
||||
end with a colon followed by the message body.
|
||||
|
||||
Examples of good commit messages:
|
||||
1. Fix typo
|
||||
2. Update CHANGELOG.md
|
||||
3. Add ACT file format support
|
||||
4. ogg_vorbis: Fix granule position when seeking Vorbis streams
|
||||
|
||||
Examples of bad commit messages:
|
||||
1. Fixed bug (rule 5)
|
||||
2. update docs (rule 3)
|
||||
3. Add very cool feature. (rule 4)
|
||||
|
||||
* Patches to fix bugs should either pass all tests, or modify the tests in some
|
||||
sane way.
|
||||
* When a new feature is added for a particular file format and that feature
|
||||
|
51
Makefile.am
51
Makefile.am
@ -13,8 +13,8 @@ endif
|
||||
endif
|
||||
|
||||
EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \
|
||||
Scripts/linux-to-win-cross-configure.sh \
|
||||
CMakeLists.txt $(cmake_files) Win32
|
||||
NEWS.OLD CHANGELOG.md Scripts/linux-to-win-cross-configure.sh \
|
||||
CMakeLists.txt $(cmake_files) Win32 SECURITY.md
|
||||
|
||||
cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \
|
||||
cmake/CMakeAutoGen.cmake cmake/CMakeAutoGenScript.cmake \
|
||||
@ -23,7 +23,9 @@ cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \
|
||||
cmake/SndFileChecks.cmake cmake/TestInline.cmake \
|
||||
cmake/TestLargeFiles.cmake cmake/TestInline.c.in \
|
||||
cmake/FindOpus.cmake cmake/SndFileConfig.cmake.in \
|
||||
cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in
|
||||
cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in \
|
||||
cmake/Findmp3lame.cmake cmake/FindMpg123.cmake \
|
||||
cmake/SetupABIVersions.cmake
|
||||
|
||||
pkgconfig_DATA = sndfile.pc
|
||||
|
||||
@ -44,7 +46,7 @@ BUILT_SOURCES = src/test_endswap.c
|
||||
|
||||
SYMBOL_FILES = src/Symbols.gnu-binutils src/Symbols.darwin src/libsndfile-1.def src/Symbols.os2 src/Symbols.static
|
||||
|
||||
EXTRA_DIST += include/sndfile.h.in src/config.h.in src/test_endswap.tpl src/test_endswap.def \
|
||||
EXTRA_DIST += src/config.h.in src/test_endswap.tpl src/test_endswap.def \
|
||||
$(SYMBOL_FILES) src/create_symbols_file.py src/binheader_writef_check.py \
|
||||
src/GSM610/README src/GSM610/COPYRIGHT src/GSM610/ChangeLog \
|
||||
src/G72x/README src/G72x/README.original src/G72x/ChangeLog \
|
||||
@ -60,28 +62,27 @@ endif
|
||||
#===============================================================================
|
||||
|
||||
lib_LTLIBRARIES = src/libsndfile.la
|
||||
include_HEADERS = include/sndfile.hh
|
||||
nodist_include_HEADERS = include/sndfile.h
|
||||
src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS)
|
||||
include_HEADERS = include/sndfile.h include/sndfile.hh
|
||||
src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_CFLAGS)
|
||||
# MinGW requires -no-undefined if a DLL is to be built.
|
||||
src_libsndfile_la_LDFLAGS = -no-undefined -version-info $(SHARED_VERSION_INFO) $(SHLIB_VERSION_ARG)
|
||||
src_libsndfile_la_SOURCES = src/sndfile.c src/aiff.c src/au.c src/avr.c src/caf.c src/dwd.c src/flac.c src/g72x.c src/htk.c src/ircam.c \
|
||||
src/macos.c src/mat4.c src/mat5.c src/nist.c src/paf.c src/pvf.c src/raw.c src/rx2.c src/sd2.c \
|
||||
src/sds.c src/svx.c src/txw.c src/voc.c src/wve.c src/w64.c src/wavlike.c src/wav.c src/xi.c src/mpc2k.c src/rf64.c \
|
||||
src/ogg_vorbis.c src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c src/ogg_vcomment.c \
|
||||
src/common.h src/sfconfig.h src/sfendian.h src/wavlike.h src/sf_unistd.h src/ogg.h src/chanmap.h src/ogg_vcomment.h
|
||||
src/ogg.c src/ogg.h src/ogg_vorbis.c src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c src/ogg_vcomment.c src/ogg_vcomment.h \
|
||||
src/common.h src/sfconfig.h src/sfendian.h src/wavlike.h src/sf_unistd.h src/chanmap.h src/mpeg.c
|
||||
nodist_src_libsndfile_la_SOURCES = $(nodist_include_HEADERS)
|
||||
src_libsndfile_la_LIBADD = src/GSM610/libgsm.la src/G72x/libg72x.la src/ALAC/libalac.la \
|
||||
src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm
|
||||
src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm $(MPEG_LIBS)
|
||||
EXTRA_src_libsndfile_la_DEPENDENCIES = $(SYMBOL_FILES)
|
||||
|
||||
noinst_LTLIBRARIES = src/libcommon.la
|
||||
src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS)
|
||||
src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_CFLAGS)
|
||||
src_libcommon_la_SOURCES = src/common.c src/file_io.c src/command.c src/pcm.c src/ulaw.c src/alaw.c \
|
||||
src/float32.c src/double64.c src/ima_adpcm.c src/ms_adpcm.c src/gsm610.c src/dwvw.c src/vox_adpcm.c \
|
||||
src/interleave.c src/strings.c src/dither.c src/cart.c src/broadcast.c src/audio_detect.c \
|
||||
src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/ogg.c src/chanmap.c \
|
||||
src/windows.c src/id3.c src/nms_adpcm.c $(WIN_VERSION_FILE)
|
||||
src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/chanmap.c \
|
||||
src/windows.c src/id3.c src/id3.h src/nms_adpcm.c src/mpeg_decode.c src/mpeg_l3_encode.c src/mpeg.h $(WIN_VERSION_FILE)
|
||||
|
||||
check_PROGRAMS = src/test_main
|
||||
src_test_main_SOURCES = src/test_main.c src/test_main.h src/test_conversions.c src/test_float.c src/test_endswap.c \
|
||||
@ -135,19 +136,19 @@ src_ALAC_libalac_la_SOURCES = src/ALAC/ALACAudioTypes.h src/ALAC/ALACBitUtilitie
|
||||
SYMBOL_SCRIPT = $(top_srcdir)/src/create_symbols_file.py
|
||||
|
||||
src/Symbols.gnu-binutils: $(SYMBOL_SCRIPT)
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) linux $(VERSION) > $(top_srcdir)/$@
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) linux $(ABI_VERSION) > $(top_srcdir)/$@
|
||||
|
||||
src/Symbols.darwin: $(SYMBOL_SCRIPT)
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) darwin $(VERSION) > $(top_srcdir)/$@
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) darwin $(ABI_VERSION) > $(top_srcdir)/$@
|
||||
|
||||
src/libsndfile-1.def: $(SYMBOL_SCRIPT)
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) win32 $(VERSION) > $(top_srcdir)/$@
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) win32 $(ABI_VERSION) > $(top_srcdir)/$@
|
||||
|
||||
src/Symbols.os2: $(SYMBOL_SCRIPT)
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) os2 $(VERSION) > $(top_srcdir)/$@
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) os2 $(ABI_VERSION) > $(top_srcdir)/$@
|
||||
|
||||
src/Symbols.static: $(SYMBOL_SCRIPT)
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) static $(VERSION) > $(top_srcdir)/$@
|
||||
$(PYTHON) $(SYMBOL_SCRIPT) static $(ABI_VERSION) > $(top_srcdir)/$@
|
||||
|
||||
#===============================================================================
|
||||
# Building windows resource files (if needed).
|
||||
@ -221,7 +222,8 @@ check_PROGRAMS += tests/sfversion tests/floating_point_test tests/write_read_tes
|
||||
tests/locale_test tests/win32_ordinal_test tests/ogg_test tests/compression_size_test \
|
||||
tests/checksum_test tests/external_libs_test tests/rdwr_test tests/format_check_test $(CPP_TEST) \
|
||||
tests/channel_test tests/long_read_write_test tests/stdin_test tests/stdout_test \
|
||||
tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test
|
||||
tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test \
|
||||
tests/mpeg_test
|
||||
|
||||
BUILT_SOURCES += \
|
||||
tests/write_read_test.c \
|
||||
@ -377,6 +379,9 @@ tests_cpp_test_LDADD = src/libsndfile.la
|
||||
tests_checksum_test_SOURCES = tests/checksum_test.c tests/utils.c tests/utils.h
|
||||
tests_checksum_test_LDADD = src/libsndfile.la
|
||||
|
||||
tests_mpeg_test_SOURCES = tests/mpeg_test.c tests/utils.c tests/utils.h
|
||||
tests_mpeg_test_LDADD = src/libsndfile.la
|
||||
|
||||
# Lite remove start
|
||||
tests_dwvw_test_SOURCES = tests/dwvw_test.c tests/utils.c tests/utils.h
|
||||
tests_dwvw_test_LDADD = src/libsndfile.la
|
||||
@ -457,7 +462,8 @@ endif
|
||||
|
||||
if USE_OSSFUZZERS
|
||||
noinst_PROGRAMS += \
|
||||
ossfuzz/sndfile_fuzzer
|
||||
ossfuzz/sndfile_fuzzer \
|
||||
ossfuzz/sndfile_alt_fuzzer
|
||||
|
||||
noinst_LTLIBRARIES += \
|
||||
ossfuzz/libstandaloneengine.la
|
||||
@ -468,6 +474,11 @@ ossfuzz_sndfile_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
|
||||
ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
||||
ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
|
||||
|
||||
ossfuzz_sndfile_alt_fuzzer_SOURCES = ossfuzz/sndfile_alt_fuzzer.cc
|
||||
ossfuzz_sndfile_alt_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
|
||||
ossfuzz_sndfile_alt_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
||||
ossfuzz_sndfile_alt_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
|
||||
|
||||
ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h
|
||||
ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
|
||||
|
2
README
2
README
@ -1,4 +1,4 @@
|
||||
This is libsndfile, 1.0.29
|
||||
This is libsndfile, 1.1.0
|
||||
|
||||
libsndfile is a library of C routines for reading and writing
|
||||
files containing sampled audio data.
|
||||
|
43
README.md
43
README.md
@ -18,7 +18,7 @@ for details.
|
||||
## Hacking
|
||||
|
||||
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:
|
||||
|
||||
@ -33,19 +33,20 @@ below.
|
||||
Setting up a build environment for libsndfile on Debian or Ubuntu is as simple as:
|
||||
|
||||
sudo apt install autoconf autogen automake build-essential libasound2-dev \
|
||||
libflac-dev libogg-dev libtool libvorbis-dev libopus-dev pkg-config python
|
||||
libflac-dev libogg-dev libtool libvorbis-dev libopus-dev libmp3lame-dev \
|
||||
libmpg123-dev pkg-config python
|
||||
|
||||
For other Linux distributions or any of the *BSDs, the setup should be similar
|
||||
although the package install tools and package names may be slightly different.
|
||||
|
||||
Similarly on Mac OS X, assuming [brew] is already installed:
|
||||
|
||||
brew install autoconf autogen automake flac libogg libtool libvorbis opus pkg-config
|
||||
brew install autoconf autogen automake flac libogg libtool libvorbis opus mpg123 pkg-config
|
||||
|
||||
Once the build environment has been set up, building and testing libsndfile is
|
||||
as simple as:
|
||||
|
||||
./autogen.sh
|
||||
autoreconf -vif
|
||||
./configure --enable-werror
|
||||
make
|
||||
make check
|
||||
@ -134,6 +135,8 @@ You can pass additional options with `/D<parameter>=<value>` when you run
|
||||
`ON` by default. Setting `BUILD_SHARED_LIBS` to `ON` disables this option.
|
||||
* `ENABLE_EXTERNAL_LIBS` - enable Ogg, Vorbis, FLAC and Opus support. This
|
||||
option is available and set to `ON` if all dependency libraries were found.
|
||||
* `ENABLE_MPEG` - MP3 support. This option is available and set to `ON` if all
|
||||
dependency libraries were found.
|
||||
* `ENABLE_CPU_CLIP` - enable tricky cpu specific clipper. Enabled and set to
|
||||
`ON` when CPU clips negative\positive. Don't touch it if you are not sure
|
||||
* `ENABLE_BOW_DOCS` - enable black-on-white documentation theme, `OFF` by
|
||||
@ -232,7 +235,7 @@ You can find related option in Visual Studio project properties:
|
||||
|
||||
C/C++ -> Code Generation -> Runtime Library
|
||||
|
||||
Dynamic version of system CRT library is defaut and it means that end user needs
|
||||
Dynamic version of system CRT library is default and it means that end user needs
|
||||
to have the same runtime library installed on his system. Most likely it is so,
|
||||
but if it is not, the user will see this error message using libsndfile DLL:
|
||||
|
||||
@ -270,21 +273,35 @@ have standard option `CMAKE_MSVC_RUNTIME_LIBRARY` now.
|
||||
|
||||
Second advice is about Ogg, Vorbis FLAC and Opus support. Searching external
|
||||
libraries under Windows is a little bit tricky. The best way is to use
|
||||
[Vcpkg](https://github.com/Microsoft/vcpkg). You need to install static libogg,
|
||||
libvorbis, libflac and libopus libraries:
|
||||
[Vcpkg](https://github.com/Microsoft/vcpkg).
|
||||
|
||||
vcpkg install libogg:x64-windows-static libvorbis:x64-windows-static
|
||||
libflac:x64-windows-static opus:x64-windows-static libogg:x86-windows-static
|
||||
libvorbis:x86-windows-static libflac:x86-windows-static opus:x86-windows-static
|
||||
|
||||
Then and add this parameter to cmake command line:
|
||||
Install Vcpkg and then add this parameter to cmake command line:
|
||||
|
||||
-DCMAKE_TOOLCHAIN_FILE=<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
|
||||
|
||||
Then you need to install static libogg, libvorbis, libflac, libopus, mpg123 and
|
||||
mp3lame Vcpkg packages.
|
||||
|
||||
After 1.1.0beta2 you don't need to install dependencies manually. Libsndfile
|
||||
now supports [Vcpkg manifest mode](https://vcpkg.readthedocs.io/en/latest/users/manifests/)
|
||||
and all dependencies are installed automatically.
|
||||
|
||||
However, you can turn off the manifest mode and return to the classic mode using
|
||||
the `VCPKG_MANIFEST_MODE` parameter from the command line:
|
||||
|
||||
-DVCPKG_MANIFEST_MODE=OFF
|
||||
|
||||
In classic mode, you need to install the required libraries manually:
|
||||
|
||||
vcpkg install libvorbis:x64-windows-static libflac:x64-windows-static
|
||||
opus:x64-windows-static mp3lame:x86-windows-static mpg123:x86-windows-static
|
||||
libvorbis:x86-windows-static libflac:x86-windows-static
|
||||
opus:x86-windows-static mp3lame:x86-windows-static mpg123:x86-windows-static
|
||||
|
||||
**Note**: Use must use the same CRT library for external libraries and the
|
||||
libsndfile library itself. For `*-static` triplets Vcpkg uses
|
||||
[static CRT](https://vcpkg.readthedocs.io/en/latest/users/triplets/).
|
||||
|
11
SECURITY.md
Normal file
11
SECURITY.md
Normal 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.
|
@ -95,7 +95,7 @@ Build/Stamp/build-ogg : Build/Stamp/sha256sum
|
||||
ifeq ($(disable_ogg_crc), true)
|
||||
echo "Ogg/CRC enabled"
|
||||
(cd Build && git clone https://github.com/xiph/ogg $(ogg_version))
|
||||
(cd Build/$(ogg_version) && ./autogen.sh && CFLAGS=-fPIC ./configure $(config_options) --disable-crc && make all install)
|
||||
(cd Build/$(ogg_version) && autoreconf -vif && CFLAGS=-fPIC ./configure $(config_options) --disable-crc && make all install)
|
||||
else
|
||||
echo "Ogg/CRC disabled"
|
||||
(cd Build && tar xf Tarballs/$(ogg_tarball))
|
||||
@ -110,7 +110,7 @@ Build/Stamp/install-libs : Build/Stamp/extract Build/Stamp/build-ogg
|
||||
touch $@
|
||||
|
||||
configure : configure.ac
|
||||
./autogen.sh
|
||||
autoreconf -vif
|
||||
|
||||
Build/Stamp/configure : Build/Stamp/install-libs configure
|
||||
PKG_CONFIG_LIBDIR=Build/lib/pkgconfig ./configure
|
||||
|
176
autogen.sh
176
autogen.sh
@ -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
64
cmake/FindMpg123.cmake
Normal 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
67
cmake/Findmp3lame.cmake
Normal 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)
|
56
cmake/SetupABIVersions.cmake
Normal file
56
cmake/SetupABIVersions.cmake
Normal 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)
|
@ -16,13 +16,6 @@ if (LARGE_FILES_DEFINITIONS)
|
||||
add_definitions(${LARGE_FILES_DEFINITIONS})
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
set(TYPEOF_SF_COUNT_T __int64)
|
||||
else ()
|
||||
set(TYPEOF_SF_COUNT_T int64_t)
|
||||
endif ()
|
||||
set (SF_COUNT_MAX 0x7fffffffffffffffll)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
find_package (Sndio)
|
||||
elseif (NOT WIN32)
|
||||
@ -56,6 +49,14 @@ else ()
|
||||
set (HAVE_EXTERNAL_XIPH_LIBS 0)
|
||||
endif ()
|
||||
|
||||
find_package (mp3lame)
|
||||
find_package (Mpg123 1.25.10)
|
||||
if (TARGET mp3lame::mp3lame AND (TARGET MPG123::libmpg123))
|
||||
set (HAVE_MPEG_LIBS 1)
|
||||
else ()
|
||||
set (HAVE_MPEG_LIBS 0)
|
||||
endif()
|
||||
|
||||
find_package (Speex)
|
||||
find_package (SQLite3)
|
||||
|
||||
@ -70,6 +71,7 @@ check_include_file (sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_file (sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_file (unistd.h HAVE_UNISTD_H)
|
||||
check_include_file (immintrin.h HAVE_IMMINTRIN_H)
|
||||
check_include_file (stdbool.h HAVE_STDBOOL_H)
|
||||
|
||||
check_cpu_arch_x86 (CPU_IS_X86)
|
||||
check_cpu_arch_x64 (CPU_IS_X64)
|
||||
@ -112,28 +114,6 @@ if (ENABLE_TESTING)
|
||||
check_type_size (void* SIZEOF_VOIDP)
|
||||
endif()
|
||||
|
||||
if ((SIZEOF_OFF_T EQUAL 8) OR (SIZEOF_LOFF_T EQUAL 8) OR (SIZEOF_OFF64_T EQUAL 8))
|
||||
set (TYPEOF_SF_COUNT_T "int64_t")
|
||||
set (SF_COUNT_MAX "0x7FFFFFFFFFFFFFFFLL")
|
||||
set (SIZEOF_SF_COUNT_T 8)
|
||||
else ()
|
||||
if (WIN32)
|
||||
set (TYPEOF_SF_COUNT_T "__int64")
|
||||
set (SF_COUNT_MAX "0x7FFFFFFFFFFFFFFFLL")
|
||||
set (SIZEOF_SF_COUNT_T 8)
|
||||
else ()
|
||||
message ("")
|
||||
message ("*** The configure process has determined that this system is capable")
|
||||
message ("*** of Large File Support but has not been able to find a type which")
|
||||
message ("*** is an unambiguous 64 bit file offset.")
|
||||
message ("*** Please contact the author to help resolve this problem.")
|
||||
message ("")
|
||||
message (FATAL_ERROR "Bad file offset type.")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
check_type_size (${TYPEOF_SF_COUNT_T} SIZEOF_SF_COUNT_T)
|
||||
|
||||
if (NOT WIN32)
|
||||
check_library_exists (m floor "" LIBM_REQUIRED)
|
||||
if (LIBM_REQUIRED)
|
||||
|
@ -4,6 +4,7 @@ set(SndFile_VERSION_MINOR @PROJECT_VERSION_MINOR@)
|
||||
set(SndFile_VERSION_PATCH @PROJECT_VERSION_PATCH@)
|
||||
|
||||
set (SndFile_WITH_EXTERNAL_LIBS @SndFile_WITH_EXTERNAL_LIBS@)
|
||||
set (SndFile_WITH_MPEG @SndFile_WITH_MPEG@)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
@ -16,6 +17,11 @@ if (SndFile_WITH_EXTERNAL_LIBS AND NOT @BUILD_SHARED_LIBS@)
|
||||
find_dependency (Opus)
|
||||
endif ()
|
||||
|
||||
if (SndFile_WITH_MPEG AND NOT @BUILD_SHARED_LIBS@)
|
||||
find_dependency (mp3lame)
|
||||
find_dependency (MPG123)
|
||||
endif ()
|
||||
|
||||
include (${CMAKE_CURRENT_LIST_DIR}/SndFileTargets.cmake)
|
||||
|
||||
set_and_check (SndFile_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
|
180
configure.ac
180
configure.ac
@ -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
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
AC_INIT([libsndfile],[1.0.31],[sndfile@mega-nerd.com],
|
||||
AC_INIT([libsndfile],[1.2.0],[sndfile@mega-nerd.com],
|
||||
[libsndfile],[http://libsndfile.github.io/libsndfile/])
|
||||
|
||||
dnl Check whether we want to set defaults for CFLAGS, CXXFLAGS, CPPFLAGS and LDFLAGS
|
||||
@ -30,7 +30,7 @@ AC_CANONICAL_HOST
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([src/config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.14 foreign dist-bzip2 no-dist-gzip serial-tests subdir-objects])
|
||||
AM_INIT_AUTOMAKE([1.14 foreign dist-xz no-dist-gzip serial-tests subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
dnl ====================================================================================
|
||||
@ -57,7 +57,7 @@ AC_LANG_POP([C++])
|
||||
AC_PROG_SED
|
||||
AM_PROG_AR
|
||||
|
||||
LT_INIT([win32-dll])
|
||||
LT_INIT([disable-static win32-dll])
|
||||
LT_PROG_RC
|
||||
|
||||
AC_PROG_INSTALL
|
||||
@ -84,17 +84,29 @@ dnl 5. If any interfaces have been added since the last public release, then i
|
||||
dnl age.
|
||||
dnl 6. If any interfaces have been removed since the last public release, then set age
|
||||
dnl to 0.
|
||||
SHARED_VERSION_INFO="1:31:0"
|
||||
|
||||
dnl This is libtool version of library, we add it to `--version-info` property.
|
||||
|
||||
m4_define([lt_current], [1])
|
||||
m4_define([lt_revision], [35])
|
||||
m4_define([lt_age], [0])
|
||||
|
||||
dnl This is ABI version for linker scripts, CMake uses the same format for
|
||||
dnl VERSION property of shared library.
|
||||
dnl The formula is: c:r:a -> c-a:a:r
|
||||
|
||||
m4_define([abi_version_major], [m4_eval(lt_current - lt_age)])
|
||||
m4_define([abi_version_minor], [lt_age])
|
||||
m4_define([abi_version_patch], [lt_revision])
|
||||
|
||||
dnl ------------------------------------------------------------------------------------
|
||||
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_CHECK_HEADERS([endian.h])
|
||||
AC_CHECK_HEADERS([byteswap.h])
|
||||
AC_CHECK_HEADERS([locale.h])
|
||||
AC_CHECK_HEADERS([sys/time.h])
|
||||
AC_CHECK_HEADERS([immintrin.h])
|
||||
AC_CHECK_HEADERS([stdbool.h])
|
||||
|
||||
AC_HEADER_SYS_WAIT
|
||||
|
||||
@ -129,9 +141,6 @@ AC_DEFINE_UNQUOTED([ENABLE_EXPERIMENTAL_CODE], [${EXPERIMENTAL_CODE}], [Set to 1
|
||||
AC_ARG_ENABLE([werror],
|
||||
[AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])])
|
||||
|
||||
AC_ARG_ENABLE([stack-smash-protection],
|
||||
[AS_HELP_STRING([--enable-stack-smash-protection], [Enable GNU GCC stack smash protection])])
|
||||
|
||||
AC_ARG_ENABLE([cpu-clip],
|
||||
[AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])])
|
||||
|
||||
@ -147,6 +156,9 @@ AC_ARG_ENABLE([alsa],
|
||||
AC_ARG_ENABLE([external-libs],
|
||||
[AS_HELP_STRING([--disable-external-libs], [disable use of FLAC, Ogg and Vorbis [[default=no]]])])
|
||||
|
||||
AC_ARG_ENABLE([mpeg],
|
||||
[AS_HELP_STRING([--disable-mpeg], [disable use of LAME/MPG123 for MPEG (MP3) [[defaults=no]]])])
|
||||
|
||||
AC_ARG_ENABLE(octave,
|
||||
[AS_HELP_STRING([--enable-octave], [enable building of GNU Octave module])])
|
||||
|
||||
@ -159,10 +171,8 @@ AC_ARG_ENABLE([test-coverage],
|
||||
AM_CONDITIONAL([ENABLE_TEST_COVERAGE], [test "x$enable_test_coverage" = "xyes"])
|
||||
|
||||
AC_ARG_ENABLE([ossfuzzers],
|
||||
[AS_HELP_STRING([--enable-ossfuzzers],
|
||||
[Whether to generate the fuzzers for OSS-Fuzz])],
|
||||
[have_ossfuzzers=yes], [have_ossfuzzers=no])
|
||||
AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_ossfuzzers" = "xyes"])
|
||||
[AS_HELP_STRING([--enable-ossfuzzers], [Whether to generate the fuzzers for OSS-Fuzz])])
|
||||
AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$enable_ossfuzzers" = "xyes"])
|
||||
|
||||
AC_SUBST([LIB_FUZZING_ENGINE])
|
||||
AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
|
||||
@ -182,12 +192,6 @@ AC_CHECK_SIZEOF([size_t], [4])
|
||||
AC_CHECK_SIZEOF([int64_t], [8])
|
||||
AC_CHECK_SIZEOF([long long], [8])
|
||||
|
||||
dnl ====================================================================================
|
||||
dnl Find an appropriate type for sf_count_t.
|
||||
dnl On systems supporting files larger than 2 Gig, sf_count_t must be a 64 bit value.
|
||||
dnl Unfortunately there is more than one way of ensuring this so need to do some
|
||||
dnl pretty rigourous testing here.
|
||||
|
||||
dnl Check for common 64 bit file offset types.
|
||||
AC_CHECK_SIZEOF([off_t], [1])
|
||||
|
||||
@ -197,25 +201,12 @@ AS_IF([test "x$enable_largefile:$ac_cv_sizeof_off_t" = "xno:8"], [
|
||||
|
||||
AS_CASE([$host_os],
|
||||
[mingw32*], [
|
||||
TYPEOF_SF_COUNT_T="__int64"
|
||||
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
|
||||
SIZEOF_SF_COUNT_T=8
|
||||
AC_DEFINE([__USE_MINGW_ANSI_STDIO], [1], [Set to 1 to use C99 printf/snprintf in MinGW.])
|
||||
],
|
||||
|
||||
[linux-android*], [
|
||||
TYPEOF_SF_COUNT_T="int64_t"
|
||||
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
|
||||
SIZEOF_SF_COUNT_T=8
|
||||
],
|
||||
|
||||
[
|
||||
SIZEOF_SF_COUNT_T=0
|
||||
AS_IF([test "x$ac_cv_sizeof_off_t" = "x8"], [
|
||||
dnl If sizeof (off_t) is 8, no further checking is needed.
|
||||
TYPEOF_SF_COUNT_T="int64_t"
|
||||
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
|
||||
SIZEOF_SF_COUNT_T=8
|
||||
], [
|
||||
dnl Save the old sizeof (off_t) value and then unset it to see if it
|
||||
dnl changes when Large File Support is enabled.
|
||||
@ -234,43 +225,9 @@ AS_CASE([$host_os],
|
||||
])
|
||||
|
||||
AC_CHECK_SIZEOF(off_t,1)
|
||||
|
||||
AS_IF([test "x$ac_cv_sizeof_off_t" = "x8"], [
|
||||
TYPEOF_SF_COUNT_T="int64_t"
|
||||
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
|
||||
SIZEOF_SF_COUNT_T=8
|
||||
], [test "x$TYPEOF_SF_COUNT_T" = "xunknown"], [
|
||||
AS_ECHO([""])
|
||||
AS_ECHO(["*** The configure process has determined that this system is capable"])
|
||||
AS_ECHO(["*** of Large File Support but has not been able to find a type which"])
|
||||
AS_ECHO(["*** is an unambiguous 64 bit file offset."])
|
||||
AS_ECHO(["*** Please contact the author to help resolve this problem."])
|
||||
AS_ECHO([""])
|
||||
AC_MSG_ERROR([[Bad file offset type.]])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
AS_CASE([$host_vendor],
|
||||
[vita], [
|
||||
TYPEOF_SF_COUNT_T="int64_t"
|
||||
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
|
||||
SIZEOF_SF_COUNT_T=8
|
||||
])
|
||||
|
||||
AS_IF([test "x$SIZEOF_SF_COUNT_T" = "x4"], [
|
||||
SF_COUNT_MAX="0x7FFFFFFF"
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED([TYPEOF_SF_COUNT_T], [${TYPEOF_SF_COUNT_T}], [Set to long if unknown.])
|
||||
AC_SUBST(TYPEOF_SF_COUNT_T)
|
||||
|
||||
AC_DEFINE_UNQUOTED([SIZEOF_SF_COUNT_T], [${SIZEOF_SF_COUNT_T}], [Set to sizeof (long) if unknown.])
|
||||
AC_SUBST(SIZEOF_SF_COUNT_T)
|
||||
|
||||
AC_DEFINE_UNQUOTED([SF_COUNT_MAX], [${SF_COUNT_MAX}], [Set to maximum allowed value of sf_count_t type.])
|
||||
AC_SUBST(SF_COUNT_MAX)
|
||||
|
||||
AC_TYPE_SSIZE_T
|
||||
|
||||
dnl ====================================================================================
|
||||
@ -374,8 +331,8 @@ AS_IF([test -n "$PKG_CONFIG"], [
|
||||
fi
|
||||
], [
|
||||
AS_ECHO([""])
|
||||
AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg and]])
|
||||
AC_MSG_WARN([[*** libvorbis) is either missing (possibly only the development]])
|
||||
AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg,]])
|
||||
AC_MSG_WARN([[*** libvorbis and libopus) is either missing (possibly only the development]])
|
||||
AC_MSG_WARN([[*** headers) or is of an unsupported version.]])
|
||||
AC_MSG_WARN([[***]])
|
||||
AC_MSG_WARN([[*** Unfortunately, for ease of maintenance, the external libs]])
|
||||
@ -387,6 +344,53 @@ AS_IF([test -n "$PKG_CONFIG"], [
|
||||
|
||||
AC_DEFINE_UNQUOTED([HAVE_EXTERNAL_XIPH_LIBS], [$HAVE_EXTERNAL_XIPH_LIBS], [Will be set to 1 if flac, ogg, vorbis, and opus are available.])
|
||||
|
||||
dnl ====================================================================================
|
||||
dnl Check for MPEG libraris liblame
|
||||
|
||||
ac_cv_lame="no"
|
||||
ac_cv_mpg123="no"
|
||||
HAVE_MPEG=0
|
||||
EXTERNAL_MPEG_REQUIRE=""
|
||||
EXTERNAL_MPEG_LIBS=""
|
||||
|
||||
AS_IF([test -n "$PKG_CONFIG"], [
|
||||
AS_IF([test "x$enable_mpeg" = "xno"], [
|
||||
AC_MSG_WARN([[*** MPEG (Lame/MPG123) disabled. ***]])
|
||||
], [
|
||||
AC_CHECK_HEADER(lame/lame.h,
|
||||
lame_header_found="yes",
|
||||
lame_header_found="no")
|
||||
AC_SEARCH_LIBS(lame_set_VBR_q, [lame mp3lame], [lame_lib_found="yes"], [lame_lib_found="no"])
|
||||
AS_IF([test "x$lame_lib_found$lame_header_found" = "xyesyes"], [
|
||||
ac_cv_lame="yes"
|
||||
], [
|
||||
AC_MSG_WARN([["MPEG support selected but external Lame library cannot be found.]])
|
||||
])
|
||||
|
||||
PKG_CHECK_MOD_VERSION([MPG123], [libmpg123 >= 1.25.10], [
|
||||
ac_cv_mpg123="yes"
|
||||
], [
|
||||
AC_MSG_WARN([["MPEG support selected but external MPG123 library cannot be found.]])
|
||||
])
|
||||
|
||||
AS_IF([test "x$ac_cv_lame$ac_cv_mpg123" = "xyesyes"], [
|
||||
enable_mpeg="yes"
|
||||
HAVE_MPEG=1
|
||||
EXTERNAL_MPEG_REQUIRE="libmpg123"
|
||||
EXTERNAL_MPEG_LIBS="-lmp3lame"
|
||||
MPEG_CFLAGS="$MPG123_CFLAGS"
|
||||
MPEG_LIBS="$MPG123_LIBS"
|
||||
], [
|
||||
enable_mpeg="no"
|
||||
AS_ECHO([""])
|
||||
AC_MSG_WARN([[*** MPEG support disabled.]])
|
||||
AS_ECHO([""])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED([HAVE_MPEG], [$HAVE_MPEG], [Will be set to 1 if lame, mpg123 mpeg support is available.])
|
||||
|
||||
dnl ====================================================================================
|
||||
dnl Check for libsqlite3 (only used in regtest).
|
||||
|
||||
@ -574,18 +578,24 @@ AS_IF([test "x$enable_werror" = "xyes"], [
|
||||
AC_LANG_POP([C++])
|
||||
])
|
||||
|
||||
common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self -Wno-format-truncation"
|
||||
AX_APPEND_COMPILE_FLAGS([${common_flags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS])
|
||||
common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self"
|
||||
common_cflags="${common_flags}"
|
||||
dnl Clang doesn't know about -Wno-format-truncation
|
||||
dnl and would spew tons of warnings otherwise.
|
||||
AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [
|
||||
common_cflags+=" -Wno-format-truncation"
|
||||
])
|
||||
common_cxxflags="${common_flags}"
|
||||
AS_IF([test "x$ax_cv_cxx_compiler_vendor" = "xgnu"], [
|
||||
common_cxxflags+=" -Wno-format-truncation"
|
||||
])
|
||||
|
||||
AX_APPEND_COMPILE_FLAGS([${common_cflags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS])
|
||||
|
||||
AC_LANG_PUSH([C++])
|
||||
AX_APPEND_COMPILE_FLAGS([${common_flags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS])
|
||||
AX_APPEND_COMPILE_FLAGS([${common_cxxflags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS])
|
||||
AC_LANG_POP([C++])
|
||||
|
||||
AS_IF([test "x$enable_stack_smash_protection" = "xyes"], [
|
||||
XIPH_GCC_STACK_PROTECTOR
|
||||
XIPH_GXX_STACK_PROTECTOR
|
||||
])
|
||||
|
||||
AS_IF([test "x$enable_test_coverage" = "xyes"], [
|
||||
AX_APPEND_COMPILE_FLAGS([-coverage], [CFLAGS])
|
||||
])
|
||||
@ -638,7 +648,7 @@ AS_IF([test "$HOST_TRIPLET" = "x86_64-w64-mingw32"], [
|
||||
OS_SPECIFIC_LINKS=" -static-libgcc $OS_SPECIFIC_LINKS"
|
||||
])
|
||||
|
||||
WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/p.*//" -e "s/\./,/g"`
|
||||
WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/pre.*//" -e "s/beta.*//" -e "s/\./,/g"`
|
||||
|
||||
|
||||
AS_IF([test "x$enable_static" = "xno"], [
|
||||
@ -657,7 +667,8 @@ AC_SUBST(HTML_BGCOLOUR)
|
||||
AC_SUBST(HTML_FGCOLOUR)
|
||||
|
||||
AC_SUBST(SHLIB_VERSION_ARG)
|
||||
AC_SUBST(SHARED_VERSION_INFO)
|
||||
AC_SUBST([SHARED_VERSION_INFO], [lt_current:lt_revision:lt_age])
|
||||
AC_SUBST([ABI_VERSION], [abi_version_major.abi_version_minor.abi_version_patch])
|
||||
AC_SUBST(CLEAN_VERSION)
|
||||
AC_SUBST(VERSION_MAJOR)
|
||||
AC_SUBST(GEN_TOOL)
|
||||
@ -665,6 +676,7 @@ AC_SUBST(GEN_TOOL)
|
||||
AC_SUBST(WIN_RC_VERSION)
|
||||
|
||||
AC_SUBST(HAVE_EXTERNAL_XIPH_LIBS)
|
||||
AC_SUBST(HAVE_MPEG)
|
||||
AC_SUBST(OS_SPECIFIC_CFLAGS)
|
||||
AC_SUBST(OS_SPECIFIC_LINKS)
|
||||
AC_SUBST(SNDIO_LIBS)
|
||||
@ -672,12 +684,18 @@ AC_SUBST(SNDIO_LIBS)
|
||||
AC_SUBST(EXTERNAL_XIPH_CFLAGS)
|
||||
AC_SUBST(EXTERNAL_XIPH_LIBS)
|
||||
AC_SUBST(EXTERNAL_XIPH_REQUIRE)
|
||||
AC_SUBST(EXTERNAL_MPEG_LIBS)
|
||||
AC_SUBST(EXTERNAL_MPEG_REQUIRE)
|
||||
AC_SUBST(MPG123_CFLAGS)
|
||||
AC_SUBST(MPG123_LIBS)
|
||||
AC_SUBST(MPEG_CFLAGS)
|
||||
AC_SUBST(MPEG_LIBS)
|
||||
AC_SUBST(SRC_BINDIR)
|
||||
AC_SUBST(TEST_BINDIR)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile Octave/Makefile
|
||||
src/version-metadata.rc include/sndfile.h
|
||||
src/version-metadata.rc
|
||||
tests/test_wrapper.sh tests/pedantic-header-test.sh
|
||||
libsndfile.spec sndfile.pc
|
||||
Scripts/build-test-tarball.mk
|
||||
@ -717,6 +735,7 @@ AC_MSG_RESULT([
|
||||
Experimental code : ................... ${enable_experimental:-no}
|
||||
Using ALSA in example programs : ...... ${enable_alsa:-no}
|
||||
External FLAC/Ogg/Vorbis/Opus : ....... ${enable_external_libs:-no}
|
||||
External MPEG Lame/MPG123 : ........... ${enable_mpeg:-no}
|
||||
Building Octave interface : ........... ${OCTAVE_BUILD}
|
||||
|
||||
Tools :
|
||||
@ -725,7 +744,6 @@ AC_MSG_RESULT([
|
||||
CXX Compiler Vendor is : .............. ${ax_cv_cxx_compiler_vendor} (${ax_cv_cxx_compiler_version})
|
||||
|
||||
Sanitizer enabled : ................... ${enable_sanitizer:-no}
|
||||
Stack smash protection : .............. ${enable_stack_smash_protection:-no}
|
||||
|
||||
Installation directories :
|
||||
|
||||
|
@ -438,10 +438,12 @@ Use CMake project.
|
||||
|
||||
## Q20 : Why doesn't libsndfile support MP3? {#Q020}
|
||||
|
||||
In the past, MP3 was not supported because the technology behind MP3 was
|
||||
~~In the past, MP3 was not supported because the technology behind MP3 was
|
||||
patented. Those patents have now expired and there is an
|
||||
[open ticket](https://github.com/libsndfile/libsndfile/issues/258) to implement
|
||||
MP3 support.
|
||||
MP3 support.~~
|
||||
|
||||
**Update :** Starting from version 1.1.0 libsndfile supports MP3 format.
|
||||
|
||||
## Q21 : How do I use libsndfile in a closed source or commercial program and comply with the license? {#Q021}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
author: "The libsndfile team"
|
||||
version: "1.0.31"
|
||||
version: "1.1.0"
|
||||
|
||||
markdown: kramdown
|
||||
plugins:
|
||||
|
@ -12,7 +12,7 @@ title: libsndfile home page
|
||||
<a href="#history">History</a> -+-
|
||||
<a href="#features">Features</a> -+-
|
||||
<a href="#similar-or-related-projects">Similar or related projects</a> -+-
|
||||
<a href="https://github.com/libsndfile/libsndfile/blob/master/NEWS">News</a>
|
||||
<a href="https://github.com/libsndfile/libsndfile/blob/master/CHANGELOG.md">News</a>
|
||||
<br>
|
||||
<a href="development.html">Development</a> -+-
|
||||
<a href="api.html">Programming interface</a> -+-
|
||||
|
144
docs/api.md
144
docs/api.md
@ -97,6 +97,10 @@ calling **sf_open**(). The only exception to this is the case of RAW files where
|
||||
the caller has to set the **samplerate**, **channels** and **format** fields to
|
||||
valid values. All other fields of the structure are filled in by the library.
|
||||
|
||||
**Note:** The libsndfile library will reject values for field **channels** that
|
||||
are greater than `1024`. These value represent the maximum theoretical limit
|
||||
and may be less for specific formats.
|
||||
|
||||
When opening a file for write, the caller must fill in structure members
|
||||
**samplerate**, **channels**, and **format**.
|
||||
|
||||
@ -107,74 +111,78 @@ value. The currently understood formats are listed in *sndfile.h* as follows and
|
||||
also include bitmasks for separating major and minor file types. Not all
|
||||
combinations of endian-ness and major and minor file types are valid.
|
||||
|
||||
| Name | Value | Description |
|
||||
|:-----------------------|:-----------|:-------------------------------------------|
|
||||
| **Major formats.** |
|
||||
| SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). |
|
||||
| SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). |
|
||||
| SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). |
|
||||
| SF_FORMAT_RAW | 0x040000 | RAW PCM data. |
|
||||
| SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. |
|
||||
| SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. |
|
||||
| SF_FORMAT_NIST | 0x070000 | Sphere NIST format. |
|
||||
| SF_FORMAT_VOC | 0x080000 | VOC files. |
|
||||
| SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL |
|
||||
| SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV |
|
||||
| SF_FORMAT_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 |
|
||||
| SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 |
|
||||
| SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format |
|
||||
| SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument |
|
||||
| SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format |
|
||||
| SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard |
|
||||
| SF_FORMAT_AVR | 0x120000 | Audio Visual Research |
|
||||
| SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX |
|
||||
| SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 |
|
||||
| SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format |
|
||||
| SF_FORMAT_CAF | 0x180000 | Core Audio File format |
|
||||
| SF_FORMAT_WVE | 0x190000 | Psion WVE format |
|
||||
| SF_FORMAT_OGG | 0x200000 | Xiph OGG container |
|
||||
| SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler |
|
||||
| SF_FORMAT_RF64 | 0x220000 | RF64 WAV file |
|
||||
| **Subtypes.** |
|
||||
| SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data |
|
||||
| SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data |
|
||||
| SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data |
|
||||
| SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data |
|
||||
| SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) |
|
||||
| SF_FORMAT_FLOAT | 0x0006 | 32 bit float data |
|
||||
| SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data |
|
||||
| SF_FORMAT_ULAW | 0x0010 | U-Law encoded. |
|
||||
| SF_FORMAT_ALAW | 0x0011 | A-Law encoded. |
|
||||
| SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. |
|
||||
| SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. |
|
||||
| SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. |
|
||||
| SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM |
|
||||
| SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. |
|
||||
| SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. |
|
||||
| SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. |
|
||||
| SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. |
|
||||
| SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. |
|
||||
| SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. |
|
||||
| SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) |
|
||||
| SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) |
|
||||
| SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. |
|
||||
| SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. |
|
||||
| SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). |
|
||||
| SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). |
|
||||
| SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). |
|
||||
| SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). |
|
||||
| **Endian-ness options.** |
|
||||
| SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. |
|
||||
| SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. |
|
||||
| SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. |
|
||||
| SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. |
|
||||
| SF_FORMAT_SUBMASK | 0x0000FFFF | |
|
||||
| SF_FORMAT_TYPEMASK | 0x0FFF0000 | |
|
||||
| SF_FORMAT_ENDMASK | 0x30000000 | |
|
||||
| Name | Value | Description |
|
||||
|:-------------------------|:-----------|:-------------------------------------------|
|
||||
| **Major formats.** |
|
||||
| SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). |
|
||||
| SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). |
|
||||
| SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). |
|
||||
| SF_FORMAT_RAW | 0x040000 | RAW PCM data. |
|
||||
| SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. |
|
||||
| SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. |
|
||||
| SF_FORMAT_NIST | 0x070000 | Sphere NIST format. |
|
||||
| SF_FORMAT_VOC | 0x080000 | VOC files. |
|
||||
| SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL |
|
||||
| SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV |
|
||||
| SF_FORMAT_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 |
|
||||
| SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 |
|
||||
| SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format |
|
||||
| SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument |
|
||||
| SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format |
|
||||
| SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard |
|
||||
| SF_FORMAT_AVR | 0x120000 | Audio Visual Research |
|
||||
| SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX |
|
||||
| SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 |
|
||||
| SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format |
|
||||
| SF_FORMAT_CAF | 0x180000 | Core Audio File format |
|
||||
| SF_FORMAT_WVE | 0x190000 | Psion WVE format |
|
||||
| SF_FORMAT_OGG | 0x200000 | Xiph OGG container |
|
||||
| SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler |
|
||||
| SF_FORMAT_RF64 | 0x220000 | RF64 WAV file |
|
||||
| SF_FORMAT_MPEG | 0x230000 | MPEG-1/2 audio stream |
|
||||
| **Subtypes.** |
|
||||
| SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data |
|
||||
| SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data |
|
||||
| SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data |
|
||||
| SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data |
|
||||
| SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) |
|
||||
| SF_FORMAT_FLOAT | 0x0006 | 32 bit float data |
|
||||
| SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data |
|
||||
| SF_FORMAT_ULAW | 0x0010 | U-Law encoded. |
|
||||
| SF_FORMAT_ALAW | 0x0011 | A-Law encoded. |
|
||||
| SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. |
|
||||
| SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. |
|
||||
| SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. |
|
||||
| SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM |
|
||||
| SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. |
|
||||
| SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. |
|
||||
| SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. |
|
||||
| SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. |
|
||||
| SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. |
|
||||
| SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. |
|
||||
| SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. |
|
||||
| SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) |
|
||||
| SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) |
|
||||
| SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. |
|
||||
| SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. |
|
||||
| SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). |
|
||||
| SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). |
|
||||
| SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). |
|
||||
| SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). |
|
||||
| SF_FORMAT_MPEG_LAYER_I | 0x0080 | MPEG-1 Audio Layer I. |
|
||||
| SF_FORMAT_MPEG_LAYER_II | 0x0081 | MPEG-1 Audio Layer II. |
|
||||
| SF_FORMAT_MPEG_LAYER_III | 0x0082 | MPEG-2 Audio Layer III. |
|
||||
| **Endian-ness options.** |
|
||||
| SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. |
|
||||
| SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. |
|
||||
| SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. |
|
||||
| SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. |
|
||||
| SF_FORMAT_SUBMASK | 0x0000FFFF | |
|
||||
| SF_FORMAT_TYPEMASK | 0x0FFF0000 | |
|
||||
| SF_FORMAT_ENDMASK | 0x30000000 | |
|
||||
|
||||
Every call to **sf_open**() should be matched with a call to
|
||||
[**sf_close**()](#close) to free up memory allocated during the call to **sf_open**().
|
||||
|
@ -64,6 +64,7 @@ The available commands are as follows:
|
||||
| [SFC_WAVEX_SET_AMBISONIC](#sfc_wavex_set_ambisonic) | Modify a WAVEX header for Ambisonic format. |
|
||||
| [SFC_SET_VBR_ENCODING_QUALITY](#sfc_set_vbr_encoding_quality) | Set the Variable Bit Rate encoding quality. |
|
||||
| [SFC_SET_OGG_PAGE_LATENCY_MS](#sfc_set_ogg_page_latency_ms) | Set Ogg page latency for Opus file. |
|
||||
| [SFC_GET_OGG_STREAM_SERIALNO](#sfc_get_ogg_stream_serialno) | Get Ogg stream serial number. |
|
||||
| [SFC_SET_COMPRESSION_LEVEL](#sfc_set_compression_level) | Set the compression level. |
|
||||
| [SFC_RAW_DATA_NEEDS_ENDSWAP](#sfc_raw_data_needs_endswap) | Determine if raw data needs endswapping. |
|
||||
| [SFC_GET_BROADCAST_INFO](#sfc_get_broadcast_info) | Get the Broadcast Chunk info. |
|
||||
@ -81,6 +82,8 @@ The available commands are as follows:
|
||||
| [SFC_RF64_AUTO_DOWNGRADE](#sfc_rf64_auto_downgrade) | Set auto downgrade from RF64 to WAV. |
|
||||
| [SFC_GET_ORIGINAL_SAMPLERATE](#sfc_get_original_samplerate) | Get original samplerate metadata. |
|
||||
| [SFC_SET_ORIGINAL_SAMPLERATE](#sfc_set_original_samplerate) | Set original samplerate metadata. |
|
||||
| [SFC_GET_BITRATE_MODE](#sfc_get_bitrate_mode) | Get bitrate mode. |
|
||||
| [SFC_SET_BITRATE_MODE](#sfc_set_bitrate_mode) | Set bitrate mode. |
|
||||
|
||||
---
|
||||
|
||||
@ -1271,6 +1274,30 @@ datasize
|
||||
|
||||
0 on success and non-zero otherwise.
|
||||
|
||||
## SFC_GET_OGG_STREAM_SERIALNO
|
||||
|
||||
Get the Ogg stream serial number for files with the Ogg major format. Ogg
|
||||
stream serail numbers are a randomly chosen 32-bit value, used for
|
||||
differentiating logical Ogg streams.
|
||||
|
||||
### Parameters
|
||||
|
||||
sndfile
|
||||
: A valid SNDFILE* pointer
|
||||
|
||||
cmd
|
||||
: SFC_SET_OGG_STREAM_SERIALNO
|
||||
|
||||
data
|
||||
: A pointer to a 32-bit int value
|
||||
|
||||
datasize
|
||||
: sizeof (int32_t) = 4
|
||||
|
||||
### Return value
|
||||
|
||||
0 on success and non-zero otherwise.
|
||||
|
||||
## SFC_SET_COMPRESSION_LEVEL
|
||||
|
||||
Set the compression level. The compression level should be between 0.0 (minimum
|
||||
@ -1927,3 +1954,63 @@ Returns SF_TRUE on success, SF_FALSE otherwise.
|
||||
On write, can only succeed if no data has been written. On read, if successful,
|
||||
[SFC_GET_CURRENT_SF_INFO](#sfc_get_current_sf_info) should be called to
|
||||
determine the new frames count and samplerate
|
||||
|
||||
## SFC_GET_BITRATE_MODE
|
||||
|
||||
Get bitrate mode.
|
||||
|
||||
The bitrate mode is one of:
|
||||
|
||||
| Name | Value | Description |
|
||||
|:-------------------------|:------|:------------------|
|
||||
| SF_BITRATE_MODE_CONSTANT | 800 | Constant bitrate. |
|
||||
| SF_BITRATE_MODE_AVERAGE | 801 | Average bitrate. |
|
||||
| SF_BITRATE_MODE_VARIABLE | 802 | Variable bitrate. |
|
||||
|
||||
### Parameters
|
||||
|
||||
sndfile
|
||||
: A valid SNDFILE* pointer
|
||||
|
||||
cmd
|
||||
: SFC_GET_BITRATE_MODE
|
||||
|
||||
data
|
||||
: NULL
|
||||
|
||||
datasize
|
||||
: anything
|
||||
|
||||
### Return value
|
||||
|
||||
Returns one of `SF_BITRATE_MODE_XXX` on success, `-1` otherwise.
|
||||
|
||||
## SFC_SET_BITRATE_MODE
|
||||
|
||||
Set bitrate mode.
|
||||
|
||||
The bitrate mode is one of:
|
||||
|
||||
| Name | Value | Description |
|
||||
|:-------------------------|:------|:------------------|
|
||||
| SF_BITRATE_MODE_CONSTANT | 800 | Constant bitrate. |
|
||||
| SF_BITRATE_MODE_AVERAGE | 801 | Average bitrate. |
|
||||
| SF_BITRATE_MODE_VARIABLE | 802 | Variable bitrate. |
|
||||
|
||||
### Parameters
|
||||
|
||||
sndfile
|
||||
: A valid SNDFILE* pointer
|
||||
|
||||
cmd
|
||||
: SFC_SET_BITRATE_MODE
|
||||
|
||||
data
|
||||
: pointer to an integer
|
||||
|
||||
datasize
|
||||
: sizeof (int)
|
||||
|
||||
### Return value
|
||||
|
||||
Returns `SF_TRUE` on success, `SF_FALSE` otherwise.
|
||||
|
@ -9,7 +9,7 @@ interested in helping can raise an issue 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)
|
||||
on how to build libsndfile from the Git repo.
|
||||
|
@ -40,11 +40,12 @@ From version 1.0.18, libsndfile also reads and writes
|
||||
From version 1.0.29, libsndfile can read and write
|
||||
[Ogg/Opus](https://opus-codec.org/).
|
||||
|
||||
From version 1.1.0, libsndfile can read and write MP3.
|
||||
|
||||
Some of the file formats I am also interested in adding are:
|
||||
|
||||
- Kurzweil K2000 sampler files.
|
||||
- Ogg Speex.
|
||||
- MPEG Layer 3 (commonly known as MP3)
|
||||
|
||||
Other file formats may also be added on request.
|
||||
|
||||
|
@ -142,6 +142,8 @@ Here is the release history for libsndfile:
|
||||
problems, delete old generated sndfile.h from $(top_builddir)/src.
|
||||
* Version 1.0.31 (January 24 2021) Bugfix release. Fix multiple memory leaks
|
||||
reported by OSS-Fuzz. More SSE2-optimized functions for x86 and amd64.
|
||||
* Version 1.1.0 (March 27 2022) Minor release, backward compatible with previous
|
||||
releases. Added long-awaited MP3 support. Numerous improvements and bugfixes.
|
||||
|
||||
## Similar or Related Projects
|
||||
|
||||
@ -194,7 +196,7 @@ long as you abide by [the license](http://www.gnu.org/copyleft/lesser.html).
|
||||
Check latest version on
|
||||
[GitHub Releases page](https://github.com/libsndfile/libsndfile/releases/).
|
||||
|
||||
Binatries and source packages are signed by current releaser David Seifert aka
|
||||
Binaries and source packages are signed by current releaser David Seifert aka
|
||||
@SoapGentoo. You can verify signatures with his public GPG key:
|
||||
|
||||
```
|
||||
|
@ -55,7 +55,7 @@ to disable gcc optimisations and make debugging with gdb/ddd easier.
|
||||
|
||||
Add a unique identifier for the new file type.
|
||||
|
||||
Edit src/sndfile.h.in and find the enum containing the SF_FORMAT_XXX identifiers.
|
||||
Edit src/sndfile.h and find the enum containing the SF_FORMAT_XXX identifiers.
|
||||
Since you will be adding a major file type you should add your identifier to the
|
||||
top part of the list where the values are above 0x10000 in value. The easiest
|
||||
way to do this is to find the largest value in the list, add 0x10000 to it and
|
||||
|
@ -118,7 +118,7 @@ encode_file (const char *infilename, const char *outfilename, int filetype)
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
while ((readcount = sf_read_float (infile, buffer, BUFFER_LEN)) > 0)
|
||||
while ((readcount = (int) sf_read_float (infile, buffer, BUFFER_LEN)) > 0)
|
||||
sf_write_float (outfile, buffer, readcount) ;
|
||||
|
||||
sf_close (infile) ;
|
||||
|
@ -74,12 +74,12 @@ main (void)
|
||||
|
||||
if (sfinfo.channels == 1)
|
||||
{ for (k = 0 ; k < SAMPLE_COUNT ; k++)
|
||||
buffer [k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ;
|
||||
buffer [k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ;
|
||||
}
|
||||
else if (sfinfo.channels == 2)
|
||||
{ for (k = 0 ; k < SAMPLE_COUNT ; k++)
|
||||
{ buffer [2 * k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ;
|
||||
buffer [2 * k + 1] = AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI) ;
|
||||
{ buffer [2 * k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ;
|
||||
buffer [2 * k + 1] = (int) (AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI)) ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
|
@ -98,19 +98,21 @@ main (void)
|
||||
|
||||
if (sfinfo.channels > MAX_CHANNELS)
|
||||
{ printf ("Not able to process more than %d channels\n", MAX_CHANNELS) ;
|
||||
sf_close (infile) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
/* Open the output file. */
|
||||
if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo)))
|
||||
{ printf ("Not able to open output file %s.\n", outfilename) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
sf_close (infile) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
/* While there are.frames in the input file, read them, process
|
||||
** them and write them to the output file.
|
||||
*/
|
||||
while ((readcount = sf_read_double (infile, data, BUFFER_LEN)))
|
||||
while ((readcount = (int) sf_read_double (infile, data, BUFFER_LEN)))
|
||||
{ process_data (data, readcount, sfinfo.channels) ;
|
||||
sf_write_double (outfile, data, readcount) ;
|
||||
} ;
|
||||
|
@ -46,12 +46,6 @@
|
||||
|
||||
#define BUFFER_LEN (1 << 14)
|
||||
|
||||
|
||||
typedef struct
|
||||
{ char *infilename, *outfilename ;
|
||||
SF_INFO infileinfo, outfileinfo ;
|
||||
} OptionData ;
|
||||
|
||||
const char * program_name (const char * argv0) ;
|
||||
static void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ;
|
||||
static void add_instrument_data (SNDFILE *outfile, const SF_INFO * in_info) ;
|
||||
@ -105,6 +99,7 @@ main (int argc, char * argv [])
|
||||
/* Open the output file. */
|
||||
if ((outfile = sf_open (outfilename, SFM_WRITE, &out_sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ;
|
||||
sf_close (infile) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
@ -143,7 +138,7 @@ sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels)
|
||||
readcount = frames ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_readf_int (infile, data, frames) ;
|
||||
{ readcount = (int) sf_readf_int (infile, data, frames) ;
|
||||
sf_writef_int (outfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
|
@ -60,15 +60,21 @@ print_usage (char *progname)
|
||||
|
||||
} /* print_usage */
|
||||
|
||||
static void
|
||||
static int
|
||||
convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precision)
|
||||
{ float buf [BLOCK_SIZE] ;
|
||||
{ float *buf ;
|
||||
sf_count_t frames ;
|
||||
int k, m, readcount ;
|
||||
|
||||
buf = malloc (BLOCK_SIZE * sizeof (float)) ;
|
||||
if (buf == NULL)
|
||||
{ printf ("Error : Out of memory.\n\n") ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
frames = BLOCK_SIZE / channels ;
|
||||
|
||||
while ((readcount = sf_readf_float (infile, buf, frames)) > 0)
|
||||
while ((readcount = (int) sf_readf_float (infile, buf, frames)) > 0)
|
||||
{ for (k = 0 ; k < readcount ; k++)
|
||||
{ for (m = 0 ; m < channels ; m++)
|
||||
if (full_precision)
|
||||
@ -79,7 +85,9 @@ convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precis
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
free (buf) ;
|
||||
|
||||
return 0 ;
|
||||
} /* convert_to_text */
|
||||
|
||||
int
|
||||
@ -89,6 +97,7 @@ main (int argc, char * argv [])
|
||||
FILE *outfile = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
int full_precision = 0 ;
|
||||
int ret = 1 ;
|
||||
|
||||
progname = strrchr (argv [0], '/') ;
|
||||
progname = progname ? progname + 1 : argv [0] ;
|
||||
@ -97,7 +106,7 @@ main (int argc, char * argv [])
|
||||
{ case 4 :
|
||||
if (!strcmp ("--full-precision", argv [3]))
|
||||
{ print_usage (progname) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
full_precision = 1 ;
|
||||
argv++ ;
|
||||
@ -105,7 +114,7 @@ main (int argc, char * argv [])
|
||||
break ;
|
||||
default:
|
||||
print_usage (progname) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
infilename = argv [1] ;
|
||||
@ -114,19 +123,19 @@ main (int argc, char * argv [])
|
||||
if (strcmp (infilename, outfilename) == 0)
|
||||
{ printf ("Error : Input and output filenames are the same.\n\n") ;
|
||||
print_usage (progname) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (infilename [0] == '-')
|
||||
{ printf ("Error : Input filename (%s) looks like an option.\n\n", infilename) ;
|
||||
print_usage (progname) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (outfilename [0] == '-')
|
||||
{ printf ("Error : Output filename (%s) looks like an option.\n\n", outfilename) ;
|
||||
print_usage (progname) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
@ -134,23 +143,26 @@ main (int argc, char * argv [])
|
||||
if ((infile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open input file %s.\n", infilename) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
/* Open the output file. */
|
||||
if ((outfile = fopen (outfilename, "w")) == NULL)
|
||||
{ printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
fprintf (outfile, "# Converted from file %s.\n", infilename) ;
|
||||
fprintf (outfile, "# Channels %d, Sample rate %d\n", sfinfo.channels, sfinfo.samplerate) ;
|
||||
|
||||
convert_to_text (infile, outfile, sfinfo.channels, full_precision) ;
|
||||
ret = convert_to_text (infile, outfile, sfinfo.channels, full_precision) ;
|
||||
|
||||
cleanup :
|
||||
|
||||
sf_close (infile) ;
|
||||
fclose (outfile) ;
|
||||
if (outfile != NULL)
|
||||
fclose (outfile) ;
|
||||
|
||||
return 0 ;
|
||||
return ret ;
|
||||
} /* main */
|
||||
|
||||
|
1272
include/sndfile.h
1272
include/sndfile.h
File diff suppressed because it is too large
Load Diff
@ -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 */
|
@ -47,6 +47,8 @@
|
||||
**
|
||||
** API documentation is in the doc/ directory of the source code tarball
|
||||
** and at http://libsndfile.github.io/libsndfile/api.html.
|
||||
**
|
||||
** This file is intended to compile with C++98 and newer.
|
||||
*/
|
||||
|
||||
#ifndef SNDFILE_HH
|
||||
@ -57,10 +59,10 @@
|
||||
#include <string>
|
||||
#include <new> // for std::nothrow
|
||||
|
||||
#if __cplusplus < 201100
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
#if ((defined (_MSC_VER) && (_MSC_VER >= 1600)) || (__cplusplus >= 201100L))
|
||||
#define SF_NULL nullptr
|
||||
#else
|
||||
#define SF_NULL NULL
|
||||
#endif
|
||||
|
||||
class SndfileHandle
|
||||
@ -78,7 +80,7 @@ class SndfileHandle
|
||||
|
||||
public :
|
||||
/* Default constructor */
|
||||
SndfileHandle (void) : p (nullptr) {} ;
|
||||
SndfileHandle (void) : p (SF_NULL) {} ;
|
||||
SndfileHandle (const char *path, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (std::string const & path, int mode = SFM_READ,
|
||||
@ -88,8 +90,8 @@ class SndfileHandle
|
||||
SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
SndfileHandle (LPCWSTR wpath, int mode = SFM_READ,
|
||||
#ifdef _WIN32
|
||||
SndfileHandle (const wchar_t *wpath, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
#endif
|
||||
|
||||
@ -99,9 +101,9 @@ class SndfileHandle
|
||||
SndfileHandle & operator = (const SndfileHandle &rhs) ;
|
||||
|
||||
/* Mainly for debugging/testing. */
|
||||
int refCount (void) const { return (p == nullptr) ? 0 : p->ref ; }
|
||||
int refCount (void) const { return (p == SF_NULL) ? 0 : p->ref ; }
|
||||
|
||||
operator bool () const { return (p != nullptr) ; }
|
||||
operator bool () const { return (p != SF_NULL) ; }
|
||||
|
||||
bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
|
||||
|
||||
@ -161,20 +163,20 @@ class SndfileHandle
|
||||
|
||||
inline
|
||||
SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
|
||||
: sf (nullptr), sfinfo (), ref (1)
|
||||
: sf (SF_NULL), sfinfo (), ref (1)
|
||||
{}
|
||||
|
||||
inline
|
||||
SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
|
||||
{ if (sf != nullptr) sf_close (sf) ; }
|
||||
{ if (sf != SF_NULL) sf_close (sf) ; }
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
: p (SF_NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
if (p != SF_NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
@ -192,11 +194,11 @@ SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, in
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
: p (SF_NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
if (p != SF_NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
@ -214,14 +216,14 @@ SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int c
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
: p (SF_NULL)
|
||||
{
|
||||
if (fd < 0)
|
||||
return ;
|
||||
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
if (p != SF_NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
@ -239,11 +241,11 @@ SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int ch
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
: p (SF_NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
if (p != SF_NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
@ -261,7 +263,7 @@ SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mod
|
||||
|
||||
inline
|
||||
SndfileHandle::~SndfileHandle (void)
|
||||
{ if (p != nullptr && -- p->ref == 0)
|
||||
{ if (p != SF_NULL && -- p->ref == 0)
|
||||
delete p ;
|
||||
} /* SndfileHandle destructor */
|
||||
|
||||
@ -269,7 +271,7 @@ SndfileHandle::~SndfileHandle (void)
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (const SndfileHandle &orig)
|
||||
: p (orig.p)
|
||||
{ if (p != nullptr)
|
||||
{ if (p != SF_NULL)
|
||||
++ p->ref ;
|
||||
} /* SndfileHandle copy constructor */
|
||||
|
||||
@ -278,11 +280,11 @@ SndfileHandle::operator = (const SndfileHandle &rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this ;
|
||||
if (p != nullptr && -- p->ref == 0)
|
||||
if (p != SF_NULL && -- p->ref == 0)
|
||||
delete p ;
|
||||
|
||||
p = rhs.p ;
|
||||
if (p != nullptr)
|
||||
if (p != SF_NULL)
|
||||
++ p->ref ;
|
||||
|
||||
return *this ;
|
||||
@ -407,30 +409,30 @@ SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::rawHandle (void)
|
||||
{ return (p ? p->sf : nullptr) ; }
|
||||
{ return (p ? p->sf : SF_NULL) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::takeOwnership (void)
|
||||
{
|
||||
if (p == nullptr || (p->ref != 1))
|
||||
return nullptr ;
|
||||
if (p == SF_NULL || (p->ref != 1))
|
||||
return SF_NULL ;
|
||||
|
||||
SNDFILE * sf = p->sf ;
|
||||
p->sf = nullptr ;
|
||||
p->sf = SF_NULL ;
|
||||
delete p ;
|
||||
p = nullptr ;
|
||||
p = SF_NULL ;
|
||||
return sf ;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
#ifdef _WIN32
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)
|
||||
: p (nullptr)
|
||||
SndfileHandle::SndfileHandle (const wchar_t *wpath, int mode, int fmt, int chans, int srate)
|
||||
: p (SF_NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != nullptr)
|
||||
if (p != SF_NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
|
@ -1,5 +1,5 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@ -9,9 +9,9 @@
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check whether -D_FORTIFY_SOURCE=2 can be added to CPPFLAGS without macro
|
||||
# redefinition warnings. Some distributions (such as Gentoo Linux) enable
|
||||
# _FORTIFY_SOURCE globally in their compilers, leading to unnecessary
|
||||
# warnings in the form of
|
||||
# redefinition warnings, other cpp warnings or linker. Some distributions
|
||||
# (such as Gentoo Linux) enable _FORTIFY_SOURCE globally in their
|
||||
# compilers, leading to unnecessary warnings in the form of
|
||||
#
|
||||
# <command-line>:0:0: error: "_FORTIFY_SOURCE" redefined [-Werror]
|
||||
# <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
|
||||
# to CPPFLAGS.
|
||||
#
|
||||
# Newer mingw-w64 msys2 package comes with a bug in
|
||||
# headers-git-7.0.0.5546.d200317d-1. It broke -D_FORTIFY_SOURCE support,
|
||||
# and would need -lssp or -fstack-protector. See
|
||||
# https://github.com/msys2/MINGW-packages/issues/5803. Try to actually
|
||||
# link it.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2017 David Seifert <soap@gentoo.org>
|
||||
# Copyright (c) 2019 Reini Urban <rurban@cpan.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 1
|
||||
#serial 4
|
||||
|
||||
AC_DEFUN([AX_ADD_FORTIFY_SOURCE],[
|
||||
ac_save_cflags=$CFLAGS
|
||||
ac_cwerror_flag=yes
|
||||
AX_CHECK_COMPILE_FLAG([-Werror],[CFLAGS="$CFLAGS -Werror"])
|
||||
AC_MSG_CHECKING([whether to add -D_FORTIFY_SOURCE=2 to CPPFLAGS])
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_SOURCE(
|
||||
AC_LANG_PROGRAM([],
|
||||
[[
|
||||
int main() {
|
||||
#ifndef _FORTIFY_SOURCE
|
||||
return 0;
|
||||
#else
|
||||
this_is_an_error;
|
||||
#endif
|
||||
}
|
||||
]]
|
||||
)], [
|
||||
AC_MSG_RESULT([yes])
|
||||
CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2"
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
)],
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_SOURCE([[
|
||||
#define _FORTIFY_SOURCE 2
|
||||
#include <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
|
||||
])
|
||||
])
|
||||
|
@ -55,10 +55,10 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [puts ("")])], pkg_link=
|
||||
CFLAGS=$pkg_link_saved_CFLAGS
|
||||
LIBS=$pkg_link_saved_LIBS
|
||||
|
||||
if test $pkg_link = no ; then
|
||||
$as_echo_n "link failed ... "
|
||||
AS_IF([test x$pkg_link = xno], [
|
||||
AS_ECHO_N(["link failed ... "])
|
||||
pkg_failed=yes
|
||||
fi
|
||||
])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
|
@ -16,7 +16,7 @@ AC_DEFUN([OCTAVE_MKOCTFILE_VERSION],
|
||||
|
||||
|
||||
AC_ARG_WITH(mkoctfile,
|
||||
AC_HELP_STRING([--with-mkoctfile], [choose the mkoctfile version]),
|
||||
AS_HELP_STRING([--with-mkoctfile], [choose the mkoctfile version]),
|
||||
[ with_mkoctfile=$withval ])
|
||||
|
||||
test -z "$with_mkoctfile" && with_mkoctfile=mkoctfile
|
||||
|
@ -29,7 +29,7 @@ AC_DEFUN([AC_OCTAVE_VERSION],
|
||||
[
|
||||
|
||||
AC_ARG_WITH(octave,
|
||||
AC_HELP_STRING([--with-octave], [choose the octave version]),
|
||||
AS_HELP_STRING([--with-octave], [choose the octave version]),
|
||||
[ with_octave=$withval ])
|
||||
|
||||
test -z "$with_octave" && with_octave=octave
|
||||
@ -63,7 +63,7 @@ AC_DEFUN([AC_OCTAVE_CONFIG_VERSION],
|
||||
[
|
||||
|
||||
AC_ARG_WITH(octave-config,
|
||||
AC_HELP_STRING([--with-octave-config], [choose the octave-config version]),
|
||||
AS_HELP_STRING([--with-octave-config], [choose the octave-config version]),
|
||||
[ with_octave_config=$withval ])
|
||||
|
||||
test -z "$with_octave_config" && with_octave_config=octave-config
|
||||
|
@ -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
|
@ -1,4 +1,4 @@
|
||||
.Dd November 2, 2014
|
||||
.Dd September 10, 2021
|
||||
.Dt SNDFILE-PLAY 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -19,6 +19,8 @@ ALSA or OSS
|
||||
sndio
|
||||
.It FreeBSD
|
||||
/dev/dsp (OSS)
|
||||
.It NetBSD
|
||||
/dev/audio
|
||||
.It Solaris
|
||||
/dev/audio
|
||||
.It MacOSX 10.6
|
||||
|
@ -23,9 +23,10 @@ apt-get -y install autoconf autogen automake libtool pkg-config python
|
||||
# libasound2-dev libflac-dev libogg-dev libopus-dev libvorbis-dev
|
||||
|
||||
# Compile the fuzzer.
|
||||
./autogen.sh
|
||||
autoreconf -vif
|
||||
./configure --disable-shared --enable-ossfuzzers
|
||||
make V=1
|
||||
|
||||
# Copy the fuzzer to the output directory.
|
||||
cp -v ossfuzz/sndfile_fuzzer $OUT/
|
||||
cp -v ossfuzz/sndfile_alt_fuzzer $OUT/
|
||||
|
79
ossfuzz/sndfile_alt_fuzzer.cc
Normal file
79
ossfuzz/sndfile_alt_fuzzer.cc
Normal 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 ;
|
||||
}
|
119
ossfuzz/sndfile_fuzz_header.h
Normal file
119
ossfuzz/sndfile_fuzz_header.h
Normal 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
|
@ -5,151 +5,35 @@
|
||||
#include <sndfile.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sf_count_t offset;
|
||||
sf_count_t length;
|
||||
const unsigned char *data;
|
||||
} VIO_DATA;
|
||||
|
||||
static sf_count_t vfget_filelen (void *user_data)
|
||||
{
|
||||
VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
return vf->length;
|
||||
}
|
||||
|
||||
static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
|
||||
{
|
||||
VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
sf_count_t new_offset;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
new_offset = offset;
|
||||
break ;
|
||||
|
||||
case SEEK_CUR:
|
||||
new_offset = vf->offset + offset;
|
||||
break ;
|
||||
|
||||
case SEEK_END:
|
||||
new_offset = vf->length + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure you can't seek outside the data */
|
||||
if (new_offset > vf->length)
|
||||
{
|
||||
/* Trying to seek past the end of the data */
|
||||
printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");"
|
||||
" whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n",
|
||||
new_offset, vf->length, whence, vf->offset, offset);
|
||||
new_offset = vf->length;
|
||||
}
|
||||
else if (new_offset < 0)
|
||||
{
|
||||
/* Trying to seek before the start of the data */
|
||||
printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset"
|
||||
"(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n",
|
||||
new_offset, whence, vf->offset, vf->length, offset);
|
||||
new_offset = 0;
|
||||
}
|
||||
vf->offset = new_offset;
|
||||
|
||||
return vf->offset;
|
||||
}
|
||||
|
||||
static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
|
||||
if (vf->offset + count > vf->length)
|
||||
{
|
||||
count = vf->length - vf->offset;
|
||||
}
|
||||
|
||||
memcpy(ptr, vf->data + vf->offset, count);
|
||||
vf->offset += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)count;
|
||||
(void)user_data;
|
||||
|
||||
// Cannot write to this virtual file.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sf_count_t vftell (void *user_data)
|
||||
{ VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
|
||||
return vf->offset;
|
||||
}
|
||||
#include "sndfile_fuzz_header.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
VIO_DATA vio_data;
|
||||
SF_VIRTUAL_IO vio;
|
||||
SF_INFO sndfile_info;
|
||||
SNDFILE *sndfile = NULL;
|
||||
float* read_buffer = NULL;
|
||||
{ VIO_DATA vio_data ;
|
||||
SF_VIRTUAL_IO vio ;
|
||||
SF_INFO sndfile_info ;
|
||||
SNDFILE *sndfile = NULL ;
|
||||
float* read_buffer = NULL ;
|
||||
|
||||
// Initialize the virtual IO structure.
|
||||
vio.get_filelen = vfget_filelen;
|
||||
vio.seek = vfseek;
|
||||
vio.read = vfread;
|
||||
vio.write = vfwrite;
|
||||
vio.tell = vftell;
|
||||
int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ;
|
||||
if (err)
|
||||
goto EXIT_LABEL ;
|
||||
|
||||
// Initialize the VIO user data.
|
||||
vio_data.data = data;
|
||||
vio_data.length = size;
|
||||
vio_data.offset = 0;
|
||||
// Just the right number of channels. Create some buffer space for reading.
|
||||
read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
|
||||
if (read_buffer == NULL)
|
||||
abort() ;
|
||||
|
||||
memset(&sndfile_info, 0, sizeof(SF_INFO));
|
||||
|
||||
// Try and open the virtual file.
|
||||
sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data);
|
||||
|
||||
if (sndfile_info.channels == 0)
|
||||
{
|
||||
// No sound channels in file.
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
else if (sndfile_info.channels > 1024 * 1024)
|
||||
{
|
||||
// Too many channels to handle.
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
// Just the right number of channels. Create some buffer space for reading.
|
||||
read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
|
||||
if (read_buffer == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
while (sf_readf_float(sndfile, read_buffer, 1))
|
||||
{
|
||||
// Do nothing with the data.
|
||||
}
|
||||
while (sf_readf_float(sndfile, read_buffer, 1))
|
||||
{
|
||||
// Do nothing with the data.
|
||||
}
|
||||
|
||||
EXIT_LABEL:
|
||||
|
||||
if (sndfile != NULL)
|
||||
{
|
||||
sf_close(sndfile);
|
||||
}
|
||||
if (sndfile != NULL)
|
||||
sf_close(sndfile) ;
|
||||
|
||||
free(read_buffer);
|
||||
free(read_buffer) ;
|
||||
|
||||
return 0;
|
||||
return 0 ;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize
|
||||
{ data [k] /= max ;
|
||||
|
||||
if (!isfinite (data [k])) /* infinite or NaN */
|
||||
return 1;
|
||||
return 1 ;
|
||||
}
|
||||
sf_writef_double (outfile, data, readcount) ;
|
||||
} ;
|
||||
@ -91,7 +91,7 @@ sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels)
|
||||
readcount = frames ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_readf_int (infile, data, frames) ;
|
||||
{ readcount = (int) sf_readf_int (infile, data, frames) ;
|
||||
sf_writef_int (outfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
@ -119,6 +119,7 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET
|
||||
{ case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
case SF_FORMAT_MPEG_LAYER_III :
|
||||
break ;
|
||||
|
||||
default :
|
||||
@ -177,7 +178,7 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET
|
||||
/* Special case for coding_history because we may want to append. */
|
||||
if (info->coding_history != NULL)
|
||||
{ if (info->coding_hist_append)
|
||||
{ int slen = strlen (binfo.coding_history) ;
|
||||
{ int slen = (int) strlen (binfo.coding_history) ;
|
||||
|
||||
while (slen > 1 && isspace (binfo.coding_history [slen - 1]))
|
||||
slen -- ;
|
||||
@ -189,7 +190,7 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET
|
||||
|
||||
memset (binfo.coding_history, 0, sizeof (binfo.coding_history)) ;
|
||||
memcpy (binfo.coding_history, info->coding_history, slen) ;
|
||||
binfo.coding_history_size = slen ;
|
||||
binfo.coding_history_size = (uint32_t) slen ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
@ -339,11 +340,12 @@ static OUTPUT_FORMAT_MAP format_map [] =
|
||||
{ "caf", 0, SF_FORMAT_CAF },
|
||||
{ "wve", 0, SF_FORMAT_WVE },
|
||||
{ "prc", 0, SF_FORMAT_WVE },
|
||||
{ "ogg", 0, SF_FORMAT_OGG },
|
||||
{ "oga", 0, SF_FORMAT_OGG },
|
||||
{ "ogg", 0, SF_FORMAT_OGG | SF_FORMAT_VORBIS },
|
||||
{ "opus", 0, SF_FORMAT_OGG | SF_FORMAT_OPUS },
|
||||
{ "mpc", 0, SF_FORMAT_MPC2K },
|
||||
{ "rf64", 0, SF_FORMAT_RF64 },
|
||||
{ "mp3", 0, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III },
|
||||
} ; /* format_map */
|
||||
|
||||
int
|
||||
@ -453,6 +455,7 @@ sfe_container_name (int format)
|
||||
case SF_FORMAT_OGG : return "OGG" ;
|
||||
case SF_FORMAT_MPC2K : return "MPC2K" ;
|
||||
case SF_FORMAT_RF64 : return "RF64" ;
|
||||
case SF_FORMAT_MPEG : return "MPEG" ;
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
@ -491,6 +494,9 @@ sfe_codec_name (int format)
|
||||
case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ;
|
||||
case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ;
|
||||
case SF_FORMAT_OPUS : return "Opus" ;
|
||||
case SF_FORMAT_MPEG_LAYER_I : return "MPEG layer 1" ;
|
||||
case SF_FORMAT_MPEG_LAYER_II : return "MPEG layer 2" ;
|
||||
case SF_FORMAT_MPEG_LAYER_III : return "MPEG layer 3" ;
|
||||
default : break ;
|
||||
} ;
|
||||
return "unknown" ;
|
||||
|
@ -143,7 +143,7 @@ concat_data_fp (SNDFILE *wfile, SNDFILE *rofile, int channels)
|
||||
sf_seek (wfile, 0, SEEK_END) ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_readf_double (rofile, data, frames) ;
|
||||
{ readcount = (int) sf_readf_double (rofile, data, frames) ;
|
||||
sf_writef_double (wfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
@ -161,7 +161,7 @@ concat_data_int (SNDFILE *wfile, SNDFILE *rofile, int channels)
|
||||
sf_seek (wfile, 0, SEEK_END) ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_readf_int (rofile, data, frames) ;
|
||||
{ readcount = (int) sf_readf_int (rofile, data, frames) ;
|
||||
sf_writef_int (wfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
|
@ -281,7 +281,7 @@ main (int argc, char * argv [])
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
printf ("Error : Not able to decode argunment '%s'.\n", argv [k]) ;
|
||||
printf ("Error : Not able to decode argument '%s'.\n", argv [k]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@ -354,7 +354,10 @@ main (int argc, char * argv [])
|
||||
|| (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT)
|
||||
|| (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT)
|
||||
|| (infileminor == SF_FORMAT_OPUS) || (outfileminor == SF_FORMAT_OPUS)
|
||||
|| (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS))
|
||||
|| (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS)
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_I)
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_II)
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_III) || (outfileminor == SF_FORMAT_MPEG_LAYER_III))
|
||||
{ if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0)
|
||||
{ printf ("Error : Not able to decode input file %s.\n", infilename) ;
|
||||
return 1 ;
|
||||
@ -388,7 +391,7 @@ copy_metadata (SNDFILE *outfile, SNDFILE *infile, int channels)
|
||||
memset (&binfo, 0, sizeof (binfo)) ;
|
||||
|
||||
if (channels < ARRAY_LEN (chanmap))
|
||||
{ size_t size = channels * sizeof (chanmap [0]) ;
|
||||
{ int size = channels * sizeof (chanmap [0]) ;
|
||||
|
||||
if (sf_command (infile, SFC_GET_CHANNEL_MAP_INFO, chanmap, size) == SF_TRUE)
|
||||
sf_command (outfile, SFC_SET_CHANNEL_MAP_INFO, chanmap, size) ;
|
||||
|
@ -65,43 +65,48 @@ static void deinterleave_double (STATE * state) ;
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{ STATE state ;
|
||||
{ STATE *state = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
char pathname [512], ext [32], *cptr ;
|
||||
int ch, double_split ;
|
||||
int ch, double_split, ret = 1 ;
|
||||
|
||||
if (argc != 2)
|
||||
{ if (argc != 1)
|
||||
puts ("\nError : need a single input file.\n") ;
|
||||
usage_exit () ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
memset (&state, 0, sizeof (state)) ;
|
||||
state = calloc (1, sizeof (*state)) ;
|
||||
if (!state)
|
||||
{ printf ("\nError : Out of memory.\n") ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((state.infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL)
|
||||
if ((state->infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("\nError : Not able to open input file '%s'\n%s\n", argv [1], sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels < 2)
|
||||
{ printf ("\nError : Input file '%s' only has one channel.\n", argv [1]) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels > MAX_CHANNELS)
|
||||
{ printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n",
|
||||
argv [1], sfinfo.channels, MAX_CHANNELS) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
|
||||
state.channels = sfinfo.channels ;
|
||||
state->channels = sfinfo.channels ;
|
||||
sfinfo.channels = 1 ;
|
||||
|
||||
if (snprintf (pathname, sizeof (pathname), "%s", argv [1]) > (int) sizeof (pathname))
|
||||
{ printf ("\nError : Length of provided filename '%s' exceeds MAX_PATH (%d).\n", argv [1], (int) sizeof (pathname)) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if ((cptr = strrchr (pathname, '.')) == NULL)
|
||||
@ -114,7 +119,7 @@ main (int argc, char **argv)
|
||||
printf ("Input file : %s\n", pathname) ;
|
||||
puts ("Output files :") ;
|
||||
|
||||
for (ch = 0 ; ch < state.channels ; ch++)
|
||||
for (ch = 0 ; ch < state->channels ; ch++)
|
||||
{ char filename [520] ;
|
||||
size_t count ;
|
||||
|
||||
@ -124,9 +129,9 @@ main (int argc, char **argv)
|
||||
{ printf ("File name truncated to %s\n", filename) ;
|
||||
} ;
|
||||
|
||||
if ((state.outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
|
||||
if ((state->outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
printf (" %s\n", filename) ;
|
||||
@ -145,16 +150,24 @@ main (int argc, char **argv)
|
||||
} ;
|
||||
|
||||
if (double_split)
|
||||
deinterleave_double (&state) ;
|
||||
deinterleave_double (state) ;
|
||||
else
|
||||
deinterleave_int (&state) ;
|
||||
deinterleave_int (state) ;
|
||||
|
||||
sf_close (state.infile) ;
|
||||
for (ch = 0 ; ch < MAX_CHANNELS ; ch++)
|
||||
if (state.outfile [ch] != NULL)
|
||||
sf_close (state.outfile [ch]) ;
|
||||
ret = 0 ;
|
||||
|
||||
return 0 ;
|
||||
cleanup :
|
||||
|
||||
if (state != NULL)
|
||||
{ sf_close (state->infile) ;
|
||||
for (ch = 0 ; ch < MAX_CHANNELS ; ch++)
|
||||
if (state->outfile [ch] != NULL)
|
||||
sf_close (state->outfile [ch]) ;
|
||||
} ;
|
||||
|
||||
free (state) ;
|
||||
|
||||
return ret ;
|
||||
} /* main */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@ -170,7 +183,6 @@ usage_exit (void)
|
||||
"a_00.wav, a_01.wav and so on.\n"
|
||||
) ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
|
||||
static void
|
||||
@ -179,7 +191,7 @@ deinterleave_int (STATE * state)
|
||||
int ch, k ;
|
||||
|
||||
do
|
||||
{ read_len = sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ;
|
||||
{ read_len = (int) sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ for (k = 0 ; k < read_len ; k++)
|
||||
@ -197,7 +209,7 @@ deinterleave_double (STATE * state)
|
||||
int ch, k ;
|
||||
|
||||
do
|
||||
{ read_len = sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ;
|
||||
{ read_len = (int) sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ for (k = 0 ; k < read_len ; k++)
|
||||
|
@ -110,8 +110,6 @@ main (int argc, char *argv [])
|
||||
** Print version and usage.
|
||||
*/
|
||||
|
||||
static double data [BUFFER_LEN] ;
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname)
|
||||
{ printf ("Usage :\n %s <file> ...\n", progname) ;
|
||||
@ -167,6 +165,8 @@ calc_decibels (SF_INFO * sfinfo, double max)
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_VORBIS :
|
||||
case SF_FORMAT_OPUS :
|
||||
decibels = max / 1.0 ;
|
||||
break ;
|
||||
|
||||
@ -313,7 +313,9 @@ instrument_dump (const char *filename)
|
||||
printf (" Loop points : %d\n", inst.loop_count) ;
|
||||
|
||||
for (k = 0 ; k < inst.loop_count ; k++)
|
||||
printf (" %-2d Mode : %s Start : %6d End : %6d Count : %6d\n", k, str_of_type (inst.loops [k].mode), inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ;
|
||||
printf (" %-2d Mode : %s Start : %6" PRIu32 " End : %6" PRIu32
|
||||
" Count : %6" PRIu32 "\n", k, str_of_type (inst.loops [k].mode),
|
||||
inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ;
|
||||
|
||||
putchar ('\n') ;
|
||||
return 0 ;
|
||||
|
@ -60,46 +60,54 @@ typedef struct
|
||||
} STATE ;
|
||||
|
||||
|
||||
static void usage_exit (void) ;
|
||||
static void print_usage (void) ;
|
||||
static void interleave_int (STATE * state) ;
|
||||
static void interleave_double (STATE * state) ;
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{ STATE state ;
|
||||
{ STATE *state = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
int k, double_merge = 0 ;
|
||||
int ret = 1 ;
|
||||
|
||||
if (argc < 5)
|
||||
{ if (argc > 1)
|
||||
puts ("\nError : need at least 2 input files.") ;
|
||||
usage_exit () ;
|
||||
print_usage () ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [argc - 2], "-o") != 0)
|
||||
{ puts ("\nError : second last command line parameter should be '-o'.\n") ;
|
||||
usage_exit () ;
|
||||
print_usage () ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (argc - 3 > MAX_INPUTS)
|
||||
{ printf ("\nError : Cannot handle more than %d input channels.\n\n", MAX_INPUTS) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
state = calloc (1, sizeof (STATE)) ;
|
||||
if (state == NULL)
|
||||
{ puts ("\nError : out of memory.\n") ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
memset (&state, 0, sizeof (state)) ;
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
for (k = 1 ; k < argc - 2 ; k++)
|
||||
{
|
||||
if ((state.infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL)
|
||||
if ((state->infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("\nError : Not able to open input file '%s'\n%s\n", argv [k], sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels != 1)
|
||||
{ printf ("\bError : Input file '%s' should be mono (has %d channels).\n", argv [k], sfinfo.channels) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
switch (sfinfo.format & SF_FORMAT_SUBMASK)
|
||||
@ -113,28 +121,36 @@ main (int argc, char **argv)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
state.channels ++ ;
|
||||
state->channels ++ ;
|
||||
} ;
|
||||
|
||||
sfinfo.channels = state.channels ;
|
||||
sfinfo.channels = state->channels ;
|
||||
sfinfo.format = sfe_file_type_of_ext (argv [argc - 1], sfinfo.format) ;
|
||||
|
||||
if ((state.outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
|
||||
if ((state->outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file '%s'\n%s\n", argv [argc - 1], sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (double_merge)
|
||||
interleave_double (&state) ;
|
||||
interleave_double (state) ;
|
||||
else
|
||||
interleave_int (&state) ;
|
||||
interleave_int (state) ;
|
||||
|
||||
for (k = 0 ; k < MAX_INPUTS ; k++)
|
||||
if (state.infile [k] != NULL)
|
||||
sf_close (state.infile [k]) ;
|
||||
sf_close (state.outfile) ;
|
||||
ret = 0 ;
|
||||
|
||||
return 0 ;
|
||||
cleanup :
|
||||
|
||||
if (state != NULL)
|
||||
{ for (k = 0 ; k < MAX_INPUTS ; k++)
|
||||
if (state->infile [k] != NULL)
|
||||
sf_close (state->infile [k]) ;
|
||||
sf_close (state->outfile) ;
|
||||
}
|
||||
|
||||
free (state) ;
|
||||
|
||||
return ret ;
|
||||
} /* main */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@ -142,12 +158,11 @@ main (int argc, char **argv)
|
||||
|
||||
|
||||
static void
|
||||
usage_exit (void)
|
||||
print_usage (void)
|
||||
{ puts ("\nUsage : sndfile-interleave <input 1> <input 2> ... -o <output file>\n") ;
|
||||
puts ("Merge two or more mono files into a single multi-channel file.\n") ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
} /* print_usage */
|
||||
|
||||
|
||||
static void
|
||||
@ -159,7 +174,7 @@ interleave_int (STATE * state)
|
||||
{ max_read_len = 0 ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ read_len = sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ;
|
||||
{ read_len = (int) sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ;
|
||||
if (read_len < BUFFER_LEN)
|
||||
memset (state->din.i + read_len, 0, sizeof (state->din.i [0]) * (BUFFER_LEN - read_len)) ;
|
||||
|
||||
@ -185,7 +200,7 @@ interleave_double (STATE * state)
|
||||
{ max_read_len = 0 ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ read_len = sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ;
|
||||
{ read_len = (int) sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ;
|
||||
if (read_len < BUFFER_LEN)
|
||||
memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ;
|
||||
|
||||
|
@ -64,7 +64,7 @@
|
||||
#elif HAVE_SNDIO_H
|
||||
#include <sndio.h>
|
||||
|
||||
#elif (defined (sun) && defined (unix))
|
||||
#elif (defined (sun) && defined (unix)) || defined(__NetBSD__)
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.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 ;
|
||||
break ;
|
||||
|
||||
#if defined ESTRPIPE && ESTRPIPE != EPIPE
|
||||
case -ESTRPIPE :
|
||||
fprintf (stderr, "alsa_write_float: Suspend event.n") ;
|
||||
return 0 ;
|
||||
break ;
|
||||
#endif
|
||||
|
||||
case -EIO :
|
||||
puts ("alsa_write_float: EIO") ;
|
||||
@ -727,7 +729,7 @@ sndio_play (int argc, char *argv [])
|
||||
** Solaris.
|
||||
*/
|
||||
|
||||
#if (defined (sun) && defined (unix)) /* ie Solaris */
|
||||
#if (defined (sun) && defined (unix)) || defined(__NetBSD__)
|
||||
|
||||
static void
|
||||
solaris_play (int argc, char *argv [])
|
||||
@ -764,8 +766,6 @@ solaris_play (int argc, char *argv [])
|
||||
audio_info.play.channels = sfinfo.channels ;
|
||||
audio_info.play.precision = 16 ;
|
||||
audio_info.play.encoding = AUDIO_ENCODING_LINEAR ;
|
||||
audio_info.play.gain = AUDIO_MAX_GAIN ;
|
||||
audio_info.play.balance = AUDIO_MID_BALANCE ;
|
||||
|
||||
if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info)))
|
||||
{ perror ("ioctl (AUDIO_SETINFO) failed") ;
|
||||
@ -807,7 +807,7 @@ solaris_play (int argc, char *argv [])
|
||||
return ;
|
||||
} /* solaris_play */
|
||||
|
||||
#endif /* Solaris */
|
||||
#endif /* Solaris or NetBSD */
|
||||
|
||||
/*==============================================================================
|
||||
** Main function.
|
||||
@ -845,7 +845,7 @@ main (int argc, char *argv [])
|
||||
opensoundsys_play (argc, argv) ;
|
||||
#elif HAVE_SNDIO_H
|
||||
sndio_play (argc, argv) ;
|
||||
#elif (defined (sun) && defined (unix))
|
||||
#elif (defined (sun) && defined (unix)) || defined(__NetBSD__)
|
||||
solaris_play (argc, argv) ;
|
||||
#elif (OS_IS_WIN32 == 1)
|
||||
win32_play (argc, argv) ;
|
||||
|
@ -56,6 +56,12 @@
|
||||
|
||||
#define NOT(x) (! (x))
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef off_t sf_off_t ;
|
||||
#else
|
||||
typedef long long sf_off_t ;
|
||||
#endif
|
||||
|
||||
|
||||
static void usage_exit (const char *progname) ;
|
||||
static void salvage_file (const char * broken_wav, const char * fixed_w64) ;
|
||||
@ -74,8 +80,8 @@ main (int argc, char *argv [])
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static void lseek_or_die (int fd, off_t offset, int whence) ;
|
||||
static sf_count_t get_file_length (int fd, const char * name) ;
|
||||
static void lseek_or_die (int fd, sf_off_t offset, int whence) ;
|
||||
static sf_off_t get_file_length (int fd, const char * name) ;
|
||||
static sf_count_t find_data_offset (int fd, int format) ;
|
||||
static void copy_data (int fd, SNDFILE * sndfile, int readsize) ;
|
||||
|
||||
@ -180,9 +186,13 @@ salvage_file (const char * broken_wav, const char * fixed_w64)
|
||||
*/
|
||||
|
||||
static void
|
||||
lseek_or_die (int fd, off_t offset, int whence)
|
||||
lseek_or_die (int fd, sf_off_t offset, int whence)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (lseek (fd, offset, whence) < 0)
|
||||
#else
|
||||
if (_lseeki64 (fd, offset, whence) < 0)
|
||||
#endif
|
||||
{ printf ("lseek failed : %s\n", strerror (errno)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
@ -191,9 +201,14 @@ lseek_or_die (int fd, off_t offset, int whence)
|
||||
} /* lseek_or_die */
|
||||
|
||||
|
||||
static sf_count_t
|
||||
static sf_off_t
|
||||
get_file_length (int fd, const char * name)
|
||||
{ struct stat sbuf ;
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct stat sbuf ;
|
||||
#else
|
||||
struct _stat64 sbuf ;
|
||||
#endif
|
||||
|
||||
if (sizeof (sbuf.st_size) != 8)
|
||||
{ puts ("Error : sizeof (sbuf.st_size) != 8. Was program compiled with\n"
|
||||
@ -201,7 +216,11 @@ get_file_length (int fd, const char * name)
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (fstat (fd, &sbuf) != 0)
|
||||
#else
|
||||
if (_fstat64 (fd, &sbuf) != 0)
|
||||
#endif
|
||||
{ printf ("Error : fstat ('%s') failed : %s\n", name, strerror (errno)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
@ -233,7 +252,7 @@ find_data_offset (int fd, int format)
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
slen = strlen (target) ;
|
||||
slen = (int) strlen (target) ;
|
||||
|
||||
lseek_or_die (fd, 0, SEEK_SET) ;
|
||||
|
||||
|
@ -267,14 +267,14 @@ db_check_all (REG_DB * db_handle)
|
||||
int
|
||||
db_list_all (REG_DB * db_handle)
|
||||
{
|
||||
printf ("%s : %p\n", __func__, db_handle) ;
|
||||
printf ("%s : %p\n", __func__, (void *) db_handle) ;
|
||||
return 0 ;
|
||||
} /* db_list_all */
|
||||
|
||||
int
|
||||
db_del_entry (REG_DB * db_handle, const char * entry)
|
||||
{
|
||||
printf ("%s : %p %s\n", __func__, db_handle, entry) ;
|
||||
printf ("%s : %p %s\n", __func__, (void *) db_handle, entry) ;
|
||||
return 0 ;
|
||||
} /* db_del_entry */
|
||||
|
||||
@ -428,7 +428,7 @@ static void
|
||||
get_filename_pathname (REGTEST_DB * db, const char *filepath)
|
||||
{
|
||||
const char * basename = db_basename (filepath) ;
|
||||
int slen ;
|
||||
size_t slen ;
|
||||
|
||||
/* Test for a relative path
|
||||
*/
|
||||
|
@ -6,7 +6,8 @@ includedir=@includedir@
|
||||
Name: sndfile
|
||||
Description: A library for reading and writing audio files
|
||||
Requires:
|
||||
Requires.private: @EXTERNAL_XIPH_REQUIRE@
|
||||
Requires.private: @EXTERNAL_XIPH_REQUIRE@ @EXTERNAL_MPEG_REQUIRE@
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lsndfile
|
||||
Libs.private: @EXTERNAL_MPEG_LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -44,6 +44,8 @@
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -48,7 +48,7 @@ typedef struct alac_decoder_s
|
||||
{
|
||||
int32_t mPredictor [ALAC_FRAME_LENGTH] ;
|
||||
uint16_t mShiftBuffer [ALAC_FRAME_LENGTH] ;
|
||||
} ;
|
||||
} u ;
|
||||
uint32_t mNumChannels ;
|
||||
} ALAC_DECODER ;
|
||||
|
||||
|
@ -110,7 +110,7 @@ alac_decoder_init (ALAC_DECODER *p, void * inMagicCookie, uint32_t inMagicCookie
|
||||
|
||||
RequireAction (p->mConfig.compatibleVersion <= kALACVersion, return kALAC_IncompatibleVersion ;) ;
|
||||
RequireAction ((p->mConfig.bitDepth >= 8 && p->mConfig.bitDepth <= 32), return kALAC_BadBitWidth ;) ;
|
||||
RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->mPredictor != NULL),
|
||||
RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->u.mPredictor != NULL),
|
||||
status = kALAC_MemFullError ; goto Exit ;) ;
|
||||
}
|
||||
else
|
||||
@ -247,18 +247,18 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
|
||||
// decompress
|
||||
set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ;
|
||||
status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits1) ;
|
||||
status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ;
|
||||
RequireNoErr (status, goto Exit ;) ;
|
||||
|
||||
if (modeU == 0)
|
||||
{
|
||||
unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the special "numActive == 31" mode can be done in-place
|
||||
unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
||||
unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
||||
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -300,7 +300,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
//Assert (shift <= 16) ;
|
||||
|
||||
for (i = 0 ; i < numSamples ; i++)
|
||||
p->mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
||||
p->u.mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
||||
}
|
||||
|
||||
// convert 32-bit integers into output buffer
|
||||
@ -318,14 +318,14 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
case 24:
|
||||
out32 = sampleBuffer + channelIndex ;
|
||||
if (bytesShifted != 0)
|
||||
copyPredictorTo24Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
|
||||
copyPredictorTo24Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
|
||||
else
|
||||
copyPredictorTo24 (p->mMixBufferU, out32, numChannels, numSamples) ;
|
||||
break ;
|
||||
case 32:
|
||||
out32 = sampleBuffer + channelIndex ;
|
||||
if (bytesShifted != 0)
|
||||
copyPredictorTo32Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
|
||||
copyPredictorTo32Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
|
||||
else
|
||||
copyPredictorTo32 (p->mMixBufferU, out32, numChannels, numSamples) ;
|
||||
break ;
|
||||
@ -408,34 +408,34 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
|
||||
// decompress and run predictor for "left" channel
|
||||
set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ;
|
||||
status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits1) ;
|
||||
status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ;
|
||||
RequireNoErr (status, goto Exit ;) ;
|
||||
|
||||
if (modeU == 0)
|
||||
{
|
||||
unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the special "numActive == 31" mode can be done in-place
|
||||
unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
||||
unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
||||
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
||||
}
|
||||
|
||||
// decompress and run predictor for "right" channel
|
||||
set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorV) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ;
|
||||
status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits2) ;
|
||||
status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits2) ;
|
||||
RequireNoErr (status, goto Exit ;) ;
|
||||
|
||||
if (modeV == 0)
|
||||
{
|
||||
unpc_block (p->mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ;
|
||||
unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the special "numActive == 31" mode can be done in-place
|
||||
unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
||||
unpc_block (p->mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ;
|
||||
unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
||||
unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -488,8 +488,8 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
|
||||
for (i = 0 ; i < (numSamples * 2) ; i += 2)
|
||||
{
|
||||
p->mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
||||
p->mShiftBuffer [i + 1] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
||||
p->u.mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
||||
p->u.mShiftBuffer [i + 1] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,12 +508,12 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
case 24:
|
||||
out32 = sampleBuffer + channelIndex ;
|
||||
unmix24 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
|
||||
mixBits, mixRes, p->mShiftBuffer, bytesShifted) ;
|
||||
mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ;
|
||||
break ;
|
||||
case 32:
|
||||
out32 = sampleBuffer + channelIndex ;
|
||||
unmix32 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
|
||||
mixBits, mixRes, p->mShiftBuffer, bytesShifted) ;
|
||||
mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ;
|
||||
break ;
|
||||
}
|
||||
|
||||
@ -554,7 +554,7 @@ alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, u
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // ! DEBUG
|
||||
#if 1 // ! DEBUG
|
||||
// if we've decoded all of our channels, bail (but not in debug b/c we want to know if we're seeing bad bits)
|
||||
// - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits
|
||||
if (channelIndex >= numChannels)
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -108,6 +108,8 @@ void private_init_state (G72x_STATE *state_ptr) ;
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -294,6 +294,8 @@ extern int16_t gsm_FAC [8] ;
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#elif defined _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
@ -234,7 +234,7 @@ static int aiff_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * itera
|
||||
int
|
||||
aiff_open (SF_PRIVATE *psf)
|
||||
{ COMM_CHUNK comm_fmt ;
|
||||
int error, subformat ;
|
||||
int error = 0, subformat ;
|
||||
|
||||
memset (&comm_fmt, 0, sizeof (comm_fmt)) ;
|
||||
|
||||
@ -404,7 +404,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
|
||||
char *cptr ;
|
||||
int instr_found = 0, mark_found = 0 ;
|
||||
|
||||
if (psf->filelength > SF_PLATFORM_S64 (0xffffffff))
|
||||
if (psf->filelength > 0xFFFFFFFFLL)
|
||||
psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
|
||||
|
||||
if ((paiff = psf->container_data) == NULL)
|
||||
@ -507,7 +507,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
|
||||
if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
/* read in rest of PEAK chunk. */
|
||||
/* Read in rest of PEAK chunk. */
|
||||
psf_binheader_readf (psf, "E44", &(psf->peak_info->version), &(psf->peak_info->timestamp)) ;
|
||||
|
||||
if (psf->peak_info->version != 1)
|
||||
@ -1003,7 +1003,7 @@ aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt)
|
||||
ubuf.scbuf [0] = 0 ;
|
||||
|
||||
/* The COMM chunk has an int aligned to an odd word boundary. Some
|
||||
** procesors are not able to deal with this (ie bus fault) so we have
|
||||
** processors are not able to deal with this (ie bus fault) so we have
|
||||
** to take special care.
|
||||
*/
|
||||
|
||||
|
38
src/alac.c
38
src/alac.c
@ -51,12 +51,12 @@ typedef struct
|
||||
|
||||
|
||||
/* Can't have a decoder and an encoder at the same time so stick
|
||||
** them in an un-named union.
|
||||
** them in a union.
|
||||
*/
|
||||
union
|
||||
{ ALAC_DECODER decoder ;
|
||||
ALAC_ENCODER encoder ;
|
||||
} ;
|
||||
} u ;
|
||||
|
||||
char enctmpname [512] ;
|
||||
FILE *enctmp ;
|
||||
@ -169,7 +169,7 @@ alac_close (SF_PRIVATE *psf)
|
||||
plac = psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ ALAC_ENCODER *penc = &plac->encoder ;
|
||||
{ ALAC_ENCODER *penc = &plac->u.encoder ;
|
||||
SF_CHUNK_INFO chunk_info ;
|
||||
sf_count_t readcount ;
|
||||
uint8_t kuki_data [1024] ;
|
||||
@ -268,14 +268,14 @@ alac_reader_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info)
|
||||
/* Read in the ALAC cookie data and pass it to the init function. */
|
||||
kuki_size = alac_kuki_read (psf, info->kuki_offset, u.kuki, sizeof (u.kuki)) ;
|
||||
|
||||
if ((error = alac_decoder_init (&plac->decoder, u.kuki, kuki_size)) != ALAC_noErr)
|
||||
if ((error = alac_decoder_init (&plac->u.decoder, u.kuki, kuki_size)) != ALAC_noErr)
|
||||
{ psf_log_printf (psf, "*** alac_decoder_init() returned %s. ***\n", alac_error_string (error)) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
|
||||
if (plac->decoder.mNumChannels != (unsigned) psf->sf.channels)
|
||||
{ psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->decoder.mNumChannels, psf->sf.channels) ;
|
||||
if (plac->u.decoder.mNumChannels != (unsigned) psf->sf.channels)
|
||||
{ psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->u.decoder.mNumChannels, psf->sf.channels) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
@ -357,7 +357,7 @@ alac_writer_init (SF_PRIVATE *psf)
|
||||
return SFE_ALAC_FAIL_TMPFILE ;
|
||||
} ;
|
||||
|
||||
alac_encoder_init (&plac->encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ;
|
||||
alac_encoder_init (&plac->u.encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ;
|
||||
|
||||
return 0 ;
|
||||
} /* alac_writer_init */
|
||||
@ -402,7 +402,7 @@ alac_reader_calc_frames (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
|
||||
|
||||
static int
|
||||
alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
|
||||
{ ALAC_DECODER *pdec = &plac->decoder ;
|
||||
{ ALAC_DECODER *pdec = &plac->u.decoder ;
|
||||
uint32_t packet_size ;
|
||||
BitBuffer bit_buffer ;
|
||||
|
||||
@ -437,7 +437,7 @@ alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
|
||||
|
||||
static int
|
||||
alac_encode_block (ALAC_PRIVATE *plac)
|
||||
{ ALAC_ENCODER *penc = &plac->encoder ;
|
||||
{ ALAC_ENCODER *penc = &plac->u.encoder ;
|
||||
uint32_t num_bytes = 0 ;
|
||||
|
||||
alac_encode (penc, plac->partial_block_frames, plac->buffer, plac->byte_buffer, &num_bytes) ;
|
||||
@ -471,7 +471,7 @@ alac_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
readcount = readcount > len ? (int) len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -501,7 +501,7 @@ alac_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
readcount = readcount > len ? (int) len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -534,7 +534,7 @@ alac_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
readcount = readcount > len ? (int) len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -567,7 +567,7 @@ alac_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
readcount = readcount > len ? (int) len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -648,7 +648,7 @@ alac_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -679,7 +679,7 @@ alac_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -713,7 +713,7 @@ alac_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -746,7 +746,7 @@ alac_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
@ -824,6 +824,8 @@ alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t UNUSED (pakt_offset))
|
||||
|
||||
pakt_size = chunk_info.datalen ;
|
||||
chunk_info.data = pakt_data = malloc (pakt_size + 5) ;
|
||||
if (!chunk_info.data)
|
||||
return NULL ;
|
||||
|
||||
if ((bcount = psf->get_chunk_data (psf, chunk_iterator, &chunk_info)) != SF_ERR_NO_ERROR)
|
||||
{ while (chunk_iterator)
|
||||
@ -850,7 +852,7 @@ alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t UNUSED (pakt_offset))
|
||||
|
||||
count ++ ;
|
||||
if (count > 5 || bcount + count > pakt_size)
|
||||
{ printf ("%s %d : Ooops! count %d bcount %d\n", __func__, __LINE__, count, bcount) ;
|
||||
{ printf ("%s %d : Ooops! count %" PRIi32 " bcount %" PRIu32 "\n", __func__, __LINE__, count, bcount) ;
|
||||
value = 0 ;
|
||||
break ;
|
||||
} ;
|
||||
|
72
src/alaw.c
72
src/alaw.c
@ -292,69 +292,69 @@ unsigned char alaw_encode [2048 + 1] =
|
||||
|
||||
static inline void
|
||||
alaw2s_array (unsigned char *buffer, int count, short *ptr)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = alaw_decode [(int) buffer [count]] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
ptr [i] = alaw_decode [(int) buffer [i]] ;
|
||||
} /* alaw2s_array */
|
||||
|
||||
static inline void
|
||||
alaw2i_array (unsigned char *buffer, int count, int *ptr)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = ((uint32_t) alaw_decode [(int) buffer [count]]) << 16 ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
ptr [i] = ((uint32_t) alaw_decode [(int) buffer [i]]) << 16 ;
|
||||
} /* alaw2i_array */
|
||||
|
||||
static inline void
|
||||
alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
ptr [i] = normfact * alaw_decode [(int) buffer [i]] ;
|
||||
} /* alaw2f_array */
|
||||
|
||||
static inline void
|
||||
alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
ptr [i] = normfact * alaw_decode [(int) buffer [i]] ;
|
||||
} /* alaw2d_array */
|
||||
|
||||
static inline void
|
||||
s2alaw_array (const short *ptr, int count, unsigned char *buffer)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [ptr [count] / 16] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ if (ptr [i] >= 0)
|
||||
buffer [i] = alaw_encode [ptr [i] / 16] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ;
|
||||
buffer [i] = 0x7F & alaw_encode [ptr [i] / -16] ;
|
||||
} ;
|
||||
} /* s2alaw_array */
|
||||
|
||||
static inline void
|
||||
i2alaw_array (const int *ptr, int count, unsigned char *buffer)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] == INT_MIN)
|
||||
buffer [count] = alaw_encode [INT_MAX >> (16 + 4)] ;
|
||||
else if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ if (ptr [i] == INT_MIN)
|
||||
buffer [i] = alaw_encode [INT_MAX >> (16 + 4)] ;
|
||||
else if (ptr [i] >= 0)
|
||||
buffer [i] = alaw_encode [ptr [i] >> (16 + 4)] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ;
|
||||
buffer [i] = 0x7F & alaw_encode [- ptr [i] >> (16 + 4)] ;
|
||||
} ;
|
||||
} /* i2alaw_array */
|
||||
|
||||
static inline void
|
||||
f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [psf_lrintf (normfact * ptr [count])] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ if (ptr [i] >= 0)
|
||||
buffer [i] = alaw_encode [psf_lrintf (normfact * ptr [i])] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [count])] ;
|
||||
buffer [i] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [i])] ;
|
||||
} ;
|
||||
} /* f2alaw_array */
|
||||
|
||||
static inline void
|
||||
d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact)
|
||||
{ while (--count >= 0)
|
||||
{ if (!isfinite (ptr [count]))
|
||||
buffer [count] = 0 ;
|
||||
else if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [psf_lrint (normfact * ptr [count])] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ if (!isfinite (ptr [i]))
|
||||
buffer [i] = 0 ;
|
||||
else if (ptr [i] >= 0)
|
||||
buffer [i] = alaw_encode [psf_lrint (normfact * ptr [i])] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [count])] ;
|
||||
buffer [i] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [i])] ;
|
||||
} ;
|
||||
} /* d2alaw_array */
|
||||
|
||||
@ -372,7 +372,7 @@ alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2s_array (ubuf.ucbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@ -394,7 +394,7 @@ alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2i_array (ubuf.ucbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@ -419,7 +419,7 @@ alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@ -443,7 +443,7 @@ alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@ -469,7 +469,7 @@ alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -491,7 +491,7 @@ alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -516,7 +516,7 @@ alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
f2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -541,7 +541,7 @@ alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
d2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
|
@ -28,8 +28,6 @@
|
||||
#define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T'))
|
||||
#define AVR_HDR_SIZE 128
|
||||
|
||||
#define SFE_AVR_X 666
|
||||
|
||||
/*
|
||||
** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu)
|
||||
**
|
||||
@ -116,7 +114,7 @@ avr_read_header (SF_PRIVATE *psf)
|
||||
psf_log_printf (psf, "%M\n", hdr.marker) ;
|
||||
|
||||
if (hdr.marker != TWOBIT_MARKER)
|
||||
return SFE_AVR_X ;
|
||||
return SFE_AVR_NOT_AVR ;
|
||||
|
||||
psf_log_printf (psf, " Name : %s\n", hdr.name) ;
|
||||
|
||||
@ -145,7 +143,7 @@ avr_read_header (SF_PRIVATE *psf)
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "Error : bad rez/sign combination.\n") ;
|
||||
return SFE_AVR_X ;
|
||||
return SFE_AVR_BAD_REZ_SIGN ;
|
||||
} ;
|
||||
|
||||
psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ;
|
||||
|
@ -84,7 +84,7 @@ broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datas
|
||||
/* Force coding_history_size to be even. */
|
||||
len = strlen (psf->broadcast_16k->coding_history) ;
|
||||
len += (len & 1) ? 1 : 0 ;
|
||||
psf->broadcast_16k->coding_history_size = len ;
|
||||
psf->broadcast_16k->coding_history_size = (uint32_t) len ;
|
||||
|
||||
/* Currently writing this version. */
|
||||
psf->broadcast_16k->version = 2 ;
|
||||
@ -146,7 +146,7 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
|
||||
break ;
|
||||
|
||||
default :
|
||||
snprintf (chnstr, sizeof (chnstr), "%uchn", psfinfo->channels) ;
|
||||
snprintf (chnstr, sizeof (chnstr), "%dchn", psfinfo->channels) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
@ -180,7 +180,7 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
|
||||
} ;
|
||||
|
||||
count = snprintf (added_history, added_history_max,
|
||||
"A=PCM,F=%u,W=%d,M=%s,T=%s-%s\r\n",
|
||||
"A=PCM,F=%d,W=%d,M=%s,T=%s-%s\r\n",
|
||||
psfinfo->samplerate, width, chnstr, PACKAGE_NAME, PACKAGE_VERSION) ;
|
||||
|
||||
if (count >= added_history_max)
|
||||
|
25
src/caf.c
25
src/caf.c
@ -66,10 +66,6 @@
|
||||
|
||||
#define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8)))
|
||||
|
||||
#define SFE_CAF_NOT_CAF 666
|
||||
#define SFE_CAF_NO_DESC 667
|
||||
#define SFE_CAF_BAD_PEAK 668
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
@ -411,11 +407,16 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
{ case peak_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
|
||||
{ psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
{ psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
|
||||
psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
|
||||
return SFE_CAF_BAD_PEAK ;
|
||||
} ;
|
||||
|
||||
if (psf->peak_info)
|
||||
{ psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ;
|
||||
free (psf->peak_info) ;
|
||||
psf->peak_info = NULL ;
|
||||
} ;
|
||||
if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
@ -442,7 +443,7 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
case chan_MARKER :
|
||||
if (chunk_size < 12)
|
||||
{ psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
|
||||
break ;
|
||||
}
|
||||
|
||||
@ -454,7 +455,7 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
|
||||
case free_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
|
||||
break ;
|
||||
|
||||
case data_MARKER :
|
||||
@ -479,14 +480,14 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
if (psf->datalength + psf->dataoffset < psf->filelength)
|
||||
psf->dataend = psf->datalength + psf->dataoffset ;
|
||||
|
||||
psf_binheader_readf (psf, "j", make_size_t (psf->datalength)) ;
|
||||
psf_binheader_readf (psf, "j", (size_t) psf->datalength) ;
|
||||
have_data = 1 ;
|
||||
break ;
|
||||
|
||||
case kuki_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
|
||||
break ;
|
||||
|
||||
case pakt_MARKER :
|
||||
@ -518,7 +519,7 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ;
|
||||
|
||||
pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size) - 24) ;
|
||||
psf_binheader_readf (psf, "j", (size_t) chunk_size - 24) ;
|
||||
break ;
|
||||
|
||||
case info_MARKER :
|
||||
@ -537,7 +538,7 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
@ -845,7 +846,7 @@ caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size)
|
||||
if ((buf = malloc (chunk_size + 1)) == NULL)
|
||||
return (psf->error = SFE_MALLOC_FAILED) ;
|
||||
|
||||
psf_binheader_readf (psf, "E4b", &count, buf, make_size_t (chunk_size)) ;
|
||||
psf_binheader_readf (psf, "E4b", &count, buf, (size_t) chunk_size) ;
|
||||
psf_log_printf (psf, " count: %u\n", count) ;
|
||||
|
||||
/* Force terminate `buf` to make sure. */
|
||||
|
@ -79,7 +79,7 @@ cart_var_set (SF_PRIVATE *psf, const SF_CART_INFO * info, size_t datasize)
|
||||
len = strlen (psf->cart_16k->tag_text) ;
|
||||
len += (len & 1) ? 1 : 2 ;
|
||||
|
||||
psf->cart_16k->tag_text_size = len ;
|
||||
psf->cart_16k->tag_text_size = (uint32_t) len ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* cart_var_set */
|
||||
|
10
src/chunk.c
10
src/chunk.c
@ -75,7 +75,7 @@ psf_get_chunk_iterator (SF_PRIVATE * psf, const char * marker_str)
|
||||
hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ;
|
||||
|
||||
memcpy (psf->iterator->id, marker_str, marker_len) ;
|
||||
psf->iterator->id_size = marker_len ;
|
||||
psf->iterator->id_size = (unsigned) marker_len ;
|
||||
psf->iterator->hash = hash ;
|
||||
}
|
||||
|
||||
@ -112,6 +112,9 @@ psf_store_read_chunk (READ_CHUNKS * pchk, const READ_CHUNK * rchunk)
|
||||
{ pchk->used = 0 ;
|
||||
pchk->count = 20 ;
|
||||
pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ;
|
||||
if (!pchk->chunks)
|
||||
{ return SFE_MALLOC_FAILED ;
|
||||
} ;
|
||||
}
|
||||
else if (pchk->used > pchk->count)
|
||||
return SFE_INTERNAL ;
|
||||
@ -208,7 +211,7 @@ psf_store_read_chunk_str (READ_CHUNKS * pchk, const char * marker_str, sf_count_
|
||||
rchunk.offset = offset ;
|
||||
rchunk.len = len ;
|
||||
|
||||
rchunk.id_size = marker_len > 64 ? 64 : marker_len ;
|
||||
rchunk.id_size = marker_len > 64 ? 64 : (unsigned) marker_len ;
|
||||
memcpy (rchunk.id, marker_str, rchunk.id_size) ;
|
||||
|
||||
return psf_store_read_chunk (pchk, &rchunk) ;
|
||||
@ -227,6 +230,9 @@ psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info)
|
||||
{ pchk->used = 0 ;
|
||||
pchk->count = 20 ;
|
||||
pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ;
|
||||
if (!pchk->chunks)
|
||||
{ return SFE_MALLOC_FAILED ;
|
||||
} ;
|
||||
}
|
||||
else if (pchk->used >= pchk->count)
|
||||
{ WRITE_CHUNK * old_ptr = pchk->chunks ;
|
||||
|
@ -61,6 +61,12 @@ static SF_FORMAT_INFO const simple_formats [] =
|
||||
},
|
||||
#endif
|
||||
|
||||
#if HAVE_MPEG
|
||||
{ SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III,
|
||||
"MPEG Layer 3", "mp3"
|
||||
},
|
||||
#endif
|
||||
|
||||
{ SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM,
|
||||
"OKI Dialogic VOX ADPCM", "vox"
|
||||
},
|
||||
@ -133,6 +139,9 @@ static SF_FORMAT_INFO const major_formats [] =
|
||||
{ SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" },
|
||||
{ SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" },
|
||||
{ SF_FORMAT_MPC2K, "MPC (Akai MPC 2k)", "mpc" },
|
||||
#if HAVE_MPEG
|
||||
{ SF_FORMAT_MPEG, "MPEG-1/2 Audio", "m1a" },
|
||||
#endif
|
||||
#if HAVE_EXTERNAL_XIPH_LIBS
|
||||
{ SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" },
|
||||
#endif
|
||||
@ -215,6 +224,12 @@ static SF_FORMAT_INFO subtype_formats [] =
|
||||
{ SF_FORMAT_OPUS, "Opus", NULL },
|
||||
#endif
|
||||
|
||||
#if HAVE_MPEG
|
||||
{ SF_FORMAT_MPEG_LAYER_I, "MPEG Layer I", "mp1" },
|
||||
{ SF_FORMAT_MPEG_LAYER_II, "MPEG Layer II", "mp2" },
|
||||
{ SF_FORMAT_MPEG_LAYER_III, "MPEG Layer III", "mp3" },
|
||||
#endif
|
||||
|
||||
{ SF_FORMAT_ALAC_16, "16 bit ALAC", NULL },
|
||||
{ SF_FORMAT_ALAC_20, "20 bit ALAC", NULL },
|
||||
{ SF_FORMAT_ALAC_24, "24 bit ALAC", NULL },
|
||||
@ -309,7 +324,7 @@ psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
|
||||
len = ARRAY_LEN (ubuf.dbuf) - (ARRAY_LEN (ubuf.dbuf) % psf->sf.channels) ;
|
||||
|
||||
for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */)
|
||||
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
{ readcount = (int) sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
{ temp = fabs (data [k]) ;
|
||||
max_val = temp > max_val ? temp : max_val ;
|
||||
@ -354,7 +369,7 @@ psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize)
|
||||
chan = 0 ;
|
||||
readcount = len ;
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
{ readcount = (int) sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
{ temp = fabs (data [k]) ;
|
||||
peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ;
|
||||
|
260
src/common.c
260
src/common.c
@ -103,8 +103,8 @@ log_putchar (SF_PRIVATE *psf, char ch)
|
||||
void
|
||||
psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
{ va_list ap ;
|
||||
uint32_t u ;
|
||||
int d, tens, shift, width, width_specifier, left_align, slen ;
|
||||
uint32_t u, tens ;
|
||||
int d, shift, width, width_specifier, left_align, slen, precision ;
|
||||
char c, *strptr, istr [5], lead_char, sign_char ;
|
||||
|
||||
va_start (ap, format) ;
|
||||
@ -153,6 +153,12 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
while ((c = *format++) && isdigit (c))
|
||||
width_specifier = width_specifier * 10 + (c - '0') ;
|
||||
|
||||
precision = 0 ;
|
||||
if (c == '.')
|
||||
{ while ((c = *format++) && isdigit (c))
|
||||
precision = precision * 10 + (c - '0') ;
|
||||
} ;
|
||||
|
||||
switch (c)
|
||||
{ case 0 : /* NULL character. */
|
||||
va_end (ap) ;
|
||||
@ -162,12 +168,15 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
strptr = va_arg (ap, char *) ;
|
||||
if (strptr == NULL)
|
||||
break ;
|
||||
slen = strlen (strptr) ;
|
||||
if (precision > 0)
|
||||
slen = strnlen (strptr, precision) ;
|
||||
else
|
||||
slen = strlen (strptr) ;
|
||||
width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ;
|
||||
if (left_align == SF_FALSE)
|
||||
while (width_specifier -- > 0)
|
||||
log_putchar (psf, ' ') ;
|
||||
while (*strptr)
|
||||
while (slen--)
|
||||
log_putchar (psf, *strptr++) ;
|
||||
while (width_specifier -- > 0)
|
||||
log_putchar (psf, ' ') ;
|
||||
@ -177,15 +186,19 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
d = va_arg (ap, int) ;
|
||||
|
||||
if (d < 0)
|
||||
{ d = -d ;
|
||||
sign_char = '-' ;
|
||||
{ sign_char = '-' ;
|
||||
if (lead_char != '0' && left_align == SF_FALSE)
|
||||
width_specifier -- ;
|
||||
} ;
|
||||
|
||||
u = - ((unsigned) d) ;
|
||||
}
|
||||
else
|
||||
{ u = (unsigned) d ;
|
||||
}
|
||||
|
||||
tens = 1 ;
|
||||
width = 1 ;
|
||||
while (d / tens >= 10)
|
||||
while (u / tens >= 10)
|
||||
{ tens *= 10 ;
|
||||
width ++ ;
|
||||
} ;
|
||||
@ -215,8 +228,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
log_putchar (psf, lead_char) ;
|
||||
|
||||
while (tens > 0)
|
||||
{ log_putchar (psf, '0' + d / tens) ;
|
||||
d %= tens ;
|
||||
{ log_putchar (psf, '0' + u / tens) ;
|
||||
u %= tens ;
|
||||
tens /= 10 ;
|
||||
} ;
|
||||
|
||||
@ -225,7 +238,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
break ;
|
||||
|
||||
case 'D': /* sf_count_t */
|
||||
{ sf_count_t D, Tens ;
|
||||
{ sf_count_t D ;
|
||||
uint64_t U, Tens ;
|
||||
|
||||
D = va_arg (ap, sf_count_t) ;
|
||||
|
||||
@ -235,13 +249,19 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
log_putchar (psf, '0') ;
|
||||
break ;
|
||||
}
|
||||
if (D < 0)
|
||||
{ log_putchar (psf, '-') ;
|
||||
D = -D ;
|
||||
} ;
|
||||
else
|
||||
{ if (D < 0)
|
||||
{ log_putchar (psf, '-') ;
|
||||
U = -((uint64_t) D) ;
|
||||
}
|
||||
else
|
||||
{ U = (uint64_t) D;
|
||||
}
|
||||
}
|
||||
|
||||
Tens = 1 ;
|
||||
width = 1 ;
|
||||
while (D / Tens >= 10)
|
||||
while (U / Tens >= 10)
|
||||
{ Tens *= 10 ;
|
||||
width ++ ;
|
||||
} ;
|
||||
@ -252,8 +272,8 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
} ;
|
||||
|
||||
while (Tens > 0)
|
||||
{ log_putchar (psf, '0' + D / Tens) ;
|
||||
D %= Tens ;
|
||||
{ log_putchar (psf, '0' + U / Tens) ;
|
||||
U %= Tens ;
|
||||
Tens /= 10 ;
|
||||
} ;
|
||||
} ;
|
||||
@ -355,7 +375,7 @@ psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
|
||||
strptr = istr ;
|
||||
while (*strptr)
|
||||
{ c = *strptr++ ;
|
||||
log_putchar (psf, c) ;
|
||||
log_putchar (psf, psf_isprint (c) ? c : '.') ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
@ -520,36 +540,30 @@ header_put_le_int (SF_PRIVATE *psf, int x)
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 24) ;
|
||||
} /* header_put_le_int */
|
||||
|
||||
#if (SIZEOF_SF_COUNT_T == 8)
|
||||
|
||||
static inline void
|
||||
header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x)
|
||||
{ psf->header.ptr [psf->header.indx++] = (x >> 56) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 48) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 40) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 32) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 24) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 16) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 8) ;
|
||||
psf->header.ptr [psf->header.indx++] = x ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) x ;
|
||||
} /* header_put_be_8byte */
|
||||
|
||||
static inline void
|
||||
header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
|
||||
{ psf->header.ptr [psf->header.indx++] = x ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 8) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 16) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 24) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 32) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 40) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 48) ;
|
||||
{ psf->header.ptr [psf->header.indx++] = (unsigned char) x ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ;
|
||||
psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ;
|
||||
psf->header.ptr [psf->header.indx++] = (x >> 56) ;
|
||||
} /* header_put_le_8byte */
|
||||
|
||||
#else
|
||||
#error "SIZEOF_SF_COUNT_T != 8"
|
||||
#endif
|
||||
|
||||
int
|
||||
psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
{ va_list argptr ;
|
||||
@ -571,7 +585,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
while ((c = *format++))
|
||||
{
|
||||
if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
switch (c)
|
||||
{ case ' ' : /* Do nothing. Just used to space out format string. */
|
||||
@ -687,7 +701,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
size = strlen (strptr) + 1 ;
|
||||
|
||||
if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
if (psf->rwf_endian == SF_ENDIAN_BIG)
|
||||
header_put_be_int (psf, size + (size & 1)) ;
|
||||
@ -708,7 +722,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
strptr = va_arg (argptr, char *) ;
|
||||
size = strlen (strptr) ;
|
||||
if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
|
||||
return count ;
|
||||
break ;
|
||||
if (psf->rwf_endian == SF_ENDIAN_BIG)
|
||||
header_put_be_int (psf, size) ;
|
||||
else
|
||||
@ -728,7 +742,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
size = (size > 254) ? 254 : size ;
|
||||
|
||||
if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
header_put_byte (psf, size) ;
|
||||
memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
|
||||
@ -741,7 +755,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
size = va_arg (argptr, size_t) ;
|
||||
|
||||
if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
memcpy (&(psf->header.ptr [psf->header.indx]), bindata, size) ;
|
||||
psf->header.indx += size ;
|
||||
@ -752,7 +766,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
size = va_arg (argptr, size_t) ;
|
||||
|
||||
if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
count += size ;
|
||||
while (size)
|
||||
@ -773,7 +787,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
size = va_arg (argptr, size_t) ;
|
||||
|
||||
if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
psf->header.indx += size ;
|
||||
count += size ;
|
||||
@ -783,7 +797,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
size = va_arg (argptr, size_t) ;
|
||||
|
||||
if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
psf->header.indx = size ;
|
||||
break ;
|
||||
@ -877,7 +891,7 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
|
||||
psf_bump_header_allocation (psf, position) ;
|
||||
if (position > psf->header.len)
|
||||
{ /* Too much header to cache so just seek instead. */
|
||||
psf->header.indx = psf->header.end ;
|
||||
psf->header.indx = psf->header.end = 0 ;
|
||||
psf_fseek (psf, position, whence) ;
|
||||
return ;
|
||||
} ;
|
||||
@ -905,8 +919,22 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
|
||||
|
||||
if (psf->header.indx + position > psf->header.len)
|
||||
{ /* Need to jump this without caching it. */
|
||||
position -= (psf->header.end - psf->header.indx) ;
|
||||
psf->header.indx = psf->header.end ;
|
||||
psf_fseek (psf, position, SEEK_CUR) ;
|
||||
if (psf->is_pipe)
|
||||
{
|
||||
/* seeking is not supported on pipe input, so we read instead */
|
||||
size_t skip = position ;
|
||||
while (skip)
|
||||
{ char junk [16 * 1024] ;
|
||||
size_t to_skip = SF_MIN (skip, sizeof (junk)) ;
|
||||
psf_fread (junk, 1, to_skip, psf) ;
|
||||
skip -= to_skip ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ psf_fseek (psf, position, SEEK_CUR) ;
|
||||
}
|
||||
break ;
|
||||
} ;
|
||||
|
||||
@ -954,7 +982,7 @@ int
|
||||
psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
{ va_list argptr ;
|
||||
sf_count_t *countptr, countdata ;
|
||||
unsigned char *ucptr, sixteen_bytes [16] ;
|
||||
unsigned char *ucptr, sixteen_bytes [16] = { 0 } ;
|
||||
unsigned int *intptr, intdata ;
|
||||
unsigned short *shortptr ;
|
||||
char *charptr ;
|
||||
@ -971,7 +999,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
while ((c = *format++))
|
||||
{
|
||||
if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
|
||||
return count ;
|
||||
break ;
|
||||
|
||||
switch (c)
|
||||
{ case 'e' : /* All conversions are now from LE to host. */
|
||||
@ -1098,7 +1126,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
memset (charptr, 0, count) ;
|
||||
|
||||
if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, count))
|
||||
return 0 ;
|
||||
break ;
|
||||
|
||||
byte_count += header_gets (psf, charptr, count) ;
|
||||
break ;
|
||||
@ -1127,6 +1155,10 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
byte_count += count ;
|
||||
break ;
|
||||
|
||||
case '!' : /* Clear buffer, forcing re-read. */
|
||||
psf->header.end = psf->header.indx = 0 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
|
||||
psf->error = SFE_INTERNAL ;
|
||||
@ -1221,6 +1253,37 @@ psf_log_SF_INFO (SF_PRIVATE *psf)
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
int
|
||||
psf_isprint (int ch)
|
||||
{ return (ch >= ' ' && ch <= '~') ;
|
||||
} /* psf_isprint */
|
||||
|
||||
void
|
||||
psf_strlcat (char *dest, size_t n, const char *src)
|
||||
{ strncat (dest, src, n - strlen (dest) - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcat */
|
||||
|
||||
void
|
||||
psf_strlcpy (char *dest, size_t n, const char *src)
|
||||
{ strncpy (dest, src, n - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcpy */
|
||||
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
void *
|
||||
psf_memdup (const void *src, size_t n)
|
||||
{ if (src == NULL)
|
||||
return NULL ;
|
||||
|
||||
void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ;
|
||||
if (mem != NULL)
|
||||
memcpy (mem, src, n) ;
|
||||
return mem ;
|
||||
} /* psf_memdup */
|
||||
|
||||
void*
|
||||
psf_memset (void *s, int c, sf_count_t len)
|
||||
{ char *ptr ;
|
||||
@ -1246,7 +1309,11 @@ psf_memset (void *s, int c, sf_count_t len)
|
||||
** bodgy something up instead.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef SF_CUES_VAR (0) SF_CUES_0 ;
|
||||
#else
|
||||
typedef SF_CUES_VAR () SF_CUES_0 ;
|
||||
#endif
|
||||
|
||||
/* calculate size of SF_CUES struct given number of cues */
|
||||
#define SF_CUES_VAR_SIZE(count) (sizeof (SF_CUES_0) + count * sizeof (SF_CUE_POINT))
|
||||
@ -1257,8 +1324,9 @@ typedef SF_CUES_VAR (0) SF_CUES_0 ;
|
||||
SF_CUES *
|
||||
psf_cues_alloc (uint32_t cue_count)
|
||||
{ SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ;
|
||||
|
||||
pcues->cue_count = cue_count ;
|
||||
if (pcues)
|
||||
{ pcues->cue_count = cue_count ;
|
||||
} ;
|
||||
return pcues ;
|
||||
} /* psf_cues_alloc */
|
||||
|
||||
@ -1527,6 +1595,7 @@ str_of_major_format (int format)
|
||||
CASE_NAME (SF_FORMAT_CAF) ;
|
||||
CASE_NAME (SF_FORMAT_WVE) ;
|
||||
CASE_NAME (SF_FORMAT_OGG) ;
|
||||
CASE_NAME (SF_FORMAT_MPEG) ;
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
@ -1563,6 +1632,9 @@ str_of_minor_format (int format)
|
||||
CASE_NAME (SF_FORMAT_DPCM_8) ;
|
||||
CASE_NAME (SF_FORMAT_DPCM_16) ;
|
||||
CASE_NAME (SF_FORMAT_VORBIS) ;
|
||||
CASE_NAME (SF_FORMAT_MPEG_LAYER_I) ;
|
||||
CASE_NAME (SF_FORMAT_MPEG_LAYER_II) ;
|
||||
CASE_NAME (SF_FORMAT_MPEG_LAYER_III) ;
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
@ -1606,8 +1678,8 @@ psf_f2s_array (const float *src, short *dest, int count, int normalize)
|
||||
{ float normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrintf (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrintf (src [i] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2s_array */
|
||||
@ -1618,18 +1690,18 @@ psf_f2s_clip_array (const float *src, short *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [i] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = 0x8000 ;
|
||||
if (scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [i] = -0x7FFF - 1 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
dest [count] = psf_lrintf (scaled_value) ;
|
||||
dest [i] = psf_lrintf (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1640,8 +1712,8 @@ psf_d2s_array (const double *src, short *dest, int count, int normalize)
|
||||
{ double normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrint (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrint (src [i] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2s_array */
|
||||
@ -1652,18 +1724,18 @@ psf_d2s_clip_array (const double *src, short *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [i] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = 0x8000 ;
|
||||
if (scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [i] = -0x7FFF - 1 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
dest [count] = psf_lrint (scaled_value) ;
|
||||
dest [i] = psf_lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1675,8 +1747,8 @@ psf_f2i_array (const float *src, int *dest, int count, int normalize)
|
||||
{ float normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrintf (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrintf (src [i] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2i_array */
|
||||
@ -1687,18 +1759,22 @@ psf_f2i_clip_array (const float *src, int *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ dest [count] = 0x7FFFFFFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
#if CPU_CLIPS_POSITIVE == 0
|
||||
if (scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ dest [i] = 0x7FFFFFFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ dest [count] = 0x80000000 ;
|
||||
#endif
|
||||
#if CPU_CLIPS_NEGATIVE == 0
|
||||
if (scaled_value <= (-8.0 * 0x10000000))
|
||||
{ dest [i] = 0x80000000 ;
|
||||
continue ;
|
||||
} ;
|
||||
#endif
|
||||
|
||||
dest [count] = psf_lrintf (scaled_value) ;
|
||||
dest [i] = psf_lrintf (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1709,8 +1785,8 @@ psf_d2i_array (const double *src, int *dest, int count, int normalize)
|
||||
{ double normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrint (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrint (src [i] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2i_array */
|
||||
@ -1721,18 +1797,22 @@ psf_d2i_clip_array (const double *src, int *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ dest [count] = 0x7FFFFFFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
#if CPU_CLIPS_POSITIVE == 0
|
||||
if (scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ dest [i] = 0x7FFFFFFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ dest [count] = 0x80000000 ;
|
||||
#endif
|
||||
#if CPU_CLIPS_NEGATIVE == 0
|
||||
if (scaled_value <= (-8.0 * 0x10000000))
|
||||
{ dest [i] = 0x80000000 ;
|
||||
continue ;
|
||||
} ;
|
||||
#endif
|
||||
|
||||
dest [count] = psf_lrint (scaled_value) ;
|
||||
dest [i] = psf_lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
|
128
src/common.h
128
src/common.h
@ -23,6 +23,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
@ -47,20 +50,6 @@
|
||||
#error "This code is not designed to be compiled with a C++ compiler."
|
||||
#endif
|
||||
|
||||
#ifdef INT64_C
|
||||
# define SF_PLATFORM_S64(x) INT64_C (x)
|
||||
#elif (SIZEOF_LONG == 8)
|
||||
# define SF_PLATFORM_S64(x) x##l
|
||||
#elif (SIZEOF_LONG_LONG == 8)
|
||||
# define SF_PLATFORM_S64(x) x##ll
|
||||
#elif COMPILER_IS_GCC
|
||||
# define SF_PLATFORM_S64(x) x##ll
|
||||
#elif OS_IS_WIN32
|
||||
# define SF_PLATFORM_S64(x) x##I64
|
||||
#else
|
||||
# error "Don't know how to define a 64 bit integer constant."
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@ -99,24 +88,8 @@
|
||||
|
||||
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
|
||||
|
||||
#define NOT(x) (! (x))
|
||||
|
||||
#if COMPILER_IS_GCC
|
||||
#define SF_MAX(x, y) ({ \
|
||||
typeof (x) sf_max_x1 = (x) ; \
|
||||
typeof (y) sf_max_y1 = (y) ; \
|
||||
(void) (&sf_max_x1 == &sf_max_y1) ; \
|
||||
sf_max_x1 > sf_max_y1 ? sf_max_x1 : sf_max_y1 ; })
|
||||
|
||||
#define SF_MIN(x, y) ({ \
|
||||
typeof (x) sf_min_x2 = (x) ; \
|
||||
typeof (y) sf_min_y2 = (y) ; \
|
||||
(void) (&sf_min_x2 == &sf_min_y2) ; \
|
||||
sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; })
|
||||
#else
|
||||
#define SF_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define SF_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
|
||||
#define COMPILE_TIME_ASSERT(e) (sizeof (struct { int : - !! (e) ; }))
|
||||
@ -124,7 +97,6 @@
|
||||
|
||||
#define SF_MAX_CHANNELS 1024
|
||||
|
||||
|
||||
/*
|
||||
* Macros for spliting the format file of SF_INFO into container type,
|
||||
** codec type and endian-ness.
|
||||
@ -307,6 +279,12 @@ typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ;
|
||||
|
||||
typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ;
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t offset ;
|
||||
sf_count_t len ;
|
||||
unsigned minor_version ;
|
||||
} ID3V2_HEADER_INFO ;
|
||||
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
typedef wchar_t sfwchar_t ;
|
||||
#else
|
||||
@ -314,20 +292,13 @@ typedef int16_t sfwchar_t ;
|
||||
#endif
|
||||
|
||||
|
||||
static inline void *
|
||||
psf_memdup (const void *src, size_t n)
|
||||
{ void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ;
|
||||
return memcpy (mem, src, n) ;
|
||||
} /* psf_memdup */
|
||||
void *psf_memdup (const void *src, size_t n) ;
|
||||
|
||||
/*
|
||||
** This version of isprint specifically ignores any locale info. Its used for
|
||||
** determining which characters can be printed in things like hexdumps.
|
||||
*/
|
||||
static inline int
|
||||
psf_isprint (int ch)
|
||||
{ return (ch >= ' ' && ch <= '~') ;
|
||||
} /* psf_isprint */
|
||||
int psf_isprint (int ch) ;
|
||||
|
||||
/*=======================================================================================
|
||||
** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the
|
||||
@ -337,36 +308,23 @@ psf_isprint (int ch)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN] ;
|
||||
} path ;
|
||||
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN] ;
|
||||
} dir ;
|
||||
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN / 4] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN / 4] ;
|
||||
} name ;
|
||||
char path [SF_FILENAME_LEN] ;
|
||||
char dir [SF_FILENAME_LEN] ;
|
||||
char name [SF_FILENAME_LEN / 4] ;
|
||||
|
||||
#if USE_WINDOWS_API
|
||||
/*
|
||||
** These fields can only be used in src/file_io.c.
|
||||
** They are basically the same as a windows file HANDLE.
|
||||
*/
|
||||
void *handle, *hsaved ;
|
||||
|
||||
int use_wchar ;
|
||||
void *handle, *hsaved ;
|
||||
#else
|
||||
/* These fields can only be used in src/file_io.c. */
|
||||
int filedes, savedes ;
|
||||
int filedes, savedes ;
|
||||
#endif
|
||||
|
||||
int do_not_close_descriptor ;
|
||||
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
|
||||
int do_not_close_descriptor ;
|
||||
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
|
||||
} PSF_FILE ;
|
||||
|
||||
|
||||
@ -390,13 +348,6 @@ typedef union
|
||||
|
||||
typedef struct sf_private_tag
|
||||
{
|
||||
/* Canary in a coal mine. */
|
||||
union
|
||||
{ /* Place a double here to encourage double alignment. */
|
||||
double d [2] ;
|
||||
char c [16] ;
|
||||
} canary ;
|
||||
|
||||
PSF_FILE file, rsrc ;
|
||||
|
||||
char syserr [SF_SYSERR_LEN] ;
|
||||
@ -554,6 +505,8 @@ typedef struct sf_private_tag
|
||||
int (*get_chunk_data) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
int cpu_flags ;
|
||||
|
||||
ID3V2_HEADER_INFO id3_header ;
|
||||
} SF_PRIVATE ;
|
||||
|
||||
|
||||
@ -768,6 +721,17 @@ enum
|
||||
|
||||
SFE_OPUS_BAD_SAMPLERATE,
|
||||
|
||||
SFE_CAF_NOT_CAF,
|
||||
SFE_CAF_NO_DESC,
|
||||
SFE_CAF_BAD_PEAK,
|
||||
|
||||
SFE_AVR_NOT_AVR,
|
||||
SFE_AVR_BAD_REZ_SIGN,
|
||||
|
||||
SFE_MPC_NO_MARKER,
|
||||
|
||||
SFE_MPEG_BAD_SAMPLERATE,
|
||||
|
||||
SFE_MAX_ERROR /* This must be last in list. */
|
||||
} ;
|
||||
|
||||
@ -883,6 +847,8 @@ int psf_fclose (SF_PRIVATE *psf) ;
|
||||
int psf_open_rsrc (SF_PRIVATE *psf) ;
|
||||
int psf_close_rsrc (SF_PRIVATE *psf) ;
|
||||
|
||||
int psf_copy_filename (SF_PRIVATE *psf, const char *path) ;
|
||||
|
||||
/*
|
||||
void psf_fclearerr (SF_PRIVATE *psf) ;
|
||||
int psf_ferror (SF_PRIVATE *psf) ;
|
||||
@ -921,10 +887,10 @@ int ogg_pcm_open (SF_PRIVATE *psf) ;
|
||||
int ogg_opus_open (SF_PRIVATE *psf) ;
|
||||
int ogg_open (SF_PRIVATE *psf) ;
|
||||
|
||||
int mpeg_open (SF_PRIVATE *psf) ;
|
||||
|
||||
/* In progress. Do not currently work. */
|
||||
|
||||
int mpeg_open (SF_PRIVATE *psf) ;
|
||||
int rx2_open (SF_PRIVATE *psf) ;
|
||||
int txw_open (SF_PRIVATE *psf) ;
|
||||
int wve_open (SF_PRIVATE *psf) ;
|
||||
@ -946,6 +912,7 @@ int vox_adpcm_init (SF_PRIVATE *psf) ;
|
||||
int flac_init (SF_PRIVATE *psf) ;
|
||||
int g72x_init (SF_PRIVATE * psf) ;
|
||||
int alac_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ;
|
||||
int mpeg_init (SF_PRIVATE *psf, int bitrate_mode, int write_metadata) ;
|
||||
|
||||
int dither_init (SF_PRIVATE *psf, int mode) ;
|
||||
|
||||
@ -971,17 +938,6 @@ int psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITER
|
||||
|
||||
int psf_find_write_chunk (WRITE_CHUNKS * pchk, const char * marker) ;
|
||||
|
||||
static inline int
|
||||
fourcc_to_marker (const SF_CHUNK_INFO * chunk_info)
|
||||
{ const unsigned char * cptr ;
|
||||
|
||||
if (chunk_info->id_size != 4)
|
||||
return 0 ;
|
||||
|
||||
cptr = (const unsigned char *) chunk_info->id ;
|
||||
return (cptr [3] << 24) + (cptr [2] << 16) + (cptr [1] << 8) + cptr [0] ;
|
||||
} /* fourcc_to_marker */
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Functions that work like OpenBSD's strlcpy/strlcat to replace strncpy/strncat.
|
||||
**
|
||||
@ -994,17 +950,8 @@ fourcc_to_marker (const SF_CHUNK_INFO * chunk_info)
|
||||
** compiler errors if code is carelessly converted from one to the other.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
psf_strlcat (char *dest, size_t n, const char *src)
|
||||
{ strncat (dest, src, n - strlen (dest) - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcat */
|
||||
|
||||
static inline void
|
||||
psf_strlcpy (char *dest, size_t n, const char *src)
|
||||
{ strncpy (dest, src, n - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcpy */
|
||||
void psf_strlcat (char *dest, size_t n, const char *src) ;
|
||||
void psf_strlcpy (char *dest, size_t n, const char *src) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** SIMD optimized math functions.
|
||||
@ -1061,6 +1008,7 @@ typedef struct
|
||||
|
||||
int audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ;
|
||||
int id3_skip (SF_PRIVATE * psf) ;
|
||||
const char *id3_lookup_v1_genre (int number) ;
|
||||
|
||||
void alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet) ;
|
||||
|
||||
|
@ -43,6 +43,9 @@
|
||||
/* Will be set to 1 if flac, ogg and vorbis are available. */
|
||||
#cmakedefine01 HAVE_EXTERNAL_XIPH_LIBS
|
||||
|
||||
/* Will be set to 1 if lame and mpg123 are available. */
|
||||
#cmakedefine01 HAVE_MPEG
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#cmakedefine01 HAVE_FLOOR
|
||||
|
||||
@ -175,6 +178,9 @@
|
||||
/* Define to 1 if you have the <immintrin.h> header file. */
|
||||
#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. */
|
||||
#cmakedefine01 HAVE_VSNPRINTF
|
||||
|
||||
@ -217,9 +223,6 @@
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "@CPACK_PACKAGE_VERSION_FULL@"
|
||||
|
||||
/* Set to maximum allowed value of sf_count_t type. */
|
||||
#define SF_COUNT_MAX @SF_COUNT_MAX@
|
||||
|
||||
/* The size of `double', as computed by sizeof. */
|
||||
@SIZEOF_DOUBLE_CODE@
|
||||
|
||||
@ -247,9 +250,6 @@
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
@SIZEOF_OFF_T_CODE@
|
||||
|
||||
/* Set to sizeof (long) if unknown. */
|
||||
@SIZEOF_SF_COUNT_T_CODE@
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
@SIZEOF_SHORT_CODE@
|
||||
|
||||
@ -265,9 +265,6 @@
|
||||
/* The size of `wchar_t', as computed by sizeof. */
|
||||
@SIZEOF_WCHAR_T_CODE@
|
||||
|
||||
/* Set to long if unknown. */
|
||||
#define TYPEOF_SF_COUNT_T @TYPEOF_SF_COUNT_T@
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
|
12
src/dither.c
12
src/dither.c
@ -242,7 +242,7 @@ dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ;
|
||||
thiswrite = (int) pdither->write_short (psf, (short*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
@ -288,7 +288,7 @@ dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ;
|
||||
thiswrite = (int) pdither->write_int (psf, (int*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
@ -327,13 +327,13 @@ dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
bufferlen = sizeof (pdither->buffer) / (sizeof (float)) ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (float) len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
writecount /= psf->sf.channels ;
|
||||
writecount *= psf->sf.channels ;
|
||||
|
||||
dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ;
|
||||
thiswrite = (int) pdither->write_float (psf, (float*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
@ -373,13 +373,13 @@ dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
bufferlen = sizeof (pdither->buffer) / sizeof (double) ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (double) len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
writecount /= psf->sf.channels ;
|
||||
writecount *= psf->sf.channels ;
|
||||
|
||||
dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ;
|
||||
thiswrite = (int) pdither->write_double (psf, (double*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
|
@ -486,71 +486,71 @@ double64_get_capability (SF_PRIVATE *psf)
|
||||
|
||||
static void
|
||||
d2s_array (const double *src, int count, short *dest, double scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = psf_lrint (scale * src [count]) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = psf_lrint (scale * src [i]) ;
|
||||
} ;
|
||||
} /* d2s_array */
|
||||
|
||||
static void
|
||||
d2s_clip_array (const double *src, int count, short *dest, double scale)
|
||||
{ while (--count >= 0)
|
||||
{ double tmp = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ double tmp = scale * src [i] ;
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
|
||||
dest [count] = SHRT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
|
||||
dest [count] = SHRT_MIN ;
|
||||
if (tmp > 32767.0)
|
||||
dest [i] = SHRT_MAX ;
|
||||
else if (tmp < -32768.0)
|
||||
dest [i] = SHRT_MIN ;
|
||||
else
|
||||
dest [count] = psf_lrint (tmp) ;
|
||||
dest [i] = psf_lrint (tmp) ;
|
||||
} ;
|
||||
} /* d2s_clip_array */
|
||||
|
||||
static void
|
||||
d2i_array (const double *src, int count, int *dest, double scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = psf_lrint (scale * src [count]) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = psf_lrint (scale * src [i]) ;
|
||||
} ;
|
||||
} /* d2i_array */
|
||||
|
||||
static void
|
||||
d2i_clip_array (const double *src, int count, int *dest, double scale)
|
||||
{ while (--count >= 0)
|
||||
{ float tmp = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ float tmp = scale * src [i] ;
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX))
|
||||
dest [count] = INT_MAX ;
|
||||
dest [i] = INT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
|
||||
dest [count] = INT_MIN ;
|
||||
dest [i] = INT_MIN ;
|
||||
else
|
||||
dest [count] = psf_lrint (tmp) ;
|
||||
dest [i] = psf_lrint (tmp) ;
|
||||
} ;
|
||||
} /* d2i_clip_array */
|
||||
|
||||
static inline void
|
||||
d2f_array (const double *src, int count, float *dest)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = src [i] ;
|
||||
} ;
|
||||
} /* d2f_array */
|
||||
|
||||
static inline void
|
||||
s2d_array (const short *src, double *dest, int count, double scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = scale * src [i] ;
|
||||
} ;
|
||||
} /* s2d_array */
|
||||
|
||||
static inline void
|
||||
i2d_array (const int *src, double *dest, int count, double scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = scale * src [i] ;
|
||||
} ;
|
||||
} /* i2d_array */
|
||||
|
||||
static inline void
|
||||
f2d_array (const float *src, double *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = src [i] ;
|
||||
} ;
|
||||
} /* f2d_array */
|
||||
|
||||
@ -572,7 +572,7 @@ host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, readcount) ;
|
||||
@ -602,7 +602,7 @@ host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
@ -628,7 +628,7 @@ host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, readcount) ;
|
||||
@ -695,7 +695,7 @@ host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -726,7 +726,7 @@ host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -755,7 +755,7 @@ host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -785,7 +785,7 @@ host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
endswap_double_copy (ubuf.dbuf, ptr + total, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -811,7 +811,7 @@ replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
@ -841,7 +841,7 @@ replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
@ -869,7 +869,7 @@ replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
@ -899,7 +899,7 @@ replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, readcount) ;
|
||||
@ -940,7 +940,7 @@ replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -973,7 +973,7 @@ replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -1001,7 +1001,7 @@ replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -1034,7 +1034,7 @@ replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -1049,15 +1049,15 @@ replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
static void
|
||||
d2bd_read (double *buffer, int count)
|
||||
{ while (--count >= 0)
|
||||
{ buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ buffer [i] = DOUBLE64_READ ((unsigned char *) &buffer [i]) ;
|
||||
} ;
|
||||
} /* d2bd_read */
|
||||
|
||||
static void
|
||||
bd2d_write (double *buffer, int count)
|
||||
{ while (--count >= 0)
|
||||
{ DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ DOUBLE64_WRITE (buffer [i], (unsigned char*) &buffer [i]) ;
|
||||
} ;
|
||||
} /* bd2d_write */
|
||||
|
||||
|
@ -115,9 +115,9 @@ dwd_close (SF_PRIVATE * UNUSED (psf))
|
||||
** No assumptions are made about the packing of this struct.
|
||||
*/
|
||||
typedef struct
|
||||
{ unsigned char major, minor, compression, channels, bitwidth ;
|
||||
unsigned short srate, maxval ;
|
||||
unsigned int id, datalen, frames, offset ;
|
||||
{ uint8_t major, minor, compression, channels, bitwidth ;
|
||||
uint16_t srate, maxval ;
|
||||
uint32_t id, datalen, frames, offset ;
|
||||
} DWD_HEADER ;
|
||||
|
||||
static int
|
||||
@ -173,7 +173,7 @@ dwd_read_header (SF_PRIVATE *psf)
|
||||
|
||||
if (psf->filelength != dwdh.offset + dwdh.datalen)
|
||||
{ psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ;
|
||||
dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ;
|
||||
dwdh.datalen = (uint32_t) (psf->filelength - dwdh.offset) ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ;
|
||||
|
14
src/dwvw.c
14
src/dwvw.c
@ -198,7 +198,7 @@ dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = iptr [k] >> 16 ;
|
||||
@ -255,7 +255,7 @@ dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (float) (iptr [k]) ;
|
||||
@ -287,7 +287,7 @@ dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (iptr [k]) ;
|
||||
@ -377,7 +377,7 @@ dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count)
|
||||
/* Load bits in bit reseviour. */
|
||||
while (pdwvw->bit_count < bit_count)
|
||||
{ if (pdwvw->b.index >= pdwvw->b.end)
|
||||
{ pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ;
|
||||
{ pdwvw->b.end = (int) psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ;
|
||||
pdwvw->b.index = 0 ;
|
||||
} ;
|
||||
|
||||
@ -569,7 +569,7 @@ dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = arith_shift_left (ptr [total + k], 16) ;
|
||||
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
|
||||
@ -626,7 +626,7 @@ dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
|
||||
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
|
||||
@ -658,7 +658,7 @@ dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = psf_lrint (normfact * ptr [total + k]) ;
|
||||
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
|
||||
|
528
src/file_io.c
528
src/file_io.c
@ -76,6 +76,34 @@
|
||||
|
||||
static void psf_log_syserr (SF_PRIVATE *psf, int error) ;
|
||||
|
||||
int
|
||||
psf_copy_filename (SF_PRIVATE *psf, const char *path)
|
||||
{ const char *ccptr ;
|
||||
char *cptr ;
|
||||
|
||||
if (strlen (path) > 1 && strlen (path) - 1 >= sizeof (psf->file.path))
|
||||
{ psf->error = SFE_FILENAME_TOO_LONG ;
|
||||
return psf->error ;
|
||||
} ;
|
||||
|
||||
snprintf (psf->file.path, sizeof (psf->file.path), "%s", path) ;
|
||||
if ((ccptr = strrchr (path, '/')) || (ccptr = strrchr (path, '\\')))
|
||||
ccptr ++ ;
|
||||
else
|
||||
ccptr = path ;
|
||||
|
||||
snprintf (psf->file.name, sizeof (psf->file.name), "%s", ccptr) ;
|
||||
|
||||
/* Now grab the directory. */
|
||||
snprintf (psf->file.dir, sizeof (psf->file.dir), "%s", path) ;
|
||||
if ((cptr = strrchr (psf->file.dir, '/')) || (cptr = strrchr (psf->file.dir, '\\')))
|
||||
cptr [1] = 0 ;
|
||||
else
|
||||
psf->file.dir [0] = 0 ;
|
||||
|
||||
return 0 ;
|
||||
} /* psf_copy_filename */
|
||||
|
||||
#if (USE_WINDOWS_API == 0)
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@ -132,9 +160,9 @@ psf_open_rsrc (SF_PRIVATE *psf)
|
||||
return 0 ;
|
||||
|
||||
/* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
|
||||
count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/..namedfork/rsrc", psf->file.path.c) ;
|
||||
count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s/..namedfork/rsrc", psf->file.path) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if (count < sizeof (psf->rsrc.path.c))
|
||||
if (count < sizeof (psf->rsrc.path))
|
||||
{ if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
||||
if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE))
|
||||
@ -153,9 +181,9 @@ psf_open_rsrc (SF_PRIVATE *psf)
|
||||
** Now try for a resource fork stored as a separate file in the same
|
||||
** directory, but preceded with a dot underscore.
|
||||
*/
|
||||
count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s._%s", psf->file.dir, psf->file.name) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if (count < sizeof (psf->rsrc.path.c) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
if (count < sizeof (psf->rsrc.path) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
@ -164,9 +192,9 @@ psf_open_rsrc (SF_PRIVATE *psf)
|
||||
** Now try for a resource fork stored in a separate file in the
|
||||
** .AppleDouble/ directory.
|
||||
*/
|
||||
count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s.AppleDouble/%s", psf->file.dir, psf->file.name) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if (count < sizeof (psf->rsrc.path.c))
|
||||
if (count < sizeof (psf->rsrc.path))
|
||||
{ if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
||||
return SFE_NO_ERROR ;
|
||||
@ -477,7 +505,7 @@ psf_is_pipe (SF_PRIVATE *psf)
|
||||
static sf_count_t
|
||||
psf_get_filelen_fd (int fd)
|
||||
{
|
||||
#if (SIZEOF_OFF_T == 4 && SIZEOF_SF_COUNT_T == 8 && HAVE_FSTAT64)
|
||||
#if (SIZEOF_OFF_T == 4 && HAVE_FSTAT64)
|
||||
struct stat64 statbuf ;
|
||||
|
||||
if (fstat64 (fd, &statbuf) == -1)
|
||||
@ -572,9 +600,9 @@ psf_open_fd (PSF_FILE * pfile)
|
||||
} ;
|
||||
|
||||
if (mode == 0)
|
||||
fd = open (pfile->path.c, oflag) ;
|
||||
fd = open (pfile->path, oflag) ;
|
||||
else
|
||||
fd = open (pfile->path.c, oflag, mode) ;
|
||||
fd = open (pfile->path, oflag, mode) ;
|
||||
|
||||
return fd ;
|
||||
} /* psf_open_fd */
|
||||
@ -602,7 +630,7 @@ psf_fsync (SF_PRIVATE *psf)
|
||||
#endif
|
||||
} /* psf_fsync */
|
||||
|
||||
#elif USE_WINDOWS_API
|
||||
#else
|
||||
|
||||
/* Win32 file i/o functions implemented using native Win32 API */
|
||||
|
||||
@ -620,7 +648,7 @@ psf_fopen (SF_PRIVATE *psf)
|
||||
psf->error = 0 ;
|
||||
psf->file.handle = psf_open_handle (&psf->file) ;
|
||||
|
||||
if (psf->file.handle == NULL)
|
||||
if (psf->file.handle == INVALID_HANDLE_VALUE)
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
|
||||
return psf->error ;
|
||||
@ -634,14 +662,14 @@ psf_fclose (SF_PRIVATE *psf)
|
||||
return 0 ;
|
||||
|
||||
if (psf->file.do_not_close_descriptor)
|
||||
{ psf->file.handle = NULL ;
|
||||
{ psf->file.handle = INVALID_HANDLE_VALUE ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if ((retval = psf_close_handle (psf->file.handle)) == -1)
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
|
||||
psf->file.handle = NULL ;
|
||||
psf->file.handle = INVALID_HANDLE_VALUE ;
|
||||
|
||||
return retval ;
|
||||
} /* psf_fclose */
|
||||
@ -649,13 +677,13 @@ psf_fclose (SF_PRIVATE *psf)
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_open_rsrc (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->rsrc.handle != NULL)
|
||||
if (psf->rsrc.handle != INVALID_HANDLE_VALUE)
|
||||
return 0 ;
|
||||
|
||||
/* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/rsrc", psf->file.path.c) ;
|
||||
snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s/rsrc", psf->file.path) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
@ -664,9 +692,9 @@ psf_open_rsrc (SF_PRIVATE *psf)
|
||||
** Now try for a resource fork stored as a separate file in the same
|
||||
** directory, but preceded with a dot underscore.
|
||||
*/
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s._%s", psf->file.dir, psf->file.name) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
@ -675,19 +703,17 @@ psf_open_rsrc (SF_PRIVATE *psf)
|
||||
** Now try for a resource fork stored in a separate file in the
|
||||
** .AppleDouble/ directory.
|
||||
*/
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s.AppleDouble/%s", psf->file.dir, psf->file.name) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
|
||||
/* No resource file found. */
|
||||
if (psf->rsrc.handle == NULL)
|
||||
if (psf->rsrc.handle == INVALID_HANDLE_VALUE)
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
|
||||
psf->rsrc.handle = NULL ;
|
||||
|
||||
return psf->error ;
|
||||
} /* psf_open_rsrc */
|
||||
|
||||
@ -738,9 +764,9 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
|
||||
/* USE_WINDOWS_API */ void
|
||||
psf_init_files (SF_PRIVATE *psf)
|
||||
{ psf->file.handle = NULL ;
|
||||
psf->rsrc.handle = NULL ;
|
||||
psf->file.hsaved = NULL ;
|
||||
{ psf->file.handle = INVALID_HANDLE_VALUE ;
|
||||
psf->rsrc.handle = INVALID_HANDLE_VALUE ;
|
||||
psf->file.hsaved = INVALID_HANDLE_VALUE ;
|
||||
} /* psf_init_files */
|
||||
|
||||
/* USE_WINDOWS_API */ void
|
||||
@ -764,6 +790,7 @@ psf_open_handle (PSF_FILE * pfile)
|
||||
DWORD dwShareMode ;
|
||||
DWORD dwCreationDistribution ;
|
||||
HANDLE handle ;
|
||||
LPWSTR pwszPath = NULL ;
|
||||
|
||||
switch (pfile->mode)
|
||||
{ case SFM_READ :
|
||||
@ -785,50 +812,40 @@ psf_open_handle (PSF_FILE * pfile)
|
||||
break ;
|
||||
|
||||
default :
|
||||
return NULL ;
|
||||
return INVALID_HANDLE_VALUE ;
|
||||
} ;
|
||||
|
||||
int nResult = MultiByteToWideChar (CP_UTF8, 0, pfile->path, -1, NULL, 0) ;
|
||||
pwszPath = malloc (nResult * sizeof (WCHAR)) ;
|
||||
if (!pwszPath)
|
||||
return INVALID_HANDLE_VALUE ;
|
||||
|
||||
int nResult2 = MultiByteToWideChar (CP_UTF8, 0, pfile->path, -1, pwszPath, nResult) ;
|
||||
if (nResult != nResult2)
|
||||
{ free (pwszPath) ;
|
||||
return INVALID_HANDLE_VALUE ;
|
||||
} ;
|
||||
|
||||
#if defined (WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
if (!pfile->use_wchar)
|
||||
return NULL ;
|
||||
|
||||
CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ;
|
||||
cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ;
|
||||
cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ;
|
||||
|
||||
handle = CreateFile2 (pfile->path.wc, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return NULL ;
|
||||
|
||||
return handle ;
|
||||
handle = CreateFile2 (pwszPath, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ;
|
||||
#else
|
||||
if (pfile->use_wchar)
|
||||
handle = CreateFileW (
|
||||
pfile->path.wc, /* pointer to name of the file */
|
||||
dwDesiredAccess, /* access (read-write) mode */
|
||||
dwShareMode, /* share mode */
|
||||
0, /* pointer to security attributes */
|
||||
dwCreationDistribution, /* how to create */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
||||
NULL /* handle to file with attributes to copy */
|
||||
) ;
|
||||
else
|
||||
handle = CreateFileA (
|
||||
pfile->path.c, /* pointer to name of the file */
|
||||
dwDesiredAccess, /* access (read-write) mode */
|
||||
dwShareMode, /* share mode */
|
||||
0, /* pointer to security attributes */
|
||||
dwCreationDistribution, /* how to create */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
||||
NULL /* handle to file with attributes to copy */
|
||||
) ;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return NULL ;
|
||||
handle = CreateFileW (
|
||||
pwszPath, /* pointer to name of the file */
|
||||
dwDesiredAccess, /* access (read-write) mode */
|
||||
dwShareMode, /* share mode */
|
||||
0, /* pointer to security attributes */
|
||||
dwCreationDistribution, /* how to create */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
||||
NULL /* handle to file with attributes to copy */
|
||||
) ;
|
||||
#endif
|
||||
free (pwszPath) ;
|
||||
|
||||
return handle ;
|
||||
#endif
|
||||
} /* psf_open_handle */
|
||||
|
||||
/* USE_WINDOWS_API */ static void
|
||||
@ -860,14 +877,14 @@ psf_log_syserr (SF_PRIVATE *psf, int error)
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_close_rsrc (SF_PRIVATE *psf)
|
||||
{ psf_close_handle (psf->rsrc.handle) ;
|
||||
psf->rsrc.handle = NULL ;
|
||||
psf->rsrc.handle = INVALID_HANDLE_VALUE ;
|
||||
return 0 ;
|
||||
} /* psf_close_rsrc */
|
||||
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_set_stdio (SF_PRIVATE *psf)
|
||||
{ HANDLE handle = NULL ;
|
||||
{ HANDLE handle = INVALID_HANDLE_VALUE ;
|
||||
int error = 0 ;
|
||||
|
||||
switch (psf->file.mode)
|
||||
@ -909,9 +926,7 @@ psf_set_file (SF_PRIVATE *psf, int fd)
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_file_valid (SF_PRIVATE *psf)
|
||||
{ if (psf->file.handle == NULL)
|
||||
return SF_FALSE ;
|
||||
if (psf->file.handle == INVALID_HANDLE_VALUE)
|
||||
{ if (psf->file.handle == INVALID_HANDLE_VALUE)
|
||||
return SF_FALSE ;
|
||||
return SF_TRUE ;
|
||||
} /* psf_set_file */
|
||||
@ -1073,7 +1088,7 @@ psf_ftell (SF_PRIVATE *psf)
|
||||
|
||||
/* USE_WINDOWS_API */ static int
|
||||
psf_close_handle (HANDLE handle)
|
||||
{ if (handle == NULL)
|
||||
{ if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0 ;
|
||||
|
||||
if (CloseHandle (handle) == 0)
|
||||
@ -1187,386 +1202,5 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
||||
return retval ;
|
||||
} /* psf_ftruncate */
|
||||
|
||||
|
||||
#else
|
||||
/* Win32 file i/o functions implemented using Unix-style file i/o API */
|
||||
|
||||
/* Win32 has a 64 file offset seek function:
|
||||
**
|
||||
** __int64 _lseeki64 (int handle, __int64 offset, int origin) ;
|
||||
**
|
||||
** It also has a 64 bit fstat function:
|
||||
**
|
||||
** int fstati64 (int, struct _stati64) ;
|
||||
**
|
||||
** but the fscking thing doesn't work!!!!! The file size parameter returned
|
||||
** by this function is only valid up until more data is written at the end of
|
||||
** the file. That makes this function completely 100% useless.
|
||||
*/
|
||||
|
||||
#include <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
|
||||
|
||||
|
151
src/flac.c
151
src/flac.c
@ -43,6 +43,15 @@
|
||||
|
||||
#define ENC_BUFFER_SIZE 8192
|
||||
|
||||
/*
|
||||
** READ_LOOP_MAX_LEN is the maximum 'len' that will be passed to
|
||||
** flac_read_loop(). This is somewhat arbitrary, but must be less
|
||||
** than (UINT_MAX - FLAC__MAX_CHANNELS * FLAC__MAX_BLOCK_SIZE) to
|
||||
** avoid overflows, and must also be a multiple of the number of
|
||||
** channels (which is between 1 and 8.)
|
||||
*/
|
||||
#define READ_LOOP_MAX_LEN (0x10000 * 3 * 5 * 7)
|
||||
|
||||
typedef enum
|
||||
{ PFLAC_PCM_SHORT = 50,
|
||||
PFLAC_PCM_INT = 51,
|
||||
@ -127,39 +136,39 @@ static FLAC__StreamEncoderWriteStatus sf_flac_enc_write_callback (const FLAC__St
|
||||
|
||||
static void
|
||||
s2flac8_array (const short *src, int32_t *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
dest [count] = src [count] >> 8 ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = src [i] >> 8 ;
|
||||
} /* s2flac8_array */
|
||||
|
||||
static void
|
||||
s2flac16_array (const short *src, int32_t *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
dest [count] = src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = src [i] ;
|
||||
} /* s2flac16_array */
|
||||
|
||||
static void
|
||||
s2flac24_array (const short *src, int32_t *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
dest [count] = src [count] << 8 ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = src [i] << 8 ;
|
||||
} /* s2flac24_array */
|
||||
|
||||
static void
|
||||
i2flac8_array (const int *src, int32_t *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
dest [count] = src [count] >> 24 ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = src [i] >> 24 ;
|
||||
} /* i2flac8_array */
|
||||
|
||||
static void
|
||||
i2flac16_array (const int *src, int32_t *dest, int count)
|
||||
{
|
||||
while (--count >= 0)
|
||||
dest [count] = src [count] >> 16 ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = src [i] >> 16 ;
|
||||
} /* i2flac16_array */
|
||||
|
||||
static void
|
||||
i2flac24_array (const int *src, int32_t *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
dest [count] = src [count] >> 8 ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = src [i] >> 8 ;
|
||||
} /* i2flac24_array */
|
||||
|
||||
static sf_count_t
|
||||
@ -952,7 +961,7 @@ flac_read_loop (SF_PRIVATE *psf, unsigned len)
|
||||
/* Current frame is busted, so NULL the pointer. */
|
||||
pflac->frame = NULL ;
|
||||
break ;
|
||||
};
|
||||
} ;
|
||||
state = FLAC__stream_decoder_get_state (pflac->fsd) ;
|
||||
if (state >= FLAC__STREAM_DECODER_END_OF_STREAM)
|
||||
{ psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
|
||||
@ -977,7 +986,7 @@ flac_read_flac2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
while (total < len)
|
||||
{ pflac->ptr = ptr + total ;
|
||||
readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
|
||||
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
|
||||
current = flac_read_loop (psf, readlen) ;
|
||||
if (current == 0)
|
||||
break ;
|
||||
@ -997,7 +1006,7 @@ flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
while (total < len)
|
||||
{ pflac->ptr = ptr + total ;
|
||||
readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
|
||||
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
|
||||
current = flac_read_loop (psf, readlen) ;
|
||||
if (current == 0)
|
||||
break ;
|
||||
@ -1017,7 +1026,7 @@ flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
while (total < len)
|
||||
{ pflac->ptr = ptr + total ;
|
||||
readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
|
||||
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
|
||||
current = flac_read_loop (psf, readlen) ;
|
||||
if (current == 0)
|
||||
break ;
|
||||
@ -1037,7 +1046,7 @@ flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
while (total < len)
|
||||
{ pflac->ptr = ptr + total ;
|
||||
readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ;
|
||||
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
|
||||
|
||||
current = flac_read_loop (psf, readlen) ;
|
||||
if (current == 0)
|
||||
@ -1180,17 +1189,17 @@ f2flac8_clip_array (const float *src, int32_t *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x10) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F))
|
||||
{ dest [count] = 0x7F ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7F))
|
||||
{ dest [i] = 0x7F ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10))
|
||||
{ dest [count] = -0x80 ;
|
||||
if (scaled_value <= (-8.0 * 0x10))
|
||||
{ dest [i] = -0x80 ;
|
||||
continue ;
|
||||
} ;
|
||||
dest [count] = psf_lrintf (scaled_value) ;
|
||||
dest [i] = psf_lrintf (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1202,17 +1211,17 @@ f2flac16_clip_array (const float *src, int32_t *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [i] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = -0x8000 ;
|
||||
if (scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [i] = -0x8000 ;
|
||||
continue ;
|
||||
} ;
|
||||
dest [count] = psf_lrintf (scaled_value) ;
|
||||
dest [i] = psf_lrintf (scaled_value) ;
|
||||
} ;
|
||||
} /* f2flac16_clip_array */
|
||||
|
||||
@ -1222,18 +1231,18 @@ f2flac24_clip_array (const float *src, int32_t *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x100000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF))
|
||||
{ dest [count] = 0x7FFFFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7FFFFF))
|
||||
{ dest [i] = 0x7FFFFF ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000))
|
||||
{ dest [count] = -0x800000 ;
|
||||
if (scaled_value <= (-8.0 * 0x100000))
|
||||
{ dest [i] = -0x800000 ;
|
||||
continue ;
|
||||
}
|
||||
dest [count] = psf_lrintf (scaled_value) ;
|
||||
dest [i] = psf_lrintf (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1243,24 +1252,24 @@ static void
|
||||
f2flac8_array (const float *src, int32_t *dest, int count, int normalize)
|
||||
{ float normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrintf (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrintf (src [i] * normfact) ;
|
||||
} /* f2flac8_array */
|
||||
|
||||
static void
|
||||
f2flac16_array (const float *src, int32_t *dest, int count, int normalize)
|
||||
{ float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrintf (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrintf (src [i] * normfact) ;
|
||||
} /* f2flac16_array */
|
||||
|
||||
static void
|
||||
f2flac24_array (const float *src, int32_t *dest, int count, int normalize)
|
||||
{ float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrintf (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrintf (src [i] * normfact) ;
|
||||
} /* f2flac24_array */
|
||||
|
||||
static sf_count_t
|
||||
@ -1311,17 +1320,17 @@ d2flac8_clip_array (const double *src, int32_t *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x10) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F))
|
||||
{ dest [count] = 0x7F ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7F))
|
||||
{ dest [i] = 0x7F ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10))
|
||||
{ dest [count] = -0x80 ;
|
||||
if (scaled_value <= (-8.0 * 0x10))
|
||||
{ dest [i] = -0x80 ;
|
||||
continue ;
|
||||
} ;
|
||||
dest [count] = psf_lrint (scaled_value) ;
|
||||
dest [i] = psf_lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1333,17 +1342,17 @@ d2flac16_clip_array (const double *src, int32_t *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [i] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = -0x8000 ;
|
||||
if (scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [i] = -0x8000 ;
|
||||
continue ;
|
||||
} ;
|
||||
dest [count] = psf_lrint (scaled_value) ;
|
||||
dest [i] = psf_lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1355,17 +1364,17 @@ d2flac24_clip_array (const double *src, int32_t *dest, int count, int normalize)
|
||||
|
||||
normfact = normalize ? (8.0 * 0x100000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF))
|
||||
{ dest [count] = 0x7FFFFF ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ scaled_value = src [i] * normfact ;
|
||||
if (scaled_value >= (1.0 * 0x7FFFFF))
|
||||
{ dest [i] = 0x7FFFFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000))
|
||||
{ dest [count] = -0x800000 ;
|
||||
if (scaled_value <= (-8.0 * 0x100000))
|
||||
{ dest [i] = -0x800000 ;
|
||||
continue ;
|
||||
} ;
|
||||
dest [count] = psf_lrint (scaled_value) ;
|
||||
dest [i] = psf_lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
@ -1375,24 +1384,24 @@ static void
|
||||
d2flac8_array (const double *src, int32_t *dest, int count, int normalize)
|
||||
{ double normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrint (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrint (src [i] * normfact) ;
|
||||
} /* d2flac8_array */
|
||||
|
||||
static void
|
||||
d2flac16_array (const double *src, int32_t *dest, int count, int normalize)
|
||||
{ double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrint (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrint (src [i] * normfact) ;
|
||||
} /* d2flac16_array */
|
||||
|
||||
static void
|
||||
d2flac24_array (const double *src, int32_t *dest, int count, int normalize)
|
||||
{ double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
dest [count] = psf_lrint (src [count] * normfact) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
dest [i] = psf_lrint (src [i] * normfact) ;
|
||||
} /* d2flac24_array */
|
||||
|
||||
static sf_count_t
|
||||
|
@ -437,71 +437,71 @@ float32_get_capability (SF_PRIVATE *psf)
|
||||
static void
|
||||
f2s_array (const float *src, int count, short *dest, float scale)
|
||||
{
|
||||
while (--count >= 0)
|
||||
{ dest [count] = psf_lrintf (scale * src [count]) ;
|
||||
for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = psf_lrintf (scale * src [i]) ;
|
||||
} ;
|
||||
} /* f2s_array */
|
||||
|
||||
static void
|
||||
f2s_clip_array (const float *src, int count, short *dest, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ float tmp = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ float tmp = scale * src [i] ;
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
|
||||
dest [count] = SHRT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
|
||||
dest [count] = SHRT_MIN ;
|
||||
if (tmp > 32767.0)
|
||||
dest [i] = SHRT_MAX ;
|
||||
else if (tmp < -32768.0)
|
||||
dest [i] = SHRT_MIN ;
|
||||
else
|
||||
dest [count] = psf_lrintf (tmp) ;
|
||||
dest [i] = psf_lrintf (tmp) ;
|
||||
} ;
|
||||
} /* f2s_clip_array */
|
||||
|
||||
static inline void
|
||||
f2i_array (const float *src, int count, int *dest, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = psf_lrintf (scale * src [count]) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = psf_lrintf (scale * src [i]) ;
|
||||
} ;
|
||||
} /* f2i_array */
|
||||
|
||||
static inline void
|
||||
f2i_clip_array (const float *src, int count, int *dest, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ float tmp = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ float tmp = scale * src [i] ;
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX))
|
||||
dest [count] = INT_MAX ;
|
||||
dest [i] = INT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
|
||||
dest [count] = INT_MIN ;
|
||||
dest [i] = INT_MIN ;
|
||||
else
|
||||
dest [count] = psf_lrintf (tmp) ;
|
||||
dest [i] = psf_lrintf (tmp) ;
|
||||
} ;
|
||||
} /* f2i_clip_array */
|
||||
|
||||
static inline void
|
||||
f2d_array (const float *src, int count, double *dest)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = src [i] ;
|
||||
} ;
|
||||
} /* f2d_array */
|
||||
|
||||
static inline void
|
||||
s2f_array (const short *src, float *dest, int count, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = scale * src [i] ;
|
||||
} ;
|
||||
} /* s2f_array */
|
||||
|
||||
static inline void
|
||||
i2f_array (const int *src, float *dest, int count, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = scale * src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = scale * src [i] ;
|
||||
} ;
|
||||
} /* i2f_array */
|
||||
|
||||
static inline void
|
||||
d2f_array (const double *src, float *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = src [count] ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ dest [i] = src [i] ;
|
||||
} ;
|
||||
} /* d2f_array */
|
||||
|
||||
@ -523,7 +523,7 @@ host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
/* Fix me : Need lef2s_array */
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
@ -554,7 +554,7 @@ host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
@ -583,7 +583,7 @@ host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
endswap_int_copy ((int*) (ptr + total), ubuf.ibuf, readcount) ;
|
||||
|
||||
@ -607,7 +607,7 @@ host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
@ -645,7 +645,7 @@ host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -676,7 +676,7 @@ host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -706,7 +706,7 @@ host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
endswap_int_copy (ubuf.ibuf, (const int*) (ptr + total), bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -736,7 +736,7 @@ host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -762,7 +762,7 @@ replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
@ -787,12 +787,12 @@ replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
float scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
@ -822,7 +822,7 @@ replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
@ -851,7 +851,7 @@ replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
@ -891,7 +891,7 @@ replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -924,7 +924,7 @@ replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -957,7 +957,7 @@ replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -988,7 +988,7 @@ replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@ -1003,15 +1003,15 @@ replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
static void
|
||||
bf2f_array (float *buffer, int count)
|
||||
{ while (--count >= 0)
|
||||
{ buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ buffer [i] = FLOAT32_READ ((unsigned char *) &buffer [i]) ;
|
||||
} ;
|
||||
} /* bf2f_array */
|
||||
|
||||
static void
|
||||
f2bf_array (float *buffer, int count)
|
||||
{ while (--count >= 0)
|
||||
{ FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ;
|
||||
{ for (int i = 0 ; i < count ; i++)
|
||||
{ FLOAT32_WRITE (buffer [i], (unsigned char*) &buffer [i]) ;
|
||||
} ;
|
||||
} /* f2bf_array */
|
||||
|
||||
|
14
src/g72x.c
14
src/g72x.c
@ -141,7 +141,7 @@ g72x_init (SF_PRIVATE * psf)
|
||||
else
|
||||
pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
|
||||
|
||||
psf->sf.frames = pg72x->blocks_total * pg72x->samplesperblock ;
|
||||
psf->sf.frames = (sf_count_t) pg72x->blocks_total * pg72x->samplesperblock ;
|
||||
|
||||
psf_g72x_decode_block (psf, pg72x) ;
|
||||
}
|
||||
@ -264,7 +264,7 @@ g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
@ -297,7 +297,7 @@ g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
@ -329,7 +329,7 @@ g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (sptr [k]) ;
|
||||
@ -505,7 +505,7 @@ g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
|
||||
@ -536,7 +536,7 @@ g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
|
||||
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
|
||||
@ -568,7 +568,7 @@ g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
|
||||
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
|
||||
|
22
src/gsm610.c
22
src/gsm610.c
@ -150,7 +150,7 @@ Need separate gsm_data structs for encode and decode.
|
||||
pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
|
||||
} ;
|
||||
|
||||
psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
|
||||
psf->sf.frames = (sf_count_t) pgsm610->samplesperblock * pgsm610->blocks ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
@ -198,7 +198,7 @@ gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE)
|
||||
if ((k = (int) psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ;
|
||||
|
||||
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
|
||||
@ -226,7 +226,7 @@ gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
|
||||
if ((k = (int) psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
|
||||
|
||||
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
|
||||
@ -302,7 +302,7 @@ gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = arith_shift_left (sptr [k], 16) ;
|
||||
@ -331,7 +331,7 @@ gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
@ -360,7 +360,7 @@ gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
@ -437,7 +437,7 @@ gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
|
||||
if ((k = (int) psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
|
||||
|
||||
pgsm610->samplecount = 0 ;
|
||||
@ -458,7 +458,7 @@ gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAVLIKE_GSM610_SAMPLES / 2, pgsm610->block+WAVLIKE_GSM610_BLOCKSIZE / 2) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE)
|
||||
if ((k = (int) psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ;
|
||||
|
||||
pgsm610->samplecount = 0 ;
|
||||
@ -532,7 +532,7 @@ gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
|
||||
@ -561,7 +561,7 @@ gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
|
||||
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
|
||||
@ -592,7 +592,7 @@ gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
|
||||
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
|
||||
|
87
src/id3.c
87
src/id3.c
@ -26,34 +26,107 @@
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.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
|
||||
id3_skip (SF_PRIVATE * psf)
|
||||
{ unsigned char buf [10] ;
|
||||
int offset ;
|
||||
|
||||
memset (buf, 0, sizeof (buf)) ;
|
||||
psf_binheader_readf (psf, "pb", 0, buf, 10) ;
|
||||
|
||||
if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3')
|
||||
{ int offset = buf [6] & 0x7f ;
|
||||
{ psf->id3_header.minor_version = buf [3] ;
|
||||
offset = buf [6] & 0x7f ;
|
||||
offset = (offset << 7) | (buf [7] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [8] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [9] & 0x7f) ;
|
||||
|
||||
psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ;
|
||||
/*
|
||||
** ID3 count field is how many bytes of ID3v2 header FOLLOW the ten
|
||||
** bytes of header magic and offset, NOT the total ID3v2 header len.
|
||||
*/
|
||||
psf->id3_header.len = offset + 10 ;
|
||||
psf->id3_header.offset = psf->fileoffset ;
|
||||
|
||||
psf_log_printf (psf, " ID3v2.%d header length : %d\n----------------------------------------\n",
|
||||
psf->id3_header.minor_version, psf->id3_header.len) ;
|
||||
|
||||
/* Never want to jump backwards in a file. */
|
||||
if (offset < 0)
|
||||
return 0 ;
|
||||
|
||||
/* Calculate new file offset and position ourselves there. */
|
||||
offset += 10 ;
|
||||
if (psf->fileoffset + offset < psf->filelength)
|
||||
{ psf_binheader_readf (psf, "p", offset) ;
|
||||
psf->fileoffset += offset ;
|
||||
/* Position ourselves at the new file offset. */
|
||||
if (psf->fileoffset + psf->id3_header.len < psf->filelength)
|
||||
{ psf_binheader_readf (psf, "p!", psf->id3_header.len) ;
|
||||
psf->fileoffset += psf->id3_header.len ;
|
||||
return 1 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* id3_skip */
|
||||
|
||||
const char *
|
||||
id3_process_v2_genre (const char *genre)
|
||||
{ int num = 0 ;
|
||||
char c ;
|
||||
const char *ptr ;
|
||||
|
||||
if (!genre)
|
||||
return NULL ;
|
||||
|
||||
/*
|
||||
** Genre may require more processing.
|
||||
**
|
||||
** It is allowed to have numeric references to the genre table from ID3v1.
|
||||
** We'll just convert the simple case here, strings of the format "(nnn)".
|
||||
*/
|
||||
ptr = genre ;
|
||||
if (ptr [0] == '(' && (c = *++ ptr) && isdigit (c))
|
||||
{ num = c - '0' ;
|
||||
while ((c == *++ ptr) && isdigit (c))
|
||||
num = num * 10 + (c - '0') ;
|
||||
if (c == ')' && (c = *++ ptr) == '\0' && num < 256)
|
||||
if ((ptr = id3_lookup_v1_genre (num)))
|
||||
return ptr ;
|
||||
} ;
|
||||
|
||||
return genre ;
|
||||
} /* id3_process_v2_genre */
|
||||
|
29
src/id3.h
Normal file
29
src/id3.h
Normal 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 */
|
@ -182,7 +182,12 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
if (psf->file.mode != SFM_READ)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ;
|
||||
/*
|
||||
** Allocate enough space for 1 more than a multiple of 8 samples
|
||||
** to avoid having to branch when pulling apart the nibbles.
|
||||
*/
|
||||
count = ((samplesperblock - 2) | 7) + 2 ;
|
||||
pimasize = sizeof (IMA_ADPCM_PRIVATE) + psf->sf.channels * (blockalign + samplesperblock + sizeof(short) * count) ;
|
||||
|
||||
if (! (pima = calloc (1, pimasize)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
@ -268,7 +273,7 @@ count ++ ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels)
|
||||
if ((k = (int) psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
|
||||
|
||||
/* Read and check the block header. */
|
||||
@ -373,7 +378,7 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
} ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize)
|
||||
if ((k = (int) psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ;
|
||||
|
||||
memset (pima->block, 0, pima->channels * pima->blocksize) ;
|
||||
@ -386,7 +391,7 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
static int
|
||||
wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ int chan, k, predictor, blockindx, indx, indxstart, diff ;
|
||||
short step, bytecode, stepindx [2] ;
|
||||
short step, bytecode, stepindx [2] = { 0 };
|
||||
|
||||
pima->blockcount ++ ;
|
||||
pima->samplecount = 0 ;
|
||||
@ -396,7 +401,7 @@ wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
|
||||
if ((k = (int) psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
|
||||
|
||||
/* Read and check the block header. */
|
||||
@ -552,7 +557,7 @@ wavlike_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
|
||||
/* Write the block to disk. */
|
||||
|
||||
if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
|
||||
if ((k = (int) psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ;
|
||||
|
||||
memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ;
|
||||
|
@ -46,8 +46,6 @@
|
||||
#define HEADER_LENGTH 42 /* Sum of above data fields. */
|
||||
#define HEADER_NAME_LEN 17 /* Length of name string. */
|
||||
|
||||
#define SFE_MPC_NO_MARKER 666
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
@ -131,7 +129,7 @@ mpc2k_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name.c) ;
|
||||
snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name) ;
|
||||
|
||||
psf_binheader_writef (psf, "e11b", BHW1 (1), BHW1 (4), BHWv (sample_name), BHWz (HEADER_NAME_LEN)) ;
|
||||
psf_binheader_writef (psf, "e111", BHW1 (100), BHW1 (0), BHW1 ((psf->sf.channels - 1) & 1)) ;
|
||||
|
165
src/mpeg.c
Normal file
165
src/mpeg.c
Normal 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
74
src/mpeg.h
Normal 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
638
src/mpeg_decode.c
Normal 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
784
src/mpeg_l3_encode.c
Normal 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
|
@ -128,8 +128,14 @@ wavlike_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
|
||||
|
||||
if (blockalign < 7 * psf->sf.channels)
|
||||
{ psf_log_printf (psf, "*** Error blockalign (%d) should be > %d.\n", blockalign, 7 * psf->sf.channels) ;
|
||||
/* There's 7 samples per channel in the preamble of each block */
|
||||
if (samplesperblock < 7 * psf->sf.channels)
|
||||
{ psf_log_printf (psf, "*** Error samplesperblock (%d) should be >= %d.\n", samplesperblock, 7 * psf->sf.channels) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (2 * blockalign < samplesperblock * psf->sf.channels)
|
||||
{ psf_log_printf (psf, "*** Error blockalign (%d) should be >= %d.\n", blockalign, samplesperblock * psf->sf.channels / 2) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
@ -224,7 +230,7 @@ msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
|
||||
if ((k = (int) psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
|
||||
{ psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ;
|
||||
if (k <= 0)
|
||||
return 1 ;
|
||||
@ -349,7 +355,7 @@ msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
if ((count = msadpcm_read_block (psf, pms, ptr, readcount)) <= 0)
|
||||
if ((count = (int) msadpcm_read_block (psf, pms, ptr, readcount)) <= 0)
|
||||
return -1 ;
|
||||
|
||||
total += count ;
|
||||
@ -376,9 +382,9 @@ msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
|
||||
if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0)
|
||||
if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0)
|
||||
return -1 ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
@ -408,9 +414,9 @@ msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
|
||||
if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0)
|
||||
if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0)
|
||||
return -1 ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
@ -440,9 +446,9 @@ msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
|
||||
if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0)
|
||||
if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0)
|
||||
return -1 ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
@ -627,7 +633,7 @@ msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
|
||||
/* Write the block to disk. */
|
||||
|
||||
if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
|
||||
if ((k = (int) psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ;
|
||||
|
||||
memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ;
|
||||
@ -673,7 +679,7 @@ msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = msadpcm_write_block (psf, pms, ptr, writecount) ;
|
||||
count = (int) msadpcm_write_block (psf, pms, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
@ -699,10 +705,10 @@ msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
@ -729,10 +735,10 @@ msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
|
||||
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
@ -759,10 +765,10 @@ msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
|
||||
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
|
@ -702,7 +702,7 @@ static int
|
||||
psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms)
|
||||
{ int k ;
|
||||
|
||||
if ((k = psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock)
|
||||
if ((k = (int) psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock)
|
||||
{ psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pnms->shortsperblock) ;
|
||||
memset (pnms->block + (k * sizeof (short)), 0, (pnms->shortsperblock - k) * sizeof (short)) ;
|
||||
} ;
|
||||
@ -785,7 +785,7 @@ nms_adpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
@ -818,7 +818,7 @@ nms_adpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
@ -850,7 +850,7 @@ nms_adpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (sptr [k]) ;
|
||||
@ -875,7 +875,7 @@ psf_nms_adpcm_encode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms)
|
||||
endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock)
|
||||
if ((k = (int) psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pnms->shortsperblock) ;
|
||||
|
||||
pnms->sample_curr = 0 ;
|
||||
@ -945,7 +945,7 @@ nms_adpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;
|
||||
@ -976,7 +976,7 @@ nms_adpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
|
||||
count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;
|
||||
@ -1008,7 +1008,7 @@ nms_adpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
|
||||
count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ;
|
||||
|
28
src/ogg.c
28
src/ogg.c
@ -165,6 +165,8 @@ ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
|
||||
return SFE_NOT_SEEKABLE ;
|
||||
|
||||
buffer = ogg_sync_buffer (&odata->osync, psf->header.indx) ;
|
||||
if (buffer == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
memcpy (buffer, psf->header.ptr, psf->header.indx) ;
|
||||
ogg_sync_wrote (&odata->osync, psf->header.indx) ;
|
||||
|
||||
@ -297,6 +299,10 @@ ogg_sync_next_page (SF_PRIVATE * psf, ogg_page *og, sf_count_t readmax, sf_count
|
||||
else
|
||||
nb_read = OGG_SYNC_READ_SIZE ;
|
||||
buffer = (unsigned char *) ogg_sync_buffer (&odata->osync, nb_read) ;
|
||||
if (buffer == NULL)
|
||||
{ psf->error = SFE_MALLOC_FAILED ;
|
||||
return -1 ;
|
||||
}
|
||||
read_ret = psf_fread (buffer, 1, nb_read, psf) ;
|
||||
if (read_ret == 0)
|
||||
return psf->error ? -1 : 0 ;
|
||||
@ -447,7 +453,9 @@ ogg_sync_last_page_before (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t *gp_out
|
||||
} /* ogg_sync_last_page_before */
|
||||
|
||||
int
|
||||
ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t target_gp, uint64_t pcm_start, uint64_t pcm_end, uint64_t *best_gp, sf_count_t begin, sf_count_t end)
|
||||
ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata,
|
||||
uint64_t target_gp, uint64_t pcm_start, uint64_t pcm_end, uint64_t *best_gp,
|
||||
sf_count_t begin, sf_count_t end, uint64_t gp_rate)
|
||||
{ ogg_page page ;
|
||||
uint64_t gp ;
|
||||
sf_count_t d0, d1, d2 ;
|
||||
@ -614,7 +622,7 @@ ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t targe
|
||||
if (buffering)
|
||||
ogg_stream_reset (&odata->ostream) ;
|
||||
/* Check to see if the last packet continues. */
|
||||
if (page.header [27 + page.header [26] - 1] == 255)
|
||||
if (ogg_page_continues (&page))
|
||||
{ ogg_page_search_continued_data (odata, &page) ;
|
||||
/*
|
||||
** If we have a continued packet, remember the offset of
|
||||
@ -624,15 +632,15 @@ ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t targe
|
||||
** remember the end of the page.
|
||||
*/
|
||||
best_start = page_offset ;
|
||||
} ;
|
||||
/*
|
||||
** Then force buffering on, so that if a packet starts (but
|
||||
** does not end) on the next page, we still avoid the extra
|
||||
** seek back.
|
||||
*/
|
||||
buffering = SF_TRUE ;
|
||||
/*
|
||||
** Then force buffering on, so that if a packet starts (but
|
||||
** does not end) on the next page, we still avoid the extra
|
||||
** seek back.
|
||||
*/
|
||||
buffering = SF_TRUE ;
|
||||
} ;
|
||||
*best_gp = pcm_start = gp ;
|
||||
if (target_gp - gp > 48000)
|
||||
if (target_gp - gp > gp_rate)
|
||||
{ /* Out by over a second. Try another bisection. */
|
||||
break ;
|
||||
}
|
||||
|
41
src/ogg.h
41
src/ogg.h
@ -57,7 +57,36 @@ typedef struct
|
||||
((buf [base + 2] <<16) & 0xff0000) | \
|
||||
((buf [base + 1] << 8) & 0xff00) | \
|
||||
(buf [base] & 0xff))
|
||||
/*-----------------------------------------------------------------------------------------------
|
||||
** Inline functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
** LibOgg documentation is noted as being bad by it's author.
|
||||
** Add some useful utility inline functions for introspecting Ogg pages.
|
||||
*/
|
||||
|
||||
/* ogg_page_segments returns how many segments are in this page. */
|
||||
static inline int
|
||||
ogg_page_segments (ogg_page *pg)
|
||||
{ return (int) (pg->header [26]) ; }
|
||||
|
||||
/* ogg_page_continues returns true if this page ends in a continued packet. */
|
||||
static inline int
|
||||
ogg_page_continues (ogg_page *pg)
|
||||
{ return pg->header [27 + pg->header [26] - 1] == 255 ;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------
|
||||
** Exported functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
** ogg_read_first_page loads the first Ogg page found in the file, and sets the
|
||||
** OGG_PRIVATE serialno to match the logical stream of the page. Data is read
|
||||
** without seeking backwards, loading any data present from psf->header into
|
||||
** the ogg_sync state first, so that this function works with pipes.
|
||||
*/
|
||||
int ogg_read_first_page (SF_PRIVATE *, OGG_PRIVATE *) ;
|
||||
|
||||
/*
|
||||
@ -125,10 +154,16 @@ int ogg_stream_unpack_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) ;
|
||||
** Preforms a bisection search. If not found exactly, the best result is
|
||||
** returned in *best_gp. Found page is loaded into the virtual bitstream,
|
||||
** ready for unpacking. Arguments pcm_start and pcm_end are the highest and
|
||||
** lowest granule positions of the file. begin and end are the file offsets.
|
||||
** lowest granule positions of the file. begin and end are the file offset
|
||||
** range to search. gp_rate is an information hint so granule positions can
|
||||
** be correlated to playback time, so the search can figure out how close it
|
||||
** is, should be granule positions per second.
|
||||
*/
|
||||
int ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata,
|
||||
uint64_t target_gp, uint64_t pcm_start, uint64_t pcm_end,
|
||||
uint64_t *best_gp, sf_count_t begin, sf_count_t end) ;
|
||||
uint64_t target_gp,
|
||||
uint64_t pcm_start, uint64_t pcm_end,
|
||||
uint64_t *best_gp,
|
||||
sf_count_t begin, sf_count_t end,
|
||||
uint64_t gp_rate) ;
|
||||
|
||||
#endif /* SF_SRC_OGG_H */
|
||||
|
229
src/ogg_opus.c
229
src/ogg_opus.c
@ -171,16 +171,26 @@
|
||||
#define OGG_OPUS_COMMENT_PAD (512) /* Same as oggenc default */
|
||||
|
||||
/*
|
||||
** Opus packets can be any multiple of 2.5ms (at 48kHz). We use the recommended
|
||||
** When encoding, we can choose the size of the Opus frames.
|
||||
** Valid values are 2.5, 5, 10, 20, 40, and 60 milliseconds.
|
||||
**
|
||||
** Frames smaller than 10ms can't use CELT (MDCT) mode.
|
||||
** Frames larger than 20ms "are only interesting at fairly low bitrates."
|
||||
**
|
||||
** We choose the suggested default of 20ms for high-fidelity audio, however,
|
||||
** maybe this could be user-selected, or triggered by bitrate command.
|
||||
** default for non-realtime of 20ms. While longer packets reduce the overhead
|
||||
** data somewhat, it also decreases the quality.
|
||||
*/
|
||||
#define OGG_OPUS_ENCODE_PACKET_LEN(samplerate) ((20 * (samplerate)) / 1000)
|
||||
|
||||
/*
|
||||
** How long does it take for a decoder to converge (avoiding flush on seek.
|
||||
** The pre-roll is how long it takes for the decoder to converge. It converges
|
||||
** pretty quickly, to within -40db within 80ms. However, this also depends on
|
||||
** the signal. From experimentation, use the conservative pre-roll amount of
|
||||
** 660ms after which the output is 32-bit-exact with high probability.
|
||||
*/
|
||||
#define OGG_OPUS_PREROLL (80 * 48) /* 80 milliseconds */
|
||||
#define OGG_OPUS_PREROLL (660 * 48) /* 660 milliseconds (33 packets of 20ms) */
|
||||
|
||||
typedef struct
|
||||
{ uint8_t version ;
|
||||
@ -215,10 +225,12 @@ typedef struct
|
||||
{ uint32_t serialno ;
|
||||
OpusHeader header ;
|
||||
|
||||
/* Granule position before the current packet */
|
||||
/* Encode: Granule position after the previous packet.
|
||||
* Decode: Granule position after the current packet */
|
||||
uint64_t pkt_pos ;
|
||||
|
||||
/* Granule position at the end of the current page (encode: last completed) */
|
||||
/* Encode: Granule position at the end of the previous page.
|
||||
* Decode: Granule position at the end of the current page. */
|
||||
uint64_t pg_pos ;
|
||||
|
||||
/* integer coefficient of (current sample rate) / 48000Hz */
|
||||
@ -291,9 +303,9 @@ static sf_count_t ogg_opus_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_
|
||||
static sf_count_t ogg_opus_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
static sf_count_t ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset) ;
|
||||
static sf_count_t ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp) ;
|
||||
static int ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp) ;
|
||||
static sf_count_t ogg_opus_null_read (SF_PRIVATE *psf, sf_count_t offset) ;
|
||||
static sf_count_t ogg_opus_page_seek_manual (SF_PRIVATE *psf, uint64_t target_gp) ;
|
||||
static int ogg_opus_page_seek_search (SF_PRIVATE *psf, uint64_t target_gp) ;
|
||||
|
||||
static int ogg_opus_analyze_file (SF_PRIVATE *psf) ;
|
||||
static int ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
|
||||
@ -409,27 +421,27 @@ ogg_opus_close (SF_PRIVATE *psf)
|
||||
static void
|
||||
opus_print_header (SF_PRIVATE *psf, OpusHeader *h)
|
||||
{ psf_log_printf (psf, "Opus Header Metadata\n") ;
|
||||
psf_log_printf (psf, " OggOpus version : %d\n", h->version) ;
|
||||
psf_log_printf (psf, " Channels : %d\n", h->channels) ;
|
||||
psf_log_printf (psf, " Preskip : %d samples @48kHz\n", h->preskip) ;
|
||||
psf_log_printf (psf, " Input Samplerate : %d Hz\n", h->input_samplerate) ;
|
||||
psf_log_printf (psf, " Gain : %d.%d\n", arith_shift_right (h->gain & 0xF0, 8), h->gain & 0x0F) ;
|
||||
psf_log_printf (psf, " OggOpus version : %d\n", (int) h->version) ;
|
||||
psf_log_printf (psf, " Channels : %d\n", (int) h->channels) ;
|
||||
psf_log_printf (psf, " Preskip : %d samples @48kHz\n", (int) h->preskip) ;
|
||||
psf_log_printf (psf, " Input Samplerate : %d Hz\n", (int) h->input_samplerate) ;
|
||||
psf_log_printf (psf, " Gain : %d.%d\n", (int) arith_shift_right (h->gain & 0xF0, 8), h->gain & 0x0F) ;
|
||||
psf_log_printf (psf, " Channel Mapping : ") ;
|
||||
switch (h->channel_mapping)
|
||||
{ case 0 : psf_log_printf (psf, "0 (mono or stereo)\n") ; break ;
|
||||
case 1 : psf_log_printf (psf, "1 (surround, AC3 channel order)\n") ; break ;
|
||||
case 255 : psf_log_printf (psf, "255 (no channel order)\n") ; break ;
|
||||
default : psf_log_printf (psf, "%d (unknown or unsupported)\n", h->channel_mapping) ; break ;
|
||||
default : psf_log_printf (psf, "%d (unknown or unsupported)\n", (int) h->channel_mapping) ; break ;
|
||||
} ;
|
||||
|
||||
if (h->channel_mapping > 0)
|
||||
{ int i ;
|
||||
psf_log_printf (psf, " streams total : %d\n", h->nb_streams) ;
|
||||
psf_log_printf (psf, " streams coupled : %d\n", h->nb_coupled) ;
|
||||
psf_log_printf (psf, " stream mapping : [") ;
|
||||
psf_log_printf (psf, " streams total : %d\n", (int) h->nb_streams) ;
|
||||
psf_log_printf (psf, " streams coupled : %d\n", (int) h->nb_coupled) ;
|
||||
psf_log_printf (psf, " stream mapping : [") ;
|
||||
for (i = 0 ; i < h->channels - 1 ; i++)
|
||||
psf_log_printf (psf, "%d,", h->stream_map [i]) ;
|
||||
psf_log_printf (psf, "%d]\n", h->stream_map [i]) ;
|
||||
psf_log_printf (psf, "%d,", (int) (h->stream_map [i])) ;
|
||||
psf_log_printf (psf, "%d]\n", (int) (h->stream_map [i])) ;
|
||||
} ;
|
||||
} /* opus_print_header */
|
||||
|
||||
@ -458,7 +470,7 @@ opus_read_header_packet (SF_PRIVATE *psf, OpusHeader *h, ogg_packet *opacket)
|
||||
|
||||
count = psf_binheader_readf (psf, "ep1", 8, &h->version) ;
|
||||
if (! (h->version == 1 || h->version == 0))
|
||||
{ psf_log_printf (psf, "Opus : Unknown / unsupported embedding scheme version: %d.\n", h->version) ;
|
||||
{ psf_log_printf (psf, "Opus : Unknown / unsupported embedding scheme version: %d.\n", (int) h->version) ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
@ -955,8 +967,8 @@ ogg_opus_unpack_next_page (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oo
|
||||
oopus->pg_pos = odata->pkt [odata->pkt_len - 1].granulepos ;
|
||||
gp = ogg_opus_calculate_page_duration (odata) ;
|
||||
oopus->pkt_pos = oopus->pg_pos - gp ;
|
||||
psf_log_printf (psf, "Opus : Hole found appears to be of length %d samples.\n",
|
||||
(oopus->pkt_pos - last_page) / oopus->sr_factor) ;
|
||||
psf_log_printf (psf, "Opus : Hole found appears to be of length %D samples.\n",
|
||||
(oopus->pkt_pos - last_page) / (uint64_t) oopus->sr_factor) ;
|
||||
/*
|
||||
** Could save the hole size here, and have ogg_opus_read_refill()
|
||||
** do packet loss concealment until the hole is gone, but libopus does
|
||||
@ -1050,7 +1062,7 @@ ogg_opus_read_refill (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
|
||||
** MAY defer this action until it decodes the last packet
|
||||
** completed on that page.
|
||||
*/
|
||||
psf_log_printf (psf, "Opus : Mid-strem page's granule position %d is less than total samples of %d\n", oopus->pg_pos, pkt_granulepos) ;
|
||||
psf_log_printf (psf, "Opus : Mid-stream page's granule position %D is less than total samples of %D\n", oopus->pg_pos, pkt_granulepos) ;
|
||||
psf->error = SFE_MALFORMED_FILE ;
|
||||
return -1 ;
|
||||
} ;
|
||||
@ -1118,11 +1130,7 @@ ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
|
||||
else
|
||||
nbytes = ogg_stream_pageout_fill (&odata->ostream, &odata->opage, 255 * 255) ;
|
||||
if (nbytes > 0)
|
||||
{ /*
|
||||
** LibOgg documentation is noted as being bad by it's author. Ogg
|
||||
** page header byte 26 is the segment count.
|
||||
*/
|
||||
oopus->u.encode.last_segments -= odata->opage.header [26] ;
|
||||
{ oopus->u.encode.last_segments -= ogg_page_segments (&odata->opage) ;
|
||||
oopus->pg_pos = oopus->pkt_pos ;
|
||||
ogg_write_page (psf, &odata->opage) ;
|
||||
}
|
||||
@ -1467,7 +1475,12 @@ ogg_opus_analyze_file (SF_PRIVATE *psf)
|
||||
{ psf->sf.frames = (oopus->u.decode.gp_end - oopus->u.decode.gp_start
|
||||
- oopus->header.preskip) / oopus->sr_factor ;
|
||||
} ;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
psf_log_printf (psf, " Granule pos offset : %D\n", oopus->u.decode.gp_start) ;
|
||||
if (oopus->u.decode.gp_end != (uint64_t) -1)
|
||||
psf_log_printf (psf, " Last Granule pos : %D\n", oopus->u.decode.gp_end) ;
|
||||
|
||||
/* Go back to where we left off. */
|
||||
ogg_sync_fseek (psf, saved_offset, SEEK_SET) ;
|
||||
@ -1475,23 +1488,25 @@ ogg_opus_analyze_file (SF_PRIVATE *psf)
|
||||
} /* ogg_opus_analyze_file */
|
||||
|
||||
/*
|
||||
** ogg_opus_seek_null_read
|
||||
** ogg_opus_null_read
|
||||
**
|
||||
** Decode samples, doing nothing with them, until the desired granule position
|
||||
** is reached.
|
||||
*/
|
||||
static sf_count_t
|
||||
ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset)
|
||||
ogg_opus_null_read (SF_PRIVATE *psf, sf_count_t offset)
|
||||
{ OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
|
||||
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
|
||||
sf_count_t total ;
|
||||
sf_count_t readlen ;
|
||||
|
||||
total = oopus->pkt_pos / oopus->sr_factor ;
|
||||
total += oopus->loc ;
|
||||
|
||||
total = (oopus->pkt_pos / oopus->sr_factor) - (oopus->len - oopus->loc) ;
|
||||
for ( ; total < offset ; )
|
||||
{ if (oopus->loc == oopus->len)
|
||||
{ sf_count_t readlen = SF_MIN ((int) (offset - total), (oopus->len - oopus->loc)) ;
|
||||
if (readlen > 0)
|
||||
{ total += readlen ;
|
||||
oopus->loc += readlen ;
|
||||
} ;
|
||||
if (oopus->loc == oopus->len)
|
||||
{ if (ogg_opus_read_refill (psf, odata, oopus) <= 0)
|
||||
return total ;
|
||||
/*
|
||||
@ -1500,22 +1515,18 @@ ogg_opus_seek_null_read (SF_PRIVATE *psf, sf_count_t offset)
|
||||
*/
|
||||
oopus->loc = 0 ;
|
||||
} ;
|
||||
|
||||
readlen = SF_MIN ((int) (offset - total), (oopus->len - oopus->loc)) ;
|
||||
if (readlen > 0)
|
||||
{ total += readlen ;
|
||||
oopus->loc += readlen ;
|
||||
} ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* ogg_opus_seek_null_read */
|
||||
} /* ogg_opus_null_read */
|
||||
|
||||
/*
|
||||
** ogg_opus_page_seek_search
|
||||
**
|
||||
** Search within the file for the page with the highest granule position at or
|
||||
** before our target.
|
||||
*/
|
||||
static int
|
||||
ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp)
|
||||
ogg_opus_page_seek_search (SF_PRIVATE *psf, uint64_t target_gp)
|
||||
{ OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
|
||||
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
|
||||
uint64_t pcm_start ;
|
||||
@ -1523,49 +1534,48 @@ ogg_opus_seek_page_search (SF_PRIVATE *psf, uint64_t target_gp)
|
||||
uint64_t best_gp ;
|
||||
sf_count_t begin ;
|
||||
sf_count_t end ;
|
||||
sf_count_t old_pos ;
|
||||
int ret ;
|
||||
|
||||
best_gp = pcm_start = oopus->u.decode.gp_start ;
|
||||
pcm_end = oopus->u.decode.gp_end ;
|
||||
begin = psf->dataoffset ;
|
||||
end = oopus->u.decode.last_offset ;
|
||||
|
||||
/* Adjust the target to give time to converge. */
|
||||
if (target_gp >= OGG_OPUS_PREROLL)
|
||||
target_gp -= OGG_OPUS_PREROLL ;
|
||||
if (target_gp < pcm_start)
|
||||
target_gp = pcm_start ;
|
||||
|
||||
/* Seek to beginning special case */
|
||||
if (target_gp < pcm_start + (uint64_t) oopus->header.preskip)
|
||||
end = begin ;
|
||||
else
|
||||
end = oopus->u.decode.last_offset ;
|
||||
|
||||
ogg_stream_seek_page_search (psf, odata, target_gp, pcm_start, pcm_end, &best_gp, begin, end) ;
|
||||
/* Search the Ogg stream for such a page */
|
||||
old_pos = ogg_sync_ftell (psf) ;
|
||||
ret = ogg_stream_seek_page_search (psf, odata, target_gp, pcm_start, pcm_end, &best_gp, begin, end, 48000) ;
|
||||
if (ret != 0)
|
||||
{ ogg_sync_fseek (psf, old_pos, SEEK_SET) ;
|
||||
return ret ;
|
||||
} ;
|
||||
|
||||
/* Load the page that contains our pre-roll target */
|
||||
oopus->loc = 0 ;
|
||||
oopus->len = 0 ;
|
||||
if ((ret = ogg_opus_unpack_next_page (psf, odata, oopus)) != 1)
|
||||
return ret ;
|
||||
oopus->pkt_pos = best_gp ;
|
||||
|
||||
/* Reset the decoder (gain settings survive the reset) */
|
||||
opus_multistream_decoder_ctl (oopus->u.decode.state, OPUS_RESET_STATE) ;
|
||||
/* Gain decoder settings survive resets. */
|
||||
|
||||
return 0 ;
|
||||
} /* ogg_opus_seek_page_search */
|
||||
} /* ogg_opus_page_seek_search */
|
||||
|
||||
/*
|
||||
** ogg_opus_page_seek_manual
|
||||
**
|
||||
** Seek to the beginning of the Ogg stream and read pages until we find one with
|
||||
** a granule position at or before our target.
|
||||
*/
|
||||
static sf_count_t
|
||||
ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp)
|
||||
ogg_opus_page_seek_manual (SF_PRIVATE *psf, uint64_t target_gp)
|
||||
{ OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
|
||||
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
|
||||
sf_count_t pos ;
|
||||
int nn ;
|
||||
|
||||
if (target_gp > OGG_OPUS_PREROLL)
|
||||
target_gp -= OGG_OPUS_PREROLL ;
|
||||
if (target_gp < oopus->pg_pos)
|
||||
target_gp = oopus->pg_pos ;
|
||||
|
||||
if (oopus->pg_pos > target_gp)
|
||||
{ ogg_stream_reset (&odata->ostream) ;
|
||||
pos = ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
@ -1582,13 +1592,13 @@ ogg_opus_seek_manual (SF_PRIVATE *psf, uint64_t target_gp)
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* ogg_opus_seek_manual */
|
||||
} /* ogg_opus_page_seek_manual */
|
||||
|
||||
static sf_count_t
|
||||
ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
{ OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
|
||||
uint64_t target_gp ;
|
||||
uint64_t current ;
|
||||
{ OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
|
||||
OPUS_PRIVATE *oopus = (OPUS_PRIVATE *) psf->codec_data ;
|
||||
uint64_t target_gp, current_gp ;
|
||||
int ret ;
|
||||
|
||||
/* Only support seeking in read mode. */
|
||||
@ -1597,28 +1607,40 @@ ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
current = oopus->pkt_pos + oopus->loc * oopus->sr_factor ;
|
||||
/*
|
||||
** Remember, there are preskip granulepos worth of samples at the front of
|
||||
** the stream which are bunk. Also, granule positions can be offset.
|
||||
*/
|
||||
target_gp = offset * oopus->sr_factor + oopus->u.decode.gp_start + oopus->header.preskip ;
|
||||
/* Figure out the current position granule pos. Use the start of the
|
||||
* current buffer, to avoid backwards seeking if the target is on the page
|
||||
* but before the current locaiton. */
|
||||
oopus->loc = 0 ;
|
||||
current_gp = oopus->pkt_pos - (uint64_t) (oopus->len * oopus->sr_factor) ;
|
||||
|
||||
if (oopus->u.decode.gp_end == (uint64_t) -1)
|
||||
{ /*
|
||||
** Don't know the end of the file. Could be a chained file we don't yet
|
||||
** support. Oh well, just do it manually.
|
||||
*/
|
||||
ogg_opus_seek_manual (psf, target_gp) ;
|
||||
}
|
||||
else
|
||||
{ /*
|
||||
** Avoid seeking in the file if where we want is just ahead or exactly
|
||||
** were we are. To avoid needing to flush the decoder we choose pre-
|
||||
** roll plus 10ms.
|
||||
*/
|
||||
if (target_gp < current || target_gp - current > OGG_OPUS_PREROLL + 10 * 48)
|
||||
{ ret = ogg_opus_seek_page_search (psf, target_gp) ;
|
||||
/* Calculate the target granule pos. This includes the decoder delay and
|
||||
* the file granule position offset. */
|
||||
target_gp = offset * oopus->sr_factor ;
|
||||
target_gp += oopus->u.decode.gp_start ;
|
||||
target_gp += oopus->header.preskip ;
|
||||
|
||||
/* Check if we need to do a page seek. */
|
||||
if (target_gp < current_gp || target_gp - current_gp > OGG_OPUS_PREROLL)
|
||||
{ uint64_t preroll_gp ;
|
||||
|
||||
/* For a page seek, use an earlier target granule pos, giving the
|
||||
* decoder samples to converge before the actual target. */
|
||||
if (target_gp >= OGG_OPUS_PREROLL + oopus->u.decode.gp_start + (uint64_t) oopus->header.preskip)
|
||||
{ preroll_gp = target_gp - OGG_OPUS_PREROLL ;
|
||||
}
|
||||
else
|
||||
{ preroll_gp = oopus->u.decode.gp_start + (uint64_t) oopus->header.preskip ;
|
||||
} ;
|
||||
|
||||
if (oopus->u.decode.gp_end == (uint64_t) -1)
|
||||
{ /*
|
||||
** Don't know the end of the file. Could be a chained file we don't yet
|
||||
** support. Oh well, just do it manually.
|
||||
*/
|
||||
ogg_opus_page_seek_manual (psf, preroll_gp) ;
|
||||
}
|
||||
else
|
||||
{ ret = ogg_opus_page_seek_search (psf, preroll_gp) ;
|
||||
if (ret < 0)
|
||||
{ /*
|
||||
** Page seek failed, what to do? Could be bad data. We can
|
||||
@ -1626,7 +1648,7 @@ ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
** from the beginning has the advantage of finding where the
|
||||
** file goes bad.
|
||||
*/
|
||||
ret = ogg_opus_seek_manual (psf, target_gp) ;
|
||||
ret = ogg_opus_page_seek_manual (psf, preroll_gp) ;
|
||||
if (ret < 0)
|
||||
{ /*
|
||||
** If were here, and there is no error, we can be pretty
|
||||
@ -1638,13 +1660,29 @@ ogg_opus_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
} ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Skip over packets on the found page that are before our pre-roll
|
||||
** target to avoid unnecessary decoding, and make decoder convergence
|
||||
** independent of page boundaries for more visible errors.
|
||||
*/
|
||||
for ( ; odata->pkt_indx != odata->pkt_len ; )
|
||||
{ ogg_packet *ppkt = &odata->pkt [odata->pkt_indx] ;
|
||||
int nsamp = opus_packet_get_nb_samples (ppkt->packet, ppkt->bytes, 48000) ;
|
||||
if (oopus->pkt_pos + nsamp < preroll_gp)
|
||||
{ oopus->pkt_pos += nsamp ;
|
||||
odata->pkt_indx++ ;
|
||||
}
|
||||
else
|
||||
break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** We've seeked or skipped through pages until just before our target,
|
||||
** now decode until we hit it.
|
||||
*/
|
||||
offset = ogg_opus_seek_null_read (psf, target_gp / oopus->sr_factor) ;
|
||||
offset = ogg_opus_null_read (psf, target_gp / oopus->sr_factor) ;
|
||||
return offset - ((oopus->header.preskip + oopus->u.decode.gp_start) / oopus->sr_factor) ;
|
||||
|
||||
} /* ogg_opus_seek */
|
||||
@ -1733,6 +1771,13 @@ ogg_opus_command (SF_PRIVATE *psf, int command, void *data, int datasize)
|
||||
*((int *) data) = oopus->header.input_samplerate ;
|
||||
return SF_TRUE ;
|
||||
|
||||
case SFC_GET_OGG_STREAM_SERIALNO :
|
||||
if (data == NULL || datasize != sizeof (int32_t))
|
||||
return SF_FALSE ;
|
||||
|
||||
*((int32_t *) data) = odata->ostream.serialno ;
|
||||
return SF_TRUE ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user